@smoothbricks/lmao 0.1.0

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 (447) hide show
  1. package/README.md +269 -0
  2. package/dist/allocator.wasm +0 -0
  3. package/dist/bun/preload.d.ts +11 -0
  4. package/dist/bun/preload.d.ts.map +1 -0
  5. package/dist/bun/preload.js +10 -0
  6. package/dist/bun/trace-preload.d.ts +8 -0
  7. package/dist/bun/trace-preload.d.ts.map +1 -0
  8. package/dist/bun/trace-preload.js +12 -0
  9. package/dist/es.d.ts +8 -0
  10. package/dist/es.d.ts.map +1 -0
  11. package/dist/es.js +9 -0
  12. package/dist/index.d.ts +41 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +84 -0
  15. package/dist/lib/JsBufferStrategy.d.ts +49 -0
  16. package/dist/lib/JsBufferStrategy.d.ts.map +1 -0
  17. package/dist/lib/JsBufferStrategy.js +60 -0
  18. package/dist/lib/archive/chunkCompaction.d.ts +15 -0
  19. package/dist/lib/archive/chunkCompaction.d.ts.map +1 -0
  20. package/dist/lib/archive/chunkCompaction.js +24 -0
  21. package/dist/lib/archive/chunkEnvelope.d.ts +21 -0
  22. package/dist/lib/archive/chunkEnvelope.d.ts.map +1 -0
  23. package/dist/lib/archive/chunkEnvelope.js +55 -0
  24. package/dist/lib/archive/chunkRouting.d.ts +10 -0
  25. package/dist/lib/archive/chunkRouting.d.ts.map +1 -0
  26. package/dist/lib/archive/chunkRouting.js +47 -0
  27. package/dist/lib/archive/chunkStats.d.ts +12 -0
  28. package/dist/lib/archive/chunkStats.d.ts.map +1 -0
  29. package/dist/lib/archive/chunkStats.js +10 -0
  30. package/dist/lib/archive/index.d.ts +5 -0
  31. package/dist/lib/archive/index.d.ts.map +1 -0
  32. package/dist/lib/archive/index.js +4 -0
  33. package/dist/lib/arrow/capacityStats.d.ts +9 -0
  34. package/dist/lib/arrow/capacityStats.d.ts.map +1 -0
  35. package/dist/lib/arrow/capacityStats.js +231 -0
  36. package/dist/lib/arrow/dictionaries.d.ts +27 -0
  37. package/dist/lib/arrow/dictionaries.d.ts.map +1 -0
  38. package/dist/lib/arrow/dictionaries.js +135 -0
  39. package/dist/lib/arrow/flechette.d.ts +40 -0
  40. package/dist/lib/arrow/flechette.d.ts.map +1 -0
  41. package/dist/lib/arrow/flechette.js +67 -0
  42. package/dist/lib/arrow/utils.d.ts +38 -0
  43. package/dist/lib/arrow/utils.d.ts.map +1 -0
  44. package/dist/lib/arrow/utils.js +112 -0
  45. package/dist/lib/buffer/Nanoseconds.d.ts +109 -0
  46. package/dist/lib/buffer/Nanoseconds.d.ts.map +1 -0
  47. package/dist/lib/buffer/Nanoseconds.js +86 -0
  48. package/dist/lib/bufferStrategy.d.ts +95 -0
  49. package/dist/lib/bufferStrategy.d.ts.map +1 -0
  50. package/dist/lib/bufferStrategy.js +1 -0
  51. package/dist/lib/capacityTuning.d.ts +50 -0
  52. package/dist/lib/capacityTuning.d.ts.map +1 -0
  53. package/dist/lib/capacityTuning.js +65 -0
  54. package/dist/lib/codegen/evaluatorGenerator.d.ts +35 -0
  55. package/dist/lib/codegen/evaluatorGenerator.d.ts.map +1 -0
  56. package/dist/lib/codegen/evaluatorGenerator.js +199 -0
  57. package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts +139 -0
  58. package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts.map +1 -0
  59. package/dist/lib/codegen/fixedPositionWriterGenerator.js +289 -0
  60. package/dist/lib/codegen/spanLoggerGenerator.d.ts +115 -0
  61. package/dist/lib/codegen/spanLoggerGenerator.d.ts.map +1 -0
  62. package/dist/lib/codegen/spanLoggerGenerator.js +575 -0
  63. package/dist/lib/convertToArrow.d.ts +40 -0
  64. package/dist/lib/convertToArrow.d.ts.map +1 -0
  65. package/dist/lib/convertToArrow.js +1467 -0
  66. package/dist/lib/defineOpContext.d.ts +96 -0
  67. package/dist/lib/defineOpContext.d.ts.map +1 -0
  68. package/dist/lib/defineOpContext.js +227 -0
  69. package/dist/lib/errors/Blocked.d.ts +113 -0
  70. package/dist/lib/errors/Blocked.d.ts.map +1 -0
  71. package/dist/lib/errors/Blocked.js +68 -0
  72. package/dist/lib/errors/CodeError.d.ts +101 -0
  73. package/dist/lib/errors/CodeError.d.ts.map +1 -0
  74. package/dist/lib/errors/CodeError.js +42 -0
  75. package/dist/lib/errors/RetriesExhausted.d.ts +67 -0
  76. package/dist/lib/errors/RetriesExhausted.d.ts.map +1 -0
  77. package/dist/lib/errors/RetriesExhausted.js +31 -0
  78. package/dist/lib/errors/Transient.d.ts +115 -0
  79. package/dist/lib/errors/Transient.d.ts.map +1 -0
  80. package/dist/lib/errors/Transient.js +54 -0
  81. package/dist/lib/errors/index.d.ts +14 -0
  82. package/dist/lib/errors/index.d.ts.map +1 -0
  83. package/dist/lib/errors/index.js +16 -0
  84. package/dist/lib/errors/retry-policy.d.ts +60 -0
  85. package/dist/lib/errors/retry-policy.d.ts.map +1 -0
  86. package/dist/lib/errors/retry-policy.js +54 -0
  87. package/dist/lib/flushScheduler.d.ts +162 -0
  88. package/dist/lib/flushScheduler.d.ts.map +1 -0
  89. package/dist/lib/flushScheduler.js +388 -0
  90. package/dist/lib/library.d.ts +149 -0
  91. package/dist/lib/library.d.ts.map +1 -0
  92. package/dist/lib/library.js +588 -0
  93. package/dist/lib/logApi.d.ts +61 -0
  94. package/dist/lib/logApi.d.ts.map +1 -0
  95. package/dist/lib/logApi.js +12 -0
  96. package/dist/lib/logBinding.d.ts +63 -0
  97. package/dist/lib/logBinding.d.ts.map +1 -0
  98. package/dist/lib/logBinding.js +1 -0
  99. package/dist/lib/op.d.ts +105 -0
  100. package/dist/lib/op.d.ts.map +1 -0
  101. package/dist/lib/op.js +59 -0
  102. package/dist/lib/opContext/contextTypes.d.ts +88 -0
  103. package/dist/lib/opContext/contextTypes.d.ts.map +1 -0
  104. package/dist/lib/opContext/contextTypes.js +34 -0
  105. package/dist/lib/opContext/createOpGroup.d.ts +57 -0
  106. package/dist/lib/opContext/createOpGroup.d.ts.map +1 -0
  107. package/dist/lib/opContext/createOpGroup.js +341 -0
  108. package/dist/lib/opContext/defineOp.d.ts +83 -0
  109. package/dist/lib/opContext/defineOp.d.ts.map +1 -0
  110. package/dist/lib/opContext/defineOp.js +197 -0
  111. package/dist/lib/opContext/featureFlagTypes.d.ts +58 -0
  112. package/dist/lib/opContext/featureFlagTypes.d.ts.map +1 -0
  113. package/dist/lib/opContext/featureFlagTypes.js +1 -0
  114. package/dist/lib/opContext/index.d.ts +13 -0
  115. package/dist/lib/opContext/index.d.ts.map +1 -0
  116. package/dist/lib/opContext/index.js +15 -0
  117. package/dist/lib/opContext/opGroupTypes.d.ts +250 -0
  118. package/dist/lib/opContext/opGroupTypes.d.ts.map +1 -0
  119. package/dist/lib/opContext/opGroupTypes.js +31 -0
  120. package/dist/lib/opContext/opTypes.d.ts +48 -0
  121. package/dist/lib/opContext/opTypes.d.ts.map +1 -0
  122. package/dist/lib/opContext/opTypes.js +7 -0
  123. package/dist/lib/opContext/spanContextTypes.d.ts +347 -0
  124. package/dist/lib/opContext/spanContextTypes.d.ts.map +1 -0
  125. package/dist/lib/opContext/spanContextTypes.js +1 -0
  126. package/dist/lib/opContext/types.d.ts +297 -0
  127. package/dist/lib/opContext/types.d.ts.map +1 -0
  128. package/dist/lib/opContext/types.js +16 -0
  129. package/dist/lib/result.d.ts +308 -0
  130. package/dist/lib/result.d.ts.map +1 -0
  131. package/dist/lib/result.js +359 -0
  132. package/dist/lib/schema/LogSchema.d.ts +62 -0
  133. package/dist/lib/schema/LogSchema.d.ts.map +1 -0
  134. package/dist/lib/schema/LogSchema.js +134 -0
  135. package/dist/lib/schema/builder.d.ts +12 -0
  136. package/dist/lib/schema/builder.d.ts.map +1 -0
  137. package/dist/lib/schema/builder.js +169 -0
  138. package/dist/lib/schema/defineFeatureFlags.d.ts +60 -0
  139. package/dist/lib/schema/defineFeatureFlags.d.ts.map +1 -0
  140. package/dist/lib/schema/defineFeatureFlags.js +29 -0
  141. package/dist/lib/schema/defineLogSchema.d.ts +87 -0
  142. package/dist/lib/schema/defineLogSchema.d.ts.map +1 -0
  143. package/dist/lib/schema/defineLogSchema.js +171 -0
  144. package/dist/lib/schema/evaluator.d.ts +267 -0
  145. package/dist/lib/schema/evaluator.d.ts.map +1 -0
  146. package/dist/lib/schema/evaluator.js +169 -0
  147. package/dist/lib/schema/extend.d.ts +14 -0
  148. package/dist/lib/schema/extend.d.ts.map +1 -0
  149. package/dist/lib/schema/extend.js +51 -0
  150. package/dist/lib/schema/systemSchema.d.ts +112 -0
  151. package/dist/lib/schema/systemSchema.d.ts.map +1 -0
  152. package/dist/lib/schema/systemSchema.js +260 -0
  153. package/dist/lib/schema/typeGuards.d.ts +52 -0
  154. package/dist/lib/schema/typeGuards.d.ts.map +1 -0
  155. package/dist/lib/schema/typeGuards.js +127 -0
  156. package/dist/lib/schema/types.d.ts +156 -0
  157. package/dist/lib/schema/types.d.ts.map +1 -0
  158. package/dist/lib/schema/types.js +4 -0
  159. package/dist/lib/spanBuffer.d.ts +133 -0
  160. package/dist/lib/spanBuffer.d.ts.map +1 -0
  161. package/dist/lib/spanBuffer.js +442 -0
  162. package/dist/lib/spanBufferHelpers.d.ts +53 -0
  163. package/dist/lib/spanBufferHelpers.d.ts.map +1 -0
  164. package/dist/lib/spanBufferHelpers.js +65 -0
  165. package/dist/lib/spanBufferStats.d.ts +38 -0
  166. package/dist/lib/spanBufferStats.d.ts.map +1 -0
  167. package/dist/lib/spanBufferStats.js +1 -0
  168. package/dist/lib/spanContext.d.ts +141 -0
  169. package/dist/lib/spanContext.d.ts.map +1 -0
  170. package/dist/lib/spanContext.js +763 -0
  171. package/dist/lib/sqlite/index.d.ts +14 -0
  172. package/dist/lib/sqlite/index.d.ts.map +1 -0
  173. package/dist/lib/sqlite/index.js +12 -0
  174. package/dist/lib/sqlite/sqlite-async-writer.d.ts +24 -0
  175. package/dist/lib/sqlite/sqlite-async-writer.d.ts.map +1 -0
  176. package/dist/lib/sqlite/sqlite-async-writer.js +65 -0
  177. package/dist/lib/sqlite/sqlite-common.d.ts +37 -0
  178. package/dist/lib/sqlite/sqlite-common.d.ts.map +1 -0
  179. package/dist/lib/sqlite/sqlite-common.js +207 -0
  180. package/dist/lib/sqlite/sqlite-d1.d.ts +25 -0
  181. package/dist/lib/sqlite/sqlite-d1.d.ts.map +1 -0
  182. package/dist/lib/sqlite/sqlite-d1.js +67 -0
  183. package/dist/lib/sqlite/sqlite-db.d.ts +29 -0
  184. package/dist/lib/sqlite/sqlite-db.d.ts.map +1 -0
  185. package/dist/lib/sqlite/sqlite-db.js +1 -0
  186. package/dist/lib/sqlite/sqlite-node.d.ts +16 -0
  187. package/dist/lib/sqlite/sqlite-node.d.ts.map +1 -0
  188. package/dist/lib/sqlite/sqlite-node.js +68 -0
  189. package/dist/lib/sqlite/sqlite-writer.d.ts +39 -0
  190. package/dist/lib/sqlite/sqlite-writer.d.ts.map +1 -0
  191. package/dist/lib/sqlite/sqlite-writer.js +78 -0
  192. package/dist/lib/testing/bun-harness.d.ts +150 -0
  193. package/dist/lib/testing/bun-harness.d.ts.map +1 -0
  194. package/dist/lib/testing/bun-harness.js +729 -0
  195. package/dist/lib/testing/extractFacts.d.ts +73 -0
  196. package/dist/lib/testing/extractFacts.d.ts.map +1 -0
  197. package/dist/lib/testing/extractFacts.js +237 -0
  198. package/dist/lib/testing/facts.d.ts +235 -0
  199. package/dist/lib/testing/facts.d.ts.map +1 -0
  200. package/dist/lib/testing/facts.js +209 -0
  201. package/dist/lib/testing/index.d.ts +58 -0
  202. package/dist/lib/testing/index.d.ts.map +1 -0
  203. package/dist/lib/testing/index.js +74 -0
  204. package/dist/lib/testing/queryable-span.d.ts +39 -0
  205. package/dist/lib/testing/queryable-span.d.ts.map +1 -0
  206. package/dist/lib/testing/queryable-span.js +58 -0
  207. package/dist/lib/testing/span-query.d.ts +21 -0
  208. package/dist/lib/testing/span-query.d.ts.map +1 -0
  209. package/dist/lib/testing/span-query.js +47 -0
  210. package/dist/lib/testing/stdio-replay.d.ts +4 -0
  211. package/dist/lib/testing/stdio-replay.d.ts.map +1 -0
  212. package/dist/lib/testing/stdio-replay.js +42 -0
  213. package/dist/lib/testing/trace-query.d.ts +59 -0
  214. package/dist/lib/testing/trace-query.d.ts.map +1 -0
  215. package/dist/lib/testing/trace-query.js +462 -0
  216. package/dist/lib/testing/vitest-harness.d.ts +135 -0
  217. package/dist/lib/testing/vitest-harness.d.ts.map +1 -0
  218. package/dist/lib/testing/vitest-harness.js +486 -0
  219. package/dist/lib/threadId.d.ts +58 -0
  220. package/dist/lib/threadId.d.ts.map +1 -0
  221. package/dist/lib/threadId.js +123 -0
  222. package/dist/lib/traceContext.d.ts +116 -0
  223. package/dist/lib/traceContext.d.ts.map +1 -0
  224. package/dist/lib/traceContext.js +37 -0
  225. package/dist/lib/traceId.d.ts +78 -0
  226. package/dist/lib/traceId.d.ts.map +1 -0
  227. package/dist/lib/traceId.js +87 -0
  228. package/dist/lib/traceRoot.d.ts +133 -0
  229. package/dist/lib/traceRoot.d.ts.map +1 -0
  230. package/dist/lib/traceRoot.es.d.ts +75 -0
  231. package/dist/lib/traceRoot.es.d.ts.map +1 -0
  232. package/dist/lib/traceRoot.es.js +129 -0
  233. package/dist/lib/traceRoot.js +19 -0
  234. package/dist/lib/traceRoot.node.d.ts +77 -0
  235. package/dist/lib/traceRoot.node.d.ts.map +1 -0
  236. package/dist/lib/traceRoot.node.js +133 -0
  237. package/dist/lib/traceRoot.universal.d.ts +3 -0
  238. package/dist/lib/traceRoot.universal.d.ts.map +1 -0
  239. package/dist/lib/traceRoot.universal.js +17 -0
  240. package/dist/lib/tracer.d.ts +296 -0
  241. package/dist/lib/tracer.d.ts.map +1 -0
  242. package/dist/lib/tracer.js +346 -0
  243. package/dist/lib/tracers/ArrayQueueTracer.d.ts +56 -0
  244. package/dist/lib/tracers/ArrayQueueTracer.d.ts.map +1 -0
  245. package/dist/lib/tracers/ArrayQueueTracer.js +67 -0
  246. package/dist/lib/tracers/CompositeTracer.d.ts +24 -0
  247. package/dist/lib/tracers/CompositeTracer.d.ts.map +1 -0
  248. package/dist/lib/tracers/CompositeTracer.js +57 -0
  249. package/dist/lib/tracers/NoOpTracer.d.ts +58 -0
  250. package/dist/lib/tracers/NoOpTracer.d.ts.map +1 -0
  251. package/dist/lib/tracers/NoOpTracer.js +41 -0
  252. package/dist/lib/tracers/SQLiteTracer.d.ts +42 -0
  253. package/dist/lib/tracers/SQLiteTracer.d.ts.map +1 -0
  254. package/dist/lib/tracers/SQLiteTracer.js +84 -0
  255. package/dist/lib/tracers/StdioTracer.d.ts +83 -0
  256. package/dist/lib/tracers/StdioTracer.d.ts.map +1 -0
  257. package/dist/lib/tracers/StdioTracer.js +270 -0
  258. package/dist/lib/tracers/TestTracer.d.ts +95 -0
  259. package/dist/lib/tracers/TestTracer.d.ts.map +1 -0
  260. package/dist/lib/tracers/TestTracer.js +87 -0
  261. package/dist/lib/tracers/index.d.ts +12 -0
  262. package/dist/lib/tracers/index.d.ts.map +1 -0
  263. package/dist/lib/tracers/index.js +11 -0
  264. package/dist/lib/types.d.ts +366 -0
  265. package/dist/lib/types.d.ts.map +1 -0
  266. package/dist/lib/types.js +1 -0
  267. package/dist/lib/utf8Cache.d.ts +111 -0
  268. package/dist/lib/utf8Cache.d.ts.map +1 -0
  269. package/dist/lib/utf8Cache.js +177 -0
  270. package/dist/lib/wasm/WasmBufferStrategy.d.ts +88 -0
  271. package/dist/lib/wasm/WasmBufferStrategy.d.ts.map +1 -0
  272. package/dist/lib/wasm/WasmBufferStrategy.js +138 -0
  273. package/dist/lib/wasm/wasmAllocator.d.ts +109 -0
  274. package/dist/lib/wasm/wasmAllocator.d.ts.map +1 -0
  275. package/dist/lib/wasm/wasmAllocator.js +227 -0
  276. package/dist/lib/wasm/wasmSpanBuffer.d.ts +123 -0
  277. package/dist/lib/wasm/wasmSpanBuffer.d.ts.map +1 -0
  278. package/dist/lib/wasm/wasmSpanBuffer.js +772 -0
  279. package/dist/lib/wasm/wasmTraceRoot.d.ts +167 -0
  280. package/dist/lib/wasm/wasmTraceRoot.d.ts.map +1 -0
  281. package/dist/lib/wasm/wasmTraceRoot.js +264 -0
  282. package/dist/node.d.ts +7 -0
  283. package/dist/node.d.ts.map +1 -0
  284. package/dist/node.js +8 -0
  285. package/dist/testing.d.ts +18 -0
  286. package/dist/testing.d.ts.map +1 -0
  287. package/dist/testing.js +17 -0
  288. package/package.json +193 -0
  289. package/src/bun/preload.ts +11 -0
  290. package/src/bun/trace-preload.ts +14 -0
  291. package/src/es.ts +11 -0
  292. package/src/index.ts +194 -0
  293. package/src/lib/JsBufferStrategy.ts +102 -0
  294. package/src/lib/__tests__/arrow-builder-integration/arrow-conversion.test.ts +485 -0
  295. package/src/lib/__tests__/arrow-builder-integration/binary-arrow-conversion.test.ts +390 -0
  296. package/src/lib/__tests__/arrow-builder-integration/binary-comparison.test.ts +647 -0
  297. package/src/lib/__tests__/arrow-builder-integration/binary-format-compliance.test.ts +292 -0
  298. package/src/lib/__tests__/arrow-builder-integration/buffer-chaining.test.ts +354 -0
  299. package/src/lib/__tests__/arrow-builder-integration/foundation.test.ts +127 -0
  300. package/src/lib/__tests__/arrow-builder-integration/integration.test.ts +392 -0
  301. package/src/lib/__tests__/arrow-builder-integration/lazy-columns.test.ts +389 -0
  302. package/src/lib/__tests__/arrow-conversion-algorithms.test.ts +54 -0
  303. package/src/lib/__tests__/arrow-test-helpers.ts +71 -0
  304. package/src/lib/__tests__/binary-e2e.test.ts +203 -0
  305. package/src/lib/__tests__/buffer-overflow-op-api.test.ts +608 -0
  306. package/src/lib/__tests__/buffer-overflow.test.ts +612 -0
  307. package/src/lib/__tests__/capacity-tuning.test.ts +544 -0
  308. package/src/lib/__tests__/effective-schema.test.ts +439 -0
  309. package/src/lib/__tests__/flechette.test.ts +42 -0
  310. package/src/lib/__tests__/flushScheduler.test.ts +537 -0
  311. package/src/lib/__tests__/integration.test.ts +600 -0
  312. package/src/lib/__tests__/library.test.ts +934 -0
  313. package/src/lib/__tests__/nested-library-tasks.test.ts +849 -0
  314. package/src/lib/__tests__/op-context-binding.test.ts +135 -0
  315. package/src/lib/__tests__/op-metadata.test.ts +198 -0
  316. package/src/lib/__tests__/op-type-safety.test.ts +71 -0
  317. package/src/lib/__tests__/package-exports.test.ts +57 -0
  318. package/src/lib/__tests__/remapped-buffer-view-integration.test.ts +319 -0
  319. package/src/lib/__tests__/remapped-buffer-view.test.ts +635 -0
  320. package/src/lib/__tests__/scope-attributes.test.ts +348 -0
  321. package/src/lib/__tests__/span-lifecycle.test.ts +680 -0
  322. package/src/lib/__tests__/sync-async-trace.test.ts +435 -0
  323. package/src/lib/__tests__/test-helpers.ts +318 -0
  324. package/src/lib/__tests__/timestamp.test.ts +259 -0
  325. package/src/lib/__tests__/trace-archive-primitives.test.ts +98 -0
  326. package/src/lib/__tests__/traceContext-type-enforcement.test.ts +271 -0
  327. package/src/lib/__tests__/tracer.test.ts +211 -0
  328. package/src/lib/__tests__/type-narrowing.test.ts +137 -0
  329. package/src/lib/archive/chunkCompaction.ts +44 -0
  330. package/src/lib/archive/chunkEnvelope.ts +79 -0
  331. package/src/lib/archive/chunkRouting.ts +70 -0
  332. package/src/lib/archive/chunkStats.ts +25 -0
  333. package/src/lib/archive/index.ts +4 -0
  334. package/src/lib/arrow/capacityStats.ts +340 -0
  335. package/src/lib/arrow/dictionaries.ts +159 -0
  336. package/src/lib/arrow/flechette.ts +114 -0
  337. package/src/lib/arrow/utils.ts +126 -0
  338. package/src/lib/buffer/Nanoseconds.ts +131 -0
  339. package/src/lib/bufferStrategy.ts +106 -0
  340. package/src/lib/capacityTuning.ts +102 -0
  341. package/src/lib/codegen/__tests__/__snapshots__/evaluatorGenerator.test.ts.snap +160 -0
  342. package/src/lib/codegen/__tests__/__snapshots__/scopeGenerator.test.ts.snap +196 -0
  343. package/src/lib/codegen/__tests__/__snapshots__/spanLoggerGenerator.test.ts.snap +1965 -0
  344. package/src/lib/codegen/__tests__/evaluatorGenerator.test.ts +516 -0
  345. package/src/lib/codegen/__tests__/nullBitmap.test.ts +207 -0
  346. package/src/lib/codegen/__tests__/spanLoggerGenerator.test.ts +237 -0
  347. package/src/lib/codegen/evaluatorGenerator.ts +309 -0
  348. package/src/lib/codegen/fixedPositionWriterGenerator.ts +444 -0
  349. package/src/lib/codegen/spanLoggerGenerator.ts +715 -0
  350. package/src/lib/convertToArrow.ts +1805 -0
  351. package/src/lib/defineOpContext.ts +398 -0
  352. package/src/lib/errors/Blocked.ts +165 -0
  353. package/src/lib/errors/CodeError.ts +132 -0
  354. package/src/lib/errors/RetriesExhausted.ts +78 -0
  355. package/src/lib/errors/Transient.ts +168 -0
  356. package/src/lib/errors/__tests__/Blocked-config.test.ts +152 -0
  357. package/src/lib/errors/__tests__/Transient.test.ts +129 -0
  358. package/src/lib/errors/__tests__/retry-policy.test.ts +85 -0
  359. package/src/lib/errors/index.ts +24 -0
  360. package/src/lib/errors/retry-policy.ts +87 -0
  361. package/src/lib/flushScheduler.ts +509 -0
  362. package/src/lib/library.ts +682 -0
  363. package/src/lib/logApi.ts +70 -0
  364. package/src/lib/logBinding.ts +67 -0
  365. package/src/lib/op.ts +103 -0
  366. package/src/lib/opContext/__tests__/retry.test.ts +764 -0
  367. package/src/lib/opContext/contextTypes.ts +130 -0
  368. package/src/lib/opContext/createOpGroup.ts +456 -0
  369. package/src/lib/opContext/defineOp.ts +281 -0
  370. package/src/lib/opContext/featureFlagTypes.ts +54 -0
  371. package/src/lib/opContext/index.ts +16 -0
  372. package/src/lib/opContext/opGroupTypes.ts +342 -0
  373. package/src/lib/opContext/opTypes.ts +80 -0
  374. package/src/lib/opContext/spanContextTypes.ts +398 -0
  375. package/src/lib/opContext/types.ts +403 -0
  376. package/src/lib/result.ts +550 -0
  377. package/src/lib/schema/LogSchema.ts +153 -0
  378. package/src/lib/schema/__tests__/defineLogSchema.test.ts +342 -0
  379. package/src/lib/schema/__tests__/featureFlags.test.ts +443 -0
  380. package/src/lib/schema/builder.ts +201 -0
  381. package/src/lib/schema/defineFeatureFlags.ts +91 -0
  382. package/src/lib/schema/defineLogSchema.ts +291 -0
  383. package/src/lib/schema/evaluator.ts +404 -0
  384. package/src/lib/schema/extend.ts +69 -0
  385. package/src/lib/schema/systemSchema.ts +339 -0
  386. package/src/lib/schema/typeGuards.ts +163 -0
  387. package/src/lib/schema/types.ts +265 -0
  388. package/src/lib/spanBuffer.ts +571 -0
  389. package/src/lib/spanBufferHelpers.ts +73 -0
  390. package/src/lib/spanBufferStats.ts +40 -0
  391. package/src/lib/spanContext.ts +1566 -0
  392. package/src/lib/sqlite/__tests__/sqlite-common.test.ts +89 -0
  393. package/src/lib/sqlite/index.ts +26 -0
  394. package/src/lib/sqlite/sqlite-async-writer.ts +101 -0
  395. package/src/lib/sqlite/sqlite-common.ts +309 -0
  396. package/src/lib/sqlite/sqlite-d1.ts +104 -0
  397. package/src/lib/sqlite/sqlite-db.ts +32 -0
  398. package/src/lib/sqlite/sqlite-node.ts +83 -0
  399. package/src/lib/sqlite/sqlite-writer.ts +128 -0
  400. package/src/lib/testing/TRACE-TESTING.md +100 -0
  401. package/src/lib/testing/__tests__/bun-harness.test.ts +108 -0
  402. package/src/lib/testing/__tests__/extractFacts.test.ts +279 -0
  403. package/src/lib/testing/__tests__/facts.test.ts +324 -0
  404. package/src/lib/testing/__tests__/vitest-harness.test.ts +32 -0
  405. package/src/lib/testing/bun-harness.ts +990 -0
  406. package/src/lib/testing/extractFacts.ts +362 -0
  407. package/src/lib/testing/facts.ts +470 -0
  408. package/src/lib/testing/index.ts +141 -0
  409. package/src/lib/testing/queryable-span.ts +108 -0
  410. package/src/lib/testing/span-query.ts +65 -0
  411. package/src/lib/testing/stdio-replay.ts +50 -0
  412. package/src/lib/testing/trace-query.ts +329 -0
  413. package/src/lib/testing/vitest-harness.ts +691 -0
  414. package/src/lib/threadId.ts +135 -0
  415. package/src/lib/traceContext.ts +182 -0
  416. package/src/lib/traceId.ts +142 -0
  417. package/src/lib/traceRoot.es.ts +157 -0
  418. package/src/lib/traceRoot.node.ts +170 -0
  419. package/src/lib/traceRoot.ts +154 -0
  420. package/src/lib/traceRoot.universal.ts +22 -0
  421. package/src/lib/tracer.ts +896 -0
  422. package/src/lib/tracers/ArrayQueueTracer.ts +76 -0
  423. package/src/lib/tracers/CompositeTracer.ts +76 -0
  424. package/src/lib/tracers/NoOpTracer.ts +73 -0
  425. package/src/lib/tracers/SQLiteTracer.ts +115 -0
  426. package/src/lib/tracers/StdioTracer.ts +380 -0
  427. package/src/lib/tracers/TestTracer.ts +146 -0
  428. package/src/lib/tracers/__tests__/ArrayQueueTracer.test.ts +184 -0
  429. package/src/lib/tracers/__tests__/NoOpTracer.test.ts +204 -0
  430. package/src/lib/tracers/__tests__/StdioTracer.test.ts +313 -0
  431. package/src/lib/tracers/__tests__/TestTracer.test.ts +200 -0
  432. package/src/lib/tracers/index.ts +12 -0
  433. package/src/lib/types.ts +498 -0
  434. package/src/lib/utf8Cache.ts +201 -0
  435. package/src/lib/wasm/WasmBufferStrategy.ts +219 -0
  436. package/src/lib/wasm/__tests__/WasmBufferStrategy.test.ts +256 -0
  437. package/src/lib/wasm/__tests__/wasm-integration.test.ts +476 -0
  438. package/src/lib/wasm/__tests__/wasmAllocator.test.ts +699 -0
  439. package/src/lib/wasm/__tests__/wasmSpanBuffer.test.ts +449 -0
  440. package/src/lib/wasm/__tests__/wasmTraceRoot.test.ts +390 -0
  441. package/src/lib/wasm/__tests__/wasmTracer.test.ts.disabled +444 -0
  442. package/src/lib/wasm/allocator.zig +945 -0
  443. package/src/lib/wasm/wasmAllocator.ts +469 -0
  444. package/src/lib/wasm/wasmSpanBuffer.ts +1014 -0
  445. package/src/lib/wasm/wasmTraceRoot.ts +315 -0
  446. package/src/node.ts +10 -0
  447. package/src/testing.ts +18 -0
