Das ist eine für den Ausdruck optimierte Ansicht des gesamten Kapitels inkl. Unterseiten.
Druckvorgang starten.
Zur Standardansicht zurückkehren.
Betrieb & Wartung
Logging, Monitoring, Alerts und Updates für den laufenden Betrieb der DataBridge.
Eine laufende DataBridge-Instanz braucht Beobachtung. Dieses Kapitel erklärt, wie man
den Betrieb nachvollzieht, Fehler diagnostiziert, Warnungen automatisiert und
die Instanz auf neue Versionen aktualisiert.
| Seite | Inhalt |
|---|
| Logging | Wie Logs entstehen, Sampling von Traces und Abhängigkeiten, Custom Metrics, KQL-Abfragen |
| Monitoring & Alerts | Azure Alert Rules, Action Groups, empfohlene Schwellwerte |
| Grafana-Dashboard | Automatisch ausgeliefertes Betriebsdashboard in Application Insights |
| Updates & Upgrades | Upgrade-Pfade zwischen Versionen, Breaking Changes |
1 - 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.
| Seite | Inhalt |
|---|
| Metriken | Custom Metrics — die einzige nicht gesampelte Mengenangabe |
| Performance & Laufzeiten | KQL-Abfragen für Laufzeiten, Fehler, Abhängigkeiten und Datenvolumen |
Gepuffertes Logging — drei Lauf-Ergebnisse
| Ergebnis | Kriterium | Gesendete Log-Level |
|---|
| Normaler Lauf | Keine Fehler, keine Warnungen | Nur Warning + Error + ~20 % der Information-Einträge (konfigurierbar) |
| Lauf mit Warnungen | Mindestens eine Warning, kein Fehler | Alle Information + Warning + Error |
| Fehlerlauf | Mindestens ein unbehandelter Fehler | Alle 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
`LogTrace` ist ausschließlich live sichtbar
Log-Einträge auf Level Trace werden niemals an Application Insights gesendet —
auch nicht bei Fehler-Läufen. Der Telemetriepfad ist auf Debug und höher begrenzt.
Sichtbar sind sie nur live: lokal in der Konsole bzw. im Container-Log, in Azure im
Log Stream der Function App (oder per az webapp log tail).
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.
| Aufruf | Wird gesendet |
|---|
| Fehlgeschlagen | Immer vollständig |
Langsam (≥ TELEMETRY_DEPENDENCY_SLOW_MS) | Immer vollständig |
| Erfolgreich und schnell | Nur zum Anteil TELEMETRY_DEPENDENCY_SAMPLE_RATE (Standard 10 %) |
Die Entscheidung fällt pro Aufruf
Anders als beim Logging wird hier pro Aufruf entschieden, und zwar in dem Moment,
in dem der Aufruf endet — also bevor bekannt ist, ob die Funktionsausführung insgesamt
erfolgreich war.
Praktische Folge: Ein fehlgeschlagener Lauf enthält garantiert den fehlgeschlagenen
Aufruf, aber nicht zwangsläufig die erfolgreichen Aufrufe davor. Wird der vollständige
Verlauf für eine Analyse gebraucht, ist vorübergehend TELEMETRY_CONTROL=TRACE_ALL
zu setzen.
Steuerung über TELEMETRY_CONTROL
Die Einstellung wirkt auf beide Mechanismen — Traces und Abhängigkeiten:
| Wert | Wirkung |
|---|
TRACE_SAMPLE (Standard) | Selektives Sampling wie oben beschrieben |
TRACE_ALL | Sendet alles, deaktiviert jedes Sampling (für aktive Fehlersuche) |
TRACE_NONE | Unterdrückt Traces und Abhängigkeiten vollständig |
Eine leere Variable entspricht TRACE_SAMPLE. Details zu allen Telemetrie-Einstellungen
stehen unter Umgebungsvariablen.
`TRACE_ALL` nicht dauerhaft setzen
TRACE_ALL deaktiviert sämtliches Sampling und kann das Datenvolumen um ein Vielfaches
erhöhen — bis hin zum Erreichen der Tagesobergrenze (Daily Cap), ab der gar keine
Telemetrie mehr ankommt. Nur gezielt für die Dauer einer Analyse aktivieren.
Auswirkung auf bestehende Auswertungen
Bestehende Alerts und Dashboards prüfen
Verworfene Abhängigkeiten werden vollständig entfernt und nicht über einen
Hochrechnungsfaktor (itemCount) kompensiert.
Auswertungen über dependencies / AppDependencies, die auf absoluten Zählungen
oder Durchschnittslaufzeiten beruhen, liefern zu niedrige Werte.
Besonders kritisch sind Fehlerquoten der Form countif(success == false) / count():
Da fehlgeschlagene Aufrufe vollständig erhalten bleiben, erfolgreiche aber gesampelt
werden, ist das Ergebnis deutlich überhöht. Solche Abfragen und darauf basierende
Alerts sind zu entfernen oder auf die Tabelle requests umzustellen, die keinem
Sampling unterliegt.
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
| Feld | Beschreibung |
|---|
operation_Id | Korrelations-ID — verknüpft alle Einträge einer einzigen Funktionsausführung |
operation_ParentId | Span-ID des Requests — sorgt für die korrekte Einordnung in der End-to-End-Transaktionsansicht |
operation_Name | Name der ausgeführten Function (z. B. GetChanges, ProcessStandardQueueItems) |
timestamp | Zeitpunkt des ursprünglichen Log-Aufrufs, nicht des Sendens am Ende der Ausführung |
message | Log-Text |
severityLevel | 0 = Verbose, 1 = Information, 2 = Warning, 3 = Error, 4 = Critical |
customDimensions.Category | .NET-Logger-Kategorie |
customDimensions.Exception | Vollstä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
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.
Einzelne Ausführung verfolgen — Transaction Search
Application Insights → Untersuchen → Transaktionssuche
Filter nach operation_Id, um alle Einträge einer einzigen Ausführung zu sehen.
Tipps für die Fehlersuche
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.
Komplette Traces aktivieren: TELEMETRY_CONTROL = TRACE_ALL setzen, den
problematischen Job über ExecuteJob manuell auslösen, anschließend zurücksetzen.
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.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).
Metriken unterliegen keinem Sampling
Weder das gepufferte Logging noch das Dependency-Sampling noch das
Application-Insights-Sampling wirken auf Custom Metrics. Für belastbare Mengenangaben
sind sie deshalb die einzige verlässliche Quelle.
Verfügbare Metriken
Alle Metriken verwenden den Namespace DataBridge.
| Metrik | Dimensionen | Quelle | Bedeutung |
|---|
ChangesDetected | JobName | GetChanges → ProcessJobsForRetrievalInOrderService | Anzahl der erkannten geänderten Datensätze pro Job und Lauf (kumuliert pro Lauf, inkl. 0) |
MessagesProcessed | JobName, Outcome (Success/Failed/Transitive) | ProcessStandardQueueItems/ProcessLowPriorityQueueItems/ProcessHighPriorityQueueItems → ProcessQueueMessageService | Eine 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. |
ProcessingDurationMs | JobName | ProcessStandardQueueItems/ProcessLowPriorityQueueItems/ProcessHighPriorityQueueItems → ProcessQueueMessageService | Verarbeitungsdauer einer einzelnen Queue-Nachricht in Millisekunden, unabhängig vom Ausgang. |
GetChanges hat keine job-genaue Erfolgs- oder Laufzeit-Metrik
Für GetChanges selbst gibt es aktuell nur ChangesDetected (Anzahl, kein
Erfolg/Fehler-Signal) auf Job-Ebene. Erfolgsquote und Laufzeit von GetChanges stammen
aus den automatisch von der Functions-Runtime erzeugten Host-Metriken
(GetChanges Successes/Failures/AvgDurationMs/…, siehe unten) — die kennen nur den
gesamten Timer-Lauf, nicht die einzelnen Jobs darin.
Null-Werte sind bedeutungstragend
Auch Läufe ohne erkannte Änderungen schreiben den Wert 0. Dadurch ist unterscheidbar,
ob ein Job gelaufen ist und nichts gefunden hat oder gar nicht gelaufen ist — eine
Lücke in der Serie bedeutet Letzteres. Das macht die Metrik zur besten Grundlage für
Alerts auf hängende Jobs.
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).
Einmalige Freischaltung für Dimensionen
Um im Metrics Explorer nach der Dimension JobName zu filtern oder zu splitten, muss
einmalig pro Application-Insights-Ressource die Option „Enable alerting on custom metric
dimensions" aktiviert werden:
Application Insights → Usage and estimated costs → Custom metrics.
Ohne diese Option erscheint die Metrik nur als Gesamtaggregat über alle Jobs.
Die KQL-Abfrage funktioniert unabhängig davon.
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".
Nur Funktions-Ebene, keine Job-Ebene
Diese Host-Metriken kennen ausschließlich die aufrufende Funktion, nicht die einzelnen
Jobs, die innerhalb eines Laufs verarbeitet werden. Für job-genaue Aussagen sind
ChangesDetected bzw. MessagesProcessed/ProcessingDurationMs maßgeblich.
Limits
| Limit | Wert | Anmerkung |
|---|
| Dimensionen pro Metrik | 10 | Azure-Monitor-Limit |
| Zeitreihen pro Metrik (SDK-Default) | 1.000 | seriesCountLimit der SDK-Pre-Aggregation |
| Distinct-Werte pro Dimension (SDK-Default) | 100 | valuesPerDimensionLimit |
Konsequenz: Dimensionswerte müssen niedrig-kardinal sein — Job-Namen, Queue-Namen
und Status-Codes sind geeignet; IDs, Zeitstempel oder Datensatz-Schlüssel nicht.
1.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
Hinweis
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
Hinweis
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.
2 - Monitoring & Alerts
Azure Alert Rules und Action Groups für die automatische Überwachung der DataBridge.
Ein funktionierendes Monitoring erkennt Probleme, bevor sie auffallen.
Die DataBridge kann über Azure Monitor Alert Rules so konfiguriert werden,
dass bei Fehlern, Queue-Staus oder Dead-Letter-Einträgen automatisch Benachrichtigungen
ausgelöst werden.
Aufbau des Alert-Systems
Das Azure-Alert-System besteht aus zwei Komponenten:
Alert Rule Action Group
────────────────── ──────────────────────────
Bedingung definieren → Wer wird benachrichtigt?
Scope: Ressource E-Mail, SMS, Webhook, Azure Role
Condition: KQL / Metric
Schwellwert festlegen
Empfohlene Reihenfolge:
- Zuerst die Action Group anlegen (Empfänger)
- Dann die Alert Rules darauf zeigen lassen
Action Group anlegen
Azure Portal → Monitor → Warnungen → Action Groups → Erstellen
| Einstellung | Empfehlung |
|---|
| Name | z. B. databridge-ops-team |
| Anzeigename | kurz (max. 12 Zeichen), erscheint in Alert-E-Mails |
| Aktionstyp | E-Mail/SMS/Push/Voice oder Azure-Rolle (z. B. alle „Contributor") |
Mitgeliefertes Dashboard
Unabhängig von Alerts liefert jede Installation ein vorkonfiguriertes
Grafana-Dashboard mit — es zeigt Erfolgsraten je Funktion,
Queue-Stände (aktive und Dead-Letter-Nachrichten, siehe unten) über alle drei
Prioritäts-Queues, Laufzeiten, Ausführungen und erkannte Änderungen je Job sowie
Exceptions. Es lässt sich zusätzlich nach Job und Zeitraster filtern. Es wird
automatisch angelegt und erfordert keine Einrichtung.
Vorkonfigurierte Alerts (per Bicep)
Das Deployment kann Alert Rules für die Dead-Letter-Queue und die Queue-Länge mit
anlegen. Sie sind standardmäßig deaktiviert:
Alerts müssen aktiviert werden
Die Alerts entstehen nur, wenn beim Deployment enableAlerts = true gesetzt und eine
notificationEmail angegeben wird. Im Marketplace-Assistenten stehen beide unter
Product Settings → Alert. Ohne diese Angaben wird kein Alert angelegt.
Das Deployment erzeugt dabei auch die zugehörige Action Group (ag-<name>,
Kurzname DLQAlert) — eine handangelegte Gruppe ist dafür nicht nötig.
| Trigger | Standard-Schwellwert | Parameter | Prüfintervall | Severity |
|---|
| DLQ ≥ 1 | 1 Nachricht | dlqLowThreshold | 5 Minuten | 3 — Informational |
| DLQ > 50 | 50 Nachrichten | dlqMediumThreshold | 15 Minuten | 2 — Warning |
| DLQ > 200 | 200 Nachrichten | dlqHighThreshold | 30 Minuten | 1 — Error |
| DLQ > 500 | 500 Nachrichten | dlqCriticalThreshold | 5 Minuten | 0 — Critical |
| Queue-Länge > 300.000 | 300.000 Nachrichten | — | 15 Minuten | 2 — Warning |
Ausgewertet werden die Service-Bus-Metriken DeadletteredMessages bzw. ActiveMessages
über die Dimension EntityName = *, also je Queue einzeln. Alle Schwellwerte sind
beim Deployment als Parameter überschreibbar.
Auto-Mitigate statt einmaliger Meldung
Die Regeln sind normale Metric Alerts mit aktiviertem Auto-Mitigate: Sie lösen bei
Unterschreiten des Schwellwerts wieder auf („Entwarnung") und können danach erneut
feuern.
Eigene Alert Rule anlegen
Azure Portal → Monitor → Warnungen → Warnungsregel erstellen
Beispiel: Fehler in GetChanges-Funktion
Scope: Application Insights-Ressource der DataBridge
Condition: Custom log search (KQL)
requests
| where operation_Name == "GetChanges"
| where success == false
| summarize FailedCalls = count() by bin(timestamp, 1h)
Alert-Logik:
| Einstellung | Wert |
|---|
| Messgröße | FailedCalls |
| Aggregationstyp | Maximum |
| Granularität | 1 Stunde |
| Operator | Größer oder gleich |
| Schwellwert | 1 (sofort bei erstem Fehler) oder 5 (bei mehreren Fehlern) |
| Prüfhäufigkeit | 1 Stunde |
Action Group: hier die zuvor angelegte Gruppe auswählen.
Empfohlene Alert Rules
| Rule | Scope | Bedingung | Schwellwert | Priorität |
|---|
| DLQ-Nachrichten vorhanden | Service Bus | DLQ Count > 0 | 1 | 🔴 Kritisch |
| Fehler in GetChanges | App Insights | Fehlgeschlagene Requests | 1/h | 🔴 Kritisch |
| GetChanges arbeitet nicht mehr | App Insights | Ausführungen pro Stunde kleiner als 1 | 1 | 🔴 Kritisch |
| Fehler in ProcessStandardQueueItems | App Insights | Fehlgeschlagene Requests | 5/h | 🟡 Warnung |
| Queue wächst unkontrolliert | Service Bus | Queue Length | 10.000 | 🟡 Warnung |
| Hohe Laufzeit | App Insights | P95 > 30.000 ms | 30 Sekunden | 🔵 Info |
Stillstand erkennen
Der wichtigste Alert ist derjenige auf ausbleibende Läufe — ein stehengebliebener
Timer erzeugt keine Fehler und fällt sonst nicht auf:
requests
| where name == "GetChanges"
| summarize Executions = count() by bin(timestamp, 1h)
Operator Kleiner als, Schwellwert 1.
Alternativ metrikbasiert über die Custom Metric ChangesDetected: Da auch Läufe ohne
Änderungen den Wert 0 schreiben, bedeutet eine Lücke in der Serie, dass der Job
nicht gelaufen ist — siehe Metriken.
Der Schwellwert für die Queue-Länge ist hier bewusst strenger gewählt als der
Deployment-Standard (300.000) — er schlägt an, lange bevor sich ein Rückstau aufbaut.
Keine Alerts auf die Tabelle `dependencies`
Fehlerquoten der Form countif(success == false) / count() über dependencies sind
seit v2.1 stark überhöht, weil erfolgreiche Aufrufe gesampelt werden, fehlgeschlagene
aber vollständig ankommen. Solche Alerts auf die Tabelle requests umstellen — sie
unterliegt keinem Sampling. Details unter
Logging.
Budget-Überwachung (empfohlen)
Zusätzlich zum operativen Monitoring empfiehlt sich eine Budget-Warnung
auf Abonnement-Ebene:
Azure Portal → Cost Management → Budgets → Erstellen
- Budget für die Ressourcengruppe der DataBridge festlegen
- Alert bei 80 % und 100 % des Budgets
- Empfänger: gleiche Action Group wie operative Alerts
So werden unerwartete Kostensteigerungen (z. B. durch Queue-Stau und erhöhte
Service Bus-Operationen) frühzeitig erkannt.
3 - Grafana-Dashboard
Das mitgelieferte Betriebsdashboard in Application Insights — Erfolgsraten, Queue-Stände, Laufzeiten, Ausführungen und Fehler je Job, mit Job- und Zeitraster-Filter.
Seit v2.1 liefert jede Installation ein vorkonfiguriertes Grafana-Dashboard mit.
Es zeigt auf einen Blick, ob die DataBridge läuft, wie schnell sie arbeitet und wo Fehler
auftreten — ohne dass dafür KQL-Abfragen geschrieben werden müssen.
Ohne Zutun vorhanden
Das Dashboard wird bei jedem Deployment automatisch angelegt. Es gibt keinen
Schalter zum Abwählen und keine manuelle Einrichtung. Zusätzliche Kosten entstehen
nicht — die Abfragen laufen gegen die ohnehin vorhandene Application-Insights- und
Service-Bus-Instanz.
Wo finde ich es?
Azure Portal → Application Insights-Ressource der DataBridge → Bereich
„Dashboards with Grafana". Das Dashboard ist außerdem direkt von der
Function App aus verlinkt.
Die Dashboard-Ressource selbst liegt als dash-<name> in derselben Ressourcengruppe.
Es handelt sich nicht um eine eigene Azure-Managed-Grafana-Instanz, sondern um das
in Application Insights integrierte Grafana-Feature.
Aufbau
Das Dashboard heißt DataBridge Dashboard und zeigt standardmäßig die letzten
7 Tage. Ein automatischer Refresh ist nicht eingestellt — die Aktualisierung erfolgt
über den Refresh-Knopf bzw. beim Neuladen.
Filter (Dashboard-Variablen)
Oben im Dashboard stehen zwei Variablen zur Verfügung, die für (fast) alle Panels gelten:
| Variable | Typ | Bedeutung |
|---|
Bin Size (bin_size) | Auswahl: 5m, 10m, 15m, 30m, 1h, 2h, 4h, 12h, 1d (Standard: 10m) | Größe der Zeit-Fenster, in die die Zeitreihen-Panels ihre Werte gruppieren. Kleinerer Wert = feinere, aber unruhigere Kurven; größerer Wert = glattere Kurven über einen langen Zeitraum. |
Job Namen (jobName) | Mehrfachauswahl aus den tatsächlich aktiven Jobs, inkl. „All" | Schränkt alle job-bezogenen Panels auf die gewählten Jobs ein. Die Liste wird live aus den letzten Metrik-Daten gezogen (Jobs, die aktuell nur 0 liefern, tauchen nicht auf — siehe unten). |
Nicht jedes Panel reagiert auf beide Filter
Die Kopfzeilen-Gauges sowie die beiden Service-Bus-Gauges kennen keine Job-Dimension
und reagieren daher nicht auf Job Namen — sie sind Aggregate über die jeweilige
Funktion bzw. Queue. Alle Panels in den drei aufklappbaren Zeilen unten reagieren auf
Bin Size; die job-bezogenen darunter zusätzlich auf Job Namen.
Kopfzeile: Erfolgsraten und Queue-Stände
Immer sichtbar, sieben Kacheln:
| Kachel | Typ | Zeigt |
|---|
| GetChanges SuccessRate | Tacho (0–100 %) | Erfolgsquote der Änderungserkennung |
| ProcessQueueItems SuccessRate | Tacho (0–100 %) | Erfolgsquote der Verarbeitung, über alle drei Queues (Low/Standard/High) zusammengefasst |
| Active Messages | Tacho | Aktuell wartende Nachrichten, summiert über alle drei Export-Queues (sbqexport, sbqhighexport, sbqlowexport) |
| Deadletter | Tacho | Nachrichten in den Dead-Letter-Queues, summiert über alle drei Export-Queues |
| Low | Tacho (0–100 %) | Erfolgsquote der Verarbeitung niedriger Priorität |
| Standard | Tacho (0–100 %) | Erfolgsquote der Verarbeitung mit Standard-Priorität |
| High | Tacho (0–100 %) | Erfolgsquote der Verarbeitung hoher Priorität |
Farbschwellen der vier SuccessRate-Tachos: rot ab 0 %, gelb ab 80 %, grün ab
95 %. Die beiden Service-Bus-Tachos (Active Messages, Deadletter) färben relativ
zum aktuellen Wertebereich (grün → orange ab 70 % → rot ab 85 %), nicht anhand fester
Nachrichtenzahlen — bei sehr wenigen Nachrichten insgesamt kann die Einfärbung daher
empfindlicher wirken als bei einer großen Queue.
Alle sieben Kopfzeilen-Kacheln werten den im Dashboard gewählten Zeitraum aus (die
SuccessRate-Kacheln über dashboardTime, die Service-Bus-Kacheln, weil Azure-Monitor-
Platform-Metriken grundsätzlich immer an den Zeitraum gebunden sind).
Frühere Einschränkung entfällt
Bis einschließlich v2.2 folgten die vier SuccessRate-Kacheln dem Dashboard-Zeitraum
nicht und zeigten stattdessen einen festen Wert. Das ist seit der Überarbeitung des
Dashboards behoben — alle Kopfzeilen-Kacheln sind jetzt zeitraum-sensitiv.
Zeile „GetChanges"
Aufklappbar, drei Panels — Datenquelle sind hier weiterhin die von der Functions-Runtime
automatisch erzeugten Host-Metriken (GetChanges Successes/Failures/AvgDurationMs/…),
da GetChanges als Ganzes noch keine Job-granulare Erfolg/Fehler-Metrik im eigenen Code
erzeugt (siehe Metriken):
| Panel | Typ | Inhalt |
|---|
| Ausführungen | Balken | Erfolgreiche gegen fehlgeschlagene Läufe, gruppiert nach Bin Size |
| Laufzeiten | Verlauf | Durchschnittliche, minimale und maximale Laufzeit in Millisekunden, gruppiert nach Bin Size |
| GetChanges per Jobs | Verlauf | Erkannte Änderungen je Job — basiert auf der Custom Metric ChangesDetected mit der Dimension JobName; reagiert auf Job Namen |
Das Panel GetChanges per Jobs ist im Alltag das aussagekräftigste: Es zeigt pro Job,
wie viele Änderungen erkannt wurden. Da auch Läufe ohne Änderungen den Wert 0
schreiben, bedeutet eine Lücke in der Kurve, dass der Job gar nicht gelaufen ist —
nicht, dass es nichts zu tun gab.
Wichtige Grenze: keine Job-Erfolgsquote für GetChanges
GetChanges Successes/Failures zählen Timer-Läufe, nicht einzelne Jobs. Ein
Timer-Lauf verarbeitet üblicherweise mehrere Jobs in einer Schleife; solange dabei keine
unbehandelte Ausnahme bis zum Funktionsaufruf durchschlägt, gilt der Lauf als
„erfolgreich" — auch wenn ein einzelner Job innerhalb des Laufs intern gescheitert ist
(z. B. weil ein Connector den Fehler geloggt, aber nicht weitergeworfen hat). Für eine
job-genaue Aussage reicht diese Zeile aktuell nicht aus.
Zeile „ProcessQueueItems"
Aufklappbar, vier Panels. Anders als bei GetChanges gibt es hier bereits eine
job-granulare Custom Metric (MessagesProcessed, siehe Metriken),
die zudem queue-übergreifend ist — alle drei Queues (Low/Standard/High) laufen durch
denselben Verarbeitungscode und tauchen deshalb gemeinsam in einer Sicht auf, statt wie
früher pro Queue getrennt zu sein:
| Panel | Typ | Inhalt |
|---|
| Ausführungen | Balken | MessagesProcessed nach Ausgang (Success/Failed/Transitive), gruppiert nach Bin Size, gefiltert nach Job Namen |
| Laufzeiten | Verlauf | Durchschnittliche, minimale und maximale Verarbeitungsdauer (ProcessingDurationMs) über alle gefilterten Jobs zusammengefasst, gruppiert nach Bin Size |
| ProcessItems Success per Job | Verlauf | Erfolgreich verarbeitete Nachrichten je Job (Outcome = Success), gruppiert nach Bin Size, gefiltert nach Job Namen |
| ProcessItems Errors per Job | Verlauf | Fehlgeschlagene (Failed) und in eine Retry-Queue umgeleitete (Transitive) Nachrichten je Job, als getrennte Linien pro Job und Ausgang, gefiltert nach Job Namen |
Transitive bedeutet: die Nachricht wurde nicht endgültig verworfen, sondern in eine
Retry-Queue (TransitiveLow/TransitiveStandard/TransitiveHigh) umgeleitet, weil eine
TransitiveException aufgetreten ist — kein finaler Fehler, aber auch kein
abgeschlossener Erfolg.
Laufzeiten-Panel ist bewusst nicht nach Job aufgeschlüsselt
Das Panel „Laufzeiten" fasst Durchschnitt/Min/Max über alle durch Job Namen
ausgewählten Jobs zusammen, statt eine Linie pro Job zu zeichnen. Das hält das Panel bei
vielen aktiven Jobs lesbar. Wer die Laufzeit eines einzelnen Jobs braucht, wählt ihn über
Job Namen gezielt aus, statt „All" stehen zu lassen.
Zeile „Fehler-Überblick"
Aufklappbar, ein Panel: Heatmap — Anzahl der Ausnahmen (exceptions-Tabelle) je
Zeitfenster (Bin Size), aufgeschlüsselt nach Exception-Typ.
Keine Job-Filterung möglich
Exceptions werden ohne JobName-Property getrackt (TelemetryClient.TrackException
läuft ohne zusätzliche Properties). Die Variable Job Namen wirkt sich auf dieses
Panel nicht aus — es zeigt immer alle Exceptions im gewählten Zeitraum, unabhängig
von der Job-Auswahl oben.
Was das Dashboard nicht abdeckt
Damit klar ist, wofür weiterhin andere Werkzeuge nötig sind:
- Keine Job-genaue Fehlerursache für
GetChanges — nur Timer-Lauf-Ebene, siehe
Warnung oben. Für Details bleibt das Log (traces/exceptions) nötig. - Keine Fehlerquoten über
requests oder dependencies — hierfür die
KQL-Abfragen verwenden. - Keine Alarmierung — das Dashboard ist eine Ansicht, kein Alerting. Dafür sind
die Alerts zuständig.
Eigene Anpassungen
Manuelle Änderungen werden überschrieben
Änderungen, die direkt im Portal am Dashboard vorgenommen werden, gehen beim nächsten
Deployment verloren — das Deployment setzt die Dashboard-Definition unbedingt neu.
Anpassungen, die dauerhaft erhalten bleiben sollen, müssen in die Deployment-Vorlage
zurückfließen. Wenden Sie sich dafür an WYSA; das Dashboard wird zentral gepflegt und
mit dem nächsten Release ausgeliefert.
Wer eine rein persönliche Ansicht braucht, legt sich im Portal ein eigenes, zusätzliches
Dashboard an — dieses bleibt vom Deployment unberührt.
4 - Updates & Upgrades
Wie die DataBridge aktualisiert wird und welche Breaking Changes bei Versionssprüngen zu beachten sind.
Diese Seite beschreibt das Vorgehen bei einem Update. Die vollständigen Änderungen und
Installationshinweise je Release stehen in der Versionshistorie.
Vorgehen bei einem Update
Die Konfiguration in Table Storage bleibt bei einem Update unverändert — es sei denn, ein
Breaking Change erfordert Anpassungen.
Schritte
- Release Notes prüfen — Breaking Changes und Installationshinweise des Zielrelease
und aller dazwischenliegenden Versionen lesen (Versionshistorie)
- Wartungsfenster einplanen —
GetChanges über ein App-Setting deaktivieren:AzureWebJobs.GetChanges.Disabled = true
Bei Bedarf lassen sich die Verarbeiter analog abschalten
(AzureWebJobs.ProcessStandardQueueItems.Disabled usw.) - Warten, bis alle Queue-Nachrichten verarbeitet wurden (Queue-Länge im Azure Portal
prüfen)
- Neue Version einspielen — je nach Betriebsart:
- Container: Image-Tag auf die neue Version setzen
- Marketplace: Assistenten erneut durchlaufen (bei unveränderten Standardwerten
ergibt sich keine Änderung an bestehenden Einstellungen)
- Bicep / Pipeline: Deployment erneut ausführen
- Zip-Upload: Paket über die Pipeline oder manuell einspielen
- Konfigurationsanpassungen aus den Installationshinweisen vornehmen
- GetChanges wieder aktivieren:
AzureWebJobs.GetChanges.Disabled = false (oder Eintrag löschen)
- Ersten Lauf beobachten — z. B. über die Custom Metric
ChangesDetected je Job oder
die Fehlerquoten-Abfrage unter
Performance & Laufzeiten
App-Settings lösen einen Neustart aus
Jede Änderung an den App-Settings startet die Function App neu. Das ist beim Ein- und
Ausschalten der Funktionen in Schritt 2 und 6 eingeplant.
Breaking Changes je Version
Die vollständigen Breaking Changes und Installationshinweise stehen ausschließlich in
den Release Notes der jeweiligen Version — hier nur der Überblick, ob ein Übergang
überhaupt einen Breaking Change enthält:
Beim Überspringen von Versionen sind die Release Notes aller dazwischenliegenden
Versionen zu beachten, nicht nur die des Zielrelease.