Since the last lesson, the Kladde writes traces, logs and custom measurements to its workspace in Azure. The Application Insights views show the usual things from it. For everything else, you ask questions in a language of its own: KQL, the Kusto Query Language. With it you query Log Analytics and Application Insights, Azure Resource Graph from lesson 3.1.6 and Microsoft's security tools. The alerts of the next lesson are KQL queries, too.
KQL only reads. A query cannot change or delete anything, so you can try things out without risk. In this lesson you learn the most important building blocks, a trap that makes a whole query worthless without anyone noticing, and how the Kladde's queries get into the repository as files, with a test.
Where you ask
In the portal there are two doors to the same data:
- Application Insights → Logs. Here the tables are named as they used to be:
requests,dependencies,traces,exceptions,customMetrics. - Log Analytics workspace → Logs. Here they are named
AppRequests,AppDependencies,AppTraces,AppExceptions,AppMetrics, and next to them are the logs of the Container Apps environment.
The columns are named differently in the two worlds:
Workspace (AppRequests …) |
classic (requests …) |
Content |
|---|---|---|
TimeGenerated |
timestamp |
point in time |
AppRoleName |
cloud_RoleName |
role name of the service |
Name |
name |
name of the request or dependency, such as GET /appointments |
DurationMs |
duration |
duration in milliseconds |
Success, ResultCode |
success, resultCode |
success and status code |
OperationId |
operation_Id |
trace ID of the trace |
ItemCount |
itemCount |
how many events the row stands for |
Properties |
customDimensions |
attributes of the span or fields of the log line |
Target, DependencyType |
target, type |
target and kind of a dependency |
The Kladde writes all queries against the workspace. That is also where the console logs of the Container Apps live, and where the alerts run later. Queries from tutorials on the web often use the classic names; with the table above you translate them.
The result of every query depends on the time range. If the query itself contains a filter on TimeGenerated, that one applies; otherwise the
range you choose at the top of the portal. Write the time range into the query: Then it returns the same in the portal, in a script and in an alert.