@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.
- package/README.md +269 -0
- package/dist/allocator.wasm +0 -0
- package/dist/bun/preload.d.ts +11 -0
- package/dist/bun/preload.d.ts.map +1 -0
- package/dist/bun/preload.js +10 -0
- package/dist/bun/trace-preload.d.ts +8 -0
- package/dist/bun/trace-preload.d.ts.map +1 -0
- package/dist/bun/trace-preload.js +12 -0
- package/dist/es.d.ts +8 -0
- package/dist/es.d.ts.map +1 -0
- package/dist/es.js +9 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +84 -0
- package/dist/lib/JsBufferStrategy.d.ts +49 -0
- package/dist/lib/JsBufferStrategy.d.ts.map +1 -0
- package/dist/lib/JsBufferStrategy.js +60 -0
- package/dist/lib/archive/chunkCompaction.d.ts +15 -0
- package/dist/lib/archive/chunkCompaction.d.ts.map +1 -0
- package/dist/lib/archive/chunkCompaction.js +24 -0
- package/dist/lib/archive/chunkEnvelope.d.ts +21 -0
- package/dist/lib/archive/chunkEnvelope.d.ts.map +1 -0
- package/dist/lib/archive/chunkEnvelope.js +55 -0
- package/dist/lib/archive/chunkRouting.d.ts +10 -0
- package/dist/lib/archive/chunkRouting.d.ts.map +1 -0
- package/dist/lib/archive/chunkRouting.js +47 -0
- package/dist/lib/archive/chunkStats.d.ts +12 -0
- package/dist/lib/archive/chunkStats.d.ts.map +1 -0
- package/dist/lib/archive/chunkStats.js +10 -0
- package/dist/lib/archive/index.d.ts +5 -0
- package/dist/lib/archive/index.d.ts.map +1 -0
- package/dist/lib/archive/index.js +4 -0
- package/dist/lib/arrow/capacityStats.d.ts +9 -0
- package/dist/lib/arrow/capacityStats.d.ts.map +1 -0
- package/dist/lib/arrow/capacityStats.js +231 -0
- package/dist/lib/arrow/dictionaries.d.ts +27 -0
- package/dist/lib/arrow/dictionaries.d.ts.map +1 -0
- package/dist/lib/arrow/dictionaries.js +135 -0
- package/dist/lib/arrow/flechette.d.ts +40 -0
- package/dist/lib/arrow/flechette.d.ts.map +1 -0
- package/dist/lib/arrow/flechette.js +67 -0
- package/dist/lib/arrow/utils.d.ts +38 -0
- package/dist/lib/arrow/utils.d.ts.map +1 -0
- package/dist/lib/arrow/utils.js +112 -0
- package/dist/lib/buffer/Nanoseconds.d.ts +109 -0
- package/dist/lib/buffer/Nanoseconds.d.ts.map +1 -0
- package/dist/lib/buffer/Nanoseconds.js +86 -0
- package/dist/lib/bufferStrategy.d.ts +95 -0
- package/dist/lib/bufferStrategy.d.ts.map +1 -0
- package/dist/lib/bufferStrategy.js +1 -0
- package/dist/lib/capacityTuning.d.ts +50 -0
- package/dist/lib/capacityTuning.d.ts.map +1 -0
- package/dist/lib/capacityTuning.js +65 -0
- package/dist/lib/codegen/evaluatorGenerator.d.ts +35 -0
- package/dist/lib/codegen/evaluatorGenerator.d.ts.map +1 -0
- package/dist/lib/codegen/evaluatorGenerator.js +199 -0
- package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts +139 -0
- package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts.map +1 -0
- package/dist/lib/codegen/fixedPositionWriterGenerator.js +289 -0
- package/dist/lib/codegen/spanLoggerGenerator.d.ts +115 -0
- package/dist/lib/codegen/spanLoggerGenerator.d.ts.map +1 -0
- package/dist/lib/codegen/spanLoggerGenerator.js +575 -0
- package/dist/lib/convertToArrow.d.ts +40 -0
- package/dist/lib/convertToArrow.d.ts.map +1 -0
- package/dist/lib/convertToArrow.js +1467 -0
- package/dist/lib/defineOpContext.d.ts +96 -0
- package/dist/lib/defineOpContext.d.ts.map +1 -0
- package/dist/lib/defineOpContext.js +227 -0
- package/dist/lib/errors/Blocked.d.ts +113 -0
- package/dist/lib/errors/Blocked.d.ts.map +1 -0
- package/dist/lib/errors/Blocked.js +68 -0
- package/dist/lib/errors/CodeError.d.ts +101 -0
- package/dist/lib/errors/CodeError.d.ts.map +1 -0
- package/dist/lib/errors/CodeError.js +42 -0
- package/dist/lib/errors/RetriesExhausted.d.ts +67 -0
- package/dist/lib/errors/RetriesExhausted.d.ts.map +1 -0
- package/dist/lib/errors/RetriesExhausted.js +31 -0
- package/dist/lib/errors/Transient.d.ts +115 -0
- package/dist/lib/errors/Transient.d.ts.map +1 -0
- package/dist/lib/errors/Transient.js +54 -0
- package/dist/lib/errors/index.d.ts +14 -0
- package/dist/lib/errors/index.d.ts.map +1 -0
- package/dist/lib/errors/index.js +16 -0
- package/dist/lib/errors/retry-policy.d.ts +60 -0
- package/dist/lib/errors/retry-policy.d.ts.map +1 -0
- package/dist/lib/errors/retry-policy.js +54 -0
- package/dist/lib/flushScheduler.d.ts +162 -0
- package/dist/lib/flushScheduler.d.ts.map +1 -0
- package/dist/lib/flushScheduler.js +388 -0
- package/dist/lib/library.d.ts +149 -0
- package/dist/lib/library.d.ts.map +1 -0
- package/dist/lib/library.js +588 -0
- package/dist/lib/logApi.d.ts +61 -0
- package/dist/lib/logApi.d.ts.map +1 -0
- package/dist/lib/logApi.js +12 -0
- package/dist/lib/logBinding.d.ts +63 -0
- package/dist/lib/logBinding.d.ts.map +1 -0
- package/dist/lib/logBinding.js +1 -0
- package/dist/lib/op.d.ts +105 -0
- package/dist/lib/op.d.ts.map +1 -0
- package/dist/lib/op.js +59 -0
- package/dist/lib/opContext/contextTypes.d.ts +88 -0
- package/dist/lib/opContext/contextTypes.d.ts.map +1 -0
- package/dist/lib/opContext/contextTypes.js +34 -0
- package/dist/lib/opContext/createOpGroup.d.ts +57 -0
- package/dist/lib/opContext/createOpGroup.d.ts.map +1 -0
- package/dist/lib/opContext/createOpGroup.js +341 -0
- package/dist/lib/opContext/defineOp.d.ts +83 -0
- package/dist/lib/opContext/defineOp.d.ts.map +1 -0
- package/dist/lib/opContext/defineOp.js +197 -0
- package/dist/lib/opContext/featureFlagTypes.d.ts +58 -0
- package/dist/lib/opContext/featureFlagTypes.d.ts.map +1 -0
- package/dist/lib/opContext/featureFlagTypes.js +1 -0
- package/dist/lib/opContext/index.d.ts +13 -0
- package/dist/lib/opContext/index.d.ts.map +1 -0
- package/dist/lib/opContext/index.js +15 -0
- package/dist/lib/opContext/opGroupTypes.d.ts +250 -0
- package/dist/lib/opContext/opGroupTypes.d.ts.map +1 -0
- package/dist/lib/opContext/opGroupTypes.js +31 -0
- package/dist/lib/opContext/opTypes.d.ts +48 -0
- package/dist/lib/opContext/opTypes.d.ts.map +1 -0
- package/dist/lib/opContext/opTypes.js +7 -0
- package/dist/lib/opContext/spanContextTypes.d.ts +347 -0
- package/dist/lib/opContext/spanContextTypes.d.ts.map +1 -0
- package/dist/lib/opContext/spanContextTypes.js +1 -0
- package/dist/lib/opContext/types.d.ts +297 -0
- package/dist/lib/opContext/types.d.ts.map +1 -0
- package/dist/lib/opContext/types.js +16 -0
- package/dist/lib/result.d.ts +308 -0
- package/dist/lib/result.d.ts.map +1 -0
- package/dist/lib/result.js +359 -0
- package/dist/lib/schema/LogSchema.d.ts +62 -0
- package/dist/lib/schema/LogSchema.d.ts.map +1 -0
- package/dist/lib/schema/LogSchema.js +134 -0
- package/dist/lib/schema/builder.d.ts +12 -0
- package/dist/lib/schema/builder.d.ts.map +1 -0
- package/dist/lib/schema/builder.js +169 -0
- package/dist/lib/schema/defineFeatureFlags.d.ts +60 -0
- package/dist/lib/schema/defineFeatureFlags.d.ts.map +1 -0
- package/dist/lib/schema/defineFeatureFlags.js +29 -0
- package/dist/lib/schema/defineLogSchema.d.ts +87 -0
- package/dist/lib/schema/defineLogSchema.d.ts.map +1 -0
- package/dist/lib/schema/defineLogSchema.js +171 -0
- package/dist/lib/schema/evaluator.d.ts +267 -0
- package/dist/lib/schema/evaluator.d.ts.map +1 -0
- package/dist/lib/schema/evaluator.js +169 -0
- package/dist/lib/schema/extend.d.ts +14 -0
- package/dist/lib/schema/extend.d.ts.map +1 -0
- package/dist/lib/schema/extend.js +51 -0
- package/dist/lib/schema/systemSchema.d.ts +112 -0
- package/dist/lib/schema/systemSchema.d.ts.map +1 -0
- package/dist/lib/schema/systemSchema.js +260 -0
- package/dist/lib/schema/typeGuards.d.ts +52 -0
- package/dist/lib/schema/typeGuards.d.ts.map +1 -0
- package/dist/lib/schema/typeGuards.js +127 -0
- package/dist/lib/schema/types.d.ts +156 -0
- package/dist/lib/schema/types.d.ts.map +1 -0
- package/dist/lib/schema/types.js +4 -0
- package/dist/lib/spanBuffer.d.ts +133 -0
- package/dist/lib/spanBuffer.d.ts.map +1 -0
- package/dist/lib/spanBuffer.js +442 -0
- package/dist/lib/spanBufferHelpers.d.ts +53 -0
- package/dist/lib/spanBufferHelpers.d.ts.map +1 -0
- package/dist/lib/spanBufferHelpers.js +65 -0
- package/dist/lib/spanBufferStats.d.ts +38 -0
- package/dist/lib/spanBufferStats.d.ts.map +1 -0
- package/dist/lib/spanBufferStats.js +1 -0
- package/dist/lib/spanContext.d.ts +141 -0
- package/dist/lib/spanContext.d.ts.map +1 -0
- package/dist/lib/spanContext.js +763 -0
- package/dist/lib/sqlite/index.d.ts +14 -0
- package/dist/lib/sqlite/index.d.ts.map +1 -0
- package/dist/lib/sqlite/index.js +12 -0
- package/dist/lib/sqlite/sqlite-async-writer.d.ts +24 -0
- package/dist/lib/sqlite/sqlite-async-writer.d.ts.map +1 -0
- package/dist/lib/sqlite/sqlite-async-writer.js +65 -0
- package/dist/lib/sqlite/sqlite-common.d.ts +37 -0
- package/dist/lib/sqlite/sqlite-common.d.ts.map +1 -0
- package/dist/lib/sqlite/sqlite-common.js +207 -0
- package/dist/lib/sqlite/sqlite-d1.d.ts +25 -0
- package/dist/lib/sqlite/sqlite-d1.d.ts.map +1 -0
- package/dist/lib/sqlite/sqlite-d1.js +67 -0
- package/dist/lib/sqlite/sqlite-db.d.ts +29 -0
- package/dist/lib/sqlite/sqlite-db.d.ts.map +1 -0
- package/dist/lib/sqlite/sqlite-db.js +1 -0
- package/dist/lib/sqlite/sqlite-node.d.ts +16 -0
- package/dist/lib/sqlite/sqlite-node.d.ts.map +1 -0
- package/dist/lib/sqlite/sqlite-node.js +68 -0
- package/dist/lib/sqlite/sqlite-writer.d.ts +39 -0
- package/dist/lib/sqlite/sqlite-writer.d.ts.map +1 -0
- package/dist/lib/sqlite/sqlite-writer.js +78 -0
- package/dist/lib/testing/bun-harness.d.ts +150 -0
- package/dist/lib/testing/bun-harness.d.ts.map +1 -0
- package/dist/lib/testing/bun-harness.js +729 -0
- package/dist/lib/testing/extractFacts.d.ts +73 -0
- package/dist/lib/testing/extractFacts.d.ts.map +1 -0
- package/dist/lib/testing/extractFacts.js +237 -0
- package/dist/lib/testing/facts.d.ts +235 -0
- package/dist/lib/testing/facts.d.ts.map +1 -0
- package/dist/lib/testing/facts.js +209 -0
- package/dist/lib/testing/index.d.ts +58 -0
- package/dist/lib/testing/index.d.ts.map +1 -0
- package/dist/lib/testing/index.js +74 -0
- package/dist/lib/testing/queryable-span.d.ts +39 -0
- package/dist/lib/testing/queryable-span.d.ts.map +1 -0
- package/dist/lib/testing/queryable-span.js +58 -0
- package/dist/lib/testing/span-query.d.ts +21 -0
- package/dist/lib/testing/span-query.d.ts.map +1 -0
- package/dist/lib/testing/span-query.js +47 -0
- package/dist/lib/testing/stdio-replay.d.ts +4 -0
- package/dist/lib/testing/stdio-replay.d.ts.map +1 -0
- package/dist/lib/testing/stdio-replay.js +42 -0
- package/dist/lib/testing/trace-query.d.ts +59 -0
- package/dist/lib/testing/trace-query.d.ts.map +1 -0
- package/dist/lib/testing/trace-query.js +462 -0
- package/dist/lib/testing/vitest-harness.d.ts +135 -0
- package/dist/lib/testing/vitest-harness.d.ts.map +1 -0
- package/dist/lib/testing/vitest-harness.js +486 -0
- package/dist/lib/threadId.d.ts +58 -0
- package/dist/lib/threadId.d.ts.map +1 -0
- package/dist/lib/threadId.js +123 -0
- package/dist/lib/traceContext.d.ts +116 -0
- package/dist/lib/traceContext.d.ts.map +1 -0
- package/dist/lib/traceContext.js +37 -0
- package/dist/lib/traceId.d.ts +78 -0
- package/dist/lib/traceId.d.ts.map +1 -0
- package/dist/lib/traceId.js +87 -0
- package/dist/lib/traceRoot.d.ts +133 -0
- package/dist/lib/traceRoot.d.ts.map +1 -0
- package/dist/lib/traceRoot.es.d.ts +75 -0
- package/dist/lib/traceRoot.es.d.ts.map +1 -0
- package/dist/lib/traceRoot.es.js +129 -0
- package/dist/lib/traceRoot.js +19 -0
- package/dist/lib/traceRoot.node.d.ts +77 -0
- package/dist/lib/traceRoot.node.d.ts.map +1 -0
- package/dist/lib/traceRoot.node.js +133 -0
- package/dist/lib/traceRoot.universal.d.ts +3 -0
- package/dist/lib/traceRoot.universal.d.ts.map +1 -0
- package/dist/lib/traceRoot.universal.js +17 -0
- package/dist/lib/tracer.d.ts +296 -0
- package/dist/lib/tracer.d.ts.map +1 -0
- package/dist/lib/tracer.js +346 -0
- package/dist/lib/tracers/ArrayQueueTracer.d.ts +56 -0
- package/dist/lib/tracers/ArrayQueueTracer.d.ts.map +1 -0
- package/dist/lib/tracers/ArrayQueueTracer.js +67 -0
- package/dist/lib/tracers/CompositeTracer.d.ts +24 -0
- package/dist/lib/tracers/CompositeTracer.d.ts.map +1 -0
- package/dist/lib/tracers/CompositeTracer.js +57 -0
- package/dist/lib/tracers/NoOpTracer.d.ts +58 -0
- package/dist/lib/tracers/NoOpTracer.d.ts.map +1 -0
- package/dist/lib/tracers/NoOpTracer.js +41 -0
- package/dist/lib/tracers/SQLiteTracer.d.ts +42 -0
- package/dist/lib/tracers/SQLiteTracer.d.ts.map +1 -0
- package/dist/lib/tracers/SQLiteTracer.js +84 -0
- package/dist/lib/tracers/StdioTracer.d.ts +83 -0
- package/dist/lib/tracers/StdioTracer.d.ts.map +1 -0
- package/dist/lib/tracers/StdioTracer.js +270 -0
- package/dist/lib/tracers/TestTracer.d.ts +95 -0
- package/dist/lib/tracers/TestTracer.d.ts.map +1 -0
- package/dist/lib/tracers/TestTracer.js +87 -0
- package/dist/lib/tracers/index.d.ts +12 -0
- package/dist/lib/tracers/index.d.ts.map +1 -0
- package/dist/lib/tracers/index.js +11 -0
- package/dist/lib/types.d.ts +366 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +1 -0
- package/dist/lib/utf8Cache.d.ts +111 -0
- package/dist/lib/utf8Cache.d.ts.map +1 -0
- package/dist/lib/utf8Cache.js +177 -0
- package/dist/lib/wasm/WasmBufferStrategy.d.ts +88 -0
- package/dist/lib/wasm/WasmBufferStrategy.d.ts.map +1 -0
- package/dist/lib/wasm/WasmBufferStrategy.js +138 -0
- package/dist/lib/wasm/wasmAllocator.d.ts +109 -0
- package/dist/lib/wasm/wasmAllocator.d.ts.map +1 -0
- package/dist/lib/wasm/wasmAllocator.js +227 -0
- package/dist/lib/wasm/wasmSpanBuffer.d.ts +123 -0
- package/dist/lib/wasm/wasmSpanBuffer.d.ts.map +1 -0
- package/dist/lib/wasm/wasmSpanBuffer.js +772 -0
- package/dist/lib/wasm/wasmTraceRoot.d.ts +167 -0
- package/dist/lib/wasm/wasmTraceRoot.d.ts.map +1 -0
- package/dist/lib/wasm/wasmTraceRoot.js +264 -0
- package/dist/node.d.ts +7 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +8 -0
- package/dist/testing.d.ts +18 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +17 -0
- package/package.json +193 -0
- package/src/bun/preload.ts +11 -0
- package/src/bun/trace-preload.ts +14 -0
- package/src/es.ts +11 -0
- package/src/index.ts +194 -0
- package/src/lib/JsBufferStrategy.ts +102 -0
- package/src/lib/__tests__/arrow-builder-integration/arrow-conversion.test.ts +485 -0
- package/src/lib/__tests__/arrow-builder-integration/binary-arrow-conversion.test.ts +390 -0
- package/src/lib/__tests__/arrow-builder-integration/binary-comparison.test.ts +647 -0
- package/src/lib/__tests__/arrow-builder-integration/binary-format-compliance.test.ts +292 -0
- package/src/lib/__tests__/arrow-builder-integration/buffer-chaining.test.ts +354 -0
- package/src/lib/__tests__/arrow-builder-integration/foundation.test.ts +127 -0
- package/src/lib/__tests__/arrow-builder-integration/integration.test.ts +392 -0
- package/src/lib/__tests__/arrow-builder-integration/lazy-columns.test.ts +389 -0
- package/src/lib/__tests__/arrow-conversion-algorithms.test.ts +54 -0
- package/src/lib/__tests__/arrow-test-helpers.ts +71 -0
- package/src/lib/__tests__/binary-e2e.test.ts +203 -0
- package/src/lib/__tests__/buffer-overflow-op-api.test.ts +608 -0
- package/src/lib/__tests__/buffer-overflow.test.ts +612 -0
- package/src/lib/__tests__/capacity-tuning.test.ts +544 -0
- package/src/lib/__tests__/effective-schema.test.ts +439 -0
- package/src/lib/__tests__/flechette.test.ts +42 -0
- package/src/lib/__tests__/flushScheduler.test.ts +537 -0
- package/src/lib/__tests__/integration.test.ts +600 -0
- package/src/lib/__tests__/library.test.ts +934 -0
- package/src/lib/__tests__/nested-library-tasks.test.ts +849 -0
- package/src/lib/__tests__/op-context-binding.test.ts +135 -0
- package/src/lib/__tests__/op-metadata.test.ts +198 -0
- package/src/lib/__tests__/op-type-safety.test.ts +71 -0
- package/src/lib/__tests__/package-exports.test.ts +57 -0
- package/src/lib/__tests__/remapped-buffer-view-integration.test.ts +319 -0
- package/src/lib/__tests__/remapped-buffer-view.test.ts +635 -0
- package/src/lib/__tests__/scope-attributes.test.ts +348 -0
- package/src/lib/__tests__/span-lifecycle.test.ts +680 -0
- package/src/lib/__tests__/sync-async-trace.test.ts +435 -0
- package/src/lib/__tests__/test-helpers.ts +318 -0
- package/src/lib/__tests__/timestamp.test.ts +259 -0
- package/src/lib/__tests__/trace-archive-primitives.test.ts +98 -0
- package/src/lib/__tests__/traceContext-type-enforcement.test.ts +271 -0
- package/src/lib/__tests__/tracer.test.ts +211 -0
- package/src/lib/__tests__/type-narrowing.test.ts +137 -0
- package/src/lib/archive/chunkCompaction.ts +44 -0
- package/src/lib/archive/chunkEnvelope.ts +79 -0
- package/src/lib/archive/chunkRouting.ts +70 -0
- package/src/lib/archive/chunkStats.ts +25 -0
- package/src/lib/archive/index.ts +4 -0
- package/src/lib/arrow/capacityStats.ts +340 -0
- package/src/lib/arrow/dictionaries.ts +159 -0
- package/src/lib/arrow/flechette.ts +114 -0
- package/src/lib/arrow/utils.ts +126 -0
- package/src/lib/buffer/Nanoseconds.ts +131 -0
- package/src/lib/bufferStrategy.ts +106 -0
- package/src/lib/capacityTuning.ts +102 -0
- package/src/lib/codegen/__tests__/__snapshots__/evaluatorGenerator.test.ts.snap +160 -0
- package/src/lib/codegen/__tests__/__snapshots__/scopeGenerator.test.ts.snap +196 -0
- package/src/lib/codegen/__tests__/__snapshots__/spanLoggerGenerator.test.ts.snap +1965 -0
- package/src/lib/codegen/__tests__/evaluatorGenerator.test.ts +516 -0
- package/src/lib/codegen/__tests__/nullBitmap.test.ts +207 -0
- package/src/lib/codegen/__tests__/spanLoggerGenerator.test.ts +237 -0
- package/src/lib/codegen/evaluatorGenerator.ts +309 -0
- package/src/lib/codegen/fixedPositionWriterGenerator.ts +444 -0
- package/src/lib/codegen/spanLoggerGenerator.ts +715 -0
- package/src/lib/convertToArrow.ts +1805 -0
- package/src/lib/defineOpContext.ts +398 -0
- package/src/lib/errors/Blocked.ts +165 -0
- package/src/lib/errors/CodeError.ts +132 -0
- package/src/lib/errors/RetriesExhausted.ts +78 -0
- package/src/lib/errors/Transient.ts +168 -0
- package/src/lib/errors/__tests__/Blocked-config.test.ts +152 -0
- package/src/lib/errors/__tests__/Transient.test.ts +129 -0
- package/src/lib/errors/__tests__/retry-policy.test.ts +85 -0
- package/src/lib/errors/index.ts +24 -0
- package/src/lib/errors/retry-policy.ts +87 -0
- package/src/lib/flushScheduler.ts +509 -0
- package/src/lib/library.ts +682 -0
- package/src/lib/logApi.ts +70 -0
- package/src/lib/logBinding.ts +67 -0
- package/src/lib/op.ts +103 -0
- package/src/lib/opContext/__tests__/retry.test.ts +764 -0
- package/src/lib/opContext/contextTypes.ts +130 -0
- package/src/lib/opContext/createOpGroup.ts +456 -0
- package/src/lib/opContext/defineOp.ts +281 -0
- package/src/lib/opContext/featureFlagTypes.ts +54 -0
- package/src/lib/opContext/index.ts +16 -0
- package/src/lib/opContext/opGroupTypes.ts +342 -0
- package/src/lib/opContext/opTypes.ts +80 -0
- package/src/lib/opContext/spanContextTypes.ts +398 -0
- package/src/lib/opContext/types.ts +403 -0
- package/src/lib/result.ts +550 -0
- package/src/lib/schema/LogSchema.ts +153 -0
- package/src/lib/schema/__tests__/defineLogSchema.test.ts +342 -0
- package/src/lib/schema/__tests__/featureFlags.test.ts +443 -0
- package/src/lib/schema/builder.ts +201 -0
- package/src/lib/schema/defineFeatureFlags.ts +91 -0
- package/src/lib/schema/defineLogSchema.ts +291 -0
- package/src/lib/schema/evaluator.ts +404 -0
- package/src/lib/schema/extend.ts +69 -0
- package/src/lib/schema/systemSchema.ts +339 -0
- package/src/lib/schema/typeGuards.ts +163 -0
- package/src/lib/schema/types.ts +265 -0
- package/src/lib/spanBuffer.ts +571 -0
- package/src/lib/spanBufferHelpers.ts +73 -0
- package/src/lib/spanBufferStats.ts +40 -0
- package/src/lib/spanContext.ts +1566 -0
- package/src/lib/sqlite/__tests__/sqlite-common.test.ts +89 -0
- package/src/lib/sqlite/index.ts +26 -0
- package/src/lib/sqlite/sqlite-async-writer.ts +101 -0
- package/src/lib/sqlite/sqlite-common.ts +309 -0
- package/src/lib/sqlite/sqlite-d1.ts +104 -0
- package/src/lib/sqlite/sqlite-db.ts +32 -0
- package/src/lib/sqlite/sqlite-node.ts +83 -0
- package/src/lib/sqlite/sqlite-writer.ts +128 -0
- package/src/lib/testing/TRACE-TESTING.md +100 -0
- package/src/lib/testing/__tests__/bun-harness.test.ts +108 -0
- package/src/lib/testing/__tests__/extractFacts.test.ts +279 -0
- package/src/lib/testing/__tests__/facts.test.ts +324 -0
- package/src/lib/testing/__tests__/vitest-harness.test.ts +32 -0
- package/src/lib/testing/bun-harness.ts +990 -0
- package/src/lib/testing/extractFacts.ts +362 -0
- package/src/lib/testing/facts.ts +470 -0
- package/src/lib/testing/index.ts +141 -0
- package/src/lib/testing/queryable-span.ts +108 -0
- package/src/lib/testing/span-query.ts +65 -0
- package/src/lib/testing/stdio-replay.ts +50 -0
- package/src/lib/testing/trace-query.ts +329 -0
- package/src/lib/testing/vitest-harness.ts +691 -0
- package/src/lib/threadId.ts +135 -0
- package/src/lib/traceContext.ts +182 -0
- package/src/lib/traceId.ts +142 -0
- package/src/lib/traceRoot.es.ts +157 -0
- package/src/lib/traceRoot.node.ts +170 -0
- package/src/lib/traceRoot.ts +154 -0
- package/src/lib/traceRoot.universal.ts +22 -0
- package/src/lib/tracer.ts +896 -0
- package/src/lib/tracers/ArrayQueueTracer.ts +76 -0
- package/src/lib/tracers/CompositeTracer.ts +76 -0
- package/src/lib/tracers/NoOpTracer.ts +73 -0
- package/src/lib/tracers/SQLiteTracer.ts +115 -0
- package/src/lib/tracers/StdioTracer.ts +380 -0
- package/src/lib/tracers/TestTracer.ts +146 -0
- package/src/lib/tracers/__tests__/ArrayQueueTracer.test.ts +184 -0
- package/src/lib/tracers/__tests__/NoOpTracer.test.ts +204 -0
- package/src/lib/tracers/__tests__/StdioTracer.test.ts +313 -0
- package/src/lib/tracers/__tests__/TestTracer.test.ts +200 -0
- package/src/lib/tracers/index.ts +12 -0
- package/src/lib/types.ts +498 -0
- package/src/lib/utf8Cache.ts +201 -0
- package/src/lib/wasm/WasmBufferStrategy.ts +219 -0
- package/src/lib/wasm/__tests__/WasmBufferStrategy.test.ts +256 -0
- package/src/lib/wasm/__tests__/wasm-integration.test.ts +476 -0
- package/src/lib/wasm/__tests__/wasmAllocator.test.ts +699 -0
- package/src/lib/wasm/__tests__/wasmSpanBuffer.test.ts +449 -0
- package/src/lib/wasm/__tests__/wasmTraceRoot.test.ts +390 -0
- package/src/lib/wasm/__tests__/wasmTracer.test.ts.disabled +444 -0
- package/src/lib/wasm/allocator.zig +945 -0
- package/src/lib/wasm/wasmAllocator.ts +469 -0
- package/src/lib/wasm/wasmSpanBuffer.ts +1014 -0
- package/src/lib/wasm/wasmTraceRoot.ts +315 -0
- package/src/node.ts +10 -0
- 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
|
+
});
|