APM Tips

KQL · latency

Apdex-style satisfaction score per operation

Score each operation from 0 to 1 by sorting requests into satisfied, tolerating and frustrated against a response-time target you set in one line.

Updated

requests latency

let lookback = 24h;
let target_ms = 500.0;
requests
| where timestamp > ago(lookback)
| extend bucket = case(
    tostring(success) =~ "false", "frustrated",
    duration <= target_ms, "satisfied",
    duration <= 4 * target_ms, "tolerating",
    "frustrated")
| summarize
    requests = sum(itemCount),
    satisfied = sumif(itemCount, bucket == "satisfied"),
    tolerating = sumif(itemCount, bucket == "tolerating"),
    frustrated = sumif(itemCount, bucket == "frustrated")
    by operation_Name
| extend score = round((satisfied + tolerating / 2.0) / requests, 2)
| order by score asc

Returns: One row per operation with its request count, the satisfied, tolerating and frustrated counts against the target, and a 0-to-1 score, worst first.

Pitfalls

  • The score is only as good as the target. One target for every route is rarely right: a search page and a report export have different targets. Score them separately, or filter to one class of route.
  • Failed requests count as frustrated whatever their duration. That is this query's choice, not a rule of the standard; drop the first case() line if you want failures scored by speed alone.
  • duration is server time. Browser rendering and network time are not in it, so a server-side score overstates what users feel.
  • Counts use sum(itemCount) so sampling doesn't skew the shares.

How it works

Apdex is an open standard for turning many response times into one number between 0 and 1. You pick a target time T. A response at or under T is satisfied, one up to four times T is tolerating, and anything slower is frustrated. The score is satisfied plus half of tolerating, divided by all samples. A score of 1 means every request met the target.

The appeal is that one number per route is easy to rank and to put on a dashboard, and unlike an average it can’t be dragged around by a handful of extreme requests.

Line by line

  • let target_ms = 500.0; is T, in milliseconds. It is the one number to argue about with whoever owns the route. The tolerating ceiling is 4 * target_ms.
  • case() sorts each request into a bucket, checking conditions in order. Failures come first, so a fast error is frustrated, not satisfied; then the two time thresholds; anything left is frustrated.
  • sumif(itemCount, bucket == "...") counts each bucket the sampling-aware way. A stored row stands for itemCount requests, and requests = sum(itemCount) is the denominator.
  • score applies the formula. Dividing by 2.0 rather than 2 keeps the arithmetic in real numbers.
  • order by score asc puts the operations users like least at the top.

Reading the result

A score near 1 with a large request count is a healthy route. A low score with many frustrated requests needs the latency work: start with the slowest requests for that operation. A low score made mostly of tolerating requests often means the target is too ambitious for that route rather than that something is broken. To see the plain share of requests over a limit, without the weighting, use requests slower than a threshold.

Because duration is measured on the server, this is a back-end view of satisfaction. Page loads seen by browsers are in pageViews and browserTimings; the JavaScript snippet guide covers collecting them.

Variations

  • Score over time: group by bin(timestamp, 1h) instead of operation_Name, sort by timestamp and add | render timechart.
  • One service: add | where cloud_RoleName == "orders-api" after the time filter.
  • Workspace tables: use AppRequests, TimeGenerated, Success == false, DurationMs, ItemCount and OperationName.

Sources, checked

  1. Apdex Users Group (the open standard)apdex.org · checked
  2. Apdex (formula and the 4T tolerating threshold)en.wikipedia.org · checked
  3. case() (Kusto)learn.microsoft.com · checked
  4. sumif() (Kusto)learn.microsoft.com · checked
  5. Application Insights telemetry data modellearn.microsoft.com · checked