MES Inside – Handout für Entwickler

Stand: 0.4.0-preview.3 (M4, Preview). Die Clientpakete sind im öffentlichen MES-Public-Gitea-Feed verfügbar. Öffentliche APIs und Konfiguration können sich bis Version 1.0 noch ändern.

Zweck dieses Dokuments

Dieses Handout ist der Einstieg für Entwickler, die MES Inside in eine bestehende Anwendung einbauen oder eine vorhandene Integration warten. Es erklärt:

  • welche Aufgabe der Client übernimmt;
  • welche Pakete und Dateien benötigt werden;
  • wie Ereignisse, Fehler, Zeitmessungen und Metriken erfasst werden;
  • welche Daten ausdrücklich nicht geloggt werden dürfen;
  • wie die Integration getestet und abgenommen wird;
  • welche Fehlerbilder im Betrieb zu erwarten sind.

Die kopierbaren Details und alle Varianten stehen in der Client-Verwendungsanleitung und im Entwicklungsleitfaden.

Das mentale Modell

Ein Aufruf von MES Inside ist kein synchroner Aufruf des Monitoring-Servers. Der Client verarbeitet das Ereignis lokal:

Anwendungscode
  -> Sanitizing und Größenlimits
  -> lokale Queue
  -> dauerhafte Spool-Datei
  -> Hintergrund-Uploader
  -> HTTPS-Ingestion-API

Damit gilt:

  • Der fachliche Request wartet nicht auf die zentrale Datenbank.
  • Ein Ausfall von MES Inside darf die Fachanwendung nicht stoppen.
  • Nicht übertragene Batches bleiben lokal erhalten.
  • Die API bestätigt Batches idempotent; erst danach wird die lokale Datei entfernt.
  • Ein volles Spoollimit führt kontrolliert zur Verwerfung neuer Ereignisse nach Priorität, nicht zu unbegrenztem Plattenwachstum.

Paketauswahl

Für eine neue Integration wird die Paketversion bewusst fest eingetragen:

dotnet add package MES.Inside.Client.AspNetCore `
  --version 0.4.0-preview.3 `
  --source MES-Public-Gitea
Anwendung Integrationspaket
ASP.NET Core / .NET 8 MES.Inside.Client.AspNetCore
ASP.NET / WebForms / .NET Framework 4.8 MES.Inside.Client.AspNetFramework
Worker, Konsole oder eigene Integration MES.Inside.Client
reine Konfigurationsverarbeitung MES.Inside.Configuration
gemeinsame Ereignisverträge MES.Inside.Contracts

Die gemeinsamen Bibliotheken basieren auf netstandard2.0 und können daher von .NET 8 und .NET Framework 4.8 gemeinsam verwendet werden. Pakete werden versioniert aus dem freigegebenen NuGet-Feed bezogen; DLLs sollten nicht unkontrolliert zwischen Projekten kopiert werden.

Was in die Anwendung kommt

Eine typische Webintegration besteht aus:

  1. passendem NuGet-Paket;
  2. mesinside.json im Root beziehungsweise einem explizit konfigurierten Pfad;
  3. API-Key in einem Secret-Speicher oder einer Umgebungsvariable;
  4. beschreibbarem Spoolverzeichnis, üblicherweise unter App_Data/MES.Inside;
  5. Registrierung beim Anwendungsstart;
  6. gezielter Instrumentierung wichtiger fachlicher Grenzen.

Der API-Key gehört nicht in Git. Die Konfigurationsdatei enthält eine credentialReference, nicht zwingend das Secret selbst.

Minimal sinnvolle Instrumentierung

Ein erster Pilot sollte nicht jede Methode protokollieren. Empfohlen sind:

  • zentrale unbehandelte Exceptions;
  • in ASP.NET Core app.UseMesInsideExceptionLogging() zusätzlich und vor der vorhandenen zentralen Exception-Behandlung registrieren;
  • nach dem Routing app.UseMesInsideRequestMonitoring() aktivieren, damit Seitenaufrufe automatisch unter einem stabilen Routennamen und ohne Query-String gemessen werden;
  • erfolgreiche und fehlgeschlagene Logins;
  • wenige wichtige fachliche Vorgänge;
  • langsame oder geschäftskritische Funktionen;
  • externe HTTP-, Datenbank- oder Servicegrenzen;
  • aussagekräftige Counter;
  • ausgewählte Gauges und Ressourcenwerte.

Einen Funktionsaufruf messen

