Performance & Laufzeiten
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
Erfolgreiche, schnelle Aufrufe werden gesampelt (siehe
Sampling von Abhängigkeiten). Die Spalte Aufrufe ist
deshalb keine vollständige Zählung. Langsame und fehlgeschlagene Aufrufe sind dagegen
vollständig enthalten — für genau diese Auswertung ist die Abfrage also aussagekräftig.
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
Erfahrungsgemäß dominiert AppDependencies das Volumen deutlich. Greift die Obergrenze
trotz aktivem Sampling, ist TELEMETRY_DEPENDENCY_SAMPLE_RATE weiter zu reduzieren.
Zusätzlich ist zu prüfen, ob TELEMETRY_CONTROL versehentlich auf TRACE_ALL steht —
damit ist jedes Sampling deaktiviert.
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-Typ | Wird immer erfasst? | Enthält Laufzeit? |
|---|---|---|
| Request | Ja — jede Invocation | Ja |
| Exception | Ja — jede Exception | Nein |
| Trace | Nein — abhängig vom Outcome | Nein |
| Dependency | Nein — garantiert nur, wenn der Aufruf selbst fehlschlägt oder den Langsam-Schwellwert überschreitet | Ja |
| Custom Metric | Ja — vorab aggregiert, kein Sampling | Nein |
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.