Client im Anwendungscode verwenden

Diese Anleitung zeigt die tatsächliche Verwendung der MES-Inside-Bibliothek nach Installation und Konfiguration. Alle Aufrufe schreiben zunächst in die lokale Queue beziehungsweise Spool. Der fachliche Aufruf wartet nicht auf die Monitoring-API.

Schnellstart: Berechnen() messen

In ASP.NET Core wird der Client über Dependency Injection bezogen:

using MES.Inside.Client;

public sealed class PreisService(InsideClient inside)
{
    public decimal AngebotBerechnen()
    {
        using (inside.Measure("PreisService.AngebotBerechnen"))
        {
            return Berechnen();
        }
    }

    private decimal Berechnen()
    {
        // bestehende Fachlogik
        return 42.50m;
    }
}

Die entscheidenden zwei Zeilen sind:

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

Beim Verlassen des using-Blocks – auch bei return – wird die verstrichene Zeit als OperationCompleted mit der Operation PreisService.AngebotBerechnen protokolliert.

Für eine einzelne Anweisung ist auch diese Schreibweise möglich:

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

Der ausführliche Block ist zu bevorzugen, sobald mehrere Anweisungen gemessen werden.

Asynchronen Aufruf messen

Der Messbereich darf ein await enthalten:

public async Task<Ergebnis> BerechnenAsync(CancellationToken cancellationToken)
{
    using (inside.Measure("PreisService.BerechnenAsync"))
    {
        return await repository.BerechnenAsync(cancellationToken);
    }
}

Gemessen wird die gesamte Wartezeit bis zum Abschluss des asynchronen Aufrufs.

Messung und Fehler gemeinsam protokollieren

Measure(...) misst ausschließlich die Dauer und erkennt in der aktuellen Preview nicht selbst, ob der Block durch eine Exception verlassen wurde. Die Exception wird vom Messbereich nicht verschluckt; für die korrekte Fehlerauswertung wird sie zusätzlich als Fehlerereignis erfasst:

public Ergebnis BerechnenMitFehlerprotokoll()
{
    using (inside.Measure("PreisService.Berechnen"))
    {
        try
        {
            return Berechnen();
        }
        catch (Exception exception)
        {
            inside.LogException(exception, "PreisService.Berechnen.Failed");
            throw; // ursprüngliches Fehlerverhalten beibehalten
        }
    }
}

throw; ist wichtig: MES Inside soll bestehendes Fehlerverhalten nicht verändern. Derselbe Fehler soll nicht zusätzlich in jeder aufgerufenen Unterfunktion protokolliert werden. Sinnvolle Stellen sind fachliche Grenzen, Background-Job-Grenzen oder die zentrale HTTP-Fehlerbehandlung.

Strukturiertes Ereignis schreiben

using MES.Inside.Contracts;

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

Der Ereignisname sollte stabil und auswertbar sein. Personenbezogene Daten, Formularinhalte, Passwörter, Tokens, Cookies und Authorization-Header gehören nicht in Meldung oder Properties.

Exception protokollieren

try
{
    Berechnen();
}
catch (Exception exception)
{
    inside.LogException(exception, "Calculation.Failed");
    throw;
}

Erfasst werden Exception-Typ, Meldung und Stacktrace. Der bestehende Kontrollfluss bleibt unverändert.

Counter und Gauge

Ein Counter zählt ein Ereignis:

inside.Counter("Authentication.LoginSucceeded");
inside.Counter("Authentication.LoginFailed");

Ein anderer Wert als 1 kann ausdrücklich angegeben werden:

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

Eine Gauge beschreibt einen aktuellen Messwert:

inside.Gauge("Queue.PendingJobs", pendingJobs);
inside.Gauge("Process.MemoryMegabytes", memoryMegabytes);

Counter und Gauge sind keine Logs. Sie sind für Summen, Zeitreihen, Schwellwerte und spätere Alarmierung vorgesehen.

Verwendung in einem ASP.NET-Core-Endpunkt

Unbehandelte HTTP-Exceptions zentral erfassen

Nach AddMesInside(...) wird die Exception-Middleware in Program.cs vor einer bereits vorhandenen zentralen Fehlerbehandlung registriert:

app.UseMesInsideExceptionLogging();
app.UseCentralExceptionLogging("Meine.Anwendung"); // bestehender Logger

Die Reihenfolge ist beabsichtigt. Der bestehende Logger darf die Exception zuerst protokollieren und wirft sie danach weiter; MES Inside erfasst dieselbe Exception zusätzlich mit der ASP.NET-Core-Trace-ID. Anschließend wird mit throw; unverändert weitergeworfen. Statuscode, Exception-Handler und bisheriges Loggingverhalten werden nicht ersetzt.