Um den vorhandenen Aufruf Berechnen() wird ein Messbereich gelegt:

using (inside.Measure("PreisService.Berechnen"))
{
    Berechnen();
}

Der Name ist stabil, technisch verständlich und enthält keine variable ID. Gemessen wird die gesamte Dauer des Blocks. Auch ein asynchroner Aufruf kann innerhalb des Bereichs mit await ausgeführt werden.

Measure(...) verändert das Ergebnis und den Kontrollfluss nicht. In der aktuellen Preview erkennt der Messbereich allerdings nicht selbst, ob eine Exception aufgetreten ist. Fehler werden deshalb an einer geeigneten Grenze zusätzlich erfasst:

using (inside.Measure("PreisService.Berechnen"))
{
    try
    {
        return Berechnen();
    }
    catch (Exception exception)
    {
        inside.LogException(exception, "PreisService.Berechnen.Failed");
        throw;
    }
}

Das ursprüngliche throw; bleibt erhalten. Monitoring darf das fachliche Fehlerverhalten nicht verändern.

Strukturierte Meldungen

inside.Log(
    TelemetrySeverity.Information,
    "Authentication.LoginSucceeded",
    "Login completed successfully.",
    new Dictionary<string, string>
    {
        ["authentication.method"] = "Password",
        ["user.type"] = "Customer"
    });

Der Ereignisname ist eine stabile, auswertbare Kennung. Die Meldung beschreibt das Ereignis neutral. Properties verwenden wenige, bekannte Schlüssel aus der Allowlist.

Gute Namen:

  • Authentication.LoginSucceeded
  • Authentication.LoginFailed
  • Order.Import.Completed
  • Invoice.Generation.Failed
  • ExternalService.Timeout

Schlechte Namen:

  • Fehler 123 bei Max Mustermann
  • der vollständige URL- oder SQL-Text;
  • Namen mit Benutzer-, Objekt- oder Zeitstempel;
  • bei jedem Aufruf dynamisch zusammengesetzte Bezeichnungen.

Counter und Gauge

Counter zählen Vorgänge:

inside.Counter("Authentication.LoginSucceeded");
inside.Counter("Import.ProcessedRows", importedRows);

Gauges beschreiben einen aktuellen Wert:

inside.Gauge("Queue.PendingJobs", pendingJobs);
inside.Gauge("Cache.EntryCount", cacheCount);

Benutzername, IP-Adresse, Trace-ID oder Objekt-ID sind keine Metriknamen und keine Metrik-Labels. Eine hohe Zahl verschiedener Bezeichnungen macht Auswertungen teuer und unbrauchbar.

Korrelation

Zusammengehörige Ereignisse sollen über stabile technische Korrelationsinformationen verbunden werden, nicht über Freitext. Je nach Integration werden Trace-, Request- oder Operation-ID übernommen. Fachliche IDs dürfen nur nach ausdrücklicher Freigabe und möglichst pseudonymisiert als erlaubte Property übertragen werden.

Ein Fehler soll an einer sinnvollen Systemgrenze einmal vollständig protokolliert werden. Dieselbe Exception in jeder aufgerufenen Methode erneut zu loggen erzeugt Dubletten und erschwert die Ursachenanalyse.

Verbotene Inhalte

Nicht an MES Inside übergeben werden:

  • Passwörter und Passwort-Hashes;
  • API-Keys, Tokens und Authorization-Header;
  • Cookies und Sessioninhalte;
  • vollständige Formular-, Request- oder Response-Dumps;
  • ungeprüfte QueryStrings;
  • SQL-Parameter mit Benutzerdaten;
  • Gesundheitsdaten oder andere besondere Kategorien personenbezogener Daten;
  • hochgeladene Dateien oder deren vollständige Inhalte.

Die technische Redaction ist eine zusätzliche Schutzschicht. Sie ersetzt nicht die Verantwortung des Entwicklers, nur zulässige Daten zu übergeben.

Benutzer und IP-Adressen

Benutzer sollen über eine interne oder pseudonymisierte Kennung referenziert werden. E-Mail-Adresse und Anzeigename sind normalerweise nicht erforderlich.

IP-Erfassung ist konfigurierbar:

  • Off: keine IP-Information;
  • Pseudonymized: bevorzugter Modus mit zeitlich begrenzter Zuordenbarkeit;
  • Full: nur mit dokumentierter Freigabe, korrekter Proxy-Konfiguration, beschränktem Zugriff und kurzer Retention.

