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.