Zum Inhalt springen
Deutsch

Recording-Tracer

RecordingTracer ist das Test-Pendant zu OtelTracerAdapter. Anstatt Spans zu exportieren, speichert er sie im Speicher — Tests asserten auf die aufgezeichneten Spans.

import { TestKit, RecordingTracer, TracingExtensionId } from 'actor-ts';
const tracer = new RecordingTracer();
const tk = TestKit.create();
tk.system.extension(TracingExtensionId).configure({ tracer });
// ... Actor ausführen ...
ref.tell({ kind: 'process' });
await probe.expectMsg(...);
// Auf aufgezeichnete Spans asserten:
const spans = tracer.recordedSpans();
expect(spans).toHaveLength(1);
expect(spans[0].name).toBe('actor.receive');
expect(spans[0].attributes['actor.path']).toContain('worker');

Jeder RecordedSpan:

interface RecordedSpan {
name: string;
context: SpanContext;
parent?: SpanContext;
attributes: Record<string, AttributeValue>;
events: Array<{ name: string; attrs: ... }>;
status: { status: 'ok' | 'error'; message?: string };
startTimeMs: number;
endTimeMs: number;
ended: boolean;
kind: SpanKind;
}

Du siehst, welche Attribute gesetzt wurden, wann der Span gestartet + beendet wurde, seine Art, seinen Parent (zum Verifizieren von Kausalitätsketten) und seinen Endstatus.

class RecordingTracer implements Tracer {
// ... volles Tracer-Interface ...
recordedSpans(): RecordedSpan[]; // alle Spans, inkl. unbeendeter
finishedSpans(): RecordedSpan[]; // Spans, bei denen end() aufgerufen wurde
reset(): void; // aufgezeichneten Zustand leeren
}

recordedSpans gibt jeden Span zurück, den der Tracer erzeugen sollte. finishedSpans filtert auf die, die beendet wurden — nützlich, um „Span gestartet und nie beendet”-Bugs zu erkennen.

„Hat das Framework die Nachricht dieses Actors auto-gespan’d?”

Abschnitt betitelt „„Hat das Framework die Nachricht dieses Actors auto-gespan’d?”“
ref.tell({ kind: 'work' });
await probe.expectMsg(...);
const spans = tracer.finishedSpans();
const receive = spans.find(s => s.name === 'actor.receive' && s.attributes['actor.path']?.includes('worker'));
expect(receive).toBeDefined();
expect(receive!.status.status).toBe('ok');

„Hat mein Custom-Span mit den richtigen Attributen gefeuert?”

Abschnitt betitelt „„Hat mein Custom-Span mit den richtigen Attributen gefeuert?”“
const orderSpan = tracer.finishedSpans().find(s => s.name === 'place-order');
expect(orderSpan).toBeDefined();
expect(orderSpan!.attributes['order.id']).toBe('o-1');
expect(orderSpan!.attributes['order.amount']).toBe(42);
const spans = tracer.finishedSpans();
const parent = spans.find(s => s.name === 'http-request');
const child = spans.find(s => s.name === 'db-query');
expect(child!.parent?.traceId).toBe(parent!.context.traceId);

Nützlich zum Verifizieren der Trace-Kausalität — Parent- Kontext korrekt an Child-Spans propagiert.

beforeEach(() => tracer.reset());

Ohne Reset akkumulieren aufgezeichnete Spans über Tests hinweg. Reset bei jedem Test, um Assertions nur auf die Spans des aktuellen Tests zu halten.

Aufzeichnen ist billig — Anhängen an ein Array. Aber Spans akkumulieren im Speicher. Bei langen Test-Läufen periodisch reset, um Speicher-Wachstum zu vermeiden.

  • Tracer-API — das Interface, das dies implementiert.
  • OTel-Adapter — die Produktions-Alternative.
  • Actor-Tracing — was das Framework auto-span’d, beobachtbar via diesen Tracer.
  • TestKit — kombiniere mit dem Recording-Tracer für assertions-freundliche Tests.

Die RecordingTracer-API- Referenz deckt die volle Oberfläche ab.