Table of Contents

Class TyphonProfiler

Namespace
Typhon.Engine
Assembly
Typhon.Engine.dll

Static lifecycle façade for the Tracy-style profiler. Manages the consumer drain thread, the per-exporter consume threads, and the exporter list.

public static class TyphonProfiler
Inheritance
TyphonProfiler
Inherited Members

Remarks

Start/Stop semantics: idempotent. Calling Typhon.Engine.TyphonProfiler.Start(Typhon.Engine.IResource,Typhon.Engine.ProfilerSessionMetadata,Typhon.Engine.ProfilerOptions,System.Action) on an already-running profiler is a no-op (does NOT throw). Calling Stop() on a stopped profiler is also a no-op. This avoids brittle test setup and accommodates restart-after-crash patterns.

Producer gate vs lifecycle: Typhon.Engine.TyphonProfiler.Start(Typhon.Engine.IResource,Typhon.Engine.ProfilerSessionMetadata,Typhon.Engine.ProfilerOptions,System.Action) does NOT enable the producer hot path. The producer gate is ProfilerActive, which is set once at TelemetryConfig class load from the config file. If ProfilerActive == false, calling Typhon.Engine.TyphonProfiler.Start(Typhon.Engine.IResource,Typhon.Engine.ProfilerSessionMetadata,Typhon.Engine.ProfilerOptions,System.Action) is harmless but no events will ever be emitted. If ProfilerActive == true, events accumulate in slot ring buffers regardless of whether the profiler is started — until Typhon.Engine.TyphonProfiler.Start(Typhon.Engine.IResource,Typhon.Engine.ProfilerSessionMetadata,Typhon.Engine.ProfilerOptions,System.Action) is called there's just no consumer to drain them, so eventually the producers see drops.

Exporter mutation: AttachExporter(IProfilerExporter)/DetachExporter(IProfilerExporter) are only valid while the profiler is stopped. Attempting to mutate the exporter list while running throws InvalidOperationException — concurrent mutation would race the consumer thread reading the list during fan-out.

Threading model: Start/Stop are serialized on a static lock. The consumer thread runs on its own (managed by Typhon.Engine.Internals.ProfilerConsumerThread's Typhon.Engine.Internals.HighResolutionTimerServiceBase base). One dedicated OS thread per attached exporter runs foreach (batch in exporter.Queue.GetConsumingEnumerable) { ProcessBatch; Release; } until CompleteAdding signals shutdown.

Properties

ActiveSlotCount

Number of slots currently claimed.

public static int ActiveSlotCount { get; }

Property Value

int

FinalDrainPasses

Diagnostic: how many final-drain passes ran before the consumer's AllSlotsEmpty returned true.

public static long FinalDrainPasses { get; }

Property Value

long

FinalDrainPendingBytes

Diagnostic: bytes still pending across all producer rings when the final drain stopped (snapshot at Stop()). Non-zero means tail records were lost.

public static long FinalDrainPendingBytes { get; }

Property Value

long

FinalDrainZeroProgressPasses

Diagnostic: how many final-drain passes drained zero bytes before the loop gave up (snapshot at Stop()).

public static long FinalDrainZeroProgressPasses { get; }

Property Value

long

FirstExporterBatchesProcessed

Diagnostic: batches/records the FIRST attached exporter actually processed (snapshot at Stop).

public static long FirstExporterBatchesProcessed { get; }

Property Value

long

FirstExporterRecordsProcessed

Diagnostic: records the first attached exporter actually processed (snapshot at Stop()).

public static long FirstExporterRecordsProcessed { get; }

Property Value

long

IsRunning

True while the profiler consumer thread is running.

public static bool IsRunning { get; }

Property Value

bool

MainThreadId

Managed thread id of whichever thread called Typhon.Engine.TyphonProfiler.Start(Typhon.Engine.IResource,Typhon.Engine.ProfilerSessionMetadata,Typhon.Engine.ProfilerOptions,System.Action). The host's bootstrap flow is the canonical "main" thread for the viewer. Zero while the profiler is stopped. Read by ThreadSlotRegistry.AssignClaim to tag the corresponding slot's ThreadKind.

public static int MainThreadId { get; }

Property Value

int

SlotStateDump

Diagnostic: multi-line per-slot state dump captured at Stop(), or "(not captured)" when no snapshot was taken.

public static string SlotStateDump { get; }

Property Value

string

SpilloverPoolAcquiredCount

Snapshot of total spillover-buffer acquires across the session, captured at Stop() time. Each acquire corresponds to one chain-extension on a slot's overflow.

public static long SpilloverPoolAcquiredCount { get; }

Property Value

long

SpilloverPoolExhaustedCount

Snapshot of total spillover-pool exhaustions captured at Stop() time — overflow events that found the pool empty and fell back to the drop path. Non-zero means the configured SpilloverBufferCount was undersized for the workload.

public static long SpilloverPoolExhaustedCount { get; }

Property Value

long

TotalBatchesFannedOut

Diagnostic: batches/records the consumer fanned out (snapshot at Stop).

public static long TotalBatchesFannedOut { get; }

Property Value

long

TotalDroppedEvents

Total events dropped across all slots due to ring-buffer overflow.

public static long TotalDroppedEvents { get; }

Property Value

long

TotalDroppedExporterBatches

Snapshot of total exporter-queue drops captured at Stop() time (before the exporter list is cleared). Non-zero means the consumer produced batches faster than the exporter could drain them — events made it past the producer ring but didn't reach the sink (file / TCP wire). Distinct from TotalDroppedEvents which is producer-side ring overflow. Read AFTER Stop() for post-mortem diagnostics.

public static long TotalDroppedExporterBatches { get; }

Property Value

long

TotalRecordsFannedOut

Diagnostic: total records the consumer fanned out to exporters (snapshot at Stop()).

public static long TotalRecordsFannedOut { get; }

Property Value

long

Methods

AttachExporter(IProfilerExporter)

Attach an exporter. Must be called before Typhon.Engine.TyphonProfiler.Start(Typhon.Engine.IResource,Typhon.Engine.ProfilerSessionMetadata,Typhon.Engine.ProfilerOptions,System.Action) — attaching while running throws.

public static void AttachExporter(IProfilerExporter exporter)

Parameters

exporter IProfilerExporter

DetachExporter(IProfilerExporter)

Detach an exporter. Must be called while the profiler is stopped. Returns true if the exporter was found and removed.

public static bool DetachExporter(IProfilerExporter exporter)

Parameters

exporter IProfilerExporter

Returns

bool

Stop()

Stop the profiler. Performs a final drain pass, signals all exporter queues to complete, joins all threads, then calls Flush() + Dispose() on each attached exporter. Idempotent.

public static void Stop()