EnglishGitHub
teilweisepackages/stats-tracker/src

Stats Tracker

@ralphschuler/stats-tracker

Misst Ereigniszahlen im gleitenden Fenster mit austauschbarer monotoner Uhr.

eventssliding windowmetrics

01 · Problem

Wofür braucht man das?

Ein Gesamtzähler sagt nicht, ob Aktivität gerade stattfindet; für Raten und Bursts braucht man Werte in einem definierten Zeitfenster.

02 · Denkmodell

Das mentale Modell

Jedes Ereignis erhält einen Zeitstempel. Beim Lesen werden abgelaufene Einträge entfernt und die verbleibenden Einträge gezählt.

Im Repository

Misst Ereigniszahlen im gleitenden Fenster mit austauschbarer monotoner Uhr. Zähler betreffen das konfigurierte Fenster, nicht die gesamte Historie. Speicherbedarf wächst mit den Ereignissen im Fenster.

03 · Kontrollfluss

Was passiert in welcher Reihenfolge?

  1. Ereignisname und aktuellen Zeitpunkt erfassen.
  2. Zeitstempel in den Bucket des Ereignisses einfügen.
  3. Beim Schreiben und Lesen alle Werte vor der Fenstergrenze entfernen.
  4. Anzahl oder Rate aus dem verbleibenden Bucket ableiten.

04 · Bauteile

Die entscheidenden Verträge

logEventErfasst ein Ereignis mit der injizierten Uhr.
getCount / getRatePerMinuteLiest aktuelle Fensterzähler oder normalisierte Raten.

05 · Selbst bauen

Selbst implementieren

Mit injizierter Uhr bleibt ein gleitender Zähler klein und vollständig deterministisch testbar.

  1. Fensterlänge und now-Funktion beim Erzeugen entgegennehmen.
  2. Zeitstempel geordnet pro Ereignis speichern.
  3. Vor jeder Auswertung Einträge links bis zur Fenstergrenze entfernen.
Konzeptskizze · kann ausgelassene Helfer verwenden
class WindowCounter {
  private points: number[] = [];
  constructor(private windowMs: number, private now = Date.now) {}
  add() { this.points.push(this.now()); }
  count() {
    const cutoff = this.now() - this.windowMs;
    while (this.points[0] < cutoff) this.points.shift();
    return this.points.length;
  }
}

06 · Verifizieren

Was solltest du testen?

  • Einträge genau an der Fenstergrenze folgen der dokumentierten inklusiv/exklusiv-Regel.
  • Eine vorgerückte Fake-Uhr entfernt abgelaufene Einträge auch ohne neues Ereignis.
  • Getrennte Ereignisbuckets beeinflussen einander nicht.

Selbst ausprobieren

Formuliere die erste Prüfaussage als fehlschlagenden Test, implementiere die kleinste Korrektur und ergänze einen Grenzfall.

Einträge genau an der Fenstergrenze folgen der dokumentierten inklusiv/exklusiv-Regel.

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

  • Timestamp-Listen sind exakt, benötigen bei hohem Volumen jedoch viel Speicher.
  • Zeit-Buckets sparen Speicher und liefern dafür nur angenäherte Grenzen.
  • Lazy Cleanup vermeidet Timer, verlagert die Arbeit aber auf Lesezugriffe.
Wichtig

Zähler betreffen das konfigurierte Fenster, nicht die gesamte Historie. Speicherbedarf wächst mit den Ereignissen im Fenster.

08 · Weiterdenken

Quellcode und verwandte Ideen

yarn tsx packages/stats-tracker/examples/basic.ts