Bei Reverse Proxies dürfen Forwarded Headers nur von vertrauenswürdigen Proxyadressen akzeptiert werden.

Fehlerverhalten des Clients

Der Anwendungscode soll Telemetrie best effort schreiben. Typische Transportprobleme werden im Hintergrund behandelt:

  • Netzwerkfehler, Timeout, HTTP 408, 425, 429 und 5xx: exponentieller Backoff mit Jitter;
  • Retry-After: Servervorgabe wird berücksichtigt;
  • fehlender oder ungültiger API-Key: langsamer Prüfversuch statt schneller Fehlerschleife;
  • erfolgreiche Übertragung: Fehlerzähler und Backoff werden zurückgesetzt.

Die technische Diagnose steht ohne Secret in:

<Spoolpfad>/transport-status.json

Wichtige Felder sind state, lastSuccessUtc, httpStatusCode, consecutiveFailureCount, nextAttemptUtc und retryReason.

Konfiguration

Die Konfiguration trennt Identität, Transport, Spool, Logging, Tracing, Metriken, Datenschutz, Größenlimits und Ressourcenmessung. Sie wird beim Start validiert. Fehler sollen in Development sofort sichtbar sein; eine ungültige Produktionskonfiguration darf keine unsicheren Standardannahmen erzeugen.

Beispielausschnitt:

{
  "schemaVersion": 1,
  "enabled": true,
  "identity": {
    "tenant": "Customer",
    "project": "Portal",
    "application": "Customer.Portal",
    "environment": "Test"
  },
  "transport": {
    "mode": "InProcess",
    "apiUrl": "https://inside.example/api/v1",
    "credentialReference": "MES_INSIDE_CREDENTIAL_CUSTOMER_PORTAL"
  },
  "privacy": {
    "allowUserId": false,
    "allowIpAddress": false,
    "allowedProperties": [
      "authentication.method",
      "user.type"
    ]
  }
}

Die vollständige Feldbeschreibung steht unter Anwendungskonfiguration.

Entwicklungs- und Testablauf

  1. Paketversion und Feed festlegen.
  2. Projekt und Umgebung im MES-Inside-Server registrieren.
  3. eigenen API-Key für diese Anwendung und Umgebung erzeugen.
  4. Konfiguration ohne Secret einchecken.
  5. Secret lokal beziehungsweise im Webserver hinterlegen.
  6. Spoolpfad und Schreibrechte prüfen.
  7. ein neutrales Testereignis erzeugen.
  8. Spooldatei, Upload und Anzeige im Admin-Web prüfen.
  9. API kurz unerreichbar machen und Entkopplung testen.
  10. ungültigen API-Key testen und Diagnose prüfen.
  11. sensible Test-Properties übergeben und Redaction verifizieren.
  12. Performance messen und unnötige Instrumentierung entfernen.

Pull-Request-Checkliste

  • Ereignisname ist stabil und folgt der Namenskonvention
  • Messpunkt beantwortet eine konkrete Betriebs- oder Fachfrage
  • keine Secrets, Cookies, Formularinhalte oder ungeprüften Benutzerdaten
  • Properties stehen in der Allowlist
  • Fehler werden nicht mehrfach an jeder Aufrufebene protokolliert
  • Exception wird nach dem Logging unverändert weitergegeben
  • keine variable ID im Metrik- oder Ereignisnamen
  • Anwendung funktioniert bei unerreichbarer Ingestion-API
  • Spoolpfad ist nicht öffentlich auslieferbar und besitzt ein Größenlimit
  • Tests decken Erfolg, Fehler und Datenschutzverhalten ab
  • neue Ereignisse und Properties sind dokumentiert

Definition of Done für eine Integration

Eine Integration ist abgeschlossen, wenn:

  • das richtige Paket reproduzierbar aus dem Feed installiert wird;
  • Development, Test und Produktion getrennte Identitäten beziehungsweise API-Keys verwenden;
  • mindestens ein Fehler, eine Zeitmessung und ein relevanter Zähler Ende-zu-Ende geprüft wurden;
  • Ausfall und spätere Wiederübertragung nachgewiesen sind;
  • verbotene Testdaten nicht im Server erscheinen;
  • Betrieb und Support wissen, wo Transportstatus und Ereignisse zu finden sind;
  • Retention, Rechte und Verantwortliche festgelegt sind;
  • die bisherige Logginglösung erst nach dokumentiertem Parallelbetrieb abgeschaltet wird.

Weiterführende Dokumentation