01 · Problem
Wofür braucht man das?
Querschnittliche Telemetrie soll ergänzt werden, ohne in jede Geschäftsoperation denselben Messcode zu kopieren.
02 · Denkmodell
Das mentale Modell
Ein Wrapper legt sich um die Originaloperation und aktualisiert eine einmalig registrierte Metrik; Typ, Labels und beobachteter Wert sind explizite Konfiguration.
Verwendet benannte Metriken wieder und erfasst Counter, Gauges, Histogramme und Summaries. Legacy-Decorators erfordern passende TypeScript-Einstellungen. Labels brauchen begrenzte Kardinalität; Klassendekoration stellt einen Metrik-Handle bereit.
03 · Kontrollfluss
Was passiert in welcher Reihenfolge?
- Metrikkonfiguration validieren und über einen stabilen Namen einmalig registrieren.
- Originalmethode unter Erhalt von this und Argumenten aufrufen.
- Calls, Wert, Dauer oder Fehler mit passenden Labels beobachten.
- Sync- und Async-Ergebnis unverändert an den Aufrufer zurückgeben.
04 · Bauteile
Die entscheidenden Verträge
PromCounter / PromGauge / PromHistogram / PromSummaryErzeugt wiederverwendbare Aufruf- oder Wertinstrumentierung.TrackOption / IMetricConfigWählt Semantik, Labels und Metrikkonfiguration.05 · Selbst bauen
Selbst implementieren
Beginne mit einer normalen Wrapperfunktion; Decorator-Syntax kann später dieselbe getestete Instrumentierung aufrufen.
- Definiere eine minimale Metrikschnittstelle und eine Registry pro Prozess.
- Cache Metriken anhand Name plus Typ statt sie pro Invocation zu erzeugen.
- Erfasse Promise-Erfolg und -Fehler erst nach Settlement.
type Counter = { inc(labels?: Record<string, string>): void };
function countCalls<A extends unknown[], R>(
counter: Counter,
run: (...args: A) => R,
) {
return function (this: unknown, ...args: A): R {
counter.inc();
return run.apply(this, args);
};
}06 · Verifizieren
Was solltest du testen?
- Mehrere Aufrufe nutzen dieselbe registrierte Metrik und erhöhen sie exakt einmal je Call.
- this, Argumente, Rückgabewert und geworfener Fehler bleiben unverändert.
- Async-Dauer und Rejection werden erst beim Settlement mit korrekten Labels erfasst.
Selbst ausprobieren
Formuliere die erste Prüfaussage als fehlschlagenden Test, implementiere die kleinste Korrektur und ergänze einen Grenzfall.
Mehrere Aufrufe nutzen dieselbe registrierte Metrik und erhöhen sie exakt einmal je Call.
Ansatz vergleichen
Dein Test sollte beim gezielten Verletzen der Invariante fehlschlagen und nach der Korrektur wieder bestehen. Halte den Aufbau deterministisch und prüfe ein beobachtbares Ergebnis.
07 · Grenzen
Kompromisse und Stolperfallen
- Decorators reduzieren Boilerplate, verstecken Observability aber im Metaprogramming.
- Hohe Label-Kardinalität kann Prometheus-Speicher und Abfragen massiv belasten.
- Property-Decorators sind bei instanzlokalem State besonders fehleranfällig.
Legacy-Decorators erfordern passende TypeScript-Einstellungen. Labels brauchen begrenzte Kardinalität; Klassendekoration stellt einen Metrik-Handle bereit.
08 · Weiterdenken
Quellcode und verwandte Ideen
yarn tsx packages/prom-metrics-decorator/examples/basic.ts