Das ist eine für den Ausdruck optimierte Ansicht des gesamten Kapitels inkl. Unterseiten. Druckvorgang starten.

Zur Standardansicht zurückkehren.

Logging & Telemetrie

Wie die DataBridge Logs erzeugt, welche Telemetrie sie sendet und wie Sampling die Kosten steuert.

Die DataBridge steuert ihr Telemetrie-Volumen über zwei voneinander unabhängige Mechanismen:

  • Gepuffertes Logging — Log-Einträge werden pro Funktionsausführung gesammelt und erst am Ende des Laufs, abhängig vom Ergebnis, selektiv gesendet.
  • Sampling von Abhängigkeiten — ausgehende Aufrufe an Quell- und Zielsysteme werden nur anteilig gesendet, sofern sie erfolgreich und schnell waren.

Der zweite Mechanismus ist der eigentliche Kostenhebel: In einer Volumenanalyse über 90 Tage entfielen rund 78 % des gesamten Datenvolumens auf Abhängigkeiten und nur ein Bruchteil auf Log-Einträge.

SeiteInhalt
MetrikenCustom Metrics — die einzige nicht gesampelte Mengenangabe
Performance & LaufzeitenKQL-Abfragen für Laufzeiten, Fehler, Abhängigkeiten und Datenvolumen

Gepuffertes Logging — drei Lauf-Ergebnisse

ErgebnisKriteriumGesendete Log-Level
Normaler LaufKeine Fehler, keine WarnungenNur Warning + Error + ~20 % der Information-Einträge (konfigurierbar)
Lauf mit WarnungenMindestens eine Warning, kein FehlerAlle Information + Warning + Error
FehlerlaufMindestens ein unbehandelter FehlerAlle Debug + Information + Warning + Error

Der Anteil der Information-Einträge im Normalbetrieb wird über TELEMETRY_INFO_SAMPLE_RATE gesteuert (Standard: 20 = 20 %). Die Stichprobe wird pro Eintrag gezogen — es entstehen also vereinzelte Traces aus allen Läufen, keine vollständigen Ketten. Lückenlose Ketten gibt es nur bei Warning- und Fehler-Läufen.

Trace-Level erreicht Application Insights nie


Sampling von Abhängigkeiten

Ausgehende Aufrufe an Quell- und Zielsysteme (D365 OData, SQL, Table Storage, Service Bus) werden von Application Insights automatisch als Dependencies erfasst. Ohne Filterung verursachen sie bei kurzem Polling-Intervall ein Vielfaches aller Log-Einträge zusammen.

AufrufWird gesendet
FehlgeschlagenImmer vollständig
Langsam (≥ TELEMETRY_DEPENDENCY_SLOW_MS)Immer vollständig
Erfolgreich und schnellNur zum Anteil TELEMETRY_DEPENDENCY_SAMPLE_RATE (Standard 10 %)

Steuerung über TELEMETRY_CONTROL

Die Einstellung wirkt auf beide Mechanismen — Traces und Abhängigkeiten:

WertWirkung
TRACE_SAMPLE (Standard)Selektives Sampling wie oben beschrieben
TRACE_ALLSendet alles, deaktiviert jedes Sampling (für aktive Fehlersuche)
TRACE_NONEUnterdrückt Traces und Abhängigkeiten vollständig

Eine leere Variable entspricht TRACE_SAMPLE. Details zu allen Telemetrie-Einstellungen stehen unter Umgebungsvariablen.


Auswirkung auf bestehende Auswertungen

Nicht betroffen sind:

  • Fehleranzahlen und Fehlerursachen — fehlgeschlagene Aufrufe werden nie verworfen
  • Auswertungen langsamer Aufrufe — ab dem Schwellwert immer vollständig
  • Requests, Exceptions, Traces und Custom Metrics — unverändert

Wichtige Log-Felder in Application Insights

FeldBeschreibung
operation_IdKorrelations-ID — verknüpft alle Einträge einer einzigen Funktionsausführung
operation_ParentIdSpan-ID des Requests — sorgt für die korrekte Einordnung in der End-to-End-Transaktionsansicht
operation_NameName der ausgeführten Function (z. B. GetChanges, ProcessStandardQueueItems)
timestampZeitpunkt des ursprünglichen Log-Aufrufs, nicht des Sendens am Ende der Ausführung
messageLog-Text
severityLevel0 = Verbose, 1 = Information, 2 = Warning, 3 = Error, 4 = Critical
customDimensions.Category.NET-Logger-Kategorie
customDimensions.ExceptionVollständiger Stack Trace (nur bei Exceptions)

Automatisch erfasste Telemetrie

Neben den eigenen Log-Einträgen erfasst Application Insights selbstständig:

  • Requests — je Funktionsausführung, mit Laufzeit und Erfolgskennzeichen
  • Exceptions — jede aufgetretene Ausnahme mit Stack Trace
  • Dependencies — jeder ausgehende Aufruf (unterliegt dem Sampling, siehe oben)

Auswertung im Azure Portal

Schnelle Übersicht — Performance Blade

Application Insights → Untersuchen → Leistung

Zeigt alle Funktionsausführungen mit Durchschnittslaufzeit und P50/P95/P99-Perzentilen. Ein hoher P95-Wert deutet auf gelegentliche Verzögerungen hin (langsames Zielsystem, Queue-Stau).

