Struct TraceFileHeader
Version-stamped header at the start of a .typhon-trace file. Contains session-wide metadata that lets the viewer decode the record stream
that follows. The on-disk size grows with the format version as trailer-offset fields are appended — readers parse it version-conditionally.
public struct TraceFileHeader
- Inherited Members
Remarks
Version 3 (Tracy-style typed-event rewrite): file format uses variable-size self-describing records instead of a fixed 64 B struct. Block layout is size-prefixed records, LZ4-compressed per block. Older v1/v2 files are unreadable — the viewer and all tooling are updated in lockstep.
Fields
ArchetypeCount
Number of archetypes in the archetype table.
public ushort ArchetypeCount
Field Value
BaseTickRate
Target tick rate in Hz (e.g., 60.0 for 60 fps).
public float BaseTickRate
Field Value
ComponentTypeCount
Number of component types in the component type table.
public ushort ComponentTypeCount
Field Value
CpuSampleSectionOffset
Byte offset of the trailing CpuSampleSection (interned CPU stack samples captured by the in-process EventPipe sampler, #351). 0 when
absent — no CPU sampling companion, or the parse produced nothing. v9 and earlier traces lack this on-disk field; the reader defaults it to 0.
public long CpuSampleSectionOffset
Field Value
CreatedUtcTicks
UTC timestamp when the trace was started (DateTime.UtcNow.Ticks).
public long CreatedUtcTicks
Field Value
CurrentVersion
Current format version.
v3: variable-size typed-record layout (Tracy-style profiler rewrite).
v4: ThreadInfo records gained the trailing ThreadKind byte (#289 follow-up).
v5: trailer carries FileTable + SourceLocationManifest at offsets in the header
(#302 — profiler source attribution). Reader accepts v4 files transparently — their new offset fields
are absent in the on-disk header (51 bytes vs 71) and default to 0, which downstream readers interpret
as "no source-location manifest".
v6: SystemDefinitionTable carries RFC 07 access declarations (Phase, Reads, ReadsFresh,
ReadsSnapshot, AdditionalReads, Writes, SideWrites, ReadsEvents, WritesEvents, ReadsResources,
WritesResources, ExplicitAfter, ExplicitBefore, IsExclusivePhase). New PhasesTable section follows
ComponentTypeTable, listing the RuntimeOptions.Phases names in order. Reader accepted v5 files
transparently — RFC 07 fields default to empty arrays and PhasesTable was treated as absent.
v7: rich static-structure tables follow PhasesTable so offline analysis (Workbench schema panels
against trace sessions) has the same data a live engine offers — component definitions with full field
layout, archetype definitions with parent/child + slot map + cluster info, index catalog, runtime config,
event-queue catalog, and a resource-graph snapshot. v6 readers simply lacked the data; rather than
synthesising empty defaults (which would silently render "no schema" for old traces), the reader now
hard-rejects v6 — re-record against a v7-aware build. See the section writers in TraceFileWriter
and the matching reader methods in TraceFileReader.
v8 (2026-05-10): NamedSpan reassigned from value 200 to 246 to break a
latent collision with EcsQueryMaskAnd. v7 traces with NamedSpan records (kind=200)
would mis-decode as EcsQueryMaskAnd under a v8 reader; the reader hard-rejects v7 to surface the break loudly.
Re-record against a v8-aware build.
v9 (2026-05-11): Query Definition Export (#342). Adds two trailing sections:
QuerySourceStringTable (deduped file paths + method names referenced by query events)
at offset QuerySourceStringTableOffset, and QueryDefinitionTable
(materialized definitions accumulated from QueryDefinitionDescribe
events) at offset QueryDefinitionTableOffset. Adds two new instant kinds —
QueryDefinitionDescribe (247) and QueryArgs (248)
— and extends QueryPlan with 5 trailing fields
(QueryInstanceKind, QueryInstanceLocalId, ExecutionSourceFileId, ExecutionSourceLine,
ExecutionSourceMethodId). v8 traces continue to load: absent sections produce empty catalogs;
v8 QueryPlan records (without the trailing fields) decode with zero/sentinel defaults for the
new fields. See claude/design/Profiler/11-query-definition-export.md.
v10 (2026-05-16): CPU Sampling Integration (#351). Adds one trailing section,
CpuSampleSection (interned CPU stack samples from the in-process EventPipe sampler) at offset
CpuSampleSectionOffset. v9 and earlier traces continue to load — the absent on-disk
field defaults to 0, which downstream readers interpret as "no CPU samples".
See claude/design/Profiler/11-cpu-sampling-integration.md.
v11 (2026-05-17): Track→DAG partitioning hierarchy (#354). SystemDefinitionTable records gain a DagId
field; the global PhasesTable is replaced by a TracksTable + DagsTable (each DAG carries its own
ordered phase names). RuntimeConfigRecord drops Phases/DefaultPhase. v10-and-older traces are
hard-rejected (layout-breaking SystemDefinitionTable change).
v12 (2026-07-31): Self-describing captures (#614) — one revision covering four decisions of
claude/design/Apps/Workbench/10-database-and-profiles.md. D-2: the header gains DatabaseId,
DatabaseName and the TsnMin/TsnMax window, so a capture names the database it ran against instead of
leaving the pairing to inference. D-3: RoutingId is added to the archetype table, giving every event's
per-process catalog id a path to the database's durable identity — see the §5.3 warning on ArchetypeRecord. D-5:
DurationTicks, TickCount and SchemaFingerprint join the existing CreatedUtcTicks so a list
of captures renders from headers alone, with no sidecar cache built per row. D-9: Flags gains
MultipleEnginesObserved. v11-and-older traces are hard-rejected — the ArchetypeTable layout change would otherwise
mis-decode silently, which is precisely the class of bug this revision exists to close.
public const ushort CurrentVersion = 12
Field Value
DagCount
Number of DAGs in the DAGs table (v11+).
public ushort DagCount
Field Value
DatabaseId
Durable identity of the database this capture ran against (DatabaseEngine.DatabaseId), or Empty when the profiler ran with no
engine attached. Survives the bundle being moved, renamed or restored — co-location is not provenance, so the trace records what it saw rather than
relying on where it happens to sit (design D-2 / D-1).
public Guid DatabaseId
Field Value
DatabaseName
The database's bundle name ({name}.typhon without the extension), UTF-8, zero-padded, truncated to Length bytes.
Empty when no engine was attached. Present so a trace opened outside its bundle still says something a human can act on — DatabaseId alone
is the identity, but a GUID is not a readable answer to "which database is this?".
public TraceDatabaseName DatabaseName
Field Value
DurationTicks
Wall-clock length of the capture in Stopwatch ticks (divide by TimestampFrequency for seconds). Patched in at close.
public long DurationTicks
Field Value
FileTableOffset
Byte offset of the trailing FileTable (interned source-file paths). 0 when no source-location manifest was written
(e.g., the source-attribution generator emitted nothing). See claude/design/Profiler/10-profiler-source-attribution.md §4.6.
public long FileTableOffset
Field Value
Flags
Flags (reserved for future use).
public ushort Flags
Field Value
Magic
File magic: ASCII "TYTR" (0x52_54_59_54 little-endian).
public uint Magic
Field Value
MagicValue
File magic constant: ASCII "TYTR".
public const uint MagicValue = 1381259604
Field Value
QueryDefinitionTableOffset
Byte offset of the trailing QueryDefinitionTable (materialized definition catalog accumulated
from QueryDefinitionDescribe events, #342). 0 when absent. v8 reader compat:
pre-v9 traces lack this on-disk field; the reader defaults it to 0.
public long QueryDefinitionTableOffset
Field Value
QuerySourceStringTableOffset
Byte offset of the trailing QuerySourceStringTable (deduped file paths + method names referenced by
Query Definition Export events, #342). 0 when no Query Definition Export sections were written
(e.g., the session emitted no QueryDefinitionDescribe events). v8 traces have this field absent on disk
(the on-disk header pre-v9 ends after SourceLocationManifestOffset) and the reader
fills it with 0.
public long QuerySourceStringTableOffset
Field Value
Reserved0
Padding to keep on-disk layout future-extension-friendly. Zero-initialized; readers must ignore.
public ushort Reserved0
Field Value
Reserved1
Padding (aligning the next field to 4 bytes); zero-initialized.
public ushort Reserved1
Field Value
SamplingSessionStartQpc
Stopwatch.GetTimestamp() captured when the host's EventPipe CPU-sampling session started, or 0 if no sampling companion is
attached to this trace. The viewer correlates .nettrace CPU samples into the flame graph by mapping their relative milliseconds
against this anchor in the same TimestampFrequency time base the record stream uses.
public long SamplingSessionStartQpc
Field Value
SchemaFingerprint
Order-independent 64-bit digest of the schema the capture ran against — FNV-1a over the ordinal-sorted (name, revision) pairs of every component
and archetype. Equal fingerprints mean the schemas match; unequal means consult the database's SchemaHistoryR1 for what actually moved. 0 when no
engine was attached.
public ulong SchemaFingerprint
Field Value
SourceLocationManifestOffset
Byte offset of the trailing SourceLocationManifest (id → file/line/method/kind table). 0 when absent.
Bound to a non-zero FileTableOffset when the trace carries source attribution.
public long SourceLocationManifestOffset
Field Value
SystemCount
Number of systems in the DAG.
public ushort SystemCount
Field Value
TickCount
Number of runtime ticks the capture spans. Patched in at close; 0 when the capture ran without a scheduler.
public uint TickCount
Field Value
TimestampFrequency
Stopwatch.Frequency — needed to convert timestamp ticks to real time.
public long TimestampFrequency
Field Value
TrackCount
Number of tracks in the tracks table (v11+).
public ushort TrackCount
Field Value
TsnMax
The engine's next-free TSN sampled when the capture closed. Patched in at close. 0 when no engine was attached. See TsnMin.
public long TsnMax
Field Value
TsnMin
The engine's next-free TSN sampled when the capture started. With TsnMax this bounds the transaction window the capture covers, and is the left-hand side of the drift readout ("this profile is N transactions behind the database"). 0 when no engine was attached.
public long TsnMin
Field Value
Remarks
This is the engine's global TSN counter, not a min over emitted events — a deliberate superset. It costs nothing on the hot path (two reads of an
existing counter) and it is the exact quantity the drift measure compares against the database's persisted NextFreeTSN.
Version
Format version. See CurrentVersion for the current value and an evolution log.
public ushort Version
Field Value
WorkerCount
Number of worker threads in the DagScheduler.
public byte WorkerCount
Field Value
Properties
MultipleEnginesObserved
True when MultipleEnginesObserved is set — routing ids in this trace are absent, not merely suspect.
public bool MultipleEnginesObserved { get; }
Property Value
Methods
GetDatabaseName()
Decodes DatabaseName to a string, stopping at the first NUL. Returns an empty string when no name was recorded.
public string GetDatabaseName()
Returns
SetDatabaseName(string)
Encodes name into DatabaseName, truncating on a UTF-8 character boundary if it does not fit. Truncating a display name
is harmless; splitting a multi-byte sequence would produce a mojibake name in the profiles list, so the encoder is asked not to.
public void SetDatabaseName(string name)
Parameters
namestring