nx_trace_emit.nx
buildroot/runtime/nx_trace_emit.nx
about
nx_trace_emit.nx -- OpenTelemetry-style span emission for the
substrate. Cures the black-box critique: every decision becomes
one line of tail-able JSONL.
2025-2026 LLM-observability consensus (LangWatch / Phoenix /
Helicone): OpenTelemetry-native traces with nested spans per
decision, trace_id + session_id linking sibling operations. We
emit a deliberately small JSON shape so this works without an
external trace collector:
{"trace":T,"span":S,"parent":P,"kind":K,"start_ms":A,"end_ms":B,
"attrs":{"k0":v0,"k1":v1,...}}
Fields are written using direct sys_write to a configured fd.
Default fd = 2 (stderr) so the host process can pipe traces to
a log file without interfering with stdout (which generators may
still use for image bytes / prompts / etc.). Per-trace fd is
settable via NX_TRACE_FD (sealed below).
genealogy_id: opentelemetry_traces + langwatch_2025
lineage_id: substrate_native_trace_v1
dependencies 3 imports · 7 importers
imports: nx_syscalls.nxnx_runtime.nxnx_tier.nx
imported by: nx_batch_audit_sidecar.nxnx_batch_audit_sidecar_test.nxnx_dashboard.nxnx_dashboard_test.nxnx_trace_emit_test.nxnx_trace_query.nxnx_trace_query_test.nx
structs
| 70 | struct TraceCfg |
consts
| 38 | const NX_SPAN_BATCH_OPEN: nx_int = 0 // top-level batch root |
| 39 | const NX_SPAN_ARC_PICK: nx_int = 1 |
| 40 | const NX_SPAN_OUTFIT_PICK: nx_int = 2 |
| 41 | const NX_SPAN_LOCATION_PICK: nx_int = 3 |
| 42 | const NX_SPAN_POSE_PICK: nx_int = 4 |
| 43 | const NX_SPAN_AFFECT_PICK: nx_int = 5 |
| 44 | const NX_SPAN_CAMERA_PICK: nx_int = 6 |
| 45 | const NX_SPAN_RENDER_EMIT: nx_int = 7 |
| 46 | const NX_SPAN_VERIFY_COMMIT: nx_int = 8 // post-render verdict |
| 47 | const NX_SPAN_CONTINUITY_CHECK: nx_int = 9 |
| 48 | const NX_SPAN_POOL_UTIL: nx_int = 10 |
| 49 | const NX_SPAN_KEYNESS_AUDIT: nx_int = 11 |
| 50 | const NX_SPAN_PROMPT_ASSEMBLE: nx_int = 12 |
| 51 | const NX_SPAN_BATCH_CLOSE: nx_int = 13 |
| 52 | const NX_SPAN_N_KINDS: nx_int = 14 |
| 65 | const NX_TRACE_FD_DEFAULT: nx_int = 2 |
| 66 | const NX_TRACE_FD_MAX: nx_int = 1024 |
| 76 | const NX_TRACECFG_BYTES: nx_int = 24 |
functions
| 54 | func nx_span_kind_is_valid(k: nx_int) -> nx_int |
| 83 | func nx_trace_cfg_alloc() -> *TraceCfg |
| 91 | func nx_trace_set_fd(cfg: *TraceCfg, fd: nx_int) -> nx_int called by 1: main |
| 98 | func nx_trace_disable(cfg: *TraceCfg) -> nx_int |
| 103 | func nx_trace_enable(cfg: *TraceCfg) -> nx_int |
| 115 | func nx_trace_mint_span_id(cfg: *TraceCfg) -> nx_int |
| 126 | func _trace_write_raw(cfg: *TraceCfg, buf: *u8, n: nx_int) -> nx_int calls 1: sys_write |
| 131 | func _trace_write_z(cfg: *TraceCfg, s: *u8) -> nx_int |
| 136 | func _trace_write_i64(cfg: *TraceCfg, n: nx_int) -> nx_int |
| 151 | func nx_trace_emit_span(cfg: *TraceCfg, |
| 188 | func nx_trace_emit_simple(cfg: *TraceCfg, |
| 202 | func nx_trace_emit_one_attr(cfg: *TraceCfg, |