@smoothbricks/lmao 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (276) hide show
  1. package/dist/allocator.wasm +0 -0
  2. package/dist/index.d.ts +1 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +1 -0
  5. package/dist/lib/JsBufferStrategy.d.ts +4 -3
  6. package/dist/lib/JsBufferStrategy.d.ts.map +1 -1
  7. package/dist/lib/JsBufferStrategy.js +18 -11
  8. package/dist/lib/arrow/lease.d.ts +10 -0
  9. package/dist/lib/arrow/lease.d.ts.map +1 -0
  10. package/dist/lib/arrow/lease.js +33 -0
  11. package/dist/lib/arrow/utils.d.ts +3 -4
  12. package/dist/lib/arrow/utils.d.ts.map +1 -1
  13. package/dist/lib/arrow/utils.js +12 -13
  14. package/dist/lib/arrow/vocabularyDictionary.d.ts +21 -0
  15. package/dist/lib/arrow/vocabularyDictionary.d.ts.map +1 -0
  16. package/dist/lib/arrow/vocabularyDictionary.js +95 -0
  17. package/dist/lib/bufferStrategy.d.ts +3 -2
  18. package/dist/lib/bufferStrategy.d.ts.map +1 -1
  19. package/dist/lib/cloudflare/traceRows.d.ts.map +1 -1
  20. package/dist/lib/cloudflare/traceRows.js +3 -2
  21. package/dist/lib/codegen/evaluatorGenerator.d.ts.map +1 -1
  22. package/dist/lib/codegen/evaluatorGenerator.js +12 -11
  23. package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts +44 -82
  24. package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts.map +1 -1
  25. package/dist/lib/codegen/fixedPositionWriterGenerator.js +223 -162
  26. package/dist/lib/codegen/spanLoggerClosureMaterializer.d.ts +63 -0
  27. package/dist/lib/codegen/spanLoggerClosureMaterializer.d.ts.map +1 -0
  28. package/dist/lib/codegen/spanLoggerClosureMaterializer.js +447 -0
  29. package/dist/lib/codegen/spanLoggerGenerator.d.ts +36 -19
  30. package/dist/lib/codegen/spanLoggerGenerator.d.ts.map +1 -1
  31. package/dist/lib/codegen/spanLoggerGenerator.js +164 -158
  32. package/dist/lib/convertToArrow.d.ts +7 -2
  33. package/dist/lib/convertToArrow.d.ts.map +1 -1
  34. package/dist/lib/convertToArrow.js +499 -285
  35. package/dist/lib/defineOpContext.js +1 -1
  36. package/dist/lib/enumMetadata.d.ts +19 -0
  37. package/dist/lib/enumMetadata.d.ts.map +1 -0
  38. package/dist/lib/enumMetadata.js +86 -0
  39. package/dist/lib/flushScheduler.d.ts.map +1 -1
  40. package/dist/lib/flushScheduler.js +13 -4
  41. package/dist/lib/library.d.ts +16 -98
  42. package/dist/lib/library.d.ts.map +1 -1
  43. package/dist/lib/library.js +32 -525
  44. package/dist/lib/logBinding.d.ts +21 -27
  45. package/dist/lib/logBinding.d.ts.map +1 -1
  46. package/dist/lib/op.d.ts +30 -30
  47. package/dist/lib/op.d.ts.map +1 -1
  48. package/dist/lib/op.js +15 -22
  49. package/dist/lib/opContext/createOpGroup.d.ts +1 -1
  50. package/dist/lib/opContext/createOpGroup.d.ts.map +1 -1
  51. package/dist/lib/opContext/createOpGroup.js +22 -29
  52. package/dist/lib/opContext/defineOp.d.ts +4 -4
  53. package/dist/lib/opContext/defineOp.d.ts.map +1 -1
  54. package/dist/lib/opContext/defineOp.js +53 -10
  55. package/dist/lib/opContext/opGroupTypes.d.ts +2 -2
  56. package/dist/lib/opContext/opTypes.d.ts +1 -1
  57. package/dist/lib/opContext/opTypes.d.ts.map +1 -1
  58. package/dist/lib/opContext/spanContextTypes.d.ts +29 -14
  59. package/dist/lib/opContext/spanContextTypes.d.ts.map +1 -1
  60. package/dist/lib/opContext/types.d.ts +4 -4
  61. package/dist/lib/opContext/types.d.ts.map +1 -1
  62. package/dist/lib/physicalLayoutPlan.d.ts +89 -0
  63. package/dist/lib/physicalLayoutPlan.d.ts.map +1 -0
  64. package/dist/lib/physicalLayoutPlan.js +442 -0
  65. package/dist/lib/resolveMessage.d.ts +9 -0
  66. package/dist/lib/resolveMessage.d.ts.map +1 -0
  67. package/dist/lib/resolveMessage.js +63 -0
  68. package/dist/lib/result.d.ts +5 -7
  69. package/dist/lib/result.d.ts.map +1 -1
  70. package/dist/lib/result.js +19 -26
  71. package/dist/lib/runtimeHint.d.ts +35 -0
  72. package/dist/lib/runtimeHint.d.ts.map +1 -0
  73. package/dist/lib/runtimeHint.js +79 -0
  74. package/dist/lib/schema/types.d.ts +1 -1
  75. package/dist/lib/schema/types.d.ts.map +1 -1
  76. package/dist/lib/span-buffer/aot/v1.d.ts +2 -0
  77. package/dist/lib/span-buffer/aot/v1.d.ts.map +1 -0
  78. package/dist/lib/span-buffer/aot/v1.js +24 -0
  79. package/dist/lib/spanBuffer.d.ts +33 -4
  80. package/dist/lib/spanBuffer.d.ts.map +1 -1
  81. package/dist/lib/spanBuffer.js +583 -91
  82. package/dist/lib/spanBufferStats.d.ts +1 -1
  83. package/dist/lib/spanBufferStats.d.ts.map +1 -1
  84. package/dist/lib/spanContext.d.ts +27 -51
  85. package/dist/lib/spanContext.d.ts.map +1 -1
  86. package/dist/lib/spanContext.js +822 -344
  87. package/dist/lib/sqlite/sqlite-common.d.ts.map +1 -1
  88. package/dist/lib/sqlite/sqlite-common.js +20 -21
  89. package/dist/lib/testing/bun-harness.d.ts +8 -3
  90. package/dist/lib/testing/bun-harness.d.ts.map +1 -1
  91. package/dist/lib/testing/bun-harness.js +30 -18
  92. package/dist/lib/testing/extractFacts.d.ts +1 -1
  93. package/dist/lib/testing/extractFacts.d.ts.map +1 -1
  94. package/dist/lib/testing/extractFacts.js +55 -63
  95. package/dist/lib/testing/facts.d.ts +1 -1
  96. package/dist/lib/testing/facts.d.ts.map +1 -1
  97. package/dist/lib/testing/queryable-span.d.ts +1 -1
  98. package/dist/lib/testing/queryable-span.d.ts.map +1 -1
  99. package/dist/lib/testing/queryable-span.js +26 -28
  100. package/dist/lib/testing/span-query.d.ts.map +1 -1
  101. package/dist/lib/testing/span-query.js +19 -22
  102. package/dist/lib/testing/stdio-replay.d.ts.map +1 -1
  103. package/dist/lib/testing/stdio-replay.js +19 -8
  104. package/dist/lib/threadId.d.ts.map +1 -1
  105. package/dist/lib/threadId.js +6 -3
  106. package/dist/lib/traceRoot.d.ts +30 -8
  107. package/dist/lib/traceRoot.d.ts.map +1 -1
  108. package/dist/lib/traceRoot.es.d.ts +17 -15
  109. package/dist/lib/traceRoot.es.d.ts.map +1 -1
  110. package/dist/lib/traceRoot.es.js +68 -34
  111. package/dist/lib/traceRoot.js +11 -0
  112. package/dist/lib/traceRoot.node.d.ts +17 -19
  113. package/dist/lib/traceRoot.node.d.ts.map +1 -1
  114. package/dist/lib/traceRoot.node.js +66 -38
  115. package/dist/lib/traceTopology.d.ts +42 -0
  116. package/dist/lib/traceTopology.d.ts.map +1 -0
  117. package/dist/lib/traceTopology.js +260 -0
  118. package/dist/lib/tracer.d.ts +9 -5
  119. package/dist/lib/tracer.d.ts.map +1 -1
  120. package/dist/lib/tracer.js +65 -71
  121. package/dist/lib/tracers/ArrayQueueTracer.d.ts +1 -1
  122. package/dist/lib/tracers/ArrayQueueTracer.js +1 -1
  123. package/dist/lib/tracers/StdioTracer.d.ts.map +1 -1
  124. package/dist/lib/tracers/StdioTracer.js +15 -13
  125. package/dist/lib/tracers/TestTracer.d.ts +4 -6
  126. package/dist/lib/tracers/TestTracer.d.ts.map +1 -1
  127. package/dist/lib/tracers/TestTracer.js +6 -8
  128. package/dist/lib/types.d.ts +49 -32
  129. package/dist/lib/types.d.ts.map +1 -1
  130. package/dist/lib/vocabularyRegistry.d.ts +25 -0
  131. package/dist/lib/vocabularyRegistry.d.ts.map +1 -0
  132. package/dist/lib/vocabularyRegistry.js +372 -0
  133. package/dist/lib/wasm/WasmBufferStrategy.d.ts +6 -10
  134. package/dist/lib/wasm/WasmBufferStrategy.d.ts.map +1 -1
  135. package/dist/lib/wasm/WasmBufferStrategy.js +44 -37
  136. package/dist/lib/wasm/wasmAllocator.d.ts +27 -22
  137. package/dist/lib/wasm/wasmAllocator.d.ts.map +1 -1
  138. package/dist/lib/wasm/wasmAllocator.js +66 -44
  139. package/dist/lib/wasm/wasmPhysicalLayout.d.ts +67 -0
  140. package/dist/lib/wasm/wasmPhysicalLayout.d.ts.map +1 -0
  141. package/dist/lib/wasm/wasmPhysicalLayout.js +179 -0
  142. package/dist/lib/wasm/wasmSpanBuffer.d.ts +79 -31
  143. package/dist/lib/wasm/wasmSpanBuffer.d.ts.map +1 -1
  144. package/dist/lib/wasm/wasmSpanBuffer.js +442 -272
  145. package/dist/lib/wasm/wasmTraceRoot.d.ts +24 -22
  146. package/dist/lib/wasm/wasmTraceRoot.d.ts.map +1 -1
  147. package/dist/lib/wasm/wasmTraceRoot.js +110 -71
  148. package/dist/vocabulary/register/v1.d.ts +2 -0
  149. package/dist/vocabulary/register/v1.d.ts.map +1 -0
  150. package/dist/vocabulary/register/v1.js +1 -0
  151. package/dist/wasm.d.ts +5 -0
  152. package/dist/wasm.d.ts.map +1 -0
  153. package/dist/wasm.js +4 -0
  154. package/package.json +54 -6
  155. package/src/index.ts +1 -0
  156. package/src/lib/JsBufferStrategy.ts +27 -9
  157. package/src/lib/__tests__/arrow-builder-integration/arrow-conversion.test.ts +335 -37
  158. package/src/lib/__tests__/arrow-builder-integration/binary-arrow-conversion.test.ts +97 -26
  159. package/src/lib/__tests__/arrow-builder-integration/binary-comparison.test.ts +75 -15
  160. package/src/lib/__tests__/arrow-builder-integration/binary-format-compliance.test.ts +30 -6
  161. package/src/lib/__tests__/arrow-builder-integration/buffer-chaining.test.ts +18 -21
  162. package/src/lib/__tests__/arrow-builder-integration/foundation.test.ts +5 -2
  163. package/src/lib/__tests__/arrow-builder-integration/integration.test.ts +25 -7
  164. package/src/lib/__tests__/arrow-builder-integration/lazy-columns.test.ts +3 -2
  165. package/src/lib/__tests__/buffer-overflow.test.ts +24 -18
  166. package/src/lib/__tests__/capability-span-context.test.ts +505 -0
  167. package/src/lib/__tests__/capacity-tuning.test.ts +5 -3
  168. package/src/lib/__tests__/eager-columns.test.ts +345 -0
  169. package/src/lib/__tests__/enum-metadata-aot.test.ts +153 -0
  170. package/src/lib/__tests__/enum-metadata.test.ts +177 -0
  171. package/src/lib/__tests__/fixtures/empty-vocabulary-runtime.fixture.ts +15 -0
  172. package/src/lib/__tests__/flushScheduler.test.ts +5 -1
  173. package/src/lib/__tests__/identity-view.property.test.ts +179 -0
  174. package/src/lib/__tests__/library.test.ts +19 -235
  175. package/src/lib/__tests__/message-buffer-families.test.ts +878 -0
  176. package/src/lib/__tests__/nested-library-tasks.test.ts +14 -15
  177. package/src/lib/__tests__/op-metadata.test.ts +1 -1
  178. package/src/lib/__tests__/op-type-safety.test.ts +5 -16
  179. package/src/lib/__tests__/physical-layout-plan.test.ts +333 -0
  180. package/src/lib/__tests__/remap-descriptor-integration.test.ts +381 -0
  181. package/src/lib/__tests__/root-context-construction.test.ts +414 -0
  182. package/src/lib/__tests__/span-auto-runtime.test.ts +386 -0
  183. package/src/lib/__tests__/span-buffer-segment-stats.test.ts +221 -0
  184. package/src/lib/__tests__/span-lifecycle.test.ts +53 -25
  185. package/src/lib/__tests__/spanbuffer-materializer-parity.test.ts +266 -0
  186. package/src/lib/__tests__/sync-async-trace.test.ts +24 -23
  187. package/src/lib/__tests__/tag-writer-aot.test.ts +214 -0
  188. package/src/lib/__tests__/test-helpers.ts +67 -12
  189. package/src/lib/__tests__/threadId.test.ts +62 -0
  190. package/src/lib/__tests__/timestamp.test.ts +221 -93
  191. package/src/lib/__tests__/traceTopology.property.test.ts +383 -0
  192. package/src/lib/__tests__/type-narrowing.test.ts +63 -0
  193. package/src/lib/__tests__/vocabulary-dense-decoding.test.ts +405 -0
  194. package/src/lib/__tests__/vocabularyRegistry.test.ts +313 -0
  195. package/src/lib/arrow/lease.ts +43 -0
  196. package/src/lib/arrow/utils.ts +10 -14
  197. package/src/lib/arrow/vocabularyDictionary.ts +123 -0
  198. package/src/lib/bufferStrategy.ts +9 -1
  199. package/src/lib/cloudflare/traceRows.ts +3 -2
  200. package/src/lib/codegen/__tests__/evaluatorGenerator.test.ts +21 -141
  201. package/src/lib/codegen/__tests__/fixedPositionWriter-parity.test.ts +273 -0
  202. package/src/lib/codegen/__tests__/fixedPositionWriter-uint64.test.ts +61 -34
  203. package/src/lib/codegen/__tests__/nullBitmap.test.ts +33 -37
  204. package/src/lib/codegen/__tests__/spanLoggerGenerator.test.ts +34 -18
  205. package/src/lib/codegen/__tests__/spanLoggerMaterializerParity.test.ts +503 -0
  206. package/src/lib/codegen/evaluatorGenerator.ts +18 -13
  207. package/src/lib/codegen/fixedPositionWriterGenerator.ts +329 -245
  208. package/src/lib/codegen/spanLoggerClosureMaterializer.ts +598 -0
  209. package/src/lib/codegen/spanLoggerGenerator.ts +241 -177
  210. package/src/lib/convertToArrow.ts +598 -311
  211. package/src/lib/defineOpContext.ts +1 -1
  212. package/src/lib/enumMetadata.ts +121 -0
  213. package/src/lib/flushScheduler.ts +11 -5
  214. package/src/lib/library.ts +37 -595
  215. package/src/lib/logBinding.ts +21 -27
  216. package/src/lib/op.ts +75 -18
  217. package/src/lib/opContext/__tests__/retry.test.ts +27 -21
  218. package/src/lib/opContext/createOpGroup.ts +33 -31
  219. package/src/lib/opContext/defineOp.ts +88 -11
  220. package/src/lib/opContext/opGroupTypes.ts +2 -2
  221. package/src/lib/opContext/opTypes.ts +1 -1
  222. package/src/lib/opContext/spanContextTypes.ts +98 -17
  223. package/src/lib/opContext/types.ts +7 -3
  224. package/src/lib/physicalLayoutPlan.ts +598 -0
  225. package/src/lib/resolveMessage.ts +67 -0
  226. package/src/lib/result.ts +20 -33
  227. package/src/lib/runtimeHint.ts +98 -0
  228. package/src/lib/schema/__tests__/featureFlags.test.ts +2 -1
  229. package/src/lib/schema/builder.ts +1 -1
  230. package/src/lib/schema/types.ts +1 -1
  231. package/src/lib/span-buffer/aot/v1.ts +26 -0
  232. package/src/lib/spanBuffer.ts +658 -92
  233. package/src/lib/spanBufferStats.ts +1 -1
  234. package/src/lib/spanContext.ts +1350 -861
  235. package/src/lib/sqlite/sqlite-common.ts +20 -31
  236. package/src/lib/testing/__tests__/topology-traversal.test.ts +174 -0
  237. package/src/lib/testing/__tests__/vitest-harness.test.ts +2 -1
  238. package/src/lib/testing/bun-harness.ts +94 -43
  239. package/src/lib/testing/extractFacts.ts +64 -78
  240. package/src/lib/testing/facts.ts +1 -1
  241. package/src/lib/testing/queryable-span.ts +23 -30
  242. package/src/lib/testing/span-query.ts +16 -20
  243. package/src/lib/testing/stdio-replay.ts +25 -8
  244. package/src/lib/testing/vitest-harness.ts +1 -1
  245. package/src/lib/threadId.ts +6 -3
  246. package/src/lib/traceRoot.es.ts +77 -42
  247. package/src/lib/traceRoot.node.ts +75 -46
  248. package/src/lib/traceRoot.ts +41 -14
  249. package/src/lib/traceTopology.ts +279 -0
  250. package/src/lib/tracer.ts +109 -98
  251. package/src/lib/tracers/ArrayQueueTracer.ts +1 -1
  252. package/src/lib/tracers/StdioTracer.ts +15 -13
  253. package/src/lib/tracers/TestTracer.ts +6 -8
  254. package/src/lib/tracers/__tests__/ArrayQueueTracer.test.ts +15 -10
  255. package/src/lib/tracers/__tests__/TestTracer.test.ts +23 -13
  256. package/src/lib/types.ts +64 -33
  257. package/src/lib/vocabularyRegistry.ts +439 -0
  258. package/src/lib/wasm/WasmBufferStrategy.ts +56 -48
  259. package/src/lib/wasm/__tests__/WasmBufferStrategy.test.ts +215 -11
  260. package/src/lib/wasm/__tests__/allocatorFreeBlockClamp.test.ts +86 -0
  261. package/src/lib/wasm/__tests__/wasm-identity-view.test.ts +311 -0
  262. package/src/lib/wasm/__tests__/wasm-integration.test.ts +417 -44
  263. package/src/lib/wasm/__tests__/wasm-message-buffer-families.test.ts +588 -0
  264. package/src/lib/wasm/__tests__/wasmAllocator.test.ts +100 -668
  265. package/src/lib/wasm/__tests__/wasmSpanBuffer.test.ts +419 -63
  266. package/src/lib/wasm/__tests__/wasmTraceRoot.test.ts +24 -29
  267. package/src/lib/wasm/__tests__/wasmTracer.test.ts.disabled +2 -2
  268. package/src/lib/wasm/wasmAllocator.ts +131 -96
  269. package/src/lib/wasm/wasmPhysicalLayout.ts +309 -0
  270. package/src/lib/wasm/wasmSpanBuffer.ts +597 -341
  271. package/src/lib/wasm/wasmTraceRoot.ts +140 -78
  272. package/src/vocabulary/register/v1.ts +1 -0
  273. package/src/wasm.ts +19 -0
  274. package/src/lib/__tests__/remapped-buffer-view-integration.test.ts +0 -319
  275. package/src/lib/__tests__/remapped-buffer-view.test.ts +0 -635
  276. package/src/lib/wasm/allocator.zig +0 -948