Die Middleware protokolliert pro Request höchstens einmal. Sie erfasst keine Request-Bodies, Formulardaten, Query-Strings, Cookies oder Authorization- Header. Eigene try/catch-Blöcke sollen dieselbe Exception deshalb nicht nochmals an jeder internen Methodenebene melden.

ASP.NET-Core-Requests automatisch messen

Nach dem Routing wird zusätzlich die allgemeine Request-Messung aktiviert:

app.UseRouting();
app.UseMesInsideRequestMonitoring();

Sie misst die gesamte serverseitige Pipeline und erzeugt stabile Operationsnamen wie GET /User/Orders/{id}. Query-Strings und konkrete Routenwerte werden nicht als Teil des Namens gespeichert. Normale Requests unterliegen dem konfigurierten Sampling; Fehler und langsame Requests können über AlwaysKeepErrors und AlwaysKeepSlowOperations unabhängig davon erhalten bleiben. Statische Dateien, Ingestion und Setup-Routen sind standardmäßig ausgeschlossen.

Für die Ursachenanalyse werden wichtige Teilaufrufe weiterhin gezielt mit inside.Measure(...) instrumentiert. Dadurch zeigt die Performanceansicht sowohl die Laufzeit der gesamten Seite als auch die fachlichen Teilschritte.

Minimal API:

app.MapPost("/calculate", (InsideClient inside) =>
{
    using (inside.Measure("HTTP.Calculate"))
    {
        var result = Berechnen();
        inside.Counter("Calculation.Completed");
        return Results.Ok(result);
    }
});

Controller:

[ApiController]
[Route("api/calculation")]
public sealed class CalculationController(InsideClient inside) : ControllerBase
{
    [HttpPost]
    public IActionResult Calculate()
    {
        using (inside.Measure("CalculationController.Calculate"))
        {
            return Ok(Berechnen());
        }
    }
}

.NET Framework 4.8 / WebForms

Nach MesInsideApplication.Start(...) in Global.asax steht derselbe Client über MesInsideApplication.Current zur Verfügung:

using MES.Inside.Client.AspNetFramework;

protected void CalculateButton_Click(object sender, EventArgs e)
{
    var inside = MesInsideApplication.Current;

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

Fehler können an der zentralen WebForms-Grenze zusätzlich erfasst werden:

protected void Application_Error(object sender, EventArgs e)
{
    var exception = Server.GetLastError();
    if (exception != null && MesInsideApplication.Current != null)
        MesInsideApplication.Current.LogException(
            exception,
            "HttpRequest.UnhandledException");

    // Fehler weder löschen noch umleiten, wenn das bisher nicht geschah.
}

Benennung

Empfohlene Namen:

Bereich.Komponente.Aktion
Authentication.LoginSucceeded
Authentication.LoginFailed
OrderService.CalculateTotal
Import.Customers.Completed
Database.CustomerSearch

Keine wechselnden Werte in den Namen einbauen:

Schlecht: Order.4711.Loaded
Gut:     Order.Loaded

Die Bestellnummer wäre – nur wenn datenschutzrechtlich zulässig – eine Property. Dadurch bleibt die Anzahl unterschiedlicher Zeitreihen beherrschbar.

Was wird wann verwendet?

Ziel Methode
Dauer eines Codeblocks using (inside.Measure("..."))
normales strukturiertes Ereignis inside.Log(...)
Exception mit Stacktrace inside.LogException(...)
Anzahl von Vorgängen inside.Counter(...)
aktueller Messwert inside.Gauge(...)

Automatische Prozess-, Speicherplatz- und Spoolmessung

Diese Werte müssen nicht bei jedem Request manuell abgefragt werden. Der Client kann sie in einem konfigurierbaren Hintergrundintervall erfassen:

{
  "resources": {
    "enabled": true,
    "intervalSeconds": 300,
    "includeProcess": true,
    "includeStorage": true,
    "includeSpool": true
  }
}

Der Monitor betrachtet den aktuellen Webprozess und das Laufwerk des Spoolpfads. Er benötigt keine Administratorrechte. Die Einstellung intervalSeconds darf zwischen 30 Sekunden und 24 Stunden liegen; empfohlen sind zunächst fünf Minuten.

Wichtige Grenzen

  • keine API-Keys oder Secrets an eine Logging-Methode übergeben;
  • keine vollständigen Formulardaten protokollieren;
  • keine Messung um jede triviale Hilfsmethode legen;
  • stabile, fachlich verständliche Namen verwenden;
  • Fehler möglichst einmal an einer sinnvollen Grenze erfassen;
  • vorhandene Fehlerbehandlung und vorhandenes Logging nicht ersetzen.

Vollständige, ausführbare Anwendungen stehen im öffentlichen MES.Inside.Samples-Repository.