Chat Message Latency KQL¶
Analyze server-side operation duration for ACS chat operations using ACSChatIncomingOperations.DurationMs, which the service already emits per request.
Query Description¶
ACSChatIncomingOperations records one row per incoming chat API request. The DurationMs column is the server-side duration of the operation in milliseconds — there is no separate start-time column to subtract from TimeGenerated. The query below aggregates that duration per chat thread and per calling user for successful requests only.
KQL Query¶
ACSChatIncomingOperations
| where TimeGenerated > ago(1h)
| where ResultSignature startswith "2"
| summarize
AverageDurationMs = avg(DurationMs),
MaxDurationMs = max(DurationMs),
RequestCount = count()
by OperationName, ChatThreadId, UserId
| order by MaxDurationMs desc
Explanation¶
| Field | Description |
|---|---|
TimeGenerated > ago(1h) | Restricts the scan to the last hour to keep queries cheap and focused on current issues. |
ResultSignature startswith "2" | Keeps only requests that returned an HTTP 2xx status. ResultSignature is documented as the sub-status of the operation, which for REST API calls is the HTTP status code. |
avg(DurationMs), max(DurationMs) | Aggregates the server-side operation duration that ACS already emits — no arithmetic against TimeGenerated is required. |
by OperationName, ChatThreadId, UserId | Groups by the chat API operation, the thread, and the calling user's ID. ChatThreadId and UserId are the request-scoped identifiers on this table. |
Insights¶
- Server-side view only:
DurationMsmeasures how long ACS took to process the request. It does not include client-side send latency, network delivery to other participants, or push-notification fan-out. Client-perceived message delivery latency is not observable from this table alone. - Compare by operation: A latency spike scoped to a single
OperationName(for exampleSendChatMessagevsListChatMessages) points to a specific API path rather than a whole-service regression. - Correlate failures: Filter
ResultSignature !startswith "2"and inspectResultDescriptionto see which requests are failing and why.