@@ -7,6 +7,7 @@
7
7
  * @module testing/extractFacts
8
8
  */
9
9
 
10
+ import { resolveEntryType, resolveMessage } from '../resolveMessage.js';
10
11
  import type { LogSchema } from '../schema/LogSchema.js';
11
12
  import {
12
13
  ENTRY_TYPE_DEBUG,
@@ -17,8 +18,10 @@ import {
17
18
  ENTRY_TYPE_SPAN_ERR,
18
19
  ENTRY_TYPE_SPAN_EXCEPTION,
19
20
  ENTRY_TYPE_SPAN_OK,
21
+ ENTRY_TYPE_TRACE,
20
22
  ENTRY_TYPE_WARN,
21
23
  } from '../schema/systemSchema.js';
24
+ import { iterateSpanChildren } from '../traceTopology.js';
22
25
  import type { SpanBuffer } from '../types.js';
23
26
  import {
24
27
  createFactArray,
@@ -106,12 +109,17 @@ const DEFAULT_OPTIONS: Required<ExtractFactsOptions> = {
106
109
  tagFields: [],
107
110
  };
108
111
 
112
+ type WalkFrame<T extends LogSchema> = {
113
+ buffer: SpanBuffer<T>;
114
+ children?: Generator<SpanBuffer<T>>;
115
+ };
116
+
109
117
  /**
110
118
  * Extract facts from a SpanBuffer tree.
111
119
  *
112
120
  * Walks the buffer tree depth-first and produces facts for:
113
121
  * - Span lifecycle (started, ok, err, exception)
114
- * - Log entries (info, warn, error, debug)
122
+ * - Log entries (trace, debug, info, warn, error)
115
123
  * - Tag values (from row 0 of each span)
116
124
  * - Scope values (propagated through tree)
117
125
  * - Feature flag accesses
@@ -138,7 +146,29 @@ export function extractFacts<T extends LogSchema>(
138
146
  const opts = { ...DEFAULT_OPTIONS, ...options };
139
147
  const facts: TraceFact[] = [];
140
148
 
141
- walkBuffer(rootBuffer, facts, opts);
149
+ const stack: WalkFrame<T>[] = [{ buffer: rootBuffer }];
150
+ while (stack.length > 0) {
151
+ const frame = stack[stack.length - 1];
152
+ if (!frame) break;
153
+
154
+ if (!frame.children) {
155
+ if (frame.buffer._writeIndex === 0) {
156
+ stack.pop();
157
+ continue;
158
+ }
159
+ enterBuffer(frame.buffer, facts, opts);
160
+ frame.children = iterateSpanChildren(frame.buffer);
161
+ }
162
+
163
+ const next = frame.children.next();
164
+ if (!next.done) {
165
+ stack.push({ buffer: next.value });
166
+ continue;
167
+ }
168
+
169
+ leaveBuffer(frame.buffer, facts, opts);
170
+ stack.pop();
171
+ }
142
172
 
143
173
  return createFactArray(facts);
144
174
  }
@@ -146,112 +176,67 @@ export function extractFacts<T extends LogSchema>(
146
176
  /**
147
177
  * Walk a buffer and its children, extracting facts.
148
178
  */
149
- function walkBuffer<T extends LogSchema>(
179
+ function enterBuffer<T extends LogSchema>(
150
180
  buffer: SpanBuffer<T>,
151
181
  facts: TraceFact[],
152
182
  opts: Required<ExtractFactsOptions>,
153
183
  ): void {
154
- // Span name is in message_values[0] (written by writeSpanStart)
155
- const spanName = buffer.message_values[0];
184
+ const spanName = resolveMessage(buffer, 0) ?? '';
156
185
  const writeIndex = buffer._writeIndex;
186
+ if (writeIndex === 0) return;
157
187
 
158
- if (writeIndex === 0) {
159
- // Empty buffer - no facts to extract
160
- return;
161
- }
162
-
163
- // Always emit span:started as first fact for this span
164
188
  facts.push(spanStarted(spanName));
165
-
166
- // Extract scope facts (from buffer's scope values)
167
189
  if (opts.includeScope && buffer._scopeValues) {
168
190
  for (const [key, value] of Object.entries(buffer._scopeValues)) {
169
- if (value !== undefined && value !== null) {
170
- facts.push(scopeFact(key, String(value)));
171
- }
191
+ if (value !== undefined && value !== null) facts.push(scopeFact(key, String(value)));
172
192
  }
173
193
  }
174
-
175
- // Extract tag facts from row 0 (ctx.tag writes here)
176
- // Also check row 1 (completion row - .with() on ok()/err())
177
- // And rows 2+ (log rows - .with() on log.*)
178
194
  if (opts.includeTags) {
179
- for (let row = 0; row < writeIndex; row++) {
180
- extractTagFacts(buffer, row, facts, opts);
181
- }
195
+ for (let row = 0; row < writeIndex; row++) extractTagFacts(buffer, row, facts, opts);
182
196
  }
183
197
 
184
- // Buffer layout per specs/lmao/01h_entry_types_and_logging_primitives.md:
185
- // - Row 0: span-start (tags overwrite this row's attribute columns)
186
- // - Row 1: span-ok/err/exception (completion status)
187
- // - Row 2+: log entries (info/debug/warn/error), ff entries
188
- const entryTypes = buffer.entry_type;
189
- const messages = buffer.message_values;
190
-
191
- // Process log/ff entries from row 2 onwards
192
198
  for (let row = 2; row < writeIndex; row++) {
193
- const entryType = entryTypes[row];
194
-
199
+ const entryType = resolveEntryType(buffer, row);
195
200
  switch (entryType) {
196
201
  case ENTRY_TYPE_INFO:
197
202
  case ENTRY_TYPE_DEBUG:
198
203
  case ENTRY_TYPE_WARN:
199
- case ENTRY_TYPE_ERROR: {
200
- if (opts.includeLogs) {
201
- const level = entryTypeToLogLevel(entryType);
202
- const rowMessage = messages[row];
203
- const message = typeof rowMessage === 'string' ? rowMessage : '';
204
- facts.push(logFact(level, message));
205
- }
204
+ case ENTRY_TYPE_ERROR:
205
+ case ENTRY_TYPE_TRACE:
206
+ if (opts.includeLogs) facts.push(logFact(entryTypeToLogLevel(entryType), resolveMessage(buffer, row) ?? ''));
206
207
  break;
207
- }
208
-
209
208
  case ENTRY_TYPE_FF_ACCESS:
210
- case ENTRY_TYPE_FF_USAGE: {
211
- if (opts.includeFF) {
212
- extractFFfacts(buffer, row, facts);
213
- }
209
+ case ENTRY_TYPE_FF_USAGE:
210
+ if (opts.includeFF) extractFFfacts(buffer, row, facts);
214
211
  break;
215
- }
216
212
  }
217
213
  }
214
+ }
218
215
 
219
- // Recurse into children BEFORE completing this span
220
- // This maintains the natural execution order in facts
221
- for (const child of buffer._children) {
222
- walkBuffer(child as SpanBuffer<T>, facts, opts);
223
- }
224
-
225
- // Completion status is ALWAYS at row 1 (not last row)
226
- // Row 1 is pre-initialized as span-exception, overwritten by ok()/err()
216
+ function leaveBuffer<T extends LogSchema>(
217
+ buffer: SpanBuffer<T>,
218
+ facts: TraceFact[],
219
+ opts: Required<ExtractFactsOptions>,
220
+ ): void {
221
+ const writeIndex = buffer._writeIndex;
222
+ if (writeIndex === 0) return;
223
+ const spanName = resolveMessage(buffer, 0) ?? '';
227
224
  if (writeIndex >= 2) {
228
- const completionEntryType = entryTypes[1];
229
-
230
- switch (completionEntryType) {
225
+ switch (resolveEntryType(buffer, 1)) {
231
226
  case ENTRY_TYPE_SPAN_OK:
232
227
  facts.push(spanOk(spanName));
233
228
  break;
234
-
235
- case ENTRY_TYPE_SPAN_ERR: {
236
- const errorCode = getErrorCode(buffer, 1);
237
- facts.push(spanErr(spanName, errorCode));
229
+ case ENTRY_TYPE_SPAN_ERR:
230
+ facts.push(spanErr(spanName, getErrorCode(buffer, 1)));
238
231
  break;
239
- }
240
-
241
- case ENTRY_TYPE_SPAN_EXCEPTION: {
242
- const message = getExceptionMessage(buffer, 1);
243
- facts.push(spanException(spanName, message));
232
+ case ENTRY_TYPE_SPAN_EXCEPTION:
233
+ facts.push(spanException(spanName, getExceptionMessage(buffer, 1)));
244
234
  break;
245
- }
246
235
  }
247
236
  }
248
-
249
- // Extract duration metric if requested
250
237
  if (opts.includeMetrics) {
251
238
  const duration = getSpanDuration(buffer);
252
- if (duration !== undefined) {
253
- facts.push(metricFact(`${spanName}:duration_ns`, Number(duration)));
254
- }
239
+ if (duration !== undefined) facts.push(metricFact(`${spanName}:duration_ns`, Number(duration)));
255
240
  }
256
241
  }
257
242
 
@@ -269,7 +254,7 @@ function extractTagFacts<T extends LogSchema>(
269
254
 
270
255
  for (const fieldName of fields) {
271
256
  // Skip system fields
272
- if (fieldName.startsWith('_')) continue;
257
+ if (fieldName === 'message' || fieldName.startsWith('_')) continue;
273
258
 
274
259
  const nullsKey = `${fieldName}_nulls`;
275
260
  const valuesKey = `${fieldName}_values`;
@@ -294,10 +279,10 @@ function extractTagFacts<T extends LogSchema>(
294
279
  */
295
280
  function extractFFfacts<T extends LogSchema>(buffer: SpanBuffer<T>, row: number, facts: TraceFact[]): void {
296
281
  // Feature flag entries store the flag name in message_values and the resolved value in ff_value_values.
297
- const name = buffer.message_values[row];
282
+ const name = resolveMessage(buffer, row);
298
283
  const value = buffer.ff_value_values[row];
299
284
 
300
- if (typeof name === 'string' && typeof value === 'string') {
285
+ if (name !== undefined && typeof value === 'string') {
301
286
  facts.push(ffFact(name, value));
302
287
  }
303
288
  }
@@ -316,6 +301,8 @@ function isNull(nulls: Uint8Array, index: number): boolean {
316
301
  */
317
302
  function entryTypeToLogLevel(entryType: number): LogLevel {
318
303
  switch (entryType) {
304
+ case ENTRY_TYPE_TRACE:
305
+ return 'trace';
319
306
  case ENTRY_TYPE_DEBUG:
320
307
  return 'debug';
321
308
  case ENTRY_TYPE_INFO:
@@ -341,8 +328,7 @@ function getErrorCode<T extends LogSchema>(buffer: SpanBuffer<T>, row: number):
341
328
  * Get exception message from a span-exception row.
342
329
  */
343
330
  function getExceptionMessage<T extends LogSchema>(buffer: SpanBuffer<T>, row: number): string {
344
- const message = buffer.message_values[row];
345
- return typeof message === 'string' ? message : 'Unknown exception';
331
+ return resolveMessage(buffer, row) ?? 'Unknown exception';
346
332
  }
347
333
 
348
334
  /**
@@ -88,7 +88,7 @@ export function spanException<N extends string, M extends string>(name: N, messa
88
88
  /**
89
89
  * Log levels.
90
90
  */
91
- export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
91
+ export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error';
92
92
 
93
93
  /**
94
94
  * A log fact: `log:${level}: ${message}`
@@ -15,13 +15,15 @@
15
15
  * @module queryable-span
16
16
  */
17
17
 
18
+ import { resolveMessage } from '../resolveMessage.js';
18
19
  import type { LogSchema } from '../schema/LogSchema.js';
20
+ import { iterateSpanChildren, iterateSpanTree } from '../traceTopology.js';
19
21
  import type { SpanBuffer } from '../types.js';
20
22
  import { type ExtractFactsOptions, extractFacts } from './extractFacts.js';
21
23
  import type { FactArray } from './facts.js';
22
24
 
23
25
  export interface QueryableSpan<T extends LogSchema = LogSchema> {
24
- /** Span name (from message_values[0]) */
26
+ /** Resolved span name. */
25
27
  readonly name: string;
26
28
 
27
29
  /** Extract all facts from this span and its children */
@@ -52,7 +54,7 @@ class QueryableSpanImpl<T extends LogSchema> implements QueryableSpan<T> {
52
54
  constructor(readonly buffer: SpanBuffer<T>) {}
53
55
 
54
56
  get name(): string {
55
- return this.buffer.message_values[0];
57
+ return resolveMessage(this.buffer, 0) ?? '';
56
58
  }
57
59
 
58
60
  facts(options?: ExtractFactsOptions): FactArray {
@@ -60,49 +62,40 @@ class QueryableSpanImpl<T extends LogSchema> implements QueryableSpan<T> {
60
62
  }
61
63
 
62
64
  find(name: string): QueryableSpan<T> | undefined {
63
- return findInChildren(this.buffer._children as SpanBuffer<T>[], name);
65
+ for (const descendant of iterateDescendantSpans(this.buffer)) {
66
+ if (resolveMessage(descendant, 0) === name) return new QueryableSpanImpl(descendant);
67
+ }
68
+ return undefined;
64
69
  }
65
70
 
66
71
  findAll(name: string): QueryableSpan<T>[] {
67
72
  const results: QueryableSpan<T>[] = [];
68
- collectAll(this.buffer._children as SpanBuffer<T>[], name, results);
73
+ for (const descendant of iterateDescendantSpans(this.buffer)) {
74
+ if (resolveMessage(descendant, 0) === name) results.push(new QueryableSpanImpl(descendant));
75
+ }
69
76
  return results;
70
77
  }
71
78
 
72
79
  get children(): QueryableSpan<T>[] {
73
- return (this.buffer._children as SpanBuffer<T>[]).map((child) => new QueryableSpanImpl(child));
80
+ const result: QueryableSpan<T>[] = [];
81
+ for (const child of iterateSpanChildren(this.buffer)) result.push(new QueryableSpanImpl(child));
82
+ return result;
74
83
  }
75
84
 
76
85
  names(): string[] {
77
86
  const result: string[] = [];
78
- collectNames(this.buffer._children as SpanBuffer<T>[], result);
79
- return result;
80
- }
81
- }
82
-
83
- function findInChildren<T extends LogSchema>(children: SpanBuffer<T>[], name: string): QueryableSpan<T> | undefined {
84
- for (const child of children) {
85
- if (child.message_values[0] === name) {
86
- return new QueryableSpanImpl(child);
87
- }
88
- const found = findInChildren(child._children as SpanBuffer<T>[], name);
89
- if (found) return found;
90
- }
91
- return undefined;
92
- }
93
-
94
- function collectAll<T extends LogSchema>(children: SpanBuffer<T>[], name: string, results: QueryableSpan<T>[]): void {
95
- for (const child of children) {
96
- if (child.message_values[0] === name) {
97
- results.push(new QueryableSpanImpl(child));
87
+ for (const descendant of iterateDescendantSpans(this.buffer)) {
88
+ result.push(resolveMessage(descendant, 0) ?? '');
98
89
  }
99
- collectAll(child._children as SpanBuffer<T>[], name, results);
90
+ return result;
100
91
  }
101
92
  }
102
93
 
103
- function collectNames<T extends LogSchema>(children: SpanBuffer<T>[], result: string[]): void {
104
- for (const child of children) {
105
- result.push(child.message_values[0]);
106
- collectNames(child._children as SpanBuffer<T>[], result);
94
+ function* iterateDescendantSpans<T extends LogSchema>(root: SpanBuffer<T>): Generator<SpanBuffer<T>> {
95
+ let previousNodeIndex = root._nodeIndex;
96
+ for (const buffer of iterateSpanTree(root)) {
97
+ if (buffer._nodeIndex === previousNodeIndex) continue;
98
+ previousNodeIndex = buffer._nodeIndex;
99
+ yield buffer;
107
100
  }
108
101
  }
@@ -7,18 +7,17 @@
7
7
  * @module span-query
8
8
  */
9
9
 
10
+ import { resolveMessage } from '../resolveMessage.js';
10
11
  import type { LogSchema } from '../schema/LogSchema.js';
12
+ import { iterateSpanTree } from '../traceTopology.js';
11
13
  import type { SpanBuffer } from '../types.js';
12
14
  import { type ExtractFactsOptions, extractFacts } from './extractFacts.js';
13
15
  import type { FactArray } from './facts.js';
14
16
 
15
17
  /** Find first descendant span by name (depth-first) */
16
18
  export function findSpan<T extends LogSchema>(root: SpanBuffer<T>, name: string): SpanBuffer<T> | undefined {
17
- for (const child of root._children) {
18
- const typed = child as SpanBuffer<T>;
19
- if (typed.message_values[0] === name) return typed;
20
- const found = findSpan(typed, name);
21
- if (found) return found;
19
+ for (const descendant of iterateDescendantSpans(root)) {
20
+ if (resolveMessage(descendant, 0) === name) return descendant;
22
21
  }
23
22
  return undefined;
24
23
  }
@@ -26,7 +25,9 @@ export function findSpan<T extends LogSchema>(root: SpanBuffer<T>, name: string)
26
25
  /** Find all descendant spans matching name (depth-first) */
27
26
  export function findAllSpans<T extends LogSchema>(root: SpanBuffer<T>, name: string): SpanBuffer<T>[] {
28
27
  const results: SpanBuffer<T>[] = [];
29
- collectSpans(root, name, results);
28
+ for (const descendant of iterateDescendantSpans(root)) {
29
+ if (resolveMessage(descendant, 0) === name) results.push(descendant);
30
+ }
30
31
  return results;
31
32
  }
32
33
 
@@ -44,22 +45,17 @@ export function extractFactsFor<T extends LogSchema>(
44
45
  /** Collect all descendant span names (flat list, depth-first) */
45
46
  export function spanNames<T extends LogSchema>(root: SpanBuffer<T>): string[] {
46
47
  const result: string[] = [];
47
- collectNames(root._children as SpanBuffer<T>[], result);
48
- return result;
49
- }
50
-
51
- function collectSpans<T extends LogSchema>(root: SpanBuffer<T>, name: string, results: SpanBuffer<T>[]): void {
52
- for (const child of root._children) {
53
- const typed = child as SpanBuffer<T>;
54
- if (typed.message_values[0] === name) results.push(typed);
55
- collectSpans(typed, name, results);
48
+ for (const descendant of iterateDescendantSpans(root)) {
49
+ result.push(resolveMessage(descendant, 0) ?? '');
56
50
  }
51
+ return result;
57
52
  }
58
53
 
59
- function collectNames<T extends LogSchema>(children: SpanBuffer<T>[], result: string[]): void {
60
- for (const child of children) {
61
- const typed = child as SpanBuffer<T>;
62
- result.push(typed.message_values[0]);
63
- collectNames(typed._children as SpanBuffer<T>[], result);
54
+ function* iterateDescendantSpans<T extends LogSchema>(root: SpanBuffer<T>): Generator<SpanBuffer<T>> {
55
+ let previousNodeIndex = root._nodeIndex;
56
+ for (const buffer of iterateSpanTree(root)) {
57
+ if (buffer._nodeIndex === previousNodeIndex) continue;
58
+ previousNodeIndex = buffer._nodeIndex;
59
+ yield buffer;
64
60
  }
65
61
  }
@@ -2,6 +2,7 @@ import { JsBufferStrategy } from '../JsBufferStrategy.js';
2
2
  import type { OpContextBinding } from '../opContext/types.js';
3
3
  import { createTraceRoot } from '../traceRoot.universal.js';
4
4
  import { StdioTracer, type StdioWritable } from '../tracers/StdioTracer.js';
5
+ import { iterateSpanChildren } from '../traceTopology.js';
5
6
  import type { AnySpanBuffer } from '../types.js';
6
7
 
7
8
  function isStdioWritable(value: unknown): value is StdioWritable {
@@ -16,13 +17,31 @@ function makeConsoleWriteStream(write: (line: string) => void): StdioWritable {
16
17
  },
17
18
  };
18
19
  }
20
+ type ReplayFrame = {
21
+ buffer: AnySpanBuffer;
22
+ children: Generator<AnySpanBuffer>;
23
+ replayLifecycle: boolean;
24
+ };
19
25
 
20
- function replayChildSpan(tracer: StdioTracer<OpContextBinding>, buffer: AnySpanBuffer): void {
21
- tracer.onSpanStart(buffer);
22
- for (const child of buffer._children) {
23
- replayChildSpan(tracer, child);
26
+ function replayChildSpans(tracer: StdioTracer<OpContextBinding>, rootBuffer: AnySpanBuffer): void {
27
+ const stack: ReplayFrame[] = [
28
+ { buffer: rootBuffer, children: iterateSpanChildren(rootBuffer), replayLifecycle: false },
29
+ ];
30
+
31
+ while (stack.length > 0) {
32
+ const frame = stack[stack.length - 1];
33
+ if (!frame) break;
34
+
35
+ const next = frame.children.next();
36
+ if (!next.done) {
37
+ tracer.onSpanStart(next.value);
38
+ stack.push({ buffer: next.value, children: iterateSpanChildren(next.value), replayLifecycle: true });
39
+ continue;
40
+ }
41
+
42
+ stack.pop();
43
+ if (frame.replayLifecycle) tracer.onSpanEnd(frame.buffer);
24
44
  }
25
- tracer.onSpanEnd(buffer);
26
45
  }
27
46
 
28
47
  export function replayTraceToStdio(binding: OpContextBinding, rootBuffer: AnySpanBuffer): void {
@@ -43,8 +62,6 @@ export function replayTraceToStdio(binding: OpContextBinding, rootBuffer: AnySpa
43
62
  });
44
63
 
45
64
  tracer.onTraceStart(rootBuffer);
46
- for (const child of rootBuffer._children) {
47
- replayChildSpan(tracer, child);
48
- }
65
+ replayChildSpans(tracer, rootBuffer);
49
66
  tracer.onTraceEnd(rootBuffer);
50
67
  }
@@ -323,7 +323,7 @@ function createRootTracer<B extends OpContextBinding>({
323
323
  });
324
324
  }
325
325
 
326
- async function closeTracer(tracer: Tracer<OpContextBinding>): Promise<void> {
326
+ async function closeTracer<B extends OpContextBinding>(tracer: Tracer<B>): Promise<void> {
327
327
  const close = Reflect.get(tracer, 'close');
328
328
  if (typeof close === 'function') {
329
329
  await close.call(tracer);
@@ -39,11 +39,13 @@ let threadIdBigInt: bigint | null = null;
39
39
  function ensureInitialized(): void {
40
40
  if (threadIdBytes !== null) return;
41
41
 
42
- threadIdBytes = new Uint8Array(THREAD_ID_BYTES);
42
+ // Keep initialization transactional so a failed entropy provider can be retried.
43
+ const bytes = new Uint8Array(THREAD_ID_BYTES);
43
44
 
44
45
  // Use Web Crypto API - available in browsers, Node 19+, Deno, Bun, Workers
45
46
  if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') {
46
- crypto.getRandomValues(threadIdBytes);
47
+ crypto.getRandomValues(bytes);
48
+ threadIdBytes = bytes;
47
49
  return;
48
50
  }
49
51
 
@@ -51,7 +53,8 @@ function ensureInitialized(): void {
51
53
  try {
52
54
  const nodeCrypto = require('node:crypto');
53
55
  if (nodeCrypto && typeof nodeCrypto.randomFillSync === 'function') {
54
- nodeCrypto.randomFillSync(threadIdBytes);
56
+ nodeCrypto.randomFillSync(bytes);
57
+ threadIdBytes = bytes;
55
58
  return;
56
59
  }
57
60
  } catch {