Fehlerdiagnose — Failures Blade

Application Insights → Untersuchen → Fehler

Fehlgeschlagene Aufrufe, gruppiert nach Fehlertyp, mit direktem Zugriff auf Stack Traces.

Application Insights → Untersuchen → Transaktionssuche

Filter nach operation_Id, um alle Einträge einer einzigen Ausführung zu sehen.


Tipps für die Fehlersuche

  1. operation_Id finden: Im Failures Blade auf einen fehlgeschlagenen Request klicken → End-to-End Transaction Details → operation_Id ist in der URL bzw. in den Details sichtbar.

  2. Komplette Traces aktivieren: TELEMETRY_CONTROL = TRACE_ALL setzen, den problematischen Job über ExecuteJob manuell auslösen, anschließend zurücksetzen.

  3. Zwischen Funktionen korrelieren: Schlägt eine der Process…QueueItems-Funktionen fehl, ist die operation_Id der ursprünglichen GetChanges-Ausführung in der Nachricht gespeichert — so lässt sich der vollständige Pfad eines Datensatzes nachvollziehen. Beachten Sie dabei die Einschränkung beim Dependency-Sampling (siehe oben).

1 - Metriken

Custom Metrics der DataBridge — vorab aggregiert und ohne Sampling.

Neben Traces und Requests sendet die dsyr.DataBridge eigene Custom Metrics an Application Insights. Metriken sind numerische Zeitreihen mit Dimensionen — sie eignen sich für Dashboards, Trend-Analysen und Metric Alerts, ohne dass dafür Log-Einträge durchsucht werden müssen.

Die Metriken werden über TelemetryClient.GetMetric() vorab aggregiert: Das SDK sammelt die Werte lokal in 1-Minuten-Intervallen und sendet pro Intervall und Dimensionskombination einen aggregierten Datenpunkt (Summe, Anzahl, Min, Max).

Verfügbare Metriken

Alle Metriken verwenden den Namespace DataBridge.

MetrikDimensionenQuelleBedeutung
ChangesDetectedJobNameGetChanges → ProcessJobsForRetrievalInOrderServiceAnzahl der erkannten geänderten Datensätze pro Job und Lauf (kumuliert pro Lauf, inkl. 0)
MessagesProcessedJobName, Outcome (Success/Failed/Transitive)ProcessStandardQueueItems/ProcessLowPriorityQueueItems/ProcessHighPriorityQueueItems → ProcessQueueMessageServiceEine verarbeitete Queue-Nachricht mit ihrem Ausgang. Queue-übergreifend: alle drei Prioritäts-Queues schreiben in dieselbe Metrik, unterscheidbar nur über den Ausgang, nicht über die Queue. Transitive heißt: die Nachricht wurde nicht endgültig verworfen, sondern in eine Retry-Queue umgeleitet.
ProcessingDurationMsJobNameProcessStandardQueueItems/ProcessLowPriorityQueueItems/ProcessHighPriorityQueueItems → ProcessQueueMessageServiceVerarbeitungsdauer einer einzelnen Queue-Nachricht in Millisekunden, unabhängig vom Ausgang.

Anzeige in Azure

Metrics Explorer

Application Insights → Metriken → Namespace DataBridge auswählen → Metrik ChangesDetected. Als Aggregation eignet sich Summe (Anzahl Datensätze) oder Anzahl (Anzahl Läufe).

KQL (Logs)

Jeder aggregierte Datenpunkt landet zusätzlich in der Tabelle customMetrics:

customMetrics
| where name == "ChangesDetected"
| extend job = tostring(customDimensions["JobName"])
| summarize sum(valueSum) by bin(timestamp, 2m), job
| render timechart

Host-generierte Metriken (Functions-Runtime)

Zusätzlich zu den oben aufgeführten, selbst erzeugten Metriken schreibt die Azure-Functions-Runtime automatisch pro Funktion aggregierte Kennzahlen ebenfalls in die Tabelle customMetrics — ohne dass die DataBridge dafür Code enthält:

<FunctionName> Successes
<FunctionName> Failures
<FunctionName> SuccessRate
<FunctionName> AvgDurationMs
<FunctionName> MinDurationMs
<FunctionName> MaxDurationMs

<FunctionName> ist z. B. GetChanges, ProcessStandardQueueItems, ProcessLowPriorityQueueItems oder ProcessHighPriorityQueueItems. Diese Metriken sind Standardverhalten des Functions-Hosts (WebJobs SDK Function Result Aggregator) und daher in jeder Azure-Functions-App vorhanden, unabhängig von der DataBridge selbst. Das Grafana-Dashboard nutzt sie für die Kopfzeilen-Tachos und die Ausführungen/Laufzeiten-Panels der Zeile „GetChanges".

Limits

LimitWertAnmerkung
Dimensionen pro Metrik10Azure-Monitor-Limit
Zeitreihen pro Metrik (SDK-Default)1.000seriesCountLimit der SDK-Pre-Aggregation
Distinct-Werte pro Dimension (SDK-Default)100valuesPerDimensionLimit

Konsequenz: Dimensionswerte müssen niedrig-kardinal sein — Job-Namen, Queue-Namen und Status-Codes sind geeignet; IDs, Zeitstempel oder Datensatz-Schlüssel nicht.

2 - 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.