Performance & Laufzeiten

KQL-Abfragen für Laufzeiten, Fehlerquoten, Abhängigkeiten und Datenvolumen.

Die folgenden Abfragen können direkt im Logs-Bereich von Application Insights (Kusto Query Language) ausgeführt werden.


Laufzeiten und Fehler

Laufzeiten aller Funktionen (letzte 24 Stunden)

requests
| where timestamp > ago(24h)
| summarize
    Aufrufe        = count(),
    DurchschnittMs = avg(duration),
    P95Ms          = percentile(duration, 95),
    Fehler         = countif(success == false)
  by name
| order by DurchschnittMs desc

Verlauf einer einzelnen Funktion (letzte 7 Tage)

requests
| where timestamp > ago(7d)
| where name == "GetChanges"
| summarize
    P50Ms  = percentile(duration, 50),
    P95Ms  = percentile(duration, 95),
    Fehler = countif(success == false),
    Läufe  = count()
  by bin(timestamp, 1h)
| order by timestamp asc

Durchschnittliche Laufzeit der letzten 30 Tage (täglich)

requests
| where timestamp > ago(30d)
| summarize
    DurchschnittMs = avg(duration),
    P95Ms          = percentile(duration, 95)
  by name, bin(timestamp, 1d)
| order by name asc, timestamp asc

Fehlerquote je Funktion (letzte 7 Tage)

requests
| where timestamp > ago(7d)
| summarize
    Gesamt    = count(),
    Fehler    = countif(success == false),
    FehlerPct = round(100.0 * countif(success == false) / count(), 1)
  by name
| order by FehlerPct desc

Warnungen und Fehler im Zeitverlauf

traces
| where timestamp > ago(7d)
| where severityLevel >= 2  // 2 = Warning, 3 = Error
| summarize Anzahl = count() by severityLevel, bin(timestamp, 1h), operation_Name
| order by timestamp asc

Top-10 häufigste Fehlermeldungen

exceptions
| where timestamp > ago(7d)
| summarize Anzahl = count() by outerMessage
| top 10 by Anzahl desc

Einzelne Ausführung nachvollziehen

Alle Einträge einer Ausführung (per operation_Id)

union requests, traces, exceptions
| where operation_Id == "<operation_Id hier einfügen>"
| project timestamp, itemType, severityLevel, message, outerMessage, operation_Name
| order by timestamp asc

Fehlerläufe mit allen zugehörigen Traces (letzte 24 Stunden)

let fehlgeschlagene =
    requests
    | where timestamp > ago(24h)
    | where success == false
    | project operation_Id, FunktionsName = name, Startzeit = timestamp;
traces
| where timestamp > ago(24h)
| join kind=inner fehlgeschlagene on operation_Id
| project Startzeit, FunktionsName, severityLevel, message
| order by Startzeit desc, severityLevel desc

Abhängigkeiten

Langsamste Abhängigkeiten (letzte 24 Stunden)

Zeigt die ausgehenden Aufrufe an Quell- und Zielsysteme mit den höchsten Laufzeiten:

dependencies
| where timestamp > ago(24h)
| summarize
    Aufrufe        = count(),
    DurchschnittMs = avg(duration),
    P95Ms          = percentile(duration, 95),
    Fehler         = countif(success == false)
  by type, target, name
| order by P95Ms desc
| take 20

Fehlgeschlagene Abhängigkeiten nach Zielsystem (letzte 7 Tage)

dependencies
| where timestamp > ago(7d)
| where success == false
| summarize Fehler = count() by type, target, resultCode
| order by Fehler desc

Datenvolumen und Kosten

Datenvolumen pro Tabelle

Wenn das tägliche Datenvolumen die konfigurierte Obergrenze (Daily Cap) erreicht, zeigt diese Abfrage, welche Tabelle den Verbrauch verursacht:

union withsource = Tabelle *
| where TimeGenerated > ago(7d)
| summarize VolumenMB = round(sum(_BilledSize) / 1024.0 / 1024.0, 1) by Tabelle, bin(TimeGenerated, 1d)
| order by TimeGenerated desc, VolumenMB desc

Hinweise zur Interpretation

Warum fehlen manche Traces bei erfolgreichen Läufen?

Das Buffering sendet bei erfolgreichen Läufen nur einen Teil der Information-Einträge und keine Debug-Einträge. Die Stichprobe wird pro Eintrag gezogen: Jede einzelne Information-Zeile hat unabhängig eine Chance von 20 % (konfigurierbar via TELEMETRY_INFO_SAMPLE_RATE), gesendet zu werden. Das führt zu einem gleichmäßigen Strom vereinzelter Traces — vollständige, lückenlose Ketten gibt es nur bei Warning- und Fehler-Läufen.

Trace-Einträge erreichen Application Insights grundsätzlich nie — sie sind nur live in der Konsole bzw. im Log Stream sichtbar.

Warum fehlen manche Abhängigkeiten?

Fehlgeschlagene und langsame Aufrufe kommen immer vollständig an, erfolgreiche und schnelle nur zu einem Anteil von 10 % (konfigurierbar via TELEMETRY_DEPENDENCY_SAMPLE_RATE).

Anders als bei den Log-Einträgen wird diese Entscheidung pro Aufruf getroffen — in dem Moment, in dem der Aufruf endet, also bevor das Ergebnis der Ausführung bekannt ist. In der End-to-End-Transaktionsansicht sind daher auch bei einem fehlgeschlagenen Lauf nicht zwangsläufig alle ausgehenden Aufrufe zu sehen. Für eine lückenlose Kette ist temporär TELEMETRY_CONTROL=TRACE_ALL zu setzen.

Requests vs. Traces vs. Dependencies

Telemetrie-TypWird immer erfasst?Enthält Laufzeit?
RequestJa — jede InvocationJa
ExceptionJa — jede ExceptionNein
TraceNein — abhängig vom OutcomeNein
DependencyNein — garantiert nur, wenn der Aufruf selbst fehlschlägt oder den Langsam-Schwellwert überschreitetJa
Custom MetricJa — vorab aggregiert, kein SamplingNein

Für Laufzeit-Analysen der Funktionen immer die requests-Tabelle verwenden, für Laufzeiten einzelner Fremdsystem-Aufrufe die dependencies-Tabelle, für inhaltliche Diagnose die traces-Tabelle. Für belastbare Mengenangaben ausschließlich die Custom Metrics, da diese nicht gesampelt werden.

Korrelation über operation_Id

Jede Funktionsausführung erhält eine eindeutige operation_Id. Alle Traces, Requests und Exceptions dieser Invocation tragen dieselbe ID. Das erlaubt es, in KQL alle zusammengehörenden Einträge mit einem einzigen Filter zu finden.