@@ -0,0 +1,380 @@
1
+ /**
2
+ * StdioTracer - A tracer that prints spans to stdout/stderr
3
+ *
4
+ * Features:
5
+ * - Color-coded trace IDs based on trace_id for visual separation of concurrent traces
6
+ * - Per-trace indent tracking using Map<TraceId, number> for correct nesting
7
+ * - Human-readable timestamps (ISO 8601) and durations
8
+ * - Tree-style output with ├─ for start and └─ for end
9
+ * - Exceptions written to stderr
10
+ *
11
+ * Useful for development/debugging to see span execution in real-time.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * import { createTraceRoot } from '@smoothbricks/lmao/node';
16
+ * import { JsBufferStrategy } from '@smoothbricks/lmao';
17
+ *
18
+ * const ctx = defineOpContext({ logSchema: mySchema });
19
+ * const { trace } = new StdioTracer(ctx, {
20
+ * bufferStrategy: new JsBufferStrategy(),
21
+ * createTraceRoot,
22
+ * });
23
+ *
24
+ * await trace('fetch-user', fetchOp);
25
+ *
26
+ * // Output:
27
+ * // [2025-12-25T10:30:45.123Z] [123456] fetch-user
28
+ * // [2025-12-25T10:30:45.125Z] [123456] ├─ db-query
29
+ * // [2025-12-25T10:30:45.225Z] [123456] └─ db-query [OK] (100.00ms)
30
+ * // [2025-12-25T10:30:45.226Z] [123456] fetch-user (103.00ms) ========
31
+ * ```
32
+ */
33
+
34
+ import type { OpContextBinding } from '../opContext/types.js';
35
+ import {
36
+ ENTRY_TYPE_DEBUG,
37
+ ENTRY_TYPE_ERROR,
38
+ ENTRY_TYPE_INFO,
39
+ ENTRY_TYPE_SPAN_ERR,
40
+ ENTRY_TYPE_SPAN_EXCEPTION,
41
+ ENTRY_TYPE_SPAN_OK,
42
+ ENTRY_TYPE_TRACE,
43
+ ENTRY_TYPE_WARN,
44
+ } from '../schema/systemSchema.js';
45
+ import type { TraceId } from '../traceId.js';
46
+ import type { TracerOptions } from '../tracer.js';
47
+ import { Tracer } from '../tracer.js';
48
+ import type { AnySpanBuffer, SpanBuffer } from '../types.js';
49
+
50
+ export interface StdioWritable {
51
+ write(chunk: string): boolean;
52
+ }
53
+
54
+ // ============================================================================
55
+ // Formatting Helpers
56
+ // ============================================================================
57
+
58
+ /**
59
+ * Format nanosecond timestamp to ISO 8601 string with millisecond precision.
60
+ */
61
+ function formatTimestamp(nanos: bigint): string {
62
+ const millis = Number(nanos / 1_000_000n);
63
+ return new Date(millis).toISOString();
64
+ }
65
+
66
+ /**
67
+ * Format duration in nanoseconds to human-readable string.
68
+ */
69
+ function formatDuration(nanos: bigint): string {
70
+ const n = Number(nanos);
71
+ if (n >= 1_000_000_000) {
72
+ return `${(n / 1_000_000_000).toFixed(2)}s`;
73
+ }
74
+ if (n >= 1_000_000) {
75
+ return `${(n / 1_000_000).toFixed(2)}ms`;
76
+ }
77
+ if (n >= 1_000) {
78
+ return `${(n / 1_000).toFixed(2)}µs`;
79
+ }
80
+ return `${n}ns`;
81
+ }
82
+
83
+ /**
84
+ * ANSI color codes for visual trace separation.
85
+ * Each trace gets a consistent color based on trace_id hash.
86
+ */
87
+ const COLORS = [
88
+ '\u001b[31m', // Red
89
+ '\u001b[32m', // Green
90
+ '\u001b[33m', // Yellow
91
+ '\u001b[34m', // Blue
92
+ '\u001b[35m', // Magenta
93
+ '\u001b[36m', // Cyan
94
+ '\u001b[91m', // Bright Red
95
+ '\u001b[92m', // Bright Green
96
+ '\u001b[93m', // Bright Yellow
97
+ '\u001b[94m', // Bright Blue
98
+ '\u001b[95m', // Bright Magenta
99
+ '\u001b[96m', // Bright Cyan
100
+ ] as const;
101
+
102
+ const RESET = '\u001b[0m';
103
+
104
+ /**
105
+ * Get consistent color for a trace_id.
106
+ * Uses modulo arithmetic to map 128-bit trace_id to one of the colors.
107
+ */
108
+ function getTraceColor(traceId: TraceId): string {
109
+ // Convert TraceId (string representation) to a number for coloring
110
+ // Use simple hash of the string to pick a color
111
+ let hash = 0;
112
+ const str = String(traceId);
113
+ for (let i = 0; i < str.length; i++) {
114
+ const char = str.charCodeAt(i);
115
+ // Simple hash function
116
+ hash = (hash << 5) - hash + char;
117
+ hash = hash & hash;
118
+ }
119
+ const index = Math.abs(hash) % COLORS.length;
120
+ return COLORS[index];
121
+ }
122
+
123
+ /**
124
+ * Get status string from entry type.
125
+ */
126
+ function getStatus(entryType: number): string {
127
+ switch (entryType) {
128
+ case ENTRY_TYPE_SPAN_OK:
129
+ return 'OK';
130
+ case ENTRY_TYPE_SPAN_ERR:
131
+ return 'ERR';
132
+ case ENTRY_TYPE_SPAN_EXCEPTION:
133
+ return 'EXCEPTION';
134
+ default:
135
+ return 'UNKNOWN';
136
+ }
137
+ }
138
+
139
+ function getLogLevel(entryType: number): string | null {
140
+ switch (entryType) {
141
+ case ENTRY_TYPE_TRACE:
142
+ return 'TRACE';
143
+ case ENTRY_TYPE_DEBUG:
144
+ return 'DEBUG';
145
+ case ENTRY_TYPE_INFO:
146
+ return 'INFO';
147
+ case ENTRY_TYPE_WARN:
148
+ return 'WARN';
149
+ case ENTRY_TYPE_ERROR:
150
+ return 'ERROR';
151
+ default:
152
+ return null;
153
+ }
154
+ }
155
+
156
+ function formatTemplateMessage(buffer: AnySpanBuffer, row: number, template: string): string {
157
+ return template.replace(/\{\{([A-Za-z0-9_]+)\}\}/g, (_full, key: string) => {
158
+ const values = Reflect.get(buffer, `${key}_values`) as unknown;
159
+ if (values == null) return `{{${key}}}`;
160
+
161
+ if (Array.isArray(values)) {
162
+ const value = values[row];
163
+ return value === null || value === undefined ? `{{${key}}}` : String(value);
164
+ }
165
+
166
+ if (ArrayBuffer.isView(values)) {
167
+ const value = Reflect.get(values, row) as unknown;
168
+ return value === null || value === undefined ? `{{${key}}}` : String(value);
169
+ }
170
+
171
+ return `{{${key}}}`;
172
+ });
173
+ }
174
+
175
+ // ============================================================================
176
+ // StdioTracer Options
177
+ // ============================================================================
178
+
179
+ /**
180
+ * Options for StdioTracer
181
+ */
182
+ export interface StdioTracerOptions<
183
+ T extends import('../schema/LogSchema.js').LogSchema = import('../schema/LogSchema.js').LogSchema,
184
+ > extends TracerOptions<T> {
185
+ /** Output stream (defaults to process.stdout) */
186
+ out?: StdioWritable;
187
+ /** Error stream (defaults to process.stderr) */
188
+ err?: StdioWritable;
189
+ /** Enable ANSI colors (defaults to true) */
190
+ colorEnabled?: boolean;
191
+ }
192
+
193
+ // ============================================================================
194
+ // StdioTracer
195
+ // ============================================================================
196
+
197
+ /**
198
+ * Tracer that prints spans to stdout/stderr with colored, indented output.
199
+ *
200
+ * Features:
201
+ * - Color-coded trace IDs for visual separation of concurrent traces
202
+ * - Per-trace indent tracking (concurrent-safe via Map)
203
+ * - Tree-style output (├─ for start, └─ for end)
204
+ * - Human-readable timestamps and durations
205
+ * - Exceptions go to stderr
206
+ */
207
+ export class StdioTracer<B extends OpContextBinding = OpContextBinding> extends Tracer<B> {
208
+ /**
209
+ * Per-trace indent levels for concurrent-safe nesting.
210
+ * Key is trace_id string representation, value is current indent level.
211
+ */
212
+ private readonly indents = new Map<string, number>();
213
+
214
+ private readonly out: StdioWritable;
215
+ private readonly err: StdioWritable;
216
+ private readonly colorEnabled: boolean;
217
+
218
+ constructor(binding: B, options: StdioTracerOptions<B['logBinding']['logSchema']>) {
219
+ super(binding, options);
220
+ this.out = options.out ?? process.stdout;
221
+ this.err = options.err ?? process.stderr;
222
+ this.colorEnabled = options.colorEnabled ?? true;
223
+ }
224
+
225
+ // --------------------------------------------------------------------------
226
+ // Indent Management
227
+ // --------------------------------------------------------------------------
228
+
229
+ private getIndent(traceId: TraceId): number {
230
+ const key = String(traceId);
231
+ return this.indents.get(key) ?? 0;
232
+ }
233
+
234
+ private incrementIndent(traceId: TraceId): void {
235
+ const key = String(traceId);
236
+ this.indents.set(key, this.getIndent(traceId) + 1);
237
+ }
238
+
239
+ private decrementIndent(traceId: TraceId): void {
240
+ const key = String(traceId);
241
+ const current = this.getIndent(traceId);
242
+ if (current <= 1) {
243
+ this.indents.delete(key); // Cleanup when trace ends
244
+ } else {
245
+ this.indents.set(key, current - 1);
246
+ }
247
+ }
248
+
249
+ // --------------------------------------------------------------------------
250
+ // Color Helpers
251
+ // --------------------------------------------------------------------------
252
+
253
+ private color(traceId: TraceId): string {
254
+ return this.colorEnabled ? getTraceColor(traceId) : '';
255
+ }
256
+
257
+ private reset(): string {
258
+ return this.colorEnabled ? RESET : '';
259
+ }
260
+
261
+ private printLogRows(buffer: AnySpanBuffer, indent: number): void {
262
+ let current: AnySpanBuffer | null = buffer;
263
+ let isRootSegment = true;
264
+
265
+ while (current) {
266
+ const start = isRootSegment ? 2 : 0;
267
+ const end = current._writeIndex;
268
+
269
+ for (let i = start; i < end; i++) {
270
+ const level = getLogLevel(current.entry_type[i]);
271
+ if (!level) continue;
272
+
273
+ const template = current.message_values[i] ?? '';
274
+ const message = formatTemplateMessage(current, i, template);
275
+ const ts = formatTimestamp(current.timestamp[i]);
276
+ const traceId = current.trace_id;
277
+ const line =
278
+ `[${ts}] ${this.color(traceId)}[${traceId}]${this.reset()} ` +
279
+ `${' '.repeat(indent)}· ${level} ${message}\n`;
280
+
281
+ if (level === 'ERROR') {
282
+ this.err.write(line);
283
+ } else {
284
+ this.out.write(line);
285
+ }
286
+ }
287
+
288
+ current = current._overflow ?? null;
289
+ isRootSegment = false;
290
+ }
291
+ }
292
+
293
+ // --------------------------------------------------------------------------
294
+ // Lifecycle Hooks
295
+ // --------------------------------------------------------------------------
296
+
297
+ onTraceStart(rootBuffer: SpanBuffer<B['logBinding']['logSchema']> | AnySpanBuffer): void {
298
+ const traceId = rootBuffer.trace_id;
299
+ const name = rootBuffer.message_values[0];
300
+ const ts = formatTimestamp(rootBuffer.timestamp[0]);
301
+
302
+ this.out.write(`[${ts}] ${this.color(traceId)}[${traceId}]${this.reset()} ${name}\n`);
303
+ this.incrementIndent(traceId);
304
+ }
305
+
306
+ onTraceEnd(rootBuffer: SpanBuffer<B['logBinding']['logSchema']> | AnySpanBuffer): void {
307
+ const traceId = rootBuffer.trace_id;
308
+ this.printLogRows(rootBuffer, 1);
309
+ this.decrementIndent(traceId);
310
+
311
+ const name = rootBuffer.message_values[0];
312
+ const startTs = rootBuffer.timestamp[0];
313
+ const endTs = rootBuffer.timestamp[1];
314
+ const duration = formatDuration(endTs - startTs);
315
+ const entryType = rootBuffer.entry_type[1];
316
+ const status = getStatus(entryType);
317
+ const ts = formatTimestamp(endTs);
318
+
319
+ const line = `[${ts}] ${this.color(traceId)}[${traceId}]${this.reset()} ${name} [${status}] (${duration}) ${'='.repeat(40)}\n`;
320
+
321
+ // Write exceptions to stderr
322
+ if (entryType === ENTRY_TYPE_SPAN_EXCEPTION) {
323
+ this.err.write(line);
324
+ } else {
325
+ this.out.write(line);
326
+ }
327
+ }
328
+
329
+ onSpanStart(childBuffer: SpanBuffer<B['logBinding']['logSchema']> | AnySpanBuffer): void {
330
+ const traceId = childBuffer.trace_id;
331
+ const indent = this.getIndent(traceId);
332
+ const name = childBuffer.message_values[0];
333
+ const ts = formatTimestamp(childBuffer.timestamp[0]);
334
+
335
+ this.out.write(`[${ts}] ${this.color(traceId)}[${traceId}]${this.reset()} ${' '.repeat(indent)}├─ ${name}\n`);
336
+ this.incrementIndent(traceId);
337
+ }
338
+
339
+ onSpanEnd(childBuffer: SpanBuffer<B['logBinding']['logSchema']> | AnySpanBuffer): void {
340
+ const traceId = childBuffer.trace_id;
341
+ this.decrementIndent(traceId);
342
+ const indent = this.getIndent(traceId);
343
+ this.printLogRows(childBuffer, indent + 1);
344
+
345
+ const name = childBuffer.message_values[0];
346
+ const startTs = childBuffer.timestamp[0];
347
+ const endTs = childBuffer.timestamp[1];
348
+ const duration = formatDuration(endTs - startTs);
349
+ const entryType = childBuffer.entry_type[1];
350
+ const status = getStatus(entryType);
351
+ const ts = formatTimestamp(endTs);
352
+
353
+ const line = `[${ts}] ${this.color(traceId)}[${traceId}]${this.reset()} ${' '.repeat(indent)}└─ ${name} [${status}] (${duration})\n`;
354
+
355
+ // Write exceptions to stderr
356
+ if (entryType === ENTRY_TYPE_SPAN_EXCEPTION) {
357
+ this.err.write(line);
358
+ } else {
359
+ this.out.write(line);
360
+ }
361
+ }
362
+
363
+ onStatsWillResetFor(_buffer: SpanBuffer<B['logBinding']['logSchema']>): void {
364
+ const stats = _buffer._stats;
365
+ // Compute utilization = totalWrites / (spansCreated * usableRowsPerSpan)
366
+ const usableRowsPerSpan = stats.capacity - 2;
367
+ const utilization =
368
+ stats.spansCreated > 0
369
+ ? ((stats.totalWrites / (stats.spansCreated * usableRowsPerSpan)) * 100).toFixed(1)
370
+ : '0.0';
371
+ const traceId = _buffer.trace_id;
372
+ const ts = formatTimestamp(_buffer.timestamp[0]);
373
+
374
+ this.out.write(
375
+ `[${ts}] ${this.color(traceId)}[${traceId}]${this.reset()} ` +
376
+ `[CAPACITY] writes=${stats.totalWrites} spans=${stats.spansCreated} utilization=${utilization}% ` +
377
+ `capacity=${stats.capacity}\n`,
378
+ );
379
+ }
380
+ }
@@ -0,0 +1,146 @@
1
+ /**
2
+ * TestTracer - A tracer that accumulates completed root trace buffers for test inspection.
3
+ *
4
+ * Child spans are accessible via the buffer's `_children` tree - no need to track them separately.
5
+ * This is the primary tracer for tests that need to inspect trace output, convert to Arrow tables,
6
+ * or verify buffer contents.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { createTraceRoot } from '@smoothbricks/lmao/node';
11
+ * import { JsBufferStrategy } from '@smoothbricks/lmao';
12
+ *
13
+ * const ctx = defineOpContext({ logSchema });
14
+ * const tracer = new TestTracer(ctx, {
15
+ * bufferStrategy: new JsBufferStrategy(),
16
+ * createTraceRoot,
17
+ * });
18
+ *
19
+ * await tracer.trace('my-op', myOp);
20
+ *
21
+ * // Inspect buffers
22
+ * expect(tracer.rootBuffers).toHaveLength(1);
23
+ *
24
+ * // Convert to Arrow using strategy
25
+ * const table = await tracer.bufferStrategy.toArrowTable(tracer.rootBuffers[0]);
26
+ * ```
27
+ *
28
+ * @module tracers/TestTracer
29
+ */
30
+
31
+ import type { OpContextBinding } from '../opContext/types.js';
32
+ import type { LogSchema } from '../schema/LogSchema.js';
33
+ import { Tracer } from '../tracer.js';
34
+ import type { SpanBuffer } from '../types.js';
35
+
36
+ type ResettableBufferStrategy = {
37
+ reset: () => void;
38
+ };
39
+
40
+ function isResettableBufferStrategy(value: unknown): value is ResettableBufferStrategy {
41
+ return typeof value === 'object' && value !== null && typeof Reflect.get(value, 'reset') === 'function';
42
+ }
43
+
44
+ /**
45
+ * Snapshot of buffer stats captured before reset during capacity tuning.
46
+ */
47
+ export interface StatsSnapshot<T extends LogSchema = LogSchema> {
48
+ buffer: SpanBuffer<T>;
49
+ totalWrites: number;
50
+ spansCreated: number;
51
+ capacity: number;
52
+ }
53
+
54
+ /**
55
+ * Test tracer that accumulates root buffers for inspection.
56
+ *
57
+ * Collects all completed root trace buffers in `rootBuffers` array.
58
+ * Child spans are accessible via the buffer's `_children` tree -
59
+ * no need to track them separately.
60
+ *
61
+ * Also tracks capacity tuning events via `statsSnapshots` to verify
62
+ * that `onStatsWillResetFor` is called before stats are reset.
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * const ctx = defineOpContext({ logSchema });
67
+ * const tracer = new TestTracer(ctx);
68
+ * const { trace } = tracer;
69
+ *
70
+ * await trace('my-op', myOp);
71
+ *
72
+ * // Inspect buffer
73
+ * expect(tracer.rootBuffers).toHaveLength(1);
74
+ * expect(tracer.rootBuffers[0].message_values[0]).toBe('my-op');
75
+ *
76
+ * // Convert to Arrow for detailed inspection
77
+ * const table = convertSpanTreeToArrowTable(tracer.rootBuffers[0]);
78
+ * expect(table.numRows).toBe(2); // span-start + span-ok
79
+ *
80
+ * // Verify capacity tuning was captured
81
+ * expect(tracer.statsSnapshots.length).toBeGreaterThan(0);
82
+ * ```
83
+ */
84
+ export class TestTracer<B extends OpContextBinding = OpContextBinding> extends Tracer<B> {
85
+ /**
86
+ * All completed root trace buffers.
87
+ * Child spans are accessible via each buffer's `_children` tree.
88
+ */
89
+ readonly rootBuffers: SpanBuffer<B['logBinding']['logSchema']>[] = [];
90
+
91
+ /**
92
+ * Stats snapshots captured before reset during capacity tuning.
93
+ * Used to verify onStatsWillResetFor hook is called correctly.
94
+ */
95
+ readonly statsSnapshots: StatsSnapshot<B['logBinding']['logSchema']>[] = [];
96
+
97
+ // ===========================================================================
98
+ // Lifecycle hook implementations
99
+ // ===========================================================================
100
+
101
+ onTraceStart(_rootBuffer: SpanBuffer<B['logBinding']['logSchema']>): void {
102
+ // No-op - we collect on end, not start
103
+ }
104
+
105
+ onTraceEnd(rootBuffer: SpanBuffer<B['logBinding']['logSchema']>): void {
106
+ // Collect the root buffer when trace completes
107
+ this.rootBuffers.push(rootBuffer);
108
+ }
109
+
110
+ onSpanStart(_childBuffer: SpanBuffer<B['logBinding']['logSchema']>): void {
111
+ // No-op - children are in tree, accessed via rootBuffer._children
112
+ }
113
+
114
+ onSpanEnd(_childBuffer: SpanBuffer<B['logBinding']['logSchema']>): void {
115
+ // No-op - children are in tree, accessed via rootBuffer._children
116
+ }
117
+
118
+ onStatsWillResetFor(buffer: SpanBuffer<B['logBinding']['logSchema']>): void {
119
+ // Capture stats snapshot before they're reset
120
+ const stats = buffer._stats;
121
+ this.statsSnapshots.push({
122
+ buffer,
123
+ totalWrites: stats.totalWrites,
124
+ spansCreated: stats.spansCreated,
125
+ capacity: stats.capacity,
126
+ });
127
+ }
128
+
129
+ // ===========================================================================
130
+ // Test utilities
131
+ // ===========================================================================
132
+
133
+ /**
134
+ * Clear all collected buffers and stats snapshots.
135
+ * Useful for cleanup between tests.
136
+ */
137
+ clear(): void {
138
+ this.rootBuffers.length = 0;
139
+ this.statsSnapshots.length = 0;
140
+
141
+ // Reset the buffer strategy if it supports it (e.g., WasmBufferStrategy)
142
+ if (isResettableBufferStrategy(this.bufferStrategy)) {
143
+ this.bufferStrategy.reset();
144
+ }
145
+ }
146
+ }
@@ -0,0 +1,184 @@
1
+ // Configure Node.js timestamp implementation - MUST be first import
2
+ import '../../__tests__/test-helpers.js';
3
+
4
+ import { describe, expect, it } from 'bun:test';
5
+ import { createTestTracerOptions } from '../../__tests__/test-helpers.js';
6
+ import { convertSpanTreeToArrowTable } from '../../convertToArrow.js';
7
+ import { defineLogSchema, defineOpContext, S } from '../../defineOpContext.js';
8
+ import { ArrayQueueTracer } from '../ArrayQueueTracer.js';
9
+
10
+ describe('ArrayQueueTracer', () => {
11
+ const testSchema = defineLogSchema({
12
+ userId: S.category(),
13
+ });
14
+
15
+ const ctx = defineOpContext({
16
+ logSchema: testSchema,
17
+ });
18
+ const { defineOp } = ctx;
19
+
20
+ describe('queue accumulation', () => {
21
+ it('should start with empty queue', () => {
22
+ const tracer = new ArrayQueueTracer(ctx, { ...createTestTracerOptions() });
23
+ expect(tracer.queue).toHaveLength(0);
24
+ });
25
+
26
+ it('should queue root buffer after trace completes', async () => {
27
+ const tracer = new ArrayQueueTracer(ctx, { ...createTestTracerOptions() });
28
+ const { trace } = tracer;
29
+
30
+ const testOp = defineOp('test', (ctx) => ctx.ok('done'));
31
+ await trace('queued-trace', testOp);
32
+
33
+ expect(tracer.queue).toHaveLength(1);
34
+ expect(tracer.queue[0].message_values[0]).toBe('queued-trace');
35
+ });
36
+
37
+ it('should queue multiple traces in order', async () => {
38
+ const tracer = new ArrayQueueTracer(ctx, { ...createTestTracerOptions() });
39
+ const { trace } = tracer;
40
+
41
+ const testOp = defineOp('test', (ctx) => ctx.ok('done'));
42
+
43
+ await trace('first', testOp);
44
+ await trace('second', testOp);
45
+ await trace('third', testOp);
46
+
47
+ expect(tracer.queue).toHaveLength(3);
48
+ expect(tracer.queue[0].message_values[0]).toBe('first');
49
+ expect(tracer.queue[1].message_values[0]).toBe('second');
50
+ expect(tracer.queue[2].message_values[0]).toBe('third');
51
+ });
52
+
53
+ it('should queue buffer even if trace throws', async () => {
54
+ const tracer = new ArrayQueueTracer(ctx, { ...createTestTracerOptions() });
55
+ const { trace } = tracer;
56
+
57
+ const failOp = defineOp('fail', async () => {
58
+ throw new Error('boom');
59
+ });
60
+
61
+ await expect(trace('failing', failOp)).rejects.toThrow('boom');
62
+
63
+ expect(tracer.queue).toHaveLength(1);
64
+ expect(tracer.queue[0].message_values[0]).toBe('failing');
65
+ });
66
+ });
67
+
68
+ describe('drain()', () => {
69
+ it('should return all queued buffers', async () => {
70
+ const tracer = new ArrayQueueTracer(ctx, { ...createTestTracerOptions() });
71
+ const { trace } = tracer;
72
+
73
+ const testOp = defineOp('test', (ctx) => ctx.ok('done'));
74
+
75
+ await trace('a', testOp);
76
+ await trace('b', testOp);
77
+
78
+ const drained = tracer.drain();
79
+
80
+ expect(drained).toHaveLength(2);
81
+ expect(drained[0].message_values[0]).toBe('a');
82
+ expect(drained[1].message_values[0]).toBe('b');
83
+ });
84
+
85
+ it('should clear queue after drain', async () => {
86
+ const tracer = new ArrayQueueTracer(ctx, { ...createTestTracerOptions() });
87
+ const { trace } = tracer;
88
+
89
+ const testOp = defineOp('test', (ctx) => ctx.ok('done'));
90
+
91
+ await trace('x', testOp);
92
+ await trace('y', testOp);
93
+
94
+ tracer.drain();
95
+
96
+ expect(tracer.queue).toHaveLength(0);
97
+ });
98
+
99
+ it('should return empty array when queue is empty', () => {
100
+ const tracer = new ArrayQueueTracer(ctx, { ...createTestTracerOptions() });
101
+
102
+ const drained = tracer.drain();
103
+
104
+ expect(drained).toHaveLength(0);
105
+ expect(Array.isArray(drained)).toBe(true);
106
+ });
107
+
108
+ it('should allow new traces after drain', async () => {
109
+ const tracer = new ArrayQueueTracer(ctx, { ...createTestTracerOptions() });
110
+ const { trace } = tracer;
111
+
112
+ const testOp = defineOp('test', (ctx) => ctx.ok('done'));
113
+
114
+ await trace('before', testOp);
115
+ tracer.drain();
116
+ await trace('after', testOp);
117
+
118
+ expect(tracer.queue).toHaveLength(1);
119
+ expect(tracer.queue[0].message_values[0]).toBe('after');
120
+ });
121
+
122
+ it('should return independent array (not reference to internal queue)', async () => {
123
+ const tracer = new ArrayQueueTracer(ctx, { ...createTestTracerOptions() });
124
+ const { trace } = tracer;
125
+
126
+ const testOp = defineOp('test', (ctx) => ctx.ok('done'));
127
+
128
+ await trace('test', testOp);
129
+
130
+ const drained = tracer.drain();
131
+
132
+ // Modify returned array
133
+ drained.push(drained[0]);
134
+
135
+ // Internal queue should be unaffected
136
+ expect(tracer.queue).toHaveLength(0);
137
+ });
138
+ });
139
+
140
+ describe('production pattern: batch processing', () => {
141
+ it('should support batch-then-process pattern', async () => {
142
+ const tracer = new ArrayQueueTracer(ctx, { ...createTestTracerOptions() });
143
+ const { trace } = tracer;
144
+
145
+ const testOp = defineOp('test', (ctx) => ctx.ok('done'));
146
+
147
+ // Simulate batching traces
148
+ await trace('req-1', testOp);
149
+ await trace('req-2', testOp);
150
+ await trace('req-3', testOp);
151
+
152
+ // Process batch
153
+ const batch = tracer.drain();
154
+ const tables = batch.map((buf) => convertSpanTreeToArrowTable(buf));
155
+
156
+ expect(tables).toHaveLength(3);
157
+ for (const table of tables) {
158
+ expect(table.numRows).toBe(2); // span-start + span-ok
159
+ }
160
+
161
+ // Queue is now empty, ready for next batch
162
+ expect(tracer.queue).toHaveLength(0);
163
+ });
164
+ });
165
+
166
+ describe('child spans', () => {
167
+ it('should include child spans in queued buffer tree', async () => {
168
+ const tracer = new ArrayQueueTracer(ctx, { ...createTestTracerOptions() });
169
+ const { trace } = tracer;
170
+
171
+ const childOp = defineOp('child', (ctx) => ctx.ok('c'));
172
+ const parentOp = defineOp('parent', async (ctx) => {
173
+ await ctx.span('child-span', childOp);
174
+ return ctx.ok('p');
175
+ });
176
+
177
+ await trace('root', parentOp);
178
+
179
+ const [buffer] = tracer.drain();
180
+ expect(buffer._children).toHaveLength(1);
181
+ expect(buffer._children[0].message_values[0]).toBe('child-span');
182
+ });
183
+ });
184
+ });