Expand BizTalk operational metrics
This commit is contained in:
+95
-40
@@ -12,7 +12,7 @@ Verbindliche Randbedingungen:
|
|||||||
|
|
||||||
- Der Checkmk Windows Agent bleibt `LocalSystem`.
|
- Der Checkmk Windows Agent bleibt `LocalSystem`.
|
||||||
- `LocalSystem` erhaelt keine BizTalk-/SQL-Gruppenmitgliedschaft.
|
- `LocalSystem` erhaelt keine BizTalk-/SQL-Gruppenmitgliedschaft.
|
||||||
- Ein separates Dienstkonto oder bevorzugt gMSA sammelt minuetlich.
|
- Ein normales dediziertes AD-Servicekonto sammelt minuetlich.
|
||||||
- Der Agentpfad fuehrt niemals WMI- oder SQL-Abfragen aus.
|
- Der Agentpfad fuehrt niemals WMI- oder SQL-Abfragen aus.
|
||||||
- Fehler muessen als gueltige Checkmk-`UNKNOWN`-Services sichtbar werden.
|
- Fehler muessen als gueltige Checkmk-`UNKNOWN`-Services sichtbar werden.
|
||||||
- Schreiben und Lesen duerfen nie einen halben Snapshot exponieren.
|
- Schreiben und Lesen duerfen nie einen halben Snapshot exponieren.
|
||||||
@@ -46,7 +46,7 @@ Konto.
|
|||||||
Privilegierte Zone
|
Privilegierte Zone
|
||||||
┌──────────────────────────────────────────────────────────────┐
|
┌──────────────────────────────────────────────────────────────┐
|
||||||
│ Task Scheduler: "BizTalk Checkmk Pulse Provider" │
|
│ Task Scheduler: "BizTalk Checkmk Pulse Provider" │
|
||||||
│ Konto: DOMAIN\svc_biztalk_cmk$ (gMSA empfohlen) │
|
│ Konto: DOMAIN\svc_biztalk_cmk (RunLevel Limited) │
|
||||||
│ Intervall: 1 Minute, IgnoreNew, Laufzeitlimit 5 Minuten │
|
│ Intervall: 1 Minute, IgnoreNew, Laufzeitlimit 5 Minuten │
|
||||||
│ │
|
│ │
|
||||||
│ BizTalkCheckmkPulse.exe --collect │
|
│ BizTalkCheckmkPulse.exe --collect │
|
||||||
@@ -89,7 +89,7 @@ Ablauf:
|
|||||||
2. Tageslogs gemaess `LogRetentionDays` bereinigen.
|
2. Tageslogs gemaess `LogRetentionDays` bereinigen.
|
||||||
3. exklusives Handle auf `<SnapshotPath>.provider.lock` halten.
|
3. exklusives Handle auf `<SnapshotPath>.provider.lock` halten.
|
||||||
4. WMI-, SQL- und Event-Log-Probes ausfuehren.
|
4. WMI-, SQL- und Event-Log-Probes ausfuehren.
|
||||||
5. sechs stabile und optionale dynamische Checkmk-Zeilen formatieren.
|
5. acht stabile und optionale dynamische Checkmk-Zeilen formatieren.
|
||||||
6. Snapshot in einer eindeutigen Temporaerdatei desselben Verzeichnisses
|
6. Snapshot in einer eindeutigen Temporaerdatei desselben Verzeichnisses
|
||||||
schreiben.
|
schreiben.
|
||||||
7. `Flush(true)` ausfuehren und Temporaerdatei atomar publizieren.
|
7. `Flush(true)` ausfuehren und Temporaerdatei atomar publizieren.
|
||||||
@@ -132,19 +132,19 @@ Der Consumer:
|
|||||||
- gibt bei Erfolg ausschliesslich den validierten Payload aus.
|
- gibt bei Erfolg ausschliesslich den validierten Payload aus.
|
||||||
|
|
||||||
Er gibt immer Exitcode `0` zurueck, damit ein Fehler die komplette
|
Er gibt immer Exitcode `0` zurueck, damit ein Fehler die komplette
|
||||||
Checkmk-Agentsektion nicht zerstoert. Jede Ablehnung erzeugt sechs
|
Checkmk-Agentsektion nicht zerstoert. Jede Ablehnung erzeugt acht
|
||||||
`UNKNOWN`-Zeilen und einen Eintrag im Consumer-Log.
|
`UNKNOWN`-Zeilen und einen Eintrag im Consumer-Log.
|
||||||
|
|
||||||
## 4. Snapshot-Vertrag
|
## 4. Snapshot-Vertrag
|
||||||
|
|
||||||
Version 1:
|
Version 2:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
BIZTALK_CHECKMK_PULSE_SNAPSHOT_V1
|
BIZTALK_CHECKMK_PULSE_SNAPSHOT_V2
|
||||||
generatedUtc=2026-07-30T12:34:56.1234567Z
|
generatedUtc=2026-07-30T12:34:56.1234567Z
|
||||||
machineBase64=QVYyM0FHUFdCSU8x
|
machineBase64=QVYyM0FHUFdCSU8x
|
||||||
identityBase64=QkVXXHN2Y19iaXp0YWxrX2NtayQ=
|
identityBase64=QkVXXHN2Y19iaXp0YWxrX2NtayQ=
|
||||||
payloadLines=6
|
payloadLines=8
|
||||||
payloadSha256=<64 hex characters>
|
payloadSha256=<64 hex characters>
|
||||||
|
|
||||||
0 "BizTalk Platform" - ...
|
0 "BizTalk Platform" - ...
|
||||||
@@ -202,7 +202,37 @@ Pflichtklassen:
|
|||||||
Hostnamen werden clientseitig verglichen. Sonderzeichen und FQDN-/Kurzname
|
Hostnamen werden clientseitig verglichen. Sonderzeichen und FQDN-/Kurzname
|
||||||
gelangen nicht in dynamisch erzeugte WQL-Filter.
|
gelangen nicht in dynamisch erzeugte WQL-Filter.
|
||||||
|
|
||||||
### 5.2 SQL-Zugriffsprobe
|
`MSBTS_ServiceInstance` wird fuer `ServiceStatus=4` (resumable),
|
||||||
|
`ServiceStatus=32` (non-resumable) und `ServiceClass=64` abgefragt.
|
||||||
|
`ServiceClass=64` kennzeichnet Routing Failure Reports. Sie werden als eigene
|
||||||
|
Metrik ausgewiesen und zugleich in `suspended_nonresumable` mitgezaehlt.
|
||||||
|
|
||||||
|
### 5.2 Kompaktes Checkmk-Servicebild
|
||||||
|
|
||||||
|
Die alte Sammelzeile `BizTalk Runtime Artifacts` wurde durch drei kurze
|
||||||
|
Services ersetzt. Insgesamt entstehen acht stabile Services:
|
||||||
|
|
||||||
|
1. `BizTalk Platform`
|
||||||
|
2. `BizTalk SQL Access`
|
||||||
|
3. `BizTalk Suspended Instances`
|
||||||
|
4. `BizTalk Host Instances`
|
||||||
|
5. `BizTalk Receive Locations`
|
||||||
|
6. `BizTalk Send Ports`
|
||||||
|
7. `BizTalk Orchestrations`
|
||||||
|
8. `BizTalk Event Log`
|
||||||
|
|
||||||
|
Receive Locations und Send Ports alarmieren nur fuer unerwartete
|
||||||
|
Aus-Zustaende. Fachlich bewusst deaktivierte Namen werden exakt, ohne
|
||||||
|
Wildcards, in `ExpectedDisabledReceiveLocations` beziehungsweise
|
||||||
|
`ExpectedInactiveSendPorts` hinterlegt. Ein Eintrag ist entweder nur der Name
|
||||||
|
oder `Anwendung\Name`.
|
||||||
|
|
||||||
|
Pro Summary werden maximal `MaxSummaryItems` Treffer angezeigt. Weitere
|
||||||
|
Artefakte werden als `(+n more)` zusammengefasst. `MaxDetailCharacters`
|
||||||
|
begrenzt jede Detailausgabe, damit Checkmk-Ansichten kompakt bleiben, waehrend
|
||||||
|
alle numerischen Metriken vollstaendig erhalten bleiben.
|
||||||
|
|
||||||
|
### 5.3 SQL-Zugriffsprobe
|
||||||
|
|
||||||
Der Provider oeffnet fuer Management- und Master-MessageBox-Datenbank eine
|
Der Provider oeffnet fuer Management- und Master-MessageBox-Datenbank eine
|
||||||
kurze `System.Data.SqlClient`-Verbindung mit integrierter
|
kurze `System.Data.SqlClient`-Verbindung mit integrierter
|
||||||
@@ -213,7 +243,7 @@ Die Ausgabe `execution_identity=` zeigt deshalb das Provider-Konto, nicht mehr
|
|||||||
`NT AUTHORITY\SYSTEM`. Der Check beweist, dass genau das Scheduled-Task-Konto
|
`NT AUTHORITY\SYSTEM`. Der Check beweist, dass genau das Scheduled-Task-Konto
|
||||||
die Ziele erreichen kann.
|
die Ziele erreichen kann.
|
||||||
|
|
||||||
### 5.3 Event Log
|
### 5.4 Event Log
|
||||||
|
|
||||||
Der Provider liest das lokale Application Log im konfigurierten Zeitfenster
|
Der Provider liest das lokale Application Log im konfigurierten Zeitfenster
|
||||||
und filtert Quellen wie `BizTalk Server`, `XLANG/s`, `ENTSSO`,
|
und filtert Quellen wie `BizTalk Server`, `XLANG/s`, `ENTSSO`,
|
||||||
@@ -286,14 +316,17 @@ Sollkonfiguration:
|
|||||||
| Programm | `%ProgramFiles%\BizTalkCheckmkPulse\BizTalkCheckmkPulse.exe` |
|
| Programm | `%ProgramFiles%\BizTalkCheckmkPulse\BizTalkCheckmkPulse.exe` |
|
||||||
| Argument | `--collect` |
|
| Argument | `--collect` |
|
||||||
| Arbeitsverzeichnis | `%ProgramFiles%\BizTalkCheckmkPulse` |
|
| Arbeitsverzeichnis | `%ProgramFiles%\BizTalkCheckmkPulse` |
|
||||||
| Benutzer | dediziertes Dienstkonto oder gMSA |
|
| Benutzer | normales dediziertes AD-Servicekonto |
|
||||||
|
| Run level | `Limited`; keine lokale Administratorrolle erforderlich |
|
||||||
| Mehrfachinstanzen | `IgnoreNew` |
|
| Mehrfachinstanzen | `IgnoreNew` |
|
||||||
| Laufzeitlimit | 5 Minuten |
|
| Laufzeitlimit | 5 Minuten |
|
||||||
| StartWhenAvailable | aktiv |
|
| StartWhenAvailable | aktiv |
|
||||||
| Restart | zweimal im Minutenabstand |
|
| Restart | zweimal im Minutenabstand |
|
||||||
|
|
||||||
Der Task wird mit gespeichertem Dienstkontokennwort beziehungsweise gMSA
|
Der Task wird mit gespeichertem Dienstkontokennwort ausgefuehrt, also
|
||||||
ausgefuehrt, also unabhaengig von einer interaktiven Anmeldung.
|
unabhaengig von einer interaktiven Anmeldung. Bei Kennwortwechsel oder
|
||||||
|
-ablauf muss das Task-Kennwort aktualisiert werden. Ein gMSA ist weiterhin
|
||||||
|
optional unterstuetzt, aber nicht die produktive Standardannahme.
|
||||||
|
|
||||||
## 8. Installation
|
## 8. Installation
|
||||||
|
|
||||||
@@ -304,25 +337,7 @@ scripts\test-release.cmd
|
|||||||
scripts\package-release.cmd
|
scripts\package-release.cmd
|
||||||
```
|
```
|
||||||
|
|
||||||
### 8.2 gMSA
|
### 8.2 Normales Servicekonto
|
||||||
|
|
||||||
Voraussetzungen:
|
|
||||||
|
|
||||||
1. gMSA in AD erstellen und Abrufrecht auf den BizTalk-Server begrenzen.
|
|
||||||
2. Konto lokal installieren und mit `Test-ADServiceAccount` pruefen.
|
|
||||||
3. gMSA in die exakt konfigurierte BizTalk-Read-Only-Gruppe aufnehmen.
|
|
||||||
4. AD-Replikation abwarten.
|
|
||||||
|
|
||||||
Installation:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
.\Install-BizTalkCheckmkPulse.ps1 `
|
|
||||||
-CollectorAccount 'BEW\svc_biztalk_cmk$' `
|
|
||||||
-Gmsa `
|
|
||||||
-EnvironmentName ACC
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8.3 regulaeres Dienstkonto
|
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
.\Install-BizTalkCheckmkPulse.ps1 `
|
.\Install-BizTalkCheckmkPulse.ps1 `
|
||||||
@@ -333,6 +348,19 @@ Installation:
|
|||||||
Der Installer muss als lokaler Administrator laufen. Er vergibt keine
|
Der Installer muss als lokaler Administrator laufen. Er vergibt keine
|
||||||
AD-/BizTalk-/SQL-Rechte; diese bleiben getrennte administrative Freigaben.
|
AD-/BizTalk-/SQL-Rechte; diese bleiben getrennte administrative Freigaben.
|
||||||
|
|
||||||
|
Der installierte Task selbst laeuft mit `RunLevel Limited`. Der Installer fragt
|
||||||
|
das Kennwort mit `Get-Credential` ab; es wird nicht in Config oder Log
|
||||||
|
geschrieben. Das Konto benoetigt `Log on as a batch job`.
|
||||||
|
|
||||||
|
### 8.3 Optionales gMSA
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
.\Install-BizTalkCheckmkPulse.ps1 `
|
||||||
|
-CollectorAccount 'BEW\svc_biztalk_cmk$' `
|
||||||
|
-Gmsa `
|
||||||
|
-EnvironmentName ACC
|
||||||
|
```
|
||||||
|
|
||||||
### 8.4 Checkmk
|
### 8.4 Checkmk
|
||||||
|
|
||||||
Der installierte Wrapper liegt unter:
|
Der installierte Wrapper liegt unter:
|
||||||
@@ -350,7 +378,8 @@ Snapshot nicht zusaetzlich verzoegert.
|
|||||||
Nach dem Agent-Dump:
|
Nach dem Agent-Dump:
|
||||||
|
|
||||||
1. Service Discovery fuer den BizTalk-Host ausfuehren.
|
1. Service Discovery fuer den BizTalk-Host ausfuehren.
|
||||||
2. sechs stabile Services aufnehmen.
|
2. acht stabile Services aufnehmen; den alten Service
|
||||||
|
`BizTalk Runtime Artifacts` nach erfolgreicher Discovery entfernen.
|
||||||
3. Changes aktivieren.
|
3. Changes aktivieren.
|
||||||
4. Views/Benachrichtigungen nach Umgebung konfigurieren.
|
4. Views/Benachrichtigungen nach Umgebung konfigurieren.
|
||||||
|
|
||||||
@@ -368,6 +397,12 @@ einzeilige Nachricht. Provider-Erfolge werden pro Lauf geloggt; der Consumer
|
|||||||
loggt nur abgelehnte Snapshots. Exceptions werden mit Typ, Nachricht,
|
loggt nur abgelehnte Snapshots. Exceptions werden mit Typ, Nachricht,
|
||||||
HRESULT-/Providerdetails und Stacktrace einzeilig gespeichert.
|
HRESULT-/Providerdetails und Stacktrace einzeilig gespeichert.
|
||||||
|
|
||||||
|
Der erfolgreiche Abschluss nennt Suspensions, Routing Failure Reports,
|
||||||
|
Receive-Location-/Send-Port-Zahlen und Laufzeit. Jede strukturierte
|
||||||
|
WMI-/SQL-/Event-Log-Diagnose wird zusaetzlich als eigene `WARN`-Zeile
|
||||||
|
protokolliert und bleibt damit auch ausserhalb der gekuerzten Checkmk-Summary
|
||||||
|
vollstaendig nachvollziehbar.
|
||||||
|
|
||||||
Logging ist best effort: Ein blockiertes Log darf Checkmk-Ausgabe oder
|
Logging ist best effort: Ein blockiertes Log darf Checkmk-Ausgabe oder
|
||||||
Snapshot-Publikation nicht zerstoeren. Der Provider entfernt beim Start Dateien
|
Snapshot-Publikation nicht zerstoeren. Der Provider entfernt beim Start Dateien
|
||||||
aelter als `LogRetentionDays`.
|
aelter als `LogRetentionDays`.
|
||||||
@@ -391,7 +426,7 @@ Pruefen:
|
|||||||
1. Task existiert und ist aktiviert.
|
1. Task existiert und ist aktiviert.
|
||||||
2. `LastTaskResult` und Provider-Log.
|
2. `LastTaskResult` und Provider-Log.
|
||||||
3. Dienstkonto kann sich als Batch anmelden.
|
3. Dienstkonto kann sich als Batch anmelden.
|
||||||
4. gMSA ist lokal installiert und abrufbar.
|
4. gespeichertes Task-Kennwort ist nach Rotation/Ablauf noch gueltig.
|
||||||
5. Provider besitzt Modify auf `data` und `logs`.
|
5. Provider besitzt Modify auf `data` und `logs`.
|
||||||
6. EXE/Config sind ausfuehrbar.
|
6. EXE/Config sind ausfuehrbar.
|
||||||
|
|
||||||
@@ -468,7 +503,13 @@ Alarmierung:
|
|||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `WarnResumableThreshold` | `1` |
|
| `WarnResumableThreshold` | `1` |
|
||||||
| `CritNonResumableThreshold` | `1` |
|
| `CritNonResumableThreshold` | `1` |
|
||||||
| `AlertOnArtifactRuntimeIssues` | `false` |
|
| `CritRoutingFailureThreshold` | `1` |
|
||||||
|
| `AlertOnArtifactRuntimeIssues` | `true` |
|
||||||
|
| `ExpectedDisabledReceiveLocations` | leer; exakte Pipe-Liste |
|
||||||
|
| `ExpectedInactiveSendPorts` | leer; exakte Pipe-Liste |
|
||||||
|
| `AlertOnInactiveOrchestrations` | `false` |
|
||||||
|
| `MaxSummaryItems` | `5` |
|
||||||
|
| `MaxDetailCharacters` | `1600` |
|
||||||
| `EmitPerApplicationSuspensionServices` | `false` |
|
| `EmitPerApplicationSuspensionServices` | `false` |
|
||||||
| `EventLogWarnThreshold` | `1` |
|
| `EventLogWarnThreshold` | `1` |
|
||||||
| `EventLogCritThreshold` | `10` |
|
| `EventLogCritThreshold` | `10` |
|
||||||
@@ -478,16 +519,20 @@ Alarmierung:
|
|||||||
Automatisiert:
|
Automatisiert:
|
||||||
|
|
||||||
- Release-Build .NET Framework 4.7.2,
|
- Release-Build .NET Framework 4.7.2,
|
||||||
- exakt sechs Self-Test-Services,
|
- exakt acht Self-Test-Services,
|
||||||
- unbekannte Quellen werden `UNKNOWN`,
|
- unbekannte Quellen werden `UNKNOWN`,
|
||||||
- dynamische Anwendungsservices nur bei bekannter Anwendung,
|
- dynamische Anwendungsservices nur bei bekannter Anwendung,
|
||||||
- WMI-Queryvertrag nutzt dokumentierte Properties,
|
- WMI-Queryvertrag nutzt dokumentierte Properties,
|
||||||
- eingebetteter SQL-Loginfehler wird `Permission`,
|
- eingebetteter SQL-Loginfehler wird `Permission`,
|
||||||
- abgewiesener Principal wird extrahiert,
|
- abgewiesener Principal wird extrahiert,
|
||||||
|
- Routing Failure Reports werden separat und als non-resumable gezaehlt,
|
||||||
|
- Receive-/Send-Allowlisten trennen bewusste von unerwarteten Aus-Zustaenden,
|
||||||
|
- ein fehlender `IsDisabled`-Wert wird `UNKNOWN` statt still als enabled,
|
||||||
|
- betroffene Namen und Gesamtlaenge der Summary bleiben begrenzt,
|
||||||
- Snapshot-Roundtrip und Ersatz,
|
- Snapshot-Roundtrip und Ersatz,
|
||||||
- SHA-256-Manipulation wird verworfen,
|
- SHA-256-Manipulation wird verworfen,
|
||||||
- Stale-Snapshot wird verworfen,
|
- Stale-Snapshot wird verworfen,
|
||||||
- Consumer-Fallback enthaelt sechs `UNKNOWN`-Services.
|
- Consumer-Fallback enthaelt acht `UNKNOWN`-Services.
|
||||||
|
|
||||||
Windows-/ACC-Abnahme:
|
Windows-/ACC-Abnahme:
|
||||||
|
|
||||||
@@ -497,10 +542,16 @@ Windows-/ACC-Abnahme:
|
|||||||
4. `BizTalk Platform` zeigt `read_only_group=`.
|
4. `BizTalk Platform` zeigt `read_only_group=`.
|
||||||
5. `BizTalk SQL Access`: `targets=2`, `available=2`.
|
5. `BizTalk SQL Access`: `targets=2`, `available=2`.
|
||||||
6. keine Permission-`UNKNOWN`s.
|
6. keine Permission-`UNKNOWN`s.
|
||||||
7. ACL-Test: `LocalSystem` kann Snapshot lesen, nicht schreiben.
|
7. Suspensionsmetriken mit der BizTalk Group Hub Page plausibilisieren,
|
||||||
8. Task deaktivieren: nach 180 Sekunden sechs stale-`UNKNOWN`s.
|
einschliesslich Routing Failure Reports.
|
||||||
9. Task wieder aktivieren: naechster Snapshot stellt Echtzustand her.
|
8. Eine bewusst deaktivierte Receive Location und einen inaktiven Send Port
|
||||||
10. Agent-Dump und Checkmk Service Discovery erfolgreich.
|
ueber die exakten Allowlisten als expected bestaetigen.
|
||||||
|
9. Einen Testnamen aus der Allowlist entfernen und den erwarteten CRIT mit
|
||||||
|
kurzem `affected=`-Detail pruefen.
|
||||||
|
10. ACL-Test: `LocalSystem` kann Snapshot lesen, nicht schreiben.
|
||||||
|
11. Task deaktivieren: nach 180 Sekunden acht stale-`UNKNOWN`s.
|
||||||
|
12. Task wieder aktivieren: naechster Snapshot stellt Echtzustand her.
|
||||||
|
13. Agent-Dump und Checkmk Service Discovery erfolgreich.
|
||||||
|
|
||||||
Erst nach ACC-Abnahme erfolgt der gestufte Rollout nach DEV/TST/PRD.
|
Erst nach ACC-Abnahme erfolgt der gestufte Rollout nach DEV/TST/PRD.
|
||||||
|
|
||||||
@@ -537,6 +588,10 @@ ZIP und Base64 werden erst nach dem Git-Commit aus genau diesem Commit erzeugt.
|
|||||||
- https://learn.microsoft.com/en-us/biztalk/core/windows-groups-and-user-accounts-in-biztalk-server
|
- https://learn.microsoft.com/en-us/biztalk/core/windows-groups-and-user-accounts-in-biztalk-server
|
||||||
- https://learn.microsoft.com/en-us/biztalk/core/technical-reference/msbts-groupsetting-biztalkreadonlyusergroup-property-wmi
|
- https://learn.microsoft.com/en-us/biztalk/core/technical-reference/msbts-groupsetting-biztalkreadonlyusergroup-property-wmi
|
||||||
- https://learn.microsoft.com/en-us/biztalk/core/technical-reference/msbts-groupsetting-wmi
|
- https://learn.microsoft.com/en-us/biztalk/core/technical-reference/msbts-groupsetting-wmi
|
||||||
|
- https://learn.microsoft.com/en-us/biztalk/core/technical-reference/msbts-serviceinstance-serviceclass-property-wmi
|
||||||
|
- https://learn.microsoft.com/en-us/biztalk/core/types-of-message-failures
|
||||||
|
- https://learn.microsoft.com/en-us/biztalk/core/technical-reference/msbts-receivelocation-isdisabled-property-wmi
|
||||||
|
- https://learn.microsoft.com/en-us/biztalk/core/technical-reference/msbts-sendport-status-property-wmi
|
||||||
- https://docs.checkmk.com/latest/en/agent_windows.html
|
- https://docs.checkmk.com/latest/en/agent_windows.html
|
||||||
- https://docs.checkmk.com/latest/en/localchecks.html
|
- https://docs.checkmk.com/latest/en/localchecks.html
|
||||||
- https://docs.checkmk.com/latest/en/spool_directory.html
|
- https://docs.checkmk.com/latest/en/spool_directory.html
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ BizTalk Server 2020 auf Windows Server 2019. Die Anwendung trennt den
|
|||||||
berechtigten BizTalk-Datenzugriff vollstaendig vom Checkmk-Agenten:
|
berechtigten BizTalk-Datenzugriff vollstaendig vom Checkmk-Agenten:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Scheduled Task (dediziertes Dienstkonto oder gMSA)
|
Scheduled Task (normales dediziertes Servicekonto)
|
||||||
|
|
|
|
||||||
| jede Minute: BizTalkCheckmkPulse.exe --collect
|
| jede Minute: BizTalkCheckmkPulse.exe --collect
|
||||||
v
|
v
|
||||||
@@ -20,7 +20,7 @@ lokales BizTalk-WMI + BizTalk-SQL + Application Event Log
|
|||||||
Checkmk Windows Agent (LocalSystem)
|
Checkmk Windows Agent (LocalSystem)
|
||||||
|
|
|
|
||||||
v
|
v
|
||||||
sechs stabile Checkmk Local Checks
|
acht kompakte Checkmk Local Checks
|
||||||
```
|
```
|
||||||
|
|
||||||
Damit bekommt `LocalSystem` keine BizTalk- oder SQL-Berechtigung. Nur das
|
Damit bekommt `LocalSystem` keine BizTalk- oder SQL-Berechtigung. Nur das
|
||||||
@@ -62,7 +62,7 @@ Der Datenaustausch ist bewusst defensiv:
|
|||||||
Checkmk-Zeilen, korrekte SHA-256-Pruefsumme und ein maximales Alter von
|
Checkmk-Zeilen, korrekte SHA-256-Pruefsumme und ein maximales Alter von
|
||||||
standardmaessig 180 Sekunden.
|
standardmaessig 180 Sekunden.
|
||||||
- Fehlende, veraltete, abgeschnittene, manipulierte oder unlesbare Dateien
|
- Fehlende, veraltete, abgeschnittene, manipulierte oder unlesbare Dateien
|
||||||
ergeben sechs gueltige `UNKNOWN`-Services statt einer kaputten Agent-Ausgabe.
|
ergeben acht gueltige `UNKNOWN`-Services statt einer kaputten Agent-Ausgabe.
|
||||||
- Ein exklusives Lock und die Task-Einstellung `IgnoreNew` verhindern
|
- Ein exklusives Lock und die Task-Einstellung `IgnoreNew` verhindern
|
||||||
ueberlappende Providerlaeufe.
|
ueberlappende Providerlaeufe.
|
||||||
- Ein unerwarteter Providerfehler erzeugt nach Moeglichkeit einen aktuellen
|
- Ein unerwarteter Providerfehler erzeugt nach Moeglichkeit einen aktuellen
|
||||||
@@ -80,9 +80,23 @@ Standardmaessig entstehen:
|
|||||||
- `BizTalk SQL Access`
|
- `BizTalk SQL Access`
|
||||||
- `BizTalk Suspended Instances`
|
- `BizTalk Suspended Instances`
|
||||||
- `BizTalk Host Instances`
|
- `BizTalk Host Instances`
|
||||||
- `BizTalk Runtime Artifacts`
|
- `BizTalk Receive Locations`
|
||||||
|
- `BizTalk Send Ports`
|
||||||
|
- `BizTalk Orchestrations`
|
||||||
- `BizTalk Event Log`
|
- `BizTalk Event Log`
|
||||||
|
|
||||||
|
Die drei Artefaktbereiche sind absichtlich getrennte Services. Dadurch sind
|
||||||
|
Zustand und Graphen direkt erkennbar, ohne eine lange Sammelzeile zu lesen:
|
||||||
|
|
||||||
|
- Suspensions: total, resumable, non-resumable und Routing Failure Reports
|
||||||
|
- Receive Locations: total, enabled, unerwartet/bewusst disabled und unbekannt
|
||||||
|
- Send Ports: total, started, stopped, bound, unbekannt sowie bewusst inactive
|
||||||
|
- Orchestrations: total, started, stopped, bound, unbound und unbekannt
|
||||||
|
|
||||||
|
Pro Service werden standardmaessig maximal fuenf betroffene Namen gezeigt.
|
||||||
|
Weitere Treffer erscheinen nur als `(+n more)`; Details sind zusaetzlich auf
|
||||||
|
1600 Zeichen begrenzt. Metriken bleiben trotzdem vollstaendig.
|
||||||
|
|
||||||
Mit `EnvironmentName=ACC`, `DEV`, `TST` oder `PRD` wird die Umgebung in den
|
Mit `EnvironmentName=ACC`, `DEV`, `TST` oder `PRD` wird die Umgebung in den
|
||||||
Servicenamen aufgenommen, zum Beispiel `BizTalk ACC Platform`.
|
Servicenamen aufgenommen, zum Beispiel `BizTalk ACC Platform`.
|
||||||
|
|
||||||
@@ -106,7 +120,7 @@ BizTalk-Server:
|
|||||||
- .NET Framework 4.7.2
|
- .NET Framework 4.7.2
|
||||||
- Checkmk Windows Agent
|
- Checkmk Windows Agent
|
||||||
- administrativer Zugriff fuer die einmalige Installation
|
- administrativer Zugriff fuer die einmalige Installation
|
||||||
- dediziertes AD-Dienstkonto oder bevorzugt gMSA fuer den Provider
|
- normales dediziertes AD-Servicekonto fuer den Provider
|
||||||
|
|
||||||
Das Provider-Konto benoetigt:
|
Das Provider-Konto benoetigt:
|
||||||
|
|
||||||
@@ -116,9 +130,10 @@ Das Provider-Konto benoetigt:
|
|||||||
- Mitgliedschaft in der exakt konfigurierten BizTalk Server Read Only
|
- Mitgliedschaft in der exakt konfigurierten BizTalk Server Read Only
|
||||||
Users-Gruppe
|
Users-Gruppe
|
||||||
|
|
||||||
Es soll weder lokaler Administrator noch SQL-`sysadmin` sein. Fuer ein gMSA
|
Es soll weder lokaler Administrator noch SQL-`sysadmin` sein. Der Scheduled
|
||||||
muss der BizTalk-Server das verwaltete Kennwort abrufen duerfen und das Konto
|
Task laeuft mit `RunLevel Limited`. Das Servicekonto braucht ein gespeichertes
|
||||||
lokal installiert sein.
|
Task-Kennwort und das Recht `Log on as a batch job`. Ein gMSA bleibt optional,
|
||||||
|
ist aber fuer diese Installation nicht vorausgesetzt.
|
||||||
|
|
||||||
## Build und Tests
|
## Build und Tests
|
||||||
|
|
||||||
@@ -146,7 +161,7 @@ Format-Self-Test ohne WMI, SQL oder Event Log:
|
|||||||
artifacts\BizTalkCheckmkPulse-deploy\application\BizTalkCheckmkPulse.exe --self-test
|
artifacts\BizTalkCheckmkPulse-deploy\application\BizTalkCheckmkPulse.exe --self-test
|
||||||
```
|
```
|
||||||
|
|
||||||
Erwartet werden exakt sechs `OK`-Zeilen. Die Regressionstests pruefen
|
Erwartet werden exakt acht `OK`-Zeilen. Die Regressionstests pruefen
|
||||||
zusaetzlich Snapshot-Roundtrip, atomaren Ersatz, SHA-256-Manipulation,
|
zusaetzlich Snapshot-Roundtrip, atomaren Ersatz, SHA-256-Manipulation,
|
||||||
Stale-Erkennung, stabile Fallbacks und die bestehenden BizTalk-WMI-Diagnosen.
|
Stale-Erkennung, stabile Fallbacks und die bestehenden BizTalk-WMI-Diagnosen.
|
||||||
Ein Mono-Build ist eine hilfreiche Quellcodepruefung, ersetzt aber nicht die
|
Ein Mono-Build ist eine hilfreiche Quellcodepruefung, ersetzt aber nicht die
|
||||||
@@ -167,9 +182,8 @@ Get-CimInstance `
|
|||||||
```
|
```
|
||||||
|
|
||||||
Ein AD-Administrator nimmt das neue Provider-Konto in
|
Ein AD-Administrator nimmt das neue Provider-Konto in
|
||||||
`BizTalkReadOnlyUserGroup` auf. Bei einem gMSA endet der Kontoname mit `$`.
|
`BizTalkReadOnlyUserGroup` auf. Nach AD-Replikation muss das Servicekonto durch
|
||||||
Nach AD-Replikation muss ein regulaeres Dienstkonto einen neuen Anmeldetoken
|
einen neuen Tasklauf einen neuen Anmeldetoken erhalten.
|
||||||
erhalten; bei gMSA wird der Task nach der Gruppenfreigabe neu gestartet.
|
|
||||||
|
|
||||||
Die BizTalk-Konfiguration muss die Domain-Gruppe bereits als Windows-Login und
|
Die BizTalk-Konfiguration muss die Domain-Gruppe bereits als Windows-Login und
|
||||||
in `BizTalkMgmtDb`, `BizTalkMsgBoxDb`, `BizTalkDTADb`,
|
in `BizTalkMgmtDb`, `BizTalkMsgBoxDb`, `BizTalkDTADb`,
|
||||||
@@ -178,25 +192,7 @@ in `BizTalkMgmtDb`, `BizTalkMsgBoxDb`, `BizTalkDTADb`,
|
|||||||
SQL-Administration fuer die Gruppe repariert, nicht als Einzelberechtigung
|
SQL-Administration fuer die Gruppe repariert, nicht als Einzelberechtigung
|
||||||
fuer das Provider-Konto.
|
fuer das Provider-Konto.
|
||||||
|
|
||||||
## Installation mit gMSA
|
## Installation mit normalem Servicekonto
|
||||||
|
|
||||||
Deployment-Paket auf den BizTalk-Server kopieren. In administrativer Windows
|
|
||||||
PowerShell:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
Set-Location C:\Temp\BizTalkCheckmkPulse-deploy
|
|
||||||
|
|
||||||
# Optional, falls das gMSA noch nicht lokal installiert wurde:
|
|
||||||
Install-ADServiceAccount -Identity svc_biztalk_cmk
|
|
||||||
Test-ADServiceAccount -Identity svc_biztalk_cmk
|
|
||||||
|
|
||||||
.\Install-BizTalkCheckmkPulse.ps1 `
|
|
||||||
-CollectorAccount 'BEW\svc_biztalk_cmk$' `
|
|
||||||
-Gmsa `
|
|
||||||
-EnvironmentName ACC
|
|
||||||
```
|
|
||||||
|
|
||||||
## Installation mit regulaerem Dienstkonto
|
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
Set-Location C:\Temp\BizTalkCheckmkPulse-deploy
|
Set-Location C:\Temp\BizTalkCheckmkPulse-deploy
|
||||||
@@ -209,6 +205,13 @@ Der Installer fragt das Kennwort ueber `Get-Credential` ab und speichert es
|
|||||||
durch die Windows-Aufgabenplanung. Das Kennwort steht weder in der
|
durch die Windows-Aufgabenplanung. Das Kennwort steht weder in der
|
||||||
Konfigurationsdatei noch in den Logs.
|
Konfigurationsdatei noch in den Logs.
|
||||||
|
|
||||||
|
Wenn das Kennwort rotiert oder ablaeuft, muss es im Scheduled Task aktualisiert
|
||||||
|
werden. Bis dahin wird der Snapshot nach 180 Sekunden stale und Checkmk zeigt
|
||||||
|
alle acht Services als `UNKNOWN`.
|
||||||
|
|
||||||
|
Ein gMSA kann weiterhin optional mit `-Gmsa` installiert werden; die
|
||||||
|
produktive Standardbeschreibung geht vom normalen Servicekonto aus.
|
||||||
|
|
||||||
Der Installer:
|
Der Installer:
|
||||||
|
|
||||||
1. kopiert EXE und Config nach
|
1. kopiert EXE und Config nach
|
||||||
@@ -265,7 +268,7 @@ Verbindlicher Test im echten `LocalSystem`-Kontext:
|
|||||||
Select-String -Pattern "BizTalk|UNKNOWN|Snapshot|Permission" -Context 0,1
|
Select-String -Pattern "BizTalk|UNKNOWN|Snapshot|Permission" -Context 0,1
|
||||||
```
|
```
|
||||||
|
|
||||||
Danach in Checkmk eine Service Discovery ausfuehren, die sechs Services
|
Danach in Checkmk eine Service Discovery ausfuehren, die acht Services
|
||||||
aufnehmen und Changes aktivieren. Ein zusaetzlicher Checkmk-Async-Cache ist
|
aufnehmen und Changes aktivieren. Ein zusaetzlicher Checkmk-Async-Cache ist
|
||||||
nicht erforderlich: Der Consumer liest nur eine kleine lokale Datei und der
|
nicht erforderlich: Der Consumer liest nur eine kleine lokale Datei und der
|
||||||
Provider besitzt bereits seinen eigenen Minutentakt.
|
Provider besitzt bereits seinen eigenen Minutentakt.
|
||||||
@@ -322,7 +325,13 @@ Wichtige Werte:
|
|||||||
| `SqlConnectionTimeoutSeconds` | `5` | SQL-Timeout je Ziel. |
|
| `SqlConnectionTimeoutSeconds` | `5` | SQL-Timeout je Ziel. |
|
||||||
| `WarnResumableThreshold` | `1` | WARN ab n resumable Suspensions. |
|
| `WarnResumableThreshold` | `1` | WARN ab n resumable Suspensions. |
|
||||||
| `CritNonResumableThreshold` | `1` | CRIT ab n non-resumable Suspensions. |
|
| `CritNonResumableThreshold` | `1` | CRIT ab n non-resumable Suspensions. |
|
||||||
| `AlertOnArtifactRuntimeIssues` | `false` | WARN fuer bewusst inaktive Artefakte aktivieren. |
|
| `CritRoutingFailureThreshold` | `1` | CRIT ab n Routing Failure Reports. |
|
||||||
|
| `AlertOnArtifactRuntimeIssues` | `true` | Unerwartet deaktivierte Receive Locations bzw. inaktive Send Ports werden CRIT. |
|
||||||
|
| `ExpectedDisabledReceiveLocations` | leer | Pipe-getrennte exakte Allowlist: `Name` oder `Anwendung\Name`. |
|
||||||
|
| `ExpectedInactiveSendPorts` | leer | Pipe-getrennte exakte Allowlist: `Name` oder `Anwendung\Name`. |
|
||||||
|
| `AlertOnInactiveOrchestrations` | `false` | Optional WARN fuer stopped/bound/unbound Orchestrations. |
|
||||||
|
| `MaxSummaryItems` | `5` | Maximal angezeigte betroffene Artefakte je Service. |
|
||||||
|
| `MaxDetailCharacters` | `1600` | Harte Obergrenze fuer Checkmk-Summary. |
|
||||||
| `EmitPerApplicationSuspensionServices` | `false` | Zusaetzliche Anwendungsservices. |
|
| `EmitPerApplicationSuspensionServices` | `false` | Zusaetzliche Anwendungsservices. |
|
||||||
| `EventLogLookbackMinutes` | `60` | Event-Log-Zeitfenster des Providers. |
|
| `EventLogLookbackMinutes` | `60` | Event-Log-Zeitfenster des Providers. |
|
||||||
|
|
||||||
@@ -333,10 +342,11 @@ liest den naechsten atomar publizierten Snapshot.
|
|||||||
|
|
||||||
| Beobachtung | Ursache / Massnahme |
|
| Beobachtung | Ursache / Massnahme |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Alle sechs Services melden fehlenden Snapshot | Task, Provider-Log, Task-Konto und ACL pruefen. |
|
| Alle acht Services melden fehlenden Snapshot | Task, Provider-Log, Task-Konto/Kennwort und ACL pruefen. |
|
||||||
| Snapshot ist `stale` | `LastTaskResult`, Laufzeit, WMI-/SQL-Timeout und Log pruefen. |
|
| Snapshot ist `stale` | `LastTaskResult`, Laufzeit, WMI-/SQL-Timeout und Log pruefen. |
|
||||||
| SHA-256 oder Format ungueltig | Datei nicht manuell bearbeiten; Datentraeger/AV und Schreibpfad pruefen, Task neu starten. |
|
| SHA-256 oder Format ungueltig | Datei nicht manuell bearbeiten; Datentraeger/AV und Schreibpfad pruefen, Task neu starten. |
|
||||||
| Provider meldet `Login failed` | Provider-Konto und exakt konfigurierte Read-Only-Gruppe sowie `BTS_READONLY_USERS` pruefen. |
|
| Provider meldet `Login failed` | Provider-Konto und exakt konfigurierte Read-Only-Gruppe sowie `BTS_READONLY_USERS` pruefen. |
|
||||||
|
| Receive Locations / Send Ports sind CRIT | `affected=` pruefen; nur fachlich bewusst inaktive Namen exakt in die jeweilige Allowlist aufnehmen. |
|
||||||
| `Wmi/Schema` | Klasse/Properties gegen BizTalk-2020-Schema pruefen; keine Rechte ausweiten. |
|
| `Wmi/Schema` | Klasse/Properties gegen BizTalk-2020-Schema pruefen; keine Rechte ausweiten. |
|
||||||
| Nur Event Log `UNKNOWN` | lokalen Application-Log-Zugriff des Provider-Kontos pruefen. |
|
| Nur Event Log `UNKNOWN` | lokalen Application-Log-Zugriff des Provider-Kontos pruefen. |
|
||||||
| Task-Result `2` | Parallelstart oder Snapshot-I/O; Log und Lock/ACL pruefen. |
|
| Task-Result `2` | Parallelstart oder Snapshot-I/O; Log und Lock/ACL pruefen. |
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ if ($Gmsa) {
|
|||||||
$principal = New-ScheduledTaskPrincipal `
|
$principal = New-ScheduledTaskPrincipal `
|
||||||
-UserId $CollectorAccount `
|
-UserId $CollectorAccount `
|
||||||
-LogonType Password `
|
-LogonType Password `
|
||||||
-RunLevel Highest
|
-RunLevel Limited
|
||||||
$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings -Principal $principal
|
$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings -Principal $principal
|
||||||
Register-ScheduledTask -TaskName $taskName -InputObject $task -Force | Out-Null
|
Register-ScheduledTask -TaskName $taskName -InputObject $task -Force | Out-Null
|
||||||
}
|
}
|
||||||
@@ -143,7 +143,7 @@ else {
|
|||||||
$principal = New-ScheduledTaskPrincipal `
|
$principal = New-ScheduledTaskPrincipal `
|
||||||
-UserId $CollectorAccount `
|
-UserId $CollectorAccount `
|
||||||
-LogonType Password `
|
-LogonType Password `
|
||||||
-RunLevel Highest
|
-RunLevel Limited
|
||||||
$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings -Principal $principal
|
$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings -Principal $principal
|
||||||
Register-ScheduledTask `
|
Register-ScheduledTask `
|
||||||
-TaskName $taskName `
|
-TaskName $taskName `
|
||||||
@@ -155,8 +155,8 @@ else {
|
|||||||
|
|
||||||
Write-Host "Fuehre formatseitigen Self-Test aus ..."
|
Write-Host "Fuehre formatseitigen Self-Test aus ..."
|
||||||
$selfTest = & $targetExe --self-test
|
$selfTest = & $targetExe --self-test
|
||||||
if ($LASTEXITCODE -ne 0 -or @($selfTest).Count -ne 6) {
|
if ($LASTEXITCODE -ne 0 -or @($selfTest).Count -ne 8) {
|
||||||
throw "Self-Test fehlgeschlagen. Erwartet wurden sechs Checkmk-Zeilen."
|
throw "Self-Test fehlgeschlagen. Erwartet wurden acht Checkmk-Zeilen."
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "Starte den Provider einmalig ..."
|
Write-Host "Starte den Provider einmalig ..."
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ if not exist "%EXE%" (
|
|||||||
echo 3 "BizTalk SQL Access" - BizTalkCheckmkPulse.exe fehlt unter %BASE%. Massnahme: Deployment-Paket und Dateirechte pruefen.
|
echo 3 "BizTalk SQL Access" - BizTalkCheckmkPulse.exe fehlt unter %BASE%. Massnahme: Deployment-Paket und Dateirechte pruefen.
|
||||||
echo 3 "BizTalk Suspended Instances" - BizTalkCheckmkPulse.exe fehlt unter %BASE%. Massnahme: Deployment-Paket und Dateirechte pruefen.
|
echo 3 "BizTalk Suspended Instances" - BizTalkCheckmkPulse.exe fehlt unter %BASE%. Massnahme: Deployment-Paket und Dateirechte pruefen.
|
||||||
echo 3 "BizTalk Host Instances" - BizTalkCheckmkPulse.exe fehlt unter %BASE%. Massnahme: Deployment-Paket und Dateirechte pruefen.
|
echo 3 "BizTalk Host Instances" - BizTalkCheckmkPulse.exe fehlt unter %BASE%. Massnahme: Deployment-Paket und Dateirechte pruefen.
|
||||||
echo 3 "BizTalk Runtime Artifacts" - BizTalkCheckmkPulse.exe fehlt unter %BASE%. Massnahme: Deployment-Paket und Dateirechte pruefen.
|
echo 3 "BizTalk Receive Locations" - BizTalkCheckmkPulse.exe fehlt unter %BASE%. Massnahme: Deployment-Paket und Dateirechte pruefen.
|
||||||
|
echo 3 "BizTalk Send Ports" - BizTalkCheckmkPulse.exe fehlt unter %BASE%. Massnahme: Deployment-Paket und Dateirechte pruefen.
|
||||||
|
echo 3 "BizTalk Orchestrations" - BizTalkCheckmkPulse.exe fehlt unter %BASE%. Massnahme: Deployment-Paket und Dateirechte pruefen.
|
||||||
echo 3 "BizTalk Event Log" - BizTalkCheckmkPulse.exe fehlt unter %BASE%. Massnahme: Deployment-Paket und Dateirechte pruefen.
|
echo 3 "BizTalk Event Log" - BizTalkCheckmkPulse.exe fehlt unter %BASE%. Massnahme: Deployment-Paket und Dateirechte pruefen.
|
||||||
exit /b 0
|
exit /b 0
|
||||||
)
|
)
|
||||||
@@ -21,7 +23,9 @@ if not "%EXITCODE%"=="0" (
|
|||||||
echo 3 "BizTalk SQL Access" - BizTalkCheckmkPulse.exe endete mit Exitcode=%EXITCODE%. Massnahme: .NET Framework 4.7.2, EXE/Config-Dateien und Windows Application Log pruefen.
|
echo 3 "BizTalk SQL Access" - BizTalkCheckmkPulse.exe endete mit Exitcode=%EXITCODE%. Massnahme: .NET Framework 4.7.2, EXE/Config-Dateien und Windows Application Log pruefen.
|
||||||
echo 3 "BizTalk Suspended Instances" - BizTalkCheckmkPulse.exe endete mit Exitcode=%EXITCODE%. Massnahme: Programmstart und Windows Application Log pruefen.
|
echo 3 "BizTalk Suspended Instances" - BizTalkCheckmkPulse.exe endete mit Exitcode=%EXITCODE%. Massnahme: Programmstart und Windows Application Log pruefen.
|
||||||
echo 3 "BizTalk Host Instances" - BizTalkCheckmkPulse.exe endete mit Exitcode=%EXITCODE%. Massnahme: Programmstart und Windows Application Log pruefen.
|
echo 3 "BizTalk Host Instances" - BizTalkCheckmkPulse.exe endete mit Exitcode=%EXITCODE%. Massnahme: Programmstart und Windows Application Log pruefen.
|
||||||
echo 3 "BizTalk Runtime Artifacts" - BizTalkCheckmkPulse.exe endete mit Exitcode=%EXITCODE%. Massnahme: Programmstart und Windows Application Log pruefen.
|
echo 3 "BizTalk Receive Locations" - BizTalkCheckmkPulse.exe endete mit Exitcode=%EXITCODE%. Massnahme: Programmstart und Provider-Log pruefen.
|
||||||
|
echo 3 "BizTalk Send Ports" - BizTalkCheckmkPulse.exe endete mit Exitcode=%EXITCODE%. Massnahme: Programmstart und Provider-Log pruefen.
|
||||||
|
echo 3 "BizTalk Orchestrations" - BizTalkCheckmkPulse.exe endete mit Exitcode=%EXITCODE%. Massnahme: Programmstart und Provider-Log pruefen.
|
||||||
echo 3 "BizTalk Event Log" - BizTalkCheckmkPulse.exe endete mit Exitcode=%EXITCODE%. Massnahme: Programmstart und Windows Application Log pruefen.
|
echo 3 "BizTalk Event Log" - BizTalkCheckmkPulse.exe endete mit Exitcode=%EXITCODE%. Massnahme: Programmstart und Windows Application Log pruefen.
|
||||||
)
|
)
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ NEUE VERBINDLICHE ARCHITEKTUR
|
|||||||
|
|
||||||
Das Maschinenkonto erhaelt keine BizTalk-Berechtigung.
|
Das Maschinenkonto erhaelt keine BizTalk-Berechtigung.
|
||||||
|
|
||||||
1. Ein dediziertes Dienstkonto oder bevorzugt gMSA laeuft minuetlich als
|
1. Ein normales dediziertes Servicekonto laeuft minuetlich als
|
||||||
Scheduled Task "BizTalk Checkmk Pulse Provider".
|
Scheduled Task "BizTalk Checkmk Pulse Provider".
|
||||||
2. Dieses Konto fuehrt BizTalkCheckmkPulse.exe --collect aus.
|
2. Dieses Konto fuehrt BizTalkCheckmkPulse.exe --collect aus.
|
||||||
3. Es schreibt atomar einen SHA-256-geschuetzten Snapshot nach:
|
3. Es schreibt atomar einen SHA-256-geschuetzten Snapshot nach:
|
||||||
@@ -64,14 +64,7 @@ NICHT DURCHFUEHREN
|
|||||||
INSTALLATION
|
INSTALLATION
|
||||||
============
|
============
|
||||||
|
|
||||||
gMSA:
|
Normales Servicekonto:
|
||||||
|
|
||||||
.\Install-BizTalkCheckmkPulse.ps1 `
|
|
||||||
-CollectorAccount 'BEW\svc_biztalk_cmk$' `
|
|
||||||
-Gmsa `
|
|
||||||
-EnvironmentName ACC
|
|
||||||
|
|
||||||
Regulaeres Dienstkonto:
|
|
||||||
|
|
||||||
.\Install-BizTalkCheckmkPulse.ps1 `
|
.\Install-BizTalkCheckmkPulse.ps1 `
|
||||||
-CollectorAccount 'BEW\svc_biztalk_cmk' `
|
-CollectorAccount 'BEW\svc_biztalk_cmk' `
|
||||||
@@ -102,6 +95,8 @@ ERWARTET
|
|||||||
- Provider-Log nennt das dedizierte Konto
|
- Provider-Log nennt das dedizierte Konto
|
||||||
- BizTalk Platform zeigt read_only_group=<exakte Gruppe>
|
- BizTalk Platform zeigt read_only_group=<exakte Gruppe>
|
||||||
- BizTalk SQL Access zeigt targets=2 und available=2
|
- BizTalk SQL Access zeigt targets=2 und available=2
|
||||||
|
- Suspensionsmetriken enthalten resumable, non-resumable und Routing Failure Reports
|
||||||
|
- Receive Locations und Send Ports trennen expected von unexpected inactive
|
||||||
- keine berechtigungsbedingten UNKNOWN-Services
|
- keine berechtigungsbedingten UNKNOWN-Services
|
||||||
- LocalSystem besitzt auf data nur Lesezugriff
|
- LocalSystem besitzt auf data nur Lesezugriff
|
||||||
|
|
||||||
|
|||||||
+64
-14
@@ -11,7 +11,7 @@ Die Ausgabe ist so gebaut, dass sie auch mit Checkmk 2.4.0p4 kompatibel bleibt:
|
|||||||
Die fachlichen Daten werden minuetlich vom privilegierten Scheduled-Task-
|
Die fachlichen Daten werden minuetlich vom privilegierten Scheduled-Task-
|
||||||
Provider erzeugt. Der Checkmk-Agent liest als `LocalSystem` nur den
|
Provider erzeugt. Der Checkmk-Agent liest als `LocalSystem` nur den
|
||||||
integritaets- und altersgeprueften Snapshot. Ist dieser Transport nicht
|
integritaets- und altersgeprueften Snapshot. Ist dieser Transport nicht
|
||||||
verfuegbar, liefern alle sechs stabilen Services `UNKNOWN`.
|
verfuegbar, liefern alle acht stabilen Services `UNKNOWN`.
|
||||||
|
|
||||||
## BizTalk Platform
|
## BizTalk Platform
|
||||||
|
|
||||||
@@ -77,6 +77,7 @@ Zweck:
|
|||||||
|
|
||||||
- Ermittelt suspendierte BizTalk-Service-Instanzen.
|
- Ermittelt suspendierte BizTalk-Service-Instanzen.
|
||||||
- Unterscheidet resumable und non-resumable.
|
- Unterscheidet resumable und non-resumable.
|
||||||
|
- Zaehlt Routing Failure Reports (`ServiceClass=64`) separat.
|
||||||
- Zeigt betroffene Anwendungen und Beispiele in der Summary.
|
- Zeigt betroffene Anwendungen und Beispiele in der Summary.
|
||||||
|
|
||||||
Status:
|
Status:
|
||||||
@@ -86,6 +87,7 @@ Status:
|
|||||||
| `OK` | keine suspendierten Instanzen. |
|
| `OK` | keine suspendierten Instanzen. |
|
||||||
| `WARN` | `biztalk_suspended_resumable >= WarnResumableThreshold`. |
|
| `WARN` | `biztalk_suspended_resumable >= WarnResumableThreshold`. |
|
||||||
| `CRIT` | `biztalk_suspended_nonresumable >= CritNonResumableThreshold`. |
|
| `CRIT` | `biztalk_suspended_nonresumable >= CritNonResumableThreshold`. |
|
||||||
|
| `CRIT` | `biztalk_routing_failure_reports >= CritRoutingFailureThreshold`. |
|
||||||
| `UNKNOWN` | `MSBTS_ServiceInstance` nicht verlaesslich lesbar oder Programmfehler. |
|
| `UNKNOWN` | `MSBTS_ServiceInstance` nicht verlaesslich lesbar oder Programmfehler. |
|
||||||
|
|
||||||
Metriken:
|
Metriken:
|
||||||
@@ -95,6 +97,7 @@ Metriken:
|
|||||||
| `biztalk_suspended_total` | Summe aller suspendierten Instanzen. |
|
| `biztalk_suspended_total` | Summe aller suspendierten Instanzen. |
|
||||||
| `biztalk_suspended_resumable` | Resumable suspended instances. |
|
| `biztalk_suspended_resumable` | Resumable suspended instances. |
|
||||||
| `biztalk_suspended_nonresumable` | Non-resumable suspended instances. |
|
| `biztalk_suspended_nonresumable` | Non-resumable suspended instances. |
|
||||||
|
| `biztalk_routing_failure_reports` | Routing Failure Reports; Teilmenge der non-resumable Instanzen. |
|
||||||
|
|
||||||
## BizTalk Host Instances
|
## BizTalk Host Instances
|
||||||
|
|
||||||
@@ -123,38 +126,85 @@ Metriken:
|
|||||||
| `biztalk_host_instances_pending` | StartPending/StopPending. |
|
| `biztalk_host_instances_pending` | StartPending/StopPending. |
|
||||||
| `biztalk_host_instances_unknown` | Nicht interpretierbarer Status. |
|
| `biztalk_host_instances_unknown` | Nicht interpretierbarer Status. |
|
||||||
|
|
||||||
## BizTalk Runtime Artifacts
|
## BizTalk Receive Locations
|
||||||
|
|
||||||
Zweck:
|
Zweck:
|
||||||
|
|
||||||
- Summiert Laufzeitzustaende von Receive Locations, Send Ports und Orchestrations.
|
- Zaehlt alle konfigurierten Receive Locations und ihren `IsDisabled`-Zustand.
|
||||||
- Liefert dashboard-taugliche Zahlen zur Laufzeitlandschaft.
|
- Trennt bewusst deaktivierte von unerwartet deaktivierten Namen.
|
||||||
|
|
||||||
Status:
|
Status:
|
||||||
|
|
||||||
| Status | Bedingung |
|
| Status | Bedingung |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `OK` | Artefakte lesbar; keine unbekannten Statuswerte. |
|
| `OK` | Daten lesbar und keine unerwartet deaktivierte Receive Location. |
|
||||||
| `WARN` | Nur bei `AlertOnArtifactRuntimeIssues=true` und inaktiven/deaktivierten Artefakten. |
|
| `CRIT` | Mindestens eine unerwartet deaktivierte Receive Location bei `AlertOnArtifactRuntimeIssues=true`. |
|
||||||
| `CRIT` | Unbekannte Send-Port- oder Orchestration-Statuswerte. |
|
| `UNKNOWN` | `MSBTS_ReceiveLocation` nicht verlaesslich lesbar oder `IsDisabled` eines Objekts nicht interpretierbar. |
|
||||||
| `UNKNOWN` | Mindestens eine erforderliche Artefaktklasse nicht lesbar oder Programmfehler. |
|
|
||||||
|
|
||||||
Metriken:
|
Metriken:
|
||||||
|
|
||||||
| Metrik | Bedeutung |
|
| Metrik | Bedeutung |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `biztalk_applications` | Anzahl der per WMI erkannten Anwendungs-Buckets; `(unknown)` ist moeglich, da die dokumentierten Artefaktklassen keine verlaessliche Application-Property garantieren. |
|
| `biztalk_receive_locations_total` | Gesamtzahl Receive Locations. |
|
||||||
| `biztalk_receive_locations` | Gesamtzahl Receive Locations. |
|
| `biztalk_receive_locations_enabled` | Aktivierte Receive Locations. |
|
||||||
| `biztalk_receive_locations_disabled` | Deaktivierte Receive Locations. |
|
| `biztalk_receive_locations_disabled` | Deaktivierte Receive Locations. |
|
||||||
| `biztalk_send_ports` | Gesamtzahl Send Ports. |
|
| `biztalk_receive_locations_unexpected_disabled` | Deaktiviert und nicht in der Allowlist; CRIT ab 1. |
|
||||||
|
| `biztalk_receive_locations_expected_disabled` | Bewusst deaktiviert und exakt allowlisted. |
|
||||||
|
| `biztalk_receive_locations_unknown` | Fehlender oder nicht interpretierbarer `IsDisabled`-Wert. |
|
||||||
|
|
||||||
|
## BizTalk Send Ports
|
||||||
|
|
||||||
|
Status:
|
||||||
|
|
||||||
|
| Status | Bedingung |
|
||||||
|
| --- | --- |
|
||||||
|
| `OK` | Alle nicht allowlisted Send Ports sind started. |
|
||||||
|
| `CRIT` | Mindestens ein unerwartet stopped/bound Port oder unbekannter Status. |
|
||||||
|
| `UNKNOWN` | `MSBTS_SendPort` nicht verlaesslich lesbar. |
|
||||||
|
|
||||||
|
Metriken:
|
||||||
|
|
||||||
|
| Metrik | Bedeutung |
|
||||||
|
| --- | --- |
|
||||||
|
| `biztalk_send_ports_total` | Gesamtzahl Send Ports. |
|
||||||
| `biztalk_send_ports_started` | Gestartete Send Ports. |
|
| `biztalk_send_ports_started` | Gestartete Send Ports. |
|
||||||
| `biztalk_send_ports_inactive` | Bound oder stopped Send Ports. |
|
| `biztalk_send_ports_stopped` | Enlisted, Subscription deaktiviert (`Status=2`). |
|
||||||
|
| `biztalk_send_ports_bound` | Bound/unenlisted (`Status=1`). |
|
||||||
|
| `biztalk_send_ports_unexpected_inactive` | Stopped/bound und nicht allowlisted; CRIT ab 1. |
|
||||||
|
| `biztalk_send_ports_expected_inactive` | Bewusst inactive und exakt allowlisted. |
|
||||||
| `biztalk_send_ports_unknown` | Nicht interpretierbarer Send-Port-Status. |
|
| `biztalk_send_ports_unknown` | Nicht interpretierbarer Send-Port-Status. |
|
||||||
| `biztalk_orchestrations` | Gesamtzahl Orchestrations. |
|
|
||||||
|
## BizTalk Orchestrations
|
||||||
|
|
||||||
|
Status:
|
||||||
|
|
||||||
|
| Status | Bedingung |
|
||||||
|
| --- | --- |
|
||||||
|
| `OK` | Daten lesbar und kein unbekannter Status; inaktive Orchestrations sind standardmaessig nur Information. |
|
||||||
|
| `WARN` | stopped/bound/unbound bei `AlertOnInactiveOrchestrations=true`. |
|
||||||
|
| `CRIT` | Mindestens ein unbekannter Statuswert. |
|
||||||
|
| `UNKNOWN` | `MSBTS_Orchestration` nicht verlaesslich lesbar. |
|
||||||
|
|
||||||
|
Metriken:
|
||||||
|
|
||||||
|
| Metrik | Bedeutung |
|
||||||
|
| --- | --- |
|
||||||
|
| `biztalk_orchestrations_total` | Gesamtzahl Orchestrations. |
|
||||||
| `biztalk_orchestrations_started` | Gestartete Orchestrations. |
|
| `biztalk_orchestrations_started` | Gestartete Orchestrations. |
|
||||||
| `biztalk_orchestrations_inactive` | Bound, unbound oder stopped Orchestrations. |
|
| `biztalk_orchestrations_stopped` | Gestoppte Orchestrations. |
|
||||||
|
| `biztalk_orchestrations_bound` | Bound Orchestrations. |
|
||||||
|
| `biztalk_orchestrations_unbound` | Unbound Orchestrations. |
|
||||||
| `biztalk_orchestrations_unknown` | Nicht interpretierbarer Orchestration-Status. |
|
| `biztalk_orchestrations_unknown` | Nicht interpretierbarer Orchestration-Status. |
|
||||||
|
|
||||||
|
Allowlist-Syntax fuer Receive Locations und Send Ports:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Name|Anwendung\Name|Weiterer Name
|
||||||
|
```
|
||||||
|
|
||||||
|
Die Auswertung ist case-insensitive und exakt. Wildcards werden bewusst nicht
|
||||||
|
unterstuetzt, damit eine breite Regel keine neuen Artefaktfehler verdeckt.
|
||||||
|
|
||||||
## BizTalk Event Log
|
## BizTalk Event Log
|
||||||
|
|
||||||
Zweck:
|
Zweck:
|
||||||
|
|||||||
+33
-21
@@ -7,54 +7,66 @@
|
|||||||
0 "BizTalk SQL Access" biztalk_sql_targets_total=0;;;0 Self test OK. No SQL connection was opened.
|
0 "BizTalk SQL Access" biztalk_sql_targets_total=0;;;0 Self test OK. No SQL connection was opened.
|
||||||
0 "BizTalk Suspended Instances" biztalk_suspended_total=0;;;0 Self test OK.
|
0 "BizTalk Suspended Instances" biztalk_suspended_total=0;;;0 Self test OK.
|
||||||
0 "BizTalk Host Instances" biztalk_host_instances_total=0;;;0 Self test OK. No WMI query was executed.
|
0 "BizTalk Host Instances" biztalk_host_instances_total=0;;;0 Self test OK. No WMI query was executed.
|
||||||
0 "BizTalk Runtime Artifacts" biztalk_applications=0;;;0 Self test OK. No WMI query was executed.
|
0 "BizTalk Receive Locations" biztalk_receive_locations_total=0;;;0 Self test OK. No WMI query was executed.
|
||||||
|
0 "BizTalk Send Ports" biztalk_send_ports_total=0;;;0 Self test OK. No WMI query was executed.
|
||||||
|
0 "BizTalk Orchestrations" biztalk_orchestrations_total=0;;;0 Self test OK. No WMI query was executed.
|
||||||
0 "BizTalk Event Log" biztalk_eventlog_errors=0;;;0 Self test OK. No event log was read.
|
0 "BizTalk Event Log" biztalk_eventlog_errors=0;;;0 Self test OK. No event log was read.
|
||||||
```
|
```
|
||||||
|
|
||||||
## Gesunder BizTalk-Server
|
## Gesundes kompaktes Servicebild
|
||||||
|
|
||||||
```text
|
```text
|
||||||
0 "BizTalk Platform" - BizTalk WMI and platform data reachable, server=BIZTALK01, group=BizTalkMgmtDb, read_only_group=CONTOSO\BizTalk Server Read Only Users, operator_group=CONTOSO\BizTalk Server Operators, mgmt_db=SQL01\BizTalkMgmtDb, msgbox_db=SQL01\BizTalkMsgBoxDb
|
0 "BizTalk Suspended Instances" biztalk_suspended_total=0;;;0|biztalk_suspended_resumable=0;1;;0|biztalk_suspended_nonresumable=0;;1;0|biztalk_routing_failure_reports=0;;1;0 Suspended total=0, resumable=0, nonresumable=0, routing_failure_reports=0.
|
||||||
0 "BizTalk SQL Access" biztalk_sql_targets_total=2;;;0|biztalk_sql_targets_available=2;;;0|biztalk_sql_targets_failed=0;;1;0 SQL access targets=2, available=2, discovery_complete=True, execution_identity=CONTOSO\svc_biztalk_cmk$, network_identity=CONTOSO\svc_biztalk_cmk$; databases=Management=SQL01\BizTalkMgmtDb:OK, MasterMessageBox=SQL01\BizTalkMsgBoxDb:OK
|
0 "BizTalk Receive Locations" biztalk_receive_locations_total=24;;;0|biztalk_receive_locations_enabled=23;;;0|biztalk_receive_locations_disabled=1;;;0|biztalk_receive_locations_unexpected_disabled=0;;1;0|biztalk_receive_locations_expected_disabled=1;;;0|biztalk_receive_locations_unknown=0;;1;0 Receive locations total=24, enabled=23, unexpected_disabled=0, expected_disabled=1, unknown=0
|
||||||
0 "BizTalk Suspended Instances" biztalk_suspended_total=0;;;0|biztalk_suspended_resumable=0;1;;0|biztalk_suspended_nonresumable=0;;1;0 No suspended BizTalk service instances found.
|
0 "BizTalk Send Ports" biztalk_send_ports_total=31;;;0|biztalk_send_ports_started=30;;;0|biztalk_send_ports_stopped=1;;;0|biztalk_send_ports_bound=0;;;0|biztalk_send_ports_unexpected_inactive=0;;1;0|biztalk_send_ports_expected_inactive=1;;;0|biztalk_send_ports_unknown=0;;1;0 Send ports total=31, started=30, stopped=1, bound=0, unexpected_inactive=0, expected_inactive=1, unknown=0
|
||||||
0 "BizTalk Host Instances" biztalk_host_instances_total=4;;;0|biztalk_host_instances_started=4;;;0|biztalk_host_instances_stopped=0;;1;0|biztalk_host_instances_pending=0;1;;0|biztalk_host_instances_unknown=0;;1;0 Host instances total=4, started=4, stopped=0, pending=0, unknown=0
|
0 "BizTalk Orchestrations" biztalk_orchestrations_total=12;;;0|biztalk_orchestrations_started=11;;;0|biztalk_orchestrations_stopped=1;;;0|biztalk_orchestrations_bound=0;;;0|biztalk_orchestrations_unbound=0;;;0|biztalk_orchestrations_unknown=0;;1;0 Orchestrations total=12, started=11, stopped=1, bound=0, unbound=0, unknown=0; affected_apps=Maintenance(inactive=1,unknown=0)
|
||||||
0 "BizTalk Runtime Artifacts" biztalk_applications=8;;;0|biztalk_receive_locations=24;;;0|biztalk_receive_locations_disabled=0;1;;0|biztalk_send_ports=31;;;0|biztalk_send_ports_started=31;;;0|biztalk_send_ports_inactive=0;1;;0|biztalk_send_ports_unknown=0;;1;0|biztalk_orchestrations=12;;;0|biztalk_orchestrations_started=12;;;0|biztalk_orchestrations_inactive=0;1;;0|biztalk_orchestrations_unknown=0;;1;0 Applications=8; receive_locations total=24, disabled=0; send_ports total=31, started=31, inactive=0, unknown=0; orchestrations total=12, started=12, inactive=0, unknown=0
|
|
||||||
0 "BizTalk Event Log" biztalk_eventlog_errors=0;1;10;0|biztalk_eventlog_warnings=0;1;;0 BizTalk-related Application log entries in last 60 minutes: errors=0, warnings=0
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Suspended Instances
|
Die bewusst inaktiven Receive-/Send-Artefakte stehen in den exakten
|
||||||
|
Allowlisten. Sie bleiben als Metrik sichtbar, erzeugen aber keinen Alarm.
|
||||||
|
|
||||||
|
## Suspensions und Routing Failure Report
|
||||||
|
|
||||||
```text
|
```text
|
||||||
2 "BizTalk Suspended Instances" biztalk_suspended_total=3;;;0|biztalk_suspended_resumable=2;1;;0|biztalk_suspended_nonresumable=1;;1;0 3 suspended BizTalk service instance(s): resumable=2, nonresumable=1; applications=OrderProcessing(R=2, NR=1); examples=Send.Invoice on ProcessingHost
|
2 "BizTalk Suspended Instances" biztalk_suspended_total=3;;;0|biztalk_suspended_resumable=2;1;;0|biztalk_suspended_nonresumable=1;;1;0|biztalk_routing_failure_reports=1;;1;0 Suspended total=3, resumable=2, nonresumable=1, routing_failure_reports=1; applications=OrderProcessing(R=2,NR=0); recent=Receive.Order@ProcessingHost, Send.Invoice@ProcessingHost
|
||||||
```
|
```
|
||||||
|
|
||||||
## SQL-Berechtigungsfehler
|
Routing Failure Reports sind eine Teilmenge der non-resumable Instanzen und
|
||||||
|
werden nicht doppelt zum Total addiert.
|
||||||
|
|
||||||
|
## Unerwartet deaktivierte Receive Locations
|
||||||
|
|
||||||
```text
|
```text
|
||||||
3 "BizTalk SQL Access" biztalk_sql_targets_total=2;;;0|biztalk_sql_targets_available=0;;;0|biztalk_sql_targets_failed=2;;1;0 SQL access targets=2, available=0, discovery_complete=True, execution_identity=CONTOSO\svc_biztalk_cmk$, network_identity=CONTOSO\svc_biztalk_cmk$; databases=Management=SQL01\BizTalkMgmtDb:FAILED, MasterMessageBox=SQL01\BizTalkMsgBoxDb:FAILED; diagnostics: Sql/Permission [Management SQL01\BizTalkMgmtDb]: SQL Server hat die integrierte Anmeldung abgelehnt. Massnahme: Provider-Konto und konfigurierte BizTalk-Read-Only-Gruppe mit BTS_READONLY_USERS pruefen; keine direkten BizTalk-DB-Rollen vergeben. Technik: SqlException Number=18456: Login failed for user
|
2 "BizTalk Receive Locations" biztalk_receive_locations_total=24;;;0|biztalk_receive_locations_enabled=22;;;0|biztalk_receive_locations_disabled=2;;;0|biztalk_receive_locations_unexpected_disabled=1;;1;0|biztalk_receive_locations_expected_disabled=1;;;0|biztalk_receive_locations_unknown=0;;1;0 Receive locations total=24, enabled=22, unexpected_disabled=1, expected_disabled=1, unknown=0; affected=Orders\RL_Order_In
|
||||||
```
|
```
|
||||||
|
|
||||||
## WMI-Berechtigungsfehler
|
## Unerwartet inaktive Send Ports
|
||||||
|
|
||||||
```text
|
```text
|
||||||
3 "BizTalk Suspended Instances" - Suspendierte Instanzen konnten nicht verlaesslich gelesen werden. Ein leerer Datenbestand wird nicht als OK gewertet.; diagnostics: Wmi/Permission [MSBTS_ServiceInstance]: Zugriff des Provider-Kontos auf MSBTS_ServiceInstance wurde verweigert. Massnahme: Provider-Identitaet und konfigurierte BizTalk-Read-Only-Gruppe pruefen. Technik: UnauthorizedAccessException HRESULT=0x80070005: Access is denied
|
2 "BizTalk Send Ports" biztalk_send_ports_total=31;;;0|biztalk_send_ports_started=29;;;0|biztalk_send_ports_stopped=1;;;0|biztalk_send_ports_bound=1;;;0|biztalk_send_ports_unexpected_inactive=1;;1;0|biztalk_send_ports_expected_inactive=1;;;0|biztalk_send_ports_unknown=0;;1;0 Send ports total=31, started=29, stopped=1, bound=1, unexpected_inactive=1, expected_inactive=1, unknown=0; affected=Orders\SP_Order_Out(bound)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Begrenzte Detailausgabe
|
||||||
|
|
||||||
|
```text
|
||||||
|
2 "BizTalk Receive Locations" ... affected=App\RL1, App\RL2, App\RL3, App\RL4, App\RL5 (+17 more)
|
||||||
|
```
|
||||||
|
|
||||||
|
Die Zaehler und Performance-Daten enthalten weiterhin alle 22 betroffenen
|
||||||
|
Artefakte. Nur die Textliste ist begrenzt.
|
||||||
|
|
||||||
## Fehlender oder veralteter Provider-Snapshot
|
## Fehlender oder veralteter Provider-Snapshot
|
||||||
|
|
||||||
|
Alle acht Services werden `UNKNOWN`, zum Beispiel:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
3 "BizTalk Platform" - Privilegierter BizTalk-Datensnapshot nicht verfuegbar: Snapshot is stale: age=241s, maximum=180s. Massnahme: Scheduled Task 'BizTalk Checkmk Pulse Provider', Provider-Log, Snapshot-Alter und ACL pruefen.
|
3 "BizTalk Platform" - Privilegierter BizTalk-Datensnapshot nicht verfuegbar: Snapshot is stale: age=241s, maximum=180s. Massnahme: Scheduled Task 'BizTalk Checkmk Pulse Provider', Provider-Log, Snapshot-Alter und ACL pruefen.
|
||||||
3 "BizTalk SQL Access" - Privilegierter BizTalk-Datensnapshot nicht verfuegbar: Snapshot is stale: age=241s, maximum=180s. Massnahme: Scheduled Task 'BizTalk Checkmk Pulse Provider', Provider-Log, Snapshot-Alter und ACL pruefen.
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## WMI-Schemafehler
|
## WMI-Schemafehler
|
||||||
|
|
||||||
```text
|
Nur der fachlich betroffene Service wird `UNKNOWN`:
|
||||||
3 "BizTalk Runtime Artifacts" - BizTalk Runtime Artifacts konnten nicht vollstaendig gelesen werden. Teilwerte werden nicht als OK gewertet.; diagnostics: Wmi/Schema [MSBTS_Orchestration]: WMI-Klasse oder WQL fuer MSBTS_Orchestration wird vom installierten BizTalk-Provider nicht unterstuetzt. Massnahme: Klassen- und Property-Namen gegen das installierte BizTalk-WMI-Schema und die Microsoft-Dokumentation pruefen. Rechteerhoehung behebt InvalidClass/InvalidQuery nicht. Technik: ManagementException HRESULT=0x80041010: Invalid class WQL={SELECT * FROM MSBTS_Orchestration} DurationMs=18
|
|
||||||
```
|
|
||||||
|
|
||||||
## Fehlendes Deployment
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
3 "BizTalk Platform" - BizTalkCheckmkPulse.exe fehlt unter C:\Program Files\BizTalkCheckmkPulse. Massnahme: Install-BizTalkCheckmkPulse.ps1 erneut als Administrator ausfuehren und danach cmk-agent-ctl.exe dump erneut ausfuehren.
|
3 "BizTalk Orchestrations" - Orchestrations konnten nicht verlaesslich gelesen werden.; diagnostics: Wmi/Schema [MSBTS_Orchestration]: WMI-Klasse oder WQL wird nicht unterstuetzt. Massnahme: Klassen- und Property-Namen gegen das installierte BizTalk-WMI-Schema pruefen.
|
||||||
```
|
```
|
||||||
|
|||||||
+7
-13
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
| Team | Aufgabe |
|
| Team | Aufgabe |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| AD/Security | dediziertes Dienstkonto oder gMSA; Aufnahme in exakt konfigurierte BizTalk-Read-Only-Gruppe |
|
| AD/Security | normales dediziertes Servicekonto; Aufnahme in exakt konfigurierte BizTalk-Read-Only-Gruppe |
|
||||||
| BizTalk/SQL | Gruppenabbildung und `BTS_READONLY_USERS` bestaetigen; keine Einzelrechte |
|
| BizTalk/SQL | Gruppenabbildung und `BTS_READONLY_USERS` bestaetigen; keine Einzelrechte |
|
||||||
| Windows | Paket installieren, ACL und Scheduled Task pruefen |
|
| Windows | Paket installieren, ACL und Scheduled Task pruefen |
|
||||||
| Checkmk | Wrapper verteilen beziehungsweise Installation koordinieren, Discovery und Alarmierung |
|
| Checkmk | Wrapper verteilen beziehungsweise Installation koordinieren, Discovery und Alarmierung |
|
||||||
@@ -15,16 +15,7 @@ Provider-Konto und publiziert einen validierbaren Snapshot.
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
gMSA:
|
Normales Servicekonto:
|
||||||
|
|
||||||
```powershell
|
|
||||||
.\Install-BizTalkCheckmkPulse.ps1 `
|
|
||||||
-CollectorAccount 'BEW\svc_biztalk_cmk$' `
|
|
||||||
-Gmsa `
|
|
||||||
-EnvironmentName ACC
|
|
||||||
```
|
|
||||||
|
|
||||||
Regulaeres Dienstkonto:
|
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
.\Install-BizTalkCheckmkPulse.ps1 `
|
.\Install-BizTalkCheckmkPulse.ps1 `
|
||||||
@@ -70,7 +61,8 @@ Verbindlicher Agent-Dump:
|
|||||||
2. `LastTaskResult=0`, frischen Snapshot und Log pruefen.
|
2. `LastTaskResult=0`, frischen Snapshot und Log pruefen.
|
||||||
3. Agent-Dump im `LocalSystem`-Kontext pruefen.
|
3. Agent-Dump im `LocalSystem`-Kontext pruefen.
|
||||||
4. Service Discovery fuer den BizTalk-Host ausfuehren.
|
4. Service Discovery fuer den BizTalk-Host ausfuehren.
|
||||||
5. sechs stabile Services aufnehmen.
|
5. acht stabile Services aufnehmen und den alten
|
||||||
|
`BizTalk Runtime Artifacts`-Service entfernen.
|
||||||
6. Changes aktivieren.
|
6. Changes aktivieren.
|
||||||
7. Views, Servicegruppen und Benachrichtigungen einrichten.
|
7. Views, Servicegruppen und Benachrichtigungen einrichten.
|
||||||
|
|
||||||
@@ -117,11 +109,13 @@ Soll:
|
|||||||
- Log nennt das dedizierte Providerkonto.
|
- Log nennt das dedizierte Providerkonto.
|
||||||
- Platform zeigt `read_only_group=...`.
|
- Platform zeigt `read_only_group=...`.
|
||||||
- SQL Access zeigt `targets=2`, `available=2`.
|
- SQL Access zeigt `targets=2`, `available=2`.
|
||||||
|
- Suspended Instances zeigt total/resumable/non-resumable/routing failures.
|
||||||
|
- Receive Locations und Send Ports zeigen getrennte expected/unexpected Werte.
|
||||||
- keine berechtigungsbedingten `UNKNOWN`-Services.
|
- keine berechtigungsbedingten `UNKNOWN`-Services.
|
||||||
|
|
||||||
## Alarmierung der Transportkette
|
## Alarmierung der Transportkette
|
||||||
|
|
||||||
Ein Ausfall des Providers wird ueber alle sechs Services als `UNKNOWN`
|
Ein Ausfall des Providers wird ueber alle acht Services als `UNKNOWN`
|
||||||
sichtbar. Die Summary nennt fehlenden, unlesbaren, ungueltigen oder stale
|
sichtbar. Die Summary nennt fehlenden, unlesbaren, ungueltigen oder stale
|
||||||
Snapshot. Als Betriebsregel sollte `UNKNOWN` dieser Services genauso
|
Snapshot. Als Betriebsregel sollte `UNKNOWN` dieser Services genauso
|
||||||
eskaliert werden wie ein technischer Monitoringausfall.
|
eskaliert werden wie ein technischer Monitoringausfall.
|
||||||
|
|||||||
@@ -20,10 +20,17 @@
|
|||||||
<add key="SqlConnectionTimeoutSeconds" value="5" />
|
<add key="SqlConnectionTimeoutSeconds" value="5" />
|
||||||
<add key="WarnResumableThreshold" value="1" />
|
<add key="WarnResumableThreshold" value="1" />
|
||||||
<add key="CritNonResumableThreshold" value="1" />
|
<add key="CritNonResumableThreshold" value="1" />
|
||||||
<add key="MaxSummaryItems" value="12" />
|
<add key="CritRoutingFailureThreshold" value="1" />
|
||||||
|
<add key="MaxSummaryItems" value="5" />
|
||||||
|
<add key="MaxDetailCharacters" value="1600" />
|
||||||
|
|
||||||
<!-- Gestoppte Artefakte koennen in BizTalk-Landschaften fachlich beabsichtigt sein. -->
|
<!-- Unerwartet deaktivierte Receive Locations und inaktive Send Ports sind standardmaessig CRIT. -->
|
||||||
<add key="AlertOnArtifactRuntimeIssues" value="false" />
|
<add key="AlertOnArtifactRuntimeIssues" value="true" />
|
||||||
|
<!-- Exakte Namen, Pipe-getrennt: Name oder Anwendung\Name. Keine Wildcards. -->
|
||||||
|
<add key="ExpectedDisabledReceiveLocations" value="" />
|
||||||
|
<add key="ExpectedInactiveSendPorts" value="" />
|
||||||
|
<!-- Gestoppte/bound Orchestrations koennen fachlich beabsichtigt sein. -->
|
||||||
|
<add key="AlertOnInactiveOrchestrations" value="false" />
|
||||||
<add key="EmitPerApplicationSuspensionServices" value="false" />
|
<add key="EmitPerApplicationSuspensionServices" value="false" />
|
||||||
|
|
||||||
<add key="ProbeEventLog" value="true" />
|
<add key="ProbeEventLog" value="true" />
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ namespace BizTalkCheckmkPulse
|
|||||||
private const int HostPausePending = 6;
|
private const int HostPausePending = 6;
|
||||||
private const int HostPaused = 7;
|
private const int HostPaused = 7;
|
||||||
private const int HostUnknown = 8;
|
private const int HostUnknown = 8;
|
||||||
|
private const int SendPortBound = 1;
|
||||||
|
private const int SendPortStopped = 2;
|
||||||
|
private const int SendPortStarted = 3;
|
||||||
private readonly MonitoringOptions _options;
|
private readonly MonitoringOptions _options;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -41,7 +44,9 @@ namespace BizTalkCheckmkPulse
|
|||||||
yield return FormatSqlAccess(result);
|
yield return FormatSqlAccess(result);
|
||||||
yield return FormatSuspendedInstances(result);
|
yield return FormatSuspendedInstances(result);
|
||||||
yield return FormatHostInstances(result);
|
yield return FormatHostInstances(result);
|
||||||
yield return FormatRuntimeArtifacts(result);
|
yield return FormatReceiveLocations(result);
|
||||||
|
yield return FormatSendPorts(result);
|
||||||
|
yield return FormatOrchestrations(result);
|
||||||
yield return FormatEventLog(result);
|
yield return FormatEventLog(result);
|
||||||
|
|
||||||
if (_options.EmitPerApplicationSuspensionServices && result.Platform.SuspendedInstancesDataAvailable)
|
if (_options.EmitPerApplicationSuspensionServices && result.Platform.SuspendedInstancesDataAvailable)
|
||||||
@@ -63,7 +68,9 @@ namespace BizTalkCheckmkPulse
|
|||||||
yield return BuildLine(CheckState.Ok, _options.ServiceName("SQL Access"), "biztalk_sql_targets_total=0;;;0", "Self test OK. No SQL connection was opened.");
|
yield return BuildLine(CheckState.Ok, _options.ServiceName("SQL Access"), "biztalk_sql_targets_total=0;;;0", "Self test OK. No SQL connection was opened.");
|
||||||
yield return BuildLine(CheckState.Ok, _options.ServiceName("Suspended Instances"), "biztalk_suspended_total=0;;;0", "Self test OK.");
|
yield return BuildLine(CheckState.Ok, _options.ServiceName("Suspended Instances"), "biztalk_suspended_total=0;;;0", "Self test OK.");
|
||||||
yield return BuildLine(CheckState.Ok, _options.ServiceName("Host Instances"), "biztalk_host_instances_total=0;;;0", "Self test OK. No WMI query was executed.");
|
yield return BuildLine(CheckState.Ok, _options.ServiceName("Host Instances"), "biztalk_host_instances_total=0;;;0", "Self test OK. No WMI query was executed.");
|
||||||
yield return BuildLine(CheckState.Ok, _options.ServiceName("Runtime Artifacts"), "biztalk_applications=0;;;0", "Self test OK. No WMI query was executed.");
|
yield return BuildLine(CheckState.Ok, _options.ServiceName("Receive Locations"), "biztalk_receive_locations_total=0;;;0", "Self test OK. No WMI query was executed.");
|
||||||
|
yield return BuildLine(CheckState.Ok, _options.ServiceName("Send Ports"), "biztalk_send_ports_total=0;;;0", "Self test OK. No WMI query was executed.");
|
||||||
|
yield return BuildLine(CheckState.Ok, _options.ServiceName("Orchestrations"), "biztalk_orchestrations_total=0;;;0", "Self test OK. No WMI query was executed.");
|
||||||
yield return BuildLine(CheckState.Ok, _options.ServiceName("Event Log"), "biztalk_eventlog_errors=0;;;0", "Self test OK. No event log was read.");
|
yield return BuildLine(CheckState.Ok, _options.ServiceName("Event Log"), "biztalk_eventlog_errors=0;;;0", "Self test OK. No event log was read.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +86,9 @@ namespace BizTalkCheckmkPulse
|
|||||||
yield return BuildLine(CheckState.Unknown, _options.ServiceName("SQL Access"), "-", action);
|
yield return BuildLine(CheckState.Unknown, _options.ServiceName("SQL Access"), "-", action);
|
||||||
yield return BuildLine(CheckState.Unknown, _options.ServiceName("Suspended Instances"), "-", action);
|
yield return BuildLine(CheckState.Unknown, _options.ServiceName("Suspended Instances"), "-", action);
|
||||||
yield return BuildLine(CheckState.Unknown, _options.ServiceName("Host Instances"), "-", action);
|
yield return BuildLine(CheckState.Unknown, _options.ServiceName("Host Instances"), "-", action);
|
||||||
yield return BuildLine(CheckState.Unknown, _options.ServiceName("Runtime Artifacts"), "-", action);
|
yield return BuildLine(CheckState.Unknown, _options.ServiceName("Receive Locations"), "-", action);
|
||||||
|
yield return BuildLine(CheckState.Unknown, _options.ServiceName("Send Ports"), "-", action);
|
||||||
|
yield return BuildLine(CheckState.Unknown, _options.ServiceName("Orchestrations"), "-", action);
|
||||||
yield return BuildLine(CheckState.Unknown, _options.ServiceName("Event Log"), "-", action);
|
yield return BuildLine(CheckState.Unknown, _options.ServiceName("Event Log"), "-", action);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +104,9 @@ namespace BizTalkCheckmkPulse
|
|||||||
yield return BuildLine(CheckState.Unknown, _options.ServiceName("SQL Access"), "-", detail);
|
yield return BuildLine(CheckState.Unknown, _options.ServiceName("SQL Access"), "-", detail);
|
||||||
yield return BuildLine(CheckState.Unknown, _options.ServiceName("Suspended Instances"), "-", detail);
|
yield return BuildLine(CheckState.Unknown, _options.ServiceName("Suspended Instances"), "-", detail);
|
||||||
yield return BuildLine(CheckState.Unknown, _options.ServiceName("Host Instances"), "-", detail);
|
yield return BuildLine(CheckState.Unknown, _options.ServiceName("Host Instances"), "-", detail);
|
||||||
yield return BuildLine(CheckState.Unknown, _options.ServiceName("Runtime Artifacts"), "-", detail);
|
yield return BuildLine(CheckState.Unknown, _options.ServiceName("Receive Locations"), "-", detail);
|
||||||
|
yield return BuildLine(CheckState.Unknown, _options.ServiceName("Send Ports"), "-", detail);
|
||||||
|
yield return BuildLine(CheckState.Unknown, _options.ServiceName("Orchestrations"), "-", detail);
|
||||||
yield return BuildLine(CheckState.Unknown, _options.ServiceName("Event Log"), "-", detail);
|
yield return BuildLine(CheckState.Unknown, _options.ServiceName("Event Log"), "-", detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,19 +193,22 @@ namespace BizTalkCheckmkPulse
|
|||||||
var total = result.SuspendedInstances.Count;
|
var total = result.SuspendedInstances.Count;
|
||||||
var resumable = result.SuspendedInstances.Count(x => x.Kind == SuspendedKind.Resumable);
|
var resumable = result.SuspendedInstances.Count(x => x.Kind == SuspendedKind.Resumable);
|
||||||
var nonresumable = result.SuspendedInstances.Count(x => x.Kind == SuspendedKind.NonResumable);
|
var nonresumable = result.SuspendedInstances.Count(x => x.Kind == SuspendedKind.NonResumable);
|
||||||
var state = DetermineSuspensionState(resumable, nonresumable);
|
var routingFailureReports = result.SuspendedInstances.Count(x => x.IsRoutingFailureReport);
|
||||||
|
var state = DetermineSuspensionState(resumable, nonresumable, routingFailureReports);
|
||||||
var metrics = string.Format(
|
var metrics = string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
"biztalk_suspended_total={0};;;0|biztalk_suspended_resumable={1};{2};;0|biztalk_suspended_nonresumable={3};;{4};0",
|
"biztalk_suspended_total={0};;;0|biztalk_suspended_resumable={1};{2};;0|biztalk_suspended_nonresumable={3};;{4};0|biztalk_routing_failure_reports={5};;{6};0",
|
||||||
total,
|
total,
|
||||||
resumable,
|
resumable,
|
||||||
_options.WarnResumableThreshold,
|
_options.WarnResumableThreshold,
|
||||||
nonresumable,
|
nonresumable,
|
||||||
_options.CritNonResumableThreshold);
|
_options.CritNonResumableThreshold,
|
||||||
|
routingFailureReports,
|
||||||
|
_options.CritRoutingFailureThreshold);
|
||||||
|
|
||||||
var detail = total == 0
|
var detail = total == 0
|
||||||
? "No suspended BizTalk service instances found."
|
? "Suspended total=0, resumable=0, nonresumable=0, routing_failure_reports=0."
|
||||||
: BuildSuspensionDetail(result.SuspendedInstances, total, resumable, nonresumable);
|
: BuildSuspensionDetail(result.SuspendedInstances, total, resumable, nonresumable, routingFailureReports);
|
||||||
return BuildLine(state, _options.ServiceName("Suspended Instances"), metrics, detail);
|
return BuildLine(state, _options.ServiceName("Suspended Instances"), metrics, detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,65 +259,147 @@ namespace BizTalkCheckmkPulse
|
|||||||
return BuildLine(state, _options.ServiceName("Host Instances"), metrics, detail.ToString());
|
return BuildLine(state, _options.ServiceName("Host Instances"), metrics, detail.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
private string FormatReceiveLocations(ProbeResult result)
|
||||||
/// Formatiert aggregierte Receive-Location-, Send-Port- und Orchestration-Zustaende.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="result">Probe-Ergebnis.</param>
|
|
||||||
/// <returns>Checkmk-Zeile fuer Runtime Artifacts.</returns>
|
|
||||||
private string FormatRuntimeArtifacts(ProbeResult result)
|
|
||||||
{
|
{
|
||||||
if (!result.Platform.RuntimeArtifactsDataAvailable)
|
if (!result.Platform.ReceiveLocationsDataAvailable)
|
||||||
{
|
{
|
||||||
var errorDetail = "BizTalk Runtime Artifacts konnten nicht vollstaendig gelesen werden. Teilwerte werden nicht als OK gewertet.";
|
|
||||||
return BuildLine(
|
return BuildLine(
|
||||||
CheckState.Unknown,
|
CheckState.Unknown,
|
||||||
_options.ServiceName("Runtime Artifacts"),
|
_options.ServiceName("Receive Locations"),
|
||||||
"-",
|
"-",
|
||||||
AppendDiagnostics(errorDetail, SelectDiagnostics(result, DiagnosticArea.Wmi, "WMI namespace connection", "MSBTS_ReceiveLocation", "MSBTS_SendPort", "MSBTS_Orchestration")));
|
AppendDiagnostics(
|
||||||
|
"Receive Locations konnten nicht verlaesslich gelesen werden.",
|
||||||
|
SelectDiagnostics(result, DiagnosticArea.Wmi, "WMI namespace connection", "MSBTS_ReceiveLocation")));
|
||||||
}
|
}
|
||||||
|
|
||||||
var receiveLocations = result.Applications.Sum(x => x.ReceiveLocationTotal);
|
var disabled = result.ReceiveLocations.Where(x => x.IsDisabled == true).ToArray();
|
||||||
var receiveLocationsDisabled = result.Applications.Sum(x => x.ReceiveLocationDisabled);
|
var unknown = result.ReceiveLocations.Where(x => !x.IsDisabled.HasValue).ToArray();
|
||||||
var sendPorts = result.Applications.Sum(x => x.SendPortTotal);
|
var expectedDisabled = disabled
|
||||||
var sendPortsStarted = result.Applications.Sum(x => x.SendPortStarted);
|
.Where(x => _options.IsExpectedDisabledReceiveLocation(x.ApplicationName, x.Name))
|
||||||
var sendPortsInactive = result.Applications.Sum(x => x.SendPortStopped + x.SendPortBound);
|
.ToArray();
|
||||||
var sendPortsUnknown = result.Applications.Sum(x => x.SendPortUnknown);
|
var unexpectedDisabled = disabled.Except(expectedDisabled).ToArray();
|
||||||
var orchestrations = result.Applications.Sum(x => x.OrchestrationTotal);
|
var enabled = result.ReceiveLocations.Count - disabled.Length - unknown.Length;
|
||||||
var orchestrationsStarted = result.Applications.Sum(x => x.OrchestrationStarted);
|
var state = unknown.Length > 0
|
||||||
var orchestrationsInactive = result.Applications.Sum(x => x.OrchestrationStopped + x.OrchestrationBound + x.OrchestrationUnbound);
|
? CheckState.Unknown
|
||||||
var orchestrationsUnknown = result.Applications.Sum(x => x.OrchestrationUnknown);
|
: _options.AlertOnArtifactRuntimeIssues && unexpectedDisabled.Length > 0
|
||||||
var state = sendPortsUnknown > 0 || orchestrationsUnknown > 0
|
|
||||||
? CheckState.Critical
|
? CheckState.Critical
|
||||||
: _options.AlertOnArtifactRuntimeIssues && (receiveLocationsDisabled > 0 || sendPortsInactive > 0 || orchestrationsInactive > 0)
|
: CheckState.Ok;
|
||||||
|
var metrics = string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
"biztalk_receive_locations_total={0};;;0|biztalk_receive_locations_enabled={1};;;0|biztalk_receive_locations_disabled={2};;;0|biztalk_receive_locations_unexpected_disabled={3};;1;0|biztalk_receive_locations_expected_disabled={4};;;0|biztalk_receive_locations_unknown={5};;1;0",
|
||||||
|
result.ReceiveLocations.Count,
|
||||||
|
enabled,
|
||||||
|
disabled.Length,
|
||||||
|
unexpectedDisabled.Length,
|
||||||
|
expectedDisabled.Length,
|
||||||
|
unknown.Length);
|
||||||
|
var detail = new StringBuilder()
|
||||||
|
.Append("Receive locations total=").Append(result.ReceiveLocations.Count)
|
||||||
|
.Append(", enabled=").Append(enabled)
|
||||||
|
.Append(", unexpected_disabled=").Append(unexpectedDisabled.Length)
|
||||||
|
.Append(", expected_disabled=").Append(expectedDisabled.Length)
|
||||||
|
.Append(", unknown=").Append(unknown.Length);
|
||||||
|
AppendLimitedList(detail, "affected", unexpectedDisabled.Concat(unknown).Select(ReceiveLocationDisplay));
|
||||||
|
return BuildLine(state, _options.ServiceName("Receive Locations"), metrics, detail.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private string FormatSendPorts(ProbeResult result)
|
||||||
|
{
|
||||||
|
if (!result.Platform.SendPortsDataAvailable)
|
||||||
|
{
|
||||||
|
return BuildLine(
|
||||||
|
CheckState.Unknown,
|
||||||
|
_options.ServiceName("Send Ports"),
|
||||||
|
"-",
|
||||||
|
AppendDiagnostics(
|
||||||
|
"Send Ports konnten nicht verlaesslich gelesen werden.",
|
||||||
|
SelectDiagnostics(result, DiagnosticArea.Wmi, "WMI namespace connection", "MSBTS_SendPort")));
|
||||||
|
}
|
||||||
|
|
||||||
|
var started = result.SendPorts.Count(x => x.Status == SendPortStarted);
|
||||||
|
var stopped = result.SendPorts.Count(x => x.Status == SendPortStopped);
|
||||||
|
var bound = result.SendPorts.Count(x => x.Status == SendPortBound);
|
||||||
|
var unknown = result.SendPorts.Where(x => x.Status != SendPortStarted && x.Status != SendPortStopped && x.Status != SendPortBound).ToArray();
|
||||||
|
var inactive = result.SendPorts.Where(x => x.Status == SendPortStopped || x.Status == SendPortBound).ToArray();
|
||||||
|
var expectedInactive = inactive
|
||||||
|
.Where(x => _options.IsExpectedInactiveSendPort(x.ApplicationName, x.Name))
|
||||||
|
.ToArray();
|
||||||
|
var unexpectedInactive = inactive.Except(expectedInactive).ToArray();
|
||||||
|
var state = unknown.Length > 0 || (_options.AlertOnArtifactRuntimeIssues && unexpectedInactive.Length > 0)
|
||||||
|
? CheckState.Critical
|
||||||
|
: CheckState.Ok;
|
||||||
|
var metrics = string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
"biztalk_send_ports_total={0};;;0|biztalk_send_ports_started={1};;;0|biztalk_send_ports_stopped={2};;;0|biztalk_send_ports_bound={3};;;0|biztalk_send_ports_unexpected_inactive={4};;1;0|biztalk_send_ports_expected_inactive={5};;;0|biztalk_send_ports_unknown={6};;1;0",
|
||||||
|
result.SendPorts.Count,
|
||||||
|
started,
|
||||||
|
stopped,
|
||||||
|
bound,
|
||||||
|
unexpectedInactive.Length,
|
||||||
|
expectedInactive.Length,
|
||||||
|
unknown.Length);
|
||||||
|
var detail = new StringBuilder()
|
||||||
|
.Append("Send ports total=").Append(result.SendPorts.Count)
|
||||||
|
.Append(", started=").Append(started)
|
||||||
|
.Append(", stopped=").Append(stopped)
|
||||||
|
.Append(", bound=").Append(bound)
|
||||||
|
.Append(", unexpected_inactive=").Append(unexpectedInactive.Length)
|
||||||
|
.Append(", expected_inactive=").Append(expectedInactive.Length)
|
||||||
|
.Append(", unknown=").Append(unknown.Length);
|
||||||
|
AppendLimitedList(detail, "affected", unexpectedInactive.Concat(unknown).Select(SendPortDisplay));
|
||||||
|
return BuildLine(state, _options.ServiceName("Send Ports"), metrics, detail.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private string FormatOrchestrations(ProbeResult result)
|
||||||
|
{
|
||||||
|
if (!result.Platform.OrchestrationsDataAvailable)
|
||||||
|
{
|
||||||
|
return BuildLine(
|
||||||
|
CheckState.Unknown,
|
||||||
|
_options.ServiceName("Orchestrations"),
|
||||||
|
"-",
|
||||||
|
AppendDiagnostics(
|
||||||
|
"Orchestrations konnten nicht verlaesslich gelesen werden.",
|
||||||
|
SelectDiagnostics(result, DiagnosticArea.Wmi, "WMI namespace connection", "MSBTS_Orchestration")));
|
||||||
|
}
|
||||||
|
|
||||||
|
var total = result.Applications.Sum(x => x.OrchestrationTotal);
|
||||||
|
var started = result.Applications.Sum(x => x.OrchestrationStarted);
|
||||||
|
var stopped = result.Applications.Sum(x => x.OrchestrationStopped);
|
||||||
|
var bound = result.Applications.Sum(x => x.OrchestrationBound);
|
||||||
|
var unbound = result.Applications.Sum(x => x.OrchestrationUnbound);
|
||||||
|
var unknown = result.Applications.Sum(x => x.OrchestrationUnknown);
|
||||||
|
var inactive = stopped + bound + unbound;
|
||||||
|
var state = unknown > 0
|
||||||
|
? CheckState.Critical
|
||||||
|
: _options.AlertOnInactiveOrchestrations && inactive > 0
|
||||||
? CheckState.Warning
|
? CheckState.Warning
|
||||||
: CheckState.Ok;
|
: CheckState.Ok;
|
||||||
var metrics = string.Format(
|
var metrics = string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
"biztalk_applications={0};;;0|biztalk_receive_locations={1};;;0|biztalk_receive_locations_disabled={2};1;;0|biztalk_send_ports={3};;;0|biztalk_send_ports_started={4};;;0|biztalk_send_ports_inactive={5};1;;0|biztalk_send_ports_unknown={6};;1;0|biztalk_orchestrations={7};;;0|biztalk_orchestrations_started={8};;;0|biztalk_orchestrations_inactive={9};1;;0|biztalk_orchestrations_unknown={10};;1;0",
|
"biztalk_orchestrations_total={0};;;0|biztalk_orchestrations_started={1};;;0|biztalk_orchestrations_stopped={2};;;0|biztalk_orchestrations_bound={3};;;0|biztalk_orchestrations_unbound={4};;;0|biztalk_orchestrations_unknown={5};;1;0",
|
||||||
result.Applications.Count,
|
total,
|
||||||
receiveLocations,
|
started,
|
||||||
receiveLocationsDisabled,
|
stopped,
|
||||||
sendPorts,
|
bound,
|
||||||
sendPortsStarted,
|
unbound,
|
||||||
sendPortsInactive,
|
unknown);
|
||||||
sendPortsUnknown,
|
var detail = new StringBuilder()
|
||||||
orchestrations,
|
.Append("Orchestrations total=").Append(total)
|
||||||
orchestrationsStarted,
|
.Append(", started=").Append(started)
|
||||||
orchestrationsInactive,
|
.Append(", stopped=").Append(stopped)
|
||||||
orchestrationsUnknown);
|
.Append(", bound=").Append(bound)
|
||||||
|
.Append(", unbound=").Append(unbound)
|
||||||
var detail = new StringBuilder();
|
.Append(", unknown=").Append(unknown);
|
||||||
detail.Append("Applications=").Append(result.Applications.Count)
|
|
||||||
.Append("; receive_locations total=").Append(receiveLocations).Append(", disabled=").Append(receiveLocationsDisabled)
|
|
||||||
.Append("; send_ports total=").Append(sendPorts).Append(", started=").Append(sendPortsStarted).Append(", inactive=").Append(sendPortsInactive).Append(", unknown=").Append(sendPortsUnknown)
|
|
||||||
.Append("; orchestrations total=").Append(orchestrations).Append(", started=").Append(orchestrationsStarted).Append(", inactive=").Append(orchestrationsInactive).Append(", unknown=").Append(orchestrationsUnknown);
|
|
||||||
|
|
||||||
var affected = result.Applications
|
var affected = result.Applications
|
||||||
.Where(x => x.ReceiveLocationDisabled > 0 || x.SendPortStopped + x.SendPortBound + x.SendPortUnknown > 0 || x.OrchestrationStopped + x.OrchestrationBound + x.OrchestrationUnbound + x.OrchestrationUnknown > 0)
|
.Where(x => x.OrchestrationStopped + x.OrchestrationBound + x.OrchestrationUnbound + x.OrchestrationUnknown > 0)
|
||||||
.Take(_options.MaxSummaryItems)
|
.OrderByDescending(x => x.OrchestrationUnknown)
|
||||||
.Select(x => x.ApplicationName + "(rl_disabled=" + x.ReceiveLocationDisabled + ", sp_inactive=" + (x.SendPortStopped + x.SendPortBound) + ", orch_inactive=" + (x.OrchestrationStopped + x.OrchestrationBound + x.OrchestrationUnbound) + ")");
|
.ThenByDescending(x => x.OrchestrationStopped + x.OrchestrationBound + x.OrchestrationUnbound)
|
||||||
AppendList(detail, "notable_apps", affected);
|
.Select(x => x.ApplicationName + "(inactive="
|
||||||
return BuildLine(state, _options.ServiceName("Runtime Artifacts"), metrics, detail.ToString());
|
+ (x.OrchestrationStopped + x.OrchestrationBound + x.OrchestrationUnbound)
|
||||||
|
+ ",unknown=" + x.OrchestrationUnknown + ")");
|
||||||
|
AppendLimitedList(detail, "affected_apps", affected);
|
||||||
|
return BuildLine(state, _options.ServiceName("Orchestrations"), metrics, detail.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -362,16 +458,24 @@ namespace BizTalkCheckmkPulse
|
|||||||
{
|
{
|
||||||
var resumable = group.Count(x => x.Kind == SuspendedKind.Resumable);
|
var resumable = group.Count(x => x.Kind == SuspendedKind.Resumable);
|
||||||
var nonresumable = group.Count(x => x.Kind == SuspendedKind.NonResumable);
|
var nonresumable = group.Count(x => x.Kind == SuspendedKind.NonResumable);
|
||||||
var state = DetermineSuspensionState(resumable, nonresumable);
|
var routingFailureReports = group.Count(x => x.IsRoutingFailureReport);
|
||||||
|
var state = DetermineSuspensionState(resumable, nonresumable, routingFailureReports);
|
||||||
var metrics = string.Format(
|
var metrics = string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
"biztalk_suspended_total={0};;;0|biztalk_suspended_resumable={1};{2};;0|biztalk_suspended_nonresumable={3};;{4};0",
|
"biztalk_suspended_total={0};;;0|biztalk_suspended_resumable={1};{2};;0|biztalk_suspended_nonresumable={3};;{4};0|biztalk_routing_failure_reports={5};;{6};0",
|
||||||
group.Count(),
|
group.Count(),
|
||||||
resumable,
|
resumable,
|
||||||
_options.WarnResumableThreshold,
|
_options.WarnResumableThreshold,
|
||||||
nonresumable,
|
nonresumable,
|
||||||
_options.CritNonResumableThreshold);
|
_options.CritNonResumableThreshold,
|
||||||
yield return BuildLine(state, _options.ServiceName("Suspended " + group.Key), metrics, "Suspended instances: resumable=" + resumable + ", nonresumable=" + nonresumable);
|
routingFailureReports,
|
||||||
|
_options.CritRoutingFailureThreshold);
|
||||||
|
yield return BuildLine(
|
||||||
|
state,
|
||||||
|
_options.ServiceName("Suspended " + group.Key),
|
||||||
|
metrics,
|
||||||
|
"Suspended total=" + group.Count() + ", resumable=" + resumable
|
||||||
|
+ ", nonresumable=" + nonresumable + ", routing_failure_reports=" + routingFailureReports);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,8 +485,14 @@ namespace BizTalkCheckmkPulse
|
|||||||
/// <param name="resumable">Anzahl fortsetzbarer Instanzen.</param>
|
/// <param name="resumable">Anzahl fortsetzbarer Instanzen.</param>
|
||||||
/// <param name="nonresumable">Anzahl nicht fortsetzbarer Instanzen.</param>
|
/// <param name="nonresumable">Anzahl nicht fortsetzbarer Instanzen.</param>
|
||||||
/// <returns>Zustand gemaess konfigurierten Schwellwerten.</returns>
|
/// <returns>Zustand gemaess konfigurierten Schwellwerten.</returns>
|
||||||
private CheckState DetermineSuspensionState(int resumable, int nonresumable)
|
private CheckState DetermineSuspensionState(int resumable, int nonresumable, int routingFailureReports)
|
||||||
{
|
{
|
||||||
|
if (_options.CritRoutingFailureThreshold > 0
|
||||||
|
&& routingFailureReports >= _options.CritRoutingFailureThreshold)
|
||||||
|
{
|
||||||
|
return CheckState.Critical;
|
||||||
|
}
|
||||||
|
|
||||||
if (_options.CritNonResumableThreshold > 0 && nonresumable >= _options.CritNonResumableThreshold)
|
if (_options.CritNonResumableThreshold > 0 && nonresumable >= _options.CritNonResumableThreshold)
|
||||||
{
|
{
|
||||||
return CheckState.Critical;
|
return CheckState.Critical;
|
||||||
@@ -404,24 +514,32 @@ namespace BizTalkCheckmkPulse
|
|||||||
/// <param name="resumable">Anzahl fortsetzbarer Instanzen.</param>
|
/// <param name="resumable">Anzahl fortsetzbarer Instanzen.</param>
|
||||||
/// <param name="nonresumable">Anzahl nicht fortsetzbarer Instanzen.</param>
|
/// <param name="nonresumable">Anzahl nicht fortsetzbarer Instanzen.</param>
|
||||||
/// <returns>Kompakter Detailtext.</returns>
|
/// <returns>Kompakter Detailtext.</returns>
|
||||||
private string BuildSuspensionDetail(IEnumerable<SuspendedInstance> instances, int total, int resumable, int nonresumable)
|
private string BuildSuspensionDetail(
|
||||||
|
IEnumerable<SuspendedInstance> instances,
|
||||||
|
int total,
|
||||||
|
int resumable,
|
||||||
|
int nonresumable,
|
||||||
|
int routingFailureReports)
|
||||||
{
|
{
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
builder.Append(total).Append(" suspended BizTalk service instance(s): resumable=").Append(resumable)
|
builder.Append("Suspended total=").Append(total)
|
||||||
.Append(", nonresumable=").Append(nonresumable);
|
.Append(", resumable=").Append(resumable)
|
||||||
|
.Append(", nonresumable=").Append(nonresumable)
|
||||||
|
.Append(", routing_failure_reports=").Append(routingFailureReports);
|
||||||
|
|
||||||
var apps = instances
|
var apps = instances
|
||||||
|
.Where(x => !x.IsRoutingFailureReport
|
||||||
|
&& !string.Equals(x.ApplicationName, "(unknown)", StringComparison.OrdinalIgnoreCase))
|
||||||
.GroupBy(x => x.ApplicationName)
|
.GroupBy(x => x.ApplicationName)
|
||||||
.OrderByDescending(x => x.Count())
|
.OrderByDescending(x => x.Count())
|
||||||
.Take(_options.MaxSummaryItems)
|
|
||||||
.Select(x => x.Key + "(R=" + x.Count(y => y.Kind == SuspendedKind.Resumable) + ",NR=" + x.Count(y => y.Kind == SuspendedKind.NonResumable) + ")");
|
.Select(x => x.Key + "(R=" + x.Count(y => y.Kind == SuspendedKind.Resumable) + ",NR=" + x.Count(y => y.Kind == SuspendedKind.NonResumable) + ")");
|
||||||
AppendList(builder, "applications", apps);
|
AppendLimitedList(builder, "applications", apps);
|
||||||
|
|
||||||
var examples = instances
|
var examples = instances
|
||||||
|
.Where(x => !x.IsRoutingFailureReport)
|
||||||
.OrderByDescending(x => x.SuspendTime ?? DateTime.MinValue)
|
.OrderByDescending(x => x.SuspendTime ?? DateTime.MinValue)
|
||||||
.Take(Math.Min(_options.MaxSummaryItems, 5))
|
.Select(x => EmptyAsUnknown(x.ServiceName) + "@" + EmptyAsUnknown(x.HostName));
|
||||||
.Select(x => EmptyAsUnknown(x.ServiceName) + " on " + EmptyAsUnknown(x.HostName));
|
AppendLimitedList(builder, "recent", examples);
|
||||||
AppendList(builder, "examples", examples);
|
|
||||||
return builder.ToString();
|
return builder.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -433,13 +551,20 @@ namespace BizTalkCheckmkPulse
|
|||||||
/// <param name="metrics">Performance-Daten oder Bindestrich.</param>
|
/// <param name="metrics">Performance-Daten oder Bindestrich.</param>
|
||||||
/// <param name="detail">Menschenlesbare Service-Ausgabe.</param>
|
/// <param name="detail">Menschenlesbare Service-Ausgabe.</param>
|
||||||
/// <returns>Vollstaendige Local-Check-Zeile.</returns>
|
/// <returns>Vollstaendige Local-Check-Zeile.</returns>
|
||||||
private static string BuildLine(CheckState state, string serviceName, string metrics, string detail)
|
private string BuildLine(CheckState state, string serviceName, string metrics, string detail)
|
||||||
{
|
{
|
||||||
|
var sanitizedDetail = SanitizeDetail(detail);
|
||||||
|
if (sanitizedDetail.Length > _options.MaxDetailCharacters)
|
||||||
|
{
|
||||||
|
sanitizedDetail = sanitizedDetail.Substring(0, _options.MaxDetailCharacters - 16).TrimEnd()
|
||||||
|
+ "... [truncated]";
|
||||||
|
}
|
||||||
|
|
||||||
return ((int)state).ToString(CultureInfo.InvariantCulture)
|
return ((int)state).ToString(CultureInfo.InvariantCulture)
|
||||||
+ " \"" + SanitizeService(serviceName) + "\" "
|
+ " \"" + SanitizeService(serviceName) + "\" "
|
||||||
+ (string.IsNullOrWhiteSpace(metrics) ? "-" : metrics)
|
+ (string.IsNullOrWhiteSpace(metrics) ? "-" : metrics)
|
||||||
+ " "
|
+ " "
|
||||||
+ SanitizeDetail(detail);
|
+ sanitizedDetail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -489,6 +614,57 @@ namespace BizTalkCheckmkPulse
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AppendLimitedList(StringBuilder builder, string label, IEnumerable<string> values)
|
||||||
|
{
|
||||||
|
var all = values.Where(x => !string.IsNullOrWhiteSpace(x)).ToArray();
|
||||||
|
if (all.Length == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var visible = all.Take(_options.MaxSummaryItems).ToArray();
|
||||||
|
builder.Append("; ").Append(label).Append("=").Append(string.Join(", ", visible));
|
||||||
|
if (all.Length > visible.Length)
|
||||||
|
{
|
||||||
|
builder.Append(" (+").Append(all.Length - visible.Length).Append(" more)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ReceiveLocationDisplay(ReceiveLocationState item)
|
||||||
|
{
|
||||||
|
return ArtifactDisplay(item.ApplicationName, item.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string SendPortDisplay(SendPortState item)
|
||||||
|
{
|
||||||
|
return ArtifactDisplay(item.ApplicationName, item.Name)
|
||||||
|
+ "(" + SendPortStateName(item.Status) + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ArtifactDisplay(string applicationName, string artifactName)
|
||||||
|
{
|
||||||
|
var application = EmptyAsUnknown(applicationName);
|
||||||
|
var name = EmptyAsUnknown(artifactName);
|
||||||
|
return string.Equals(application, "(unknown)", StringComparison.OrdinalIgnoreCase)
|
||||||
|
? name
|
||||||
|
: application + "\\" + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string SendPortStateName(int status)
|
||||||
|
{
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case SendPortStarted:
|
||||||
|
return "started";
|
||||||
|
case SendPortStopped:
|
||||||
|
return "stopped";
|
||||||
|
case SendPortBound:
|
||||||
|
return "bound";
|
||||||
|
default:
|
||||||
|
return "unknown:" + status.ToString(CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Haengt einen optionalen benannten Wert an einen Detailtext an.
|
/// Haengt einen optionalen benannten Wert an einen Detailtext an.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ namespace BizTalkCheckmkPulse
|
|||||||
Platform = new PlatformState();
|
Platform = new PlatformState();
|
||||||
HostInstances = new List<HostInstanceState>();
|
HostInstances = new List<HostInstanceState>();
|
||||||
SuspendedInstances = new List<SuspendedInstance>();
|
SuspendedInstances = new List<SuspendedInstance>();
|
||||||
|
ReceiveLocations = new List<ReceiveLocationState>();
|
||||||
|
SendPorts = new List<SendPortState>();
|
||||||
Applications = new List<ApplicationRuntimeState>();
|
Applications = new List<ApplicationRuntimeState>();
|
||||||
SqlTargets = new List<SqlAccessState>();
|
SqlTargets = new List<SqlAccessState>();
|
||||||
EventLog = new EventLogState();
|
EventLog = new EventLogState();
|
||||||
@@ -105,6 +107,8 @@ namespace BizTalkCheckmkPulse
|
|||||||
public PlatformState Platform { get; private set; }
|
public PlatformState Platform { get; private set; }
|
||||||
public List<HostInstanceState> HostInstances { get; private set; }
|
public List<HostInstanceState> HostInstances { get; private set; }
|
||||||
public List<SuspendedInstance> SuspendedInstances { get; private set; }
|
public List<SuspendedInstance> SuspendedInstances { get; private set; }
|
||||||
|
public List<ReceiveLocationState> ReceiveLocations { get; private set; }
|
||||||
|
public List<SendPortState> SendPorts { get; private set; }
|
||||||
public List<ApplicationRuntimeState> Applications { get; private set; }
|
public List<ApplicationRuntimeState> Applications { get; private set; }
|
||||||
public List<SqlAccessState> SqlTargets { get; private set; }
|
public List<SqlAccessState> SqlTargets { get; private set; }
|
||||||
public string ExecutionIdentity { get; set; }
|
public string ExecutionIdentity { get; set; }
|
||||||
@@ -121,7 +125,9 @@ namespace BizTalkCheckmkPulse
|
|||||||
public bool PlatformDataAvailable { get; set; }
|
public bool PlatformDataAvailable { get; set; }
|
||||||
public bool HostInstancesDataAvailable { get; set; }
|
public bool HostInstancesDataAvailable { get; set; }
|
||||||
public bool SuspendedInstancesDataAvailable { get; set; }
|
public bool SuspendedInstancesDataAvailable { get; set; }
|
||||||
public bool RuntimeArtifactsDataAvailable { get; set; }
|
public bool ReceiveLocationsDataAvailable { get; set; }
|
||||||
|
public bool SendPortsDataAvailable { get; set; }
|
||||||
|
public bool OrchestrationsDataAvailable { get; set; }
|
||||||
public string ServerName { get; set; }
|
public string ServerName { get; set; }
|
||||||
public string GroupName { get; set; }
|
public string GroupName { get; set; }
|
||||||
public string OperatorGroup { get; set; }
|
public string OperatorGroup { get; set; }
|
||||||
@@ -169,7 +175,33 @@ namespace BizTalkCheckmkPulse
|
|||||||
public string InstanceId { get; set; }
|
public string InstanceId { get; set; }
|
||||||
public string ErrorDescription { get; set; }
|
public string ErrorDescription { get; set; }
|
||||||
public DateTime? SuspendTime { get; set; }
|
public DateTime? SuspendTime { get; set; }
|
||||||
|
public int ServiceClassId { get; set; }
|
||||||
public SuspendedKind Kind { get; set; }
|
public SuspendedKind Kind { get; set; }
|
||||||
|
|
||||||
|
public bool IsRoutingFailureReport
|
||||||
|
{
|
||||||
|
get { return ServiceClassId == 64; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Konfigurations- und Laufzeitzustand einer Receive Location.
|
||||||
|
/// </summary>
|
||||||
|
internal sealed class ReceiveLocationState
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string ApplicationName { get; set; }
|
||||||
|
public bool? IsDisabled { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Laufzeitzustand eines Send Ports.
|
||||||
|
/// </summary>
|
||||||
|
internal sealed class SendPortState
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string ApplicationName { get; set; }
|
||||||
|
public int Status { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -20,8 +20,13 @@ namespace BizTalkCheckmkPulse
|
|||||||
public int SqlConnectionTimeoutSeconds { get; set; }
|
public int SqlConnectionTimeoutSeconds { get; set; }
|
||||||
public int WarnResumableThreshold { get; set; }
|
public int WarnResumableThreshold { get; set; }
|
||||||
public int CritNonResumableThreshold { get; set; }
|
public int CritNonResumableThreshold { get; set; }
|
||||||
|
public int CritRoutingFailureThreshold { get; set; }
|
||||||
public int MaxSummaryItems { get; set; }
|
public int MaxSummaryItems { get; set; }
|
||||||
|
public int MaxDetailCharacters { get; set; }
|
||||||
public bool AlertOnArtifactRuntimeIssues { get; set; }
|
public bool AlertOnArtifactRuntimeIssues { get; set; }
|
||||||
|
public bool AlertOnInactiveOrchestrations { get; set; }
|
||||||
|
public IReadOnlyList<string> ExpectedDisabledReceiveLocations { get; set; }
|
||||||
|
public IReadOnlyList<string> ExpectedInactiveSendPorts { get; set; }
|
||||||
public bool EmitPerApplicationSuspensionServices { get; set; }
|
public bool EmitPerApplicationSuspensionServices { get; set; }
|
||||||
public bool ProbeEventLog { get; set; }
|
public bool ProbeEventLog { get; set; }
|
||||||
public int EventLogLookbackMinutes { get; set; }
|
public int EventLogLookbackMinutes { get; set; }
|
||||||
@@ -49,8 +54,13 @@ namespace BizTalkCheckmkPulse
|
|||||||
SqlConnectionTimeoutSeconds = 5;
|
SqlConnectionTimeoutSeconds = 5;
|
||||||
WarnResumableThreshold = 1;
|
WarnResumableThreshold = 1;
|
||||||
CritNonResumableThreshold = 1;
|
CritNonResumableThreshold = 1;
|
||||||
MaxSummaryItems = 12;
|
CritRoutingFailureThreshold = 1;
|
||||||
AlertOnArtifactRuntimeIssues = false;
|
MaxSummaryItems = 5;
|
||||||
|
MaxDetailCharacters = 1600;
|
||||||
|
AlertOnArtifactRuntimeIssues = true;
|
||||||
|
AlertOnInactiveOrchestrations = false;
|
||||||
|
ExpectedDisabledReceiveLocations = new string[0];
|
||||||
|
ExpectedInactiveSendPorts = new string[0];
|
||||||
EmitPerApplicationSuspensionServices = false;
|
EmitPerApplicationSuspensionServices = false;
|
||||||
ProbeEventLog = true;
|
ProbeEventLog = true;
|
||||||
EventLogLookbackMinutes = 60;
|
EventLogLookbackMinutes = 60;
|
||||||
@@ -96,8 +106,13 @@ namespace BizTalkCheckmkPulse
|
|||||||
options.SqlConnectionTimeoutSeconds = ReadInt(settings, "SqlConnectionTimeoutSeconds", options.SqlConnectionTimeoutSeconds, 3, 60);
|
options.SqlConnectionTimeoutSeconds = ReadInt(settings, "SqlConnectionTimeoutSeconds", options.SqlConnectionTimeoutSeconds, 3, 60);
|
||||||
options.WarnResumableThreshold = ReadInt(settings, "WarnResumableThreshold", options.WarnResumableThreshold, 0, 1000000);
|
options.WarnResumableThreshold = ReadInt(settings, "WarnResumableThreshold", options.WarnResumableThreshold, 0, 1000000);
|
||||||
options.CritNonResumableThreshold = ReadInt(settings, "CritNonResumableThreshold", options.CritNonResumableThreshold, 0, 1000000);
|
options.CritNonResumableThreshold = ReadInt(settings, "CritNonResumableThreshold", options.CritNonResumableThreshold, 0, 1000000);
|
||||||
|
options.CritRoutingFailureThreshold = ReadInt(settings, "CritRoutingFailureThreshold", options.CritRoutingFailureThreshold, 0, 1000000);
|
||||||
options.MaxSummaryItems = ReadInt(settings, "MaxSummaryItems", options.MaxSummaryItems, 1, 100);
|
options.MaxSummaryItems = ReadInt(settings, "MaxSummaryItems", options.MaxSummaryItems, 1, 100);
|
||||||
|
options.MaxDetailCharacters = ReadInt(settings, "MaxDetailCharacters", options.MaxDetailCharacters, 256, 8192);
|
||||||
options.AlertOnArtifactRuntimeIssues = ReadBool(settings, "AlertOnArtifactRuntimeIssues", options.AlertOnArtifactRuntimeIssues);
|
options.AlertOnArtifactRuntimeIssues = ReadBool(settings, "AlertOnArtifactRuntimeIssues", options.AlertOnArtifactRuntimeIssues);
|
||||||
|
options.AlertOnInactiveOrchestrations = ReadBool(settings, "AlertOnInactiveOrchestrations", options.AlertOnInactiveOrchestrations);
|
||||||
|
options.ExpectedDisabledReceiveLocations = ReadExactList(ReadString(settings, "ExpectedDisabledReceiveLocations", string.Empty));
|
||||||
|
options.ExpectedInactiveSendPorts = ReadExactList(ReadString(settings, "ExpectedInactiveSendPorts", string.Empty));
|
||||||
options.EmitPerApplicationSuspensionServices = ReadBool(settings, "EmitPerApplicationSuspensionServices", options.EmitPerApplicationSuspensionServices);
|
options.EmitPerApplicationSuspensionServices = ReadBool(settings, "EmitPerApplicationSuspensionServices", options.EmitPerApplicationSuspensionServices);
|
||||||
options.ProbeEventLog = ReadBool(settings, "ProbeEventLog", options.ProbeEventLog);
|
options.ProbeEventLog = ReadBool(settings, "ProbeEventLog", options.ProbeEventLog);
|
||||||
options.EventLogLookbackMinutes = ReadInt(settings, "EventLogLookbackMinutes", options.EventLogLookbackMinutes, 1, 10080);
|
options.EventLogLookbackMinutes = ReadInt(settings, "EventLogLookbackMinutes", options.EventLogLookbackMinutes, 1, 10080);
|
||||||
@@ -245,6 +260,49 @@ namespace BizTalkCheckmkPulse
|
|||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Liest eine Pipe-getrennte, exakte Allowlist. Wildcards werden bewusst nicht interpretiert.
|
||||||
|
/// </summary>
|
||||||
|
private static IReadOnlyList<string> ReadExactList(string value)
|
||||||
|
{
|
||||||
|
return (value ?? string.Empty)
|
||||||
|
.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
|
||||||
|
.Select(x => x.Trim())
|
||||||
|
.Where(x => x.Length > 0)
|
||||||
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool IsExpectedDisabledReceiveLocation(string applicationName, string artifactName)
|
||||||
|
{
|
||||||
|
return MatchesArtifact(ExpectedDisabledReceiveLocations, applicationName, artifactName);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool IsExpectedInactiveSendPort(string applicationName, string artifactName)
|
||||||
|
{
|
||||||
|
return MatchesArtifact(ExpectedInactiveSendPorts, applicationName, artifactName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool MatchesArtifact(
|
||||||
|
IEnumerable<string> configuredEntries,
|
||||||
|
string applicationName,
|
||||||
|
string artifactName)
|
||||||
|
{
|
||||||
|
var name = (artifactName ?? string.Empty).Trim();
|
||||||
|
var application = (applicationName ?? string.Empty).Trim();
|
||||||
|
if (name.Length == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var qualified = application.Length == 0 || string.Equals(application, "(unknown)", StringComparison.OrdinalIgnoreCase)
|
||||||
|
? string.Empty
|
||||||
|
: application + "\\" + name;
|
||||||
|
return configuredEntries.Any(x =>
|
||||||
|
string.Equals(x, name, StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| (qualified.Length > 0 && string.Equals(x, qualified, StringComparison.OrdinalIgnoreCase)));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prueft einen Wert ohne Beachtung der Gross-/Kleinschreibung gegen Kandidaten.
|
/// Prueft einen Wert ohne Beachtung der Gross-/Kleinschreibung gegen Kandidaten.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -70,6 +70,11 @@ namespace BizTalkCheckmkPulse
|
|||||||
{
|
{
|
||||||
logger.Info("Collection started. snapshot=" + options.SnapshotPath);
|
logger.Info("Collection started. snapshot=" + options.SnapshotPath);
|
||||||
var result = Collect(options);
|
var result = Collect(options);
|
||||||
|
foreach (var diagnostic in result.Diagnostics)
|
||||||
|
{
|
||||||
|
logger.Warning("Probe diagnostic: " + diagnostic.ToDisplayText());
|
||||||
|
}
|
||||||
|
|
||||||
var lines = formatter.Format(result).ToArray();
|
var lines = formatter.Format(result).ToArray();
|
||||||
new SnapshotStore(options.SnapshotPath, options.SnapshotMaxBytes)
|
new SnapshotStore(options.SnapshotPath, options.SnapshotMaxBytes)
|
||||||
.Write(lines, DateTime.UtcNow, CurrentIdentity());
|
.Write(lines, DateTime.UtcNow, CurrentIdentity());
|
||||||
@@ -79,6 +84,20 @@ namespace BizTalkCheckmkPulse
|
|||||||
+ lines.Length
|
+ lines.Length
|
||||||
+ " diagnostics="
|
+ " diagnostics="
|
||||||
+ result.Diagnostics.Count
|
+ result.Diagnostics.Count
|
||||||
|
+ " suspended_total="
|
||||||
|
+ result.SuspendedInstances.Count
|
||||||
|
+ " routing_failure_reports="
|
||||||
|
+ result.SuspendedInstances.Count(x => x.IsRoutingFailureReport)
|
||||||
|
+ " receive_locations_total="
|
||||||
|
+ result.ReceiveLocations.Count
|
||||||
|
+ " receive_locations_disabled="
|
||||||
|
+ result.ReceiveLocations.Count(x => x.IsDisabled == true)
|
||||||
|
+ " receive_locations_unknown="
|
||||||
|
+ result.ReceiveLocations.Count(x => !x.IsDisabled.HasValue)
|
||||||
|
+ " send_ports_total="
|
||||||
|
+ result.SendPorts.Count
|
||||||
|
+ " send_ports_not_started="
|
||||||
|
+ result.SendPorts.Count(x => x.Status != 3)
|
||||||
+ " elapsed_ms="
|
+ " elapsed_ms="
|
||||||
+ stopwatch.ElapsedMilliseconds);
|
+ stopwatch.ElapsedMilliseconds);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -6,5 +6,5 @@ using System.Reflection;
|
|||||||
[assembly: AssemblyDescription("Privileged BizTalk data provider and validated Checkmk snapshot consumer")]
|
[assembly: AssemblyDescription("Privileged BizTalk data provider and validated Checkmk snapshot consumer")]
|
||||||
[assembly: AssemblyCompany("BEW")]
|
[assembly: AssemblyCompany("BEW")]
|
||||||
[assembly: AssemblyProduct("BizTalk Checkmk Pulse")]
|
[assembly: AssemblyProduct("BizTalk Checkmk Pulse")]
|
||||||
[assembly: AssemblyVersion("2.0.0.0")]
|
[assembly: AssemblyVersion("2.1.0.0")]
|
||||||
[assembly: AssemblyFileVersion("2.0.0.0")]
|
[assembly: AssemblyFileVersion("2.1.0.0")]
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace BizTalkCheckmkPulse
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal sealed class SnapshotStore
|
internal sealed class SnapshotStore
|
||||||
{
|
{
|
||||||
internal const string Magic = "BIZTALK_CHECKMK_PULSE_SNAPSHOT_V1";
|
internal const string Magic = "BIZTALK_CHECKMK_PULSE_SNAPSHOT_V2";
|
||||||
private static readonly UTF8Encoding StrictUtf8 = new UTF8Encoding(false, true);
|
private static readonly UTF8Encoding StrictUtf8 = new UTF8Encoding(false, true);
|
||||||
private readonly string _path;
|
private readonly string _path;
|
||||||
private readonly int _maxBytes;
|
private readonly int _maxBytes;
|
||||||
@@ -258,9 +258,9 @@ namespace BizTalkCheckmkPulse
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count < 6)
|
if (count < 8)
|
||||||
{
|
{
|
||||||
throw new InvalidDataException("Snapshot must contain all six stable services.");
|
throw new InvalidDataException("Snapshot must contain all eight stable services.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ namespace BizTalkCheckmkPulse
|
|||||||
private const int EAccessDenied = unchecked((int)0x80070005);
|
private const int EAccessDenied = unchecked((int)0x80070005);
|
||||||
internal const string GroupSettingQuery =
|
internal const string GroupSettingQuery =
|
||||||
"SELECT Name, BizTalkOperatorGroup, BizTalkReadOnlyUserGroup, MgmtDbServerName, MgmtDbName, SubscriptionDBServerName, SubscriptionDBName FROM MSBTS_GroupSetting";
|
"SELECT Name, BizTalkOperatorGroup, BizTalkReadOnlyUserGroup, MgmtDbServerName, MgmtDbName, SubscriptionDBServerName, SubscriptionDBName FROM MSBTS_GroupSetting";
|
||||||
|
internal const string SuspendedInstancesQuery =
|
||||||
|
"SELECT * FROM MSBTS_ServiceInstance WHERE ServiceStatus = 4 OR ServiceStatus = 32 OR ServiceClass = 64";
|
||||||
private readonly MonitoringOptions _options;
|
private readonly MonitoringOptions _options;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -58,7 +60,7 @@ namespace BizTalkCheckmkPulse
|
|||||||
result.Platform.PlatformDataAvailable = QueryPlatform(scope, result);
|
result.Platform.PlatformDataAvailable = QueryPlatform(scope, result);
|
||||||
result.Platform.HostInstancesDataAvailable = QueryHostInstances(scope, result, server);
|
result.Platform.HostInstancesDataAvailable = QueryHostInstances(scope, result, server);
|
||||||
var applicationIndex = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
var applicationIndex = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
result.Platform.RuntimeArtifactsDataAvailable = QueryApplicationRuntime(scope, result, applicationIndex);
|
QueryApplicationRuntime(scope, result, applicationIndex);
|
||||||
if (_options.EmitPerApplicationSuspensionServices)
|
if (_options.EmitPerApplicationSuspensionServices)
|
||||||
{
|
{
|
||||||
AddArtifactIndex(scope, result, applicationIndex, "MSBTS_ReceivePort");
|
AddArtifactIndex(scope, result, applicationIndex, "MSBTS_ReceivePort");
|
||||||
@@ -196,31 +198,52 @@ namespace BizTalkCheckmkPulse
|
|||||||
/// <param name="scope">Verbundener BizTalk-WMI-Scope.</param>
|
/// <param name="scope">Verbundener BizTalk-WMI-Scope.</param>
|
||||||
/// <param name="result">Zu aktualisierendes Ergebnisobjekt.</param>
|
/// <param name="result">Zu aktualisierendes Ergebnisobjekt.</param>
|
||||||
/// <param name="applicationIndex">Best-Effort-Index fuer Suspensionsdetails.</param>
|
/// <param name="applicationIndex">Best-Effort-Index fuer Suspensionsdetails.</param>
|
||||||
/// <returns><c>true</c>, wenn alle drei Pflichtabfragen erfolgreich waren.</returns>
|
private void QueryApplicationRuntime(
|
||||||
private bool QueryApplicationRuntime(
|
|
||||||
ManagementScope scope,
|
ManagementScope scope,
|
||||||
ProbeResult result,
|
ProbeResult result,
|
||||||
Dictionary<string, string> applicationIndex)
|
Dictionary<string, string> applicationIndex)
|
||||||
{
|
{
|
||||||
var apps = new Dictionary<string, ApplicationRuntimeState>(StringComparer.OrdinalIgnoreCase);
|
var apps = new Dictionary<string, ApplicationRuntimeState>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
var receiveLocationsAvailable = TryQuery(scope, result, "MSBTS_ReceiveLocation", "SELECT * FROM MSBTS_ReceiveLocation", item =>
|
result.Platform.ReceiveLocationsDataAvailable = TryQuery(scope, result, "MSBTS_ReceiveLocation", "SELECT * FROM MSBTS_ReceiveLocation", item =>
|
||||||
{
|
{
|
||||||
AddArtifactIndexEntry(applicationIndex, item);
|
AddArtifactIndexEntry(applicationIndex, item);
|
||||||
var app = GetApplication(apps, GetApplicationName(item));
|
var applicationName = GetApplicationName(item);
|
||||||
|
var name = FirstNonEmpty(WmiHelpers.GetString(item, "Name"), WmiHelpers.GetString(item, "ReceivePortName")) ?? "(unknown)";
|
||||||
|
bool parsedIsDisabled;
|
||||||
|
var isDisabledText = WmiHelpers.GetString(item, "IsDisabled");
|
||||||
|
var isDisabled = bool.TryParse(isDisabledText, out parsedIsDisabled)
|
||||||
|
? (bool?)parsedIsDisabled
|
||||||
|
: null;
|
||||||
|
result.ReceiveLocations.Add(new ReceiveLocationState
|
||||||
|
{
|
||||||
|
Name = name,
|
||||||
|
ApplicationName = applicationName,
|
||||||
|
IsDisabled = isDisabled
|
||||||
|
});
|
||||||
|
var app = GetApplication(apps, applicationName);
|
||||||
app.ReceiveLocationTotal++;
|
app.ReceiveLocationTotal++;
|
||||||
if (WmiHelpers.GetBoolean(item, "IsDisabled", false))
|
if (isDisabled == true)
|
||||||
{
|
{
|
||||||
app.ReceiveLocationDisabled++;
|
app.ReceiveLocationDisabled++;
|
||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
var sendPortsAvailable = TryQuery(scope, result, "MSBTS_SendPort", "SELECT * FROM MSBTS_SendPort", item =>
|
result.Platform.SendPortsDataAvailable = TryQuery(scope, result, "MSBTS_SendPort", "SELECT * FROM MSBTS_SendPort", item =>
|
||||||
{
|
{
|
||||||
AddArtifactIndexEntry(applicationIndex, item);
|
AddArtifactIndexEntry(applicationIndex, item);
|
||||||
var app = GetApplication(apps, GetApplicationName(item));
|
var applicationName = GetApplicationName(item);
|
||||||
|
var name = WmiHelpers.GetString(item, "Name");
|
||||||
|
var status = WmiHelpers.GetInt32(item, "Status", 0);
|
||||||
|
result.SendPorts.Add(new SendPortState
|
||||||
|
{
|
||||||
|
Name = string.IsNullOrWhiteSpace(name) ? "(unknown)" : name,
|
||||||
|
ApplicationName = applicationName,
|
||||||
|
Status = status
|
||||||
|
});
|
||||||
|
var app = GetApplication(apps, applicationName);
|
||||||
app.SendPortTotal++;
|
app.SendPortTotal++;
|
||||||
switch (WmiHelpers.GetInt32(item, "Status", 0))
|
switch (status)
|
||||||
{
|
{
|
||||||
case SendPortStarted:
|
case SendPortStarted:
|
||||||
app.SendPortStarted++;
|
app.SendPortStarted++;
|
||||||
@@ -237,7 +260,7 @@ namespace BizTalkCheckmkPulse
|
|||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
var orchestrationsAvailable = TryQuery(scope, result, "MSBTS_Orchestration", "SELECT * FROM MSBTS_Orchestration", item =>
|
result.Platform.OrchestrationsDataAvailable = TryQuery(scope, result, "MSBTS_Orchestration", "SELECT * FROM MSBTS_Orchestration", item =>
|
||||||
{
|
{
|
||||||
AddArtifactIndexEntry(applicationIndex, item);
|
AddArtifactIndexEntry(applicationIndex, item);
|
||||||
var app = GetApplication(apps, GetApplicationName(item));
|
var app = GetApplication(apps, GetApplicationName(item));
|
||||||
@@ -263,7 +286,6 @@ namespace BizTalkCheckmkPulse
|
|||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
result.Applications.AddRange(apps.Values.OrderBy(x => x.ApplicationName, StringComparer.OrdinalIgnoreCase));
|
result.Applications.AddRange(apps.Values.OrderBy(x => x.ApplicationName, StringComparer.OrdinalIgnoreCase));
|
||||||
return receiveLocationsAvailable && sendPortsAvailable && orchestrationsAvailable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -275,9 +297,10 @@ namespace BizTalkCheckmkPulse
|
|||||||
/// <returns><c>true</c>, wenn die Pflichtabfrage erfolgreich war.</returns>
|
/// <returns><c>true</c>, wenn die Pflichtabfrage erfolgreich war.</returns>
|
||||||
private bool QuerySuspendedInstances(ManagementScope scope, ProbeResult result, Dictionary<string, string> applicationIndex)
|
private bool QuerySuspendedInstances(ManagementScope scope, ProbeResult result, Dictionary<string, string> applicationIndex)
|
||||||
{
|
{
|
||||||
return TryQuery(scope, result, "MSBTS_ServiceInstance", "SELECT * FROM MSBTS_ServiceInstance WHERE ServiceStatus = 4 OR ServiceStatus = 32", item =>
|
return TryQuery(scope, result, "MSBTS_ServiceInstance", SuspendedInstancesQuery, item =>
|
||||||
{
|
{
|
||||||
var serviceStatus = WmiHelpers.GetInt32(item, "ServiceStatus", 0);
|
var serviceStatus = WmiHelpers.GetInt32(item, "ServiceStatus", 0);
|
||||||
|
var serviceClass = WmiHelpers.GetInt32(item, "ServiceClass", 0);
|
||||||
result.SuspendedInstances.Add(new SuspendedInstance
|
result.SuspendedInstances.Add(new SuspendedInstance
|
||||||
{
|
{
|
||||||
ApplicationName = ResolveApplication(item, applicationIndex),
|
ApplicationName = ResolveApplication(item, applicationIndex),
|
||||||
@@ -287,7 +310,10 @@ namespace BizTalkCheckmkPulse
|
|||||||
InstanceId = WmiHelpers.GetString(item, "InstanceID"),
|
InstanceId = WmiHelpers.GetString(item, "InstanceID"),
|
||||||
ErrorDescription = WmiHelpers.GetString(item, "ErrorDescription"),
|
ErrorDescription = WmiHelpers.GetString(item, "ErrorDescription"),
|
||||||
SuspendTime = WmiHelpers.GetDmtfDateTime(item, "SuspendTime"),
|
SuspendTime = WmiHelpers.GetDmtfDateTime(item, "SuspendTime"),
|
||||||
Kind = serviceStatus == SuspendedNonResumable ? SuspendedKind.NonResumable : SuspendedKind.Resumable
|
ServiceClassId = serviceClass,
|
||||||
|
Kind = serviceStatus == SuspendedNonResumable || serviceClass == 64
|
||||||
|
? SuspendedKind.NonResumable
|
||||||
|
: SuspendedKind.Resumable
|
||||||
});
|
});
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,11 @@ namespace BizTalkCheckmkPulse.Tests
|
|||||||
Run("ProviderSqlLoginFailureIsPermission", ProviderSqlLoginFailureIsPermission);
|
Run("ProviderSqlLoginFailureIsPermission", ProviderSqlLoginFailureIsPermission);
|
||||||
Run("RejectedSqlPrincipalIsExtracted", RejectedSqlPrincipalIsExtracted);
|
Run("RejectedSqlPrincipalIsExtracted", RejectedSqlPrincipalIsExtracted);
|
||||||
Run("PlatformPermissionPropagatesToSqlDiscovery", PlatformPermissionPropagatesToSqlDiscovery);
|
Run("PlatformPermissionPropagatesToSqlDiscovery", PlatformPermissionPropagatesToSqlDiscovery);
|
||||||
|
Run("RoutingFailureReportsAreCounted", RoutingFailureReportsAreCounted);
|
||||||
|
Run("ReceiveLocationAllowlistSeparatesExpectedState", ReceiveLocationAllowlistSeparatesExpectedState);
|
||||||
|
Run("UnknownReceiveLocationStateIsNotGreen", UnknownReceiveLocationStateIsNotGreen);
|
||||||
|
Run("SendPortAllowlistSeparatesExpectedState", SendPortAllowlistSeparatesExpectedState);
|
||||||
|
Run("ArtifactSummaryIsBounded", ArtifactSummaryIsBounded);
|
||||||
Run("SnapshotRoundTripPreservesLines", SnapshotRoundTripPreservesLines);
|
Run("SnapshotRoundTripPreservesLines", SnapshotRoundTripPreservesLines);
|
||||||
Run("SnapshotRejectsTampering", SnapshotRejectsTampering);
|
Run("SnapshotRejectsTampering", SnapshotRejectsTampering);
|
||||||
Run("SnapshotRejectsStaleData", SnapshotRejectsStaleData);
|
Run("SnapshotRejectsStaleData", SnapshotRejectsStaleData);
|
||||||
@@ -47,16 +52,19 @@ namespace BizTalkCheckmkPulse.Tests
|
|||||||
private static void SelfTestEmitsAllStableServices()
|
private static void SelfTestEmitsAllStableServices()
|
||||||
{
|
{
|
||||||
var lines = new CheckmkLocalFormatter(new MonitoringOptions()).FormatSelfTest().ToArray();
|
var lines = new CheckmkLocalFormatter(new MonitoringOptions()).FormatSelfTest().ToArray();
|
||||||
AssertEqual(6, lines.Length, "self-test line count");
|
AssertEqual(8, lines.Length, "self-test line count");
|
||||||
AssertEqual(6, lines.Distinct(StringComparer.Ordinal).Count(), "unique self-test lines");
|
AssertEqual(8, lines.Distinct(StringComparer.Ordinal).Count(), "unique self-test lines");
|
||||||
Assert(lines.All(x => x.StartsWith("0 \"BizTalk ", StringComparison.Ordinal)), "every self-test line must be OK");
|
Assert(lines.All(x => x.StartsWith("0 \"BizTalk ", StringComparison.Ordinal)), "every self-test line must be OK");
|
||||||
Assert(lines.Any(x => x.Contains("\"BizTalk Event Log\"")), "Event Log service missing");
|
Assert(lines.Any(x => x.Contains("\"BizTalk Event Log\"")), "Event Log service missing");
|
||||||
|
Assert(lines.Any(x => x.Contains("\"BizTalk Receive Locations\"")), "Receive Locations service missing");
|
||||||
|
Assert(lines.Any(x => x.Contains("\"BizTalk Send Ports\"")), "Send Ports service missing");
|
||||||
|
Assert(lines.Any(x => x.Contains("\"BizTalk Orchestrations\"")), "Orchestrations service missing");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void UnavailableSourcesAreUnknown()
|
private static void UnavailableSourcesAreUnknown()
|
||||||
{
|
{
|
||||||
var lines = new CheckmkLocalFormatter(new MonitoringOptions()).Format(new ProbeResult()).Take(6).ToArray();
|
var lines = new CheckmkLocalFormatter(new MonitoringOptions()).Format(new ProbeResult()).Take(8).ToArray();
|
||||||
AssertEqual(6, lines.Length, "stable service count");
|
AssertEqual(8, lines.Length, "stable service count");
|
||||||
Assert(lines.All(x => x.StartsWith("3 \"BizTalk ", StringComparison.Ordinal)), "unavailable sources must be UNKNOWN");
|
Assert(lines.All(x => x.StartsWith("3 \"BizTalk ", StringComparison.Ordinal)), "unavailable sources must be UNKNOWN");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +73,7 @@ namespace BizTalkCheckmkPulse.Tests
|
|||||||
var options = new MonitoringOptions { EmitPerApplicationSuspensionServices = true };
|
var options = new MonitoringOptions { EmitPerApplicationSuspensionServices = true };
|
||||||
var result = CreateSuspensionResult("(unknown)");
|
var result = CreateSuspensionResult("(unknown)");
|
||||||
var lines = new CheckmkLocalFormatter(options).Format(result).ToArray();
|
var lines = new CheckmkLocalFormatter(options).Format(result).ToArray();
|
||||||
AssertEqual(6, lines.Length, "unknown application must not create a dynamic service");
|
AssertEqual(8, lines.Length, "unknown application must not create a dynamic service");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void KnownApplicationCreatesService()
|
private static void KnownApplicationCreatesService()
|
||||||
@@ -73,7 +81,7 @@ namespace BizTalkCheckmkPulse.Tests
|
|||||||
var options = new MonitoringOptions { EmitPerApplicationSuspensionServices = true };
|
var options = new MonitoringOptions { EmitPerApplicationSuspensionServices = true };
|
||||||
var result = CreateSuspensionResult("Orders");
|
var result = CreateSuspensionResult("Orders");
|
||||||
var lines = new CheckmkLocalFormatter(options).Format(result).ToArray();
|
var lines = new CheckmkLocalFormatter(options).Format(result).ToArray();
|
||||||
AssertEqual(7, lines.Length, "known application should create one dynamic service");
|
AssertEqual(9, lines.Length, "known application should create one dynamic service");
|
||||||
Assert(lines.Any(x => x.Contains("\"BizTalk Suspended Orders\"")), "known application service missing");
|
Assert(lines.Any(x => x.Contains("\"BizTalk Suspended Orders\"")), "known application service missing");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,6 +101,7 @@ namespace BizTalkCheckmkPulse.Tests
|
|||||||
Assert(query.Contains("SubscriptionDBServerName"), "master MessageBox server property missing");
|
Assert(query.Contains("SubscriptionDBServerName"), "master MessageBox server property missing");
|
||||||
Assert(query.Contains("SubscriptionDBName"), "master MessageBox database property missing");
|
Assert(query.Contains("SubscriptionDBName"), "master MessageBox database property missing");
|
||||||
Assert(query.IndexOf("MessageBoxSetting", StringComparison.OrdinalIgnoreCase) < 0, "unsupported MessageBoxSetting class present");
|
Assert(query.IndexOf("MessageBoxSetting", StringComparison.OrdinalIgnoreCase) < 0, "unsupported MessageBoxSetting class present");
|
||||||
|
Assert(WmiBizTalkProbe.SuspendedInstancesQuery.Contains("ServiceClass = 64"), "routing failure report filter missing");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ProviderSqlLoginFailureIsPermission()
|
private static void ProviderSqlLoginFailureIsPermission()
|
||||||
@@ -137,6 +146,167 @@ namespace BizTalkCheckmkPulse.Tests
|
|||||||
"SQL discovery classification");
|
"SQL discovery classification");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void RoutingFailureReportsAreCounted()
|
||||||
|
{
|
||||||
|
var result = new ProbeResult();
|
||||||
|
result.Platform.SuspendedInstancesDataAvailable = true;
|
||||||
|
result.SuspendedInstances.Add(new SuspendedInstance
|
||||||
|
{
|
||||||
|
ApplicationName = "(unknown)",
|
||||||
|
ServiceName = string.Empty,
|
||||||
|
ServiceClassId = 64,
|
||||||
|
Kind = SuspendedKind.NonResumable
|
||||||
|
});
|
||||||
|
result.SuspendedInstances.Add(new SuspendedInstance
|
||||||
|
{
|
||||||
|
ApplicationName = "Orders",
|
||||||
|
ServiceName = "Receive.Order",
|
||||||
|
Kind = SuspendedKind.Resumable
|
||||||
|
});
|
||||||
|
|
||||||
|
var line = FindServiceLine(result, "Suspended Instances");
|
||||||
|
Assert(line.StartsWith("2 \"BizTalk Suspended Instances\"", StringComparison.Ordinal), "routing failure must be CRIT");
|
||||||
|
Assert(line.Contains("biztalk_suspended_total=2"), "suspended total metric missing");
|
||||||
|
Assert(line.Contains("biztalk_suspended_nonresumable=1"), "non-resumable metric missing");
|
||||||
|
Assert(line.Contains("biztalk_routing_failure_reports=1"), "routing failure metric missing");
|
||||||
|
Assert(line.Contains("routing_failure_reports=1"), "routing failure summary missing");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ReceiveLocationAllowlistSeparatesExpectedState()
|
||||||
|
{
|
||||||
|
var options = new MonitoringOptions
|
||||||
|
{
|
||||||
|
ExpectedDisabledReceiveLocations = new[] { "Maintenance\\RL Expected" }
|
||||||
|
};
|
||||||
|
var result = new ProbeResult();
|
||||||
|
result.Platform.ReceiveLocationsDataAvailable = true;
|
||||||
|
result.ReceiveLocations.Add(new ReceiveLocationState
|
||||||
|
{
|
||||||
|
ApplicationName = "Maintenance",
|
||||||
|
Name = "RL Expected",
|
||||||
|
IsDisabled = true
|
||||||
|
});
|
||||||
|
result.ReceiveLocations.Add(new ReceiveLocationState
|
||||||
|
{
|
||||||
|
ApplicationName = "Orders",
|
||||||
|
Name = "RL Orders",
|
||||||
|
IsDisabled = true
|
||||||
|
});
|
||||||
|
result.ReceiveLocations.Add(new ReceiveLocationState
|
||||||
|
{
|
||||||
|
ApplicationName = "Orders",
|
||||||
|
Name = "RL Active",
|
||||||
|
IsDisabled = false
|
||||||
|
});
|
||||||
|
|
||||||
|
var line = FindServiceLine(result, "Receive Locations", options);
|
||||||
|
Assert(line.StartsWith("2 \"BizTalk Receive Locations\"", StringComparison.Ordinal), "unexpected disabled receive location must be CRIT");
|
||||||
|
Assert(line.Contains("biztalk_receive_locations_enabled=1"), "enabled receive metric missing");
|
||||||
|
Assert(line.Contains("biztalk_receive_locations_unexpected_disabled=1"), "unexpected disabled metric missing");
|
||||||
|
Assert(line.Contains("biztalk_receive_locations_expected_disabled=1"), "expected disabled metric missing");
|
||||||
|
Assert(line.Contains(@"Orders\RL Orders"), "affected receive location missing");
|
||||||
|
Assert(line.IndexOf("RL Expected", StringComparison.Ordinal) < 0, "expected disabled receive location should not clutter affected list");
|
||||||
|
|
||||||
|
options.ExpectedDisabledReceiveLocations = new[] { "Maintenance\\RL Expected", "RL Orders" };
|
||||||
|
var allExpected = FindServiceLine(result, "Receive Locations", options);
|
||||||
|
Assert(allExpected.StartsWith("0 \"BizTalk Receive Locations\"", StringComparison.Ordinal), "all expected disabled receive locations should be OK");
|
||||||
|
Assert(allExpected.Contains("biztalk_receive_locations_expected_disabled=2"), "all expected receive count missing");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SendPortAllowlistSeparatesExpectedState()
|
||||||
|
{
|
||||||
|
var options = new MonitoringOptions
|
||||||
|
{
|
||||||
|
ExpectedInactiveSendPorts = new[] { "Maintenance\\SP Expected" }
|
||||||
|
};
|
||||||
|
var result = new ProbeResult();
|
||||||
|
result.Platform.SendPortsDataAvailable = true;
|
||||||
|
result.SendPorts.Add(new SendPortState
|
||||||
|
{
|
||||||
|
ApplicationName = "Maintenance",
|
||||||
|
Name = "SP Expected",
|
||||||
|
Status = 2
|
||||||
|
});
|
||||||
|
result.SendPorts.Add(new SendPortState
|
||||||
|
{
|
||||||
|
ApplicationName = "Orders",
|
||||||
|
Name = "SP Orders",
|
||||||
|
Status = 1
|
||||||
|
});
|
||||||
|
result.SendPorts.Add(new SendPortState
|
||||||
|
{
|
||||||
|
ApplicationName = "Orders",
|
||||||
|
Name = "SP Active",
|
||||||
|
Status = 3
|
||||||
|
});
|
||||||
|
|
||||||
|
var line = FindServiceLine(result, "Send Ports", options);
|
||||||
|
Assert(line.StartsWith("2 \"BizTalk Send Ports\"", StringComparison.Ordinal), "unexpected inactive send port must be CRIT");
|
||||||
|
Assert(line.Contains("biztalk_send_ports_started=1"), "started send port metric missing");
|
||||||
|
Assert(line.Contains("biztalk_send_ports_unexpected_inactive=1"), "unexpected inactive send metric missing");
|
||||||
|
Assert(line.Contains("biztalk_send_ports_expected_inactive=1"), "expected inactive send metric missing");
|
||||||
|
Assert(line.Contains(@"Orders\SP Orders(bound)"), "affected send port missing");
|
||||||
|
Assert(line.IndexOf("SP Expected", StringComparison.Ordinal) < 0, "expected inactive send port should not clutter affected list");
|
||||||
|
|
||||||
|
options.ExpectedInactiveSendPorts = new[] { "Maintenance\\SP Expected", "SP Orders" };
|
||||||
|
var allExpected = FindServiceLine(result, "Send Ports", options);
|
||||||
|
Assert(allExpected.StartsWith("0 \"BizTalk Send Ports\"", StringComparison.Ordinal), "all expected inactive send ports should be OK");
|
||||||
|
Assert(allExpected.Contains("biztalk_send_ports_expected_inactive=2"), "all expected send count missing");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UnknownReceiveLocationStateIsNotGreen()
|
||||||
|
{
|
||||||
|
var result = new ProbeResult();
|
||||||
|
result.Platform.ReceiveLocationsDataAvailable = true;
|
||||||
|
result.ReceiveLocations.Add(new ReceiveLocationState
|
||||||
|
{
|
||||||
|
ApplicationName = "Orders",
|
||||||
|
Name = "RL Missing State",
|
||||||
|
IsDisabled = null
|
||||||
|
});
|
||||||
|
|
||||||
|
var line = FindServiceLine(result, "Receive Locations");
|
||||||
|
Assert(line.StartsWith("3 \"BizTalk Receive Locations\"", StringComparison.Ordinal), "unknown receive state must be UNKNOWN");
|
||||||
|
Assert(line.Contains("biztalk_receive_locations_unknown=1"), "unknown receive metric missing");
|
||||||
|
Assert(line.Contains(@"Orders\RL Missing State"), "unknown receive location must be visible");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ArtifactSummaryIsBounded()
|
||||||
|
{
|
||||||
|
var options = new MonitoringOptions
|
||||||
|
{
|
||||||
|
MaxSummaryItems = 2,
|
||||||
|
MaxDetailCharacters = 256
|
||||||
|
};
|
||||||
|
var result = new ProbeResult();
|
||||||
|
result.Platform.ReceiveLocationsDataAvailable = true;
|
||||||
|
for (var i = 1; i <= 6; i++)
|
||||||
|
{
|
||||||
|
result.ReceiveLocations.Add(new ReceiveLocationState
|
||||||
|
{
|
||||||
|
ApplicationName = "Application",
|
||||||
|
Name = "Disabled-" + i,
|
||||||
|
IsDisabled = true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var line = FindServiceLine(result, "Receive Locations", options);
|
||||||
|
Assert(line.Contains("(+4 more)"), "omitted item count missing");
|
||||||
|
Assert(line.Length < 700, "local check line should remain compact");
|
||||||
|
|
||||||
|
var longResult = new ProbeResult();
|
||||||
|
longResult.Platform.ReceiveLocationsDataAvailable = true;
|
||||||
|
longResult.ReceiveLocations.Add(new ReceiveLocationState
|
||||||
|
{
|
||||||
|
ApplicationName = new string('A', 400),
|
||||||
|
Name = new string('R', 400),
|
||||||
|
IsDisabled = true
|
||||||
|
});
|
||||||
|
var truncated = FindServiceLine(longResult, "Receive Locations", options);
|
||||||
|
Assert(truncated.Contains("[truncated]"), "detail character limit should be visible");
|
||||||
|
Assert(truncated.Length < 700, "truncated local check line should remain bounded");
|
||||||
|
}
|
||||||
|
|
||||||
private static void SnapshotRoundTripPreservesLines()
|
private static void SnapshotRoundTripPreservesLines()
|
||||||
{
|
{
|
||||||
WithTemporarySnapshot((path, store) =>
|
WithTemporarySnapshot((path, store) =>
|
||||||
@@ -222,7 +392,7 @@ namespace BizTalkCheckmkPulse.Tests
|
|||||||
var lines = new CheckmkLocalFormatter(new MonitoringOptions())
|
var lines = new CheckmkLocalFormatter(new MonitoringOptions())
|
||||||
.FormatSnapshotFailure("Snapshot file does not exist.")
|
.FormatSnapshotFailure("Snapshot file does not exist.")
|
||||||
.ToArray();
|
.ToArray();
|
||||||
AssertEqual(6, lines.Length, "snapshot failure stable service count");
|
AssertEqual(8, lines.Length, "snapshot failure stable service count");
|
||||||
Assert(lines.All(x => x.StartsWith("3 \"BizTalk ", StringComparison.Ordinal)), "snapshot failure must be UNKNOWN");
|
Assert(lines.All(x => x.StartsWith("3 \"BizTalk ", StringComparison.Ordinal)), "snapshot failure must be UNKNOWN");
|
||||||
Assert(lines.All(x => x.Contains("Scheduled Task")), "snapshot failure must contain provider action");
|
Assert(lines.All(x => x.Contains("Scheduled Task")), "snapshot failure must contain provider action");
|
||||||
}
|
}
|
||||||
@@ -258,6 +428,18 @@ namespace BizTalkCheckmkPulse.Tests
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string FindServiceLine(
|
||||||
|
ProbeResult result,
|
||||||
|
string serviceSuffix,
|
||||||
|
MonitoringOptions options = null)
|
||||||
|
{
|
||||||
|
var effectiveOptions = options ?? new MonitoringOptions();
|
||||||
|
var token = "\"" + effectiveOptions.ServiceName(serviceSuffix) + "\"";
|
||||||
|
return new CheckmkLocalFormatter(effectiveOptions)
|
||||||
|
.Format(result)
|
||||||
|
.Single(x => x.Contains(token));
|
||||||
|
}
|
||||||
|
|
||||||
private static void Run(string name, Action test)
|
private static void Run(string name, Action test)
|
||||||
{
|
{
|
||||||
ExecutedTests++;
|
ExecutedTests++;
|
||||||
|
|||||||
Reference in New Issue
Block a user