Custom Application-Defined Spans
A reserved wire-format span kind for app-defined names, designed to nest into the profiler flame graph โ not yet callable from application code.
Status: ๐ Planned ยท Visibility: Public ยท Level: ๐ฃ Advanced ยท Category: Profiler
๐ฏ What it solves
Application code often has its own hot paths โ a save pipeline step, a custom job, a request handler โ that a developer wants to see in the same flame graph as Typhon's built-in transaction/B+Tree/page-cache spans, without Typhon engine changes for every new span name. Today only Typhon's own instrumented call sites emit spans; there is no supported way for host application code to add its own span into the same trace.
โ๏ธ How it works (in brief)
The wire format reserves a span kind for exactly this purpose: TraceEventKind.NamedSpan (wire ID 246) carries an
inline UTF-8 name instead of a fixed typed payload, and the trace file / sidecar cache formats both support an
optional trailing name-intern table (SpanNameTable section, magic "SPAN") so repeated names aren't re-written in
full on every span. That plumbing exists on the read/replay side (Typhon.Profiler library reads and replays a
SpanNameTable if one is present). What's missing is the producer half: no factory on TyphonEvent mints a
NamedSpan record from an app-supplied string today.
๐ป Usage
Not implemented โ no factory exists yet, so nothing below compiles against the current engine.
// Illustrative only โ not a real/current Typhon API. TyphonEvent has no BeginNamedSpan/EmitNamedSpan
// factory today. This is the shape the design docs describe, but it does not exist in source.
// using var scope = TyphonEvent.BeginNamedSpan("MyCustomSpan");
// ... app-specific work ...
โ ๏ธ Guarantees & limits
- Not implemented.
src/Typhon.Engine/Profiler/internals/TyphonEvent.csโ the producer surface every other span factory (BeginBTreeInsert,BeginTransactionCommit, etc.) lives on โ has noBeginNamedSpanorEmitNamedSpanmethod.Typhon.Generators.TraceEventGeneratorhas no NamedSpan-specific codegen either. The only reference toTraceEventKind.NamedSpaninsrc/Typhon.Engineortest/is a single entry in an enum-exhaustiveness suppression test (TyphonEventKindSuppressionTests.cs) โ there is no producer call site anywhere in the codebase. - The wire slot is reserved and stable:
TraceEventKind.NamedSpan = 246in the current.typhon-traceformat (v8+). It was200until 2026-05-10, when it was found to collide withEcsQueryMaskAndand was reassigned; v7 traces carrying a kind-200NamedSpanrecord are unaffected (older format), but the two kinds are indistinguishable under the pre-fix numbering. - The
SpanNameTableintern-table format exists only in the file writer/reader and sidecar-cache writer/reader (Typhon.Profiler); it is populated by replaying a table that was already in a source file, never by the engine's ownFileExporter, which never constructs one. - The Workbench viewer's chunk decoder recognizes kind
246but falls back to a generic span decode โ the interned name is not surfaced on the server DTO or rendered distinctly in the UI today. claude/design/Profiler/typhon-profiler.mdandclaude/design/Profiler/profiler-user-manual.mdboth describe aTyphonEvent.BeginNamedSpan(string)factory as if already usable, at wire kind200. Both statements are stale against current source โ treat those sections as a design target, not a working API, until this feature is built.
๐ Related
- Sibling: Built-in Engine Instrumentation Catalog โ the engine-side equivalent this app-defined span kind is designed to parallel
- Sibling: Typed-Event Capture Pipeline โ the producer surface (
TyphonEvent) a futureBeginNamedSpanfactory would extend - Source:
src/Typhon.Profiler/TraceEventKind.cs(NamedSpan = 246),src/Typhon.Profiler/TraceFileWriter.cs,TraceFileCacheWriter.cs/TraceFileCacheReader.cs(SpanNameTableplumbing)