@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,849 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for nested library tasks with prefix remapping
|
|
3
|
+
*
|
|
4
|
+
* Per specs/lmao/01e_library_integration_pattern.md:
|
|
5
|
+
* - Libraries define clean schemas (status, method)
|
|
6
|
+
* - Prefixes applied at composition time (http_status, http_method)
|
|
7
|
+
* - Library code writes to clean names, stored in prefixed columns
|
|
8
|
+
*
|
|
9
|
+
* Per specs/lmao/01k_tree_walker_and_arrow_conversion.md:
|
|
10
|
+
* - Tree traversal visits all buffers including children
|
|
11
|
+
* - Arrow conversion uses shared dictionaries across all buffers
|
|
12
|
+
*
|
|
13
|
+
* ## Migration Note
|
|
14
|
+
* The old `createTrace()` function has been removed from `defineOpContext()`.
|
|
15
|
+
* Tests now use the Tracer class directly with the context from `defineOpContext()`.
|
|
16
|
+
* For nested ops with different schemas, use a combined schema or inline functions.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { describe, expect, it } from 'bun:test';
|
|
20
|
+
// Must import test-helpers first to initialize timestamp implementation
|
|
21
|
+
import './test-helpers.js';
|
|
22
|
+
import { convertSpanTreeToArrowTable } from '../convertToArrow.js';
|
|
23
|
+
import { defineOpContext } from '../defineOpContext.js';
|
|
24
|
+
import { S } from '../schema/builder.js';
|
|
25
|
+
import { defineLogSchema } from '../schema/defineLogSchema.js';
|
|
26
|
+
import { TestTracer } from '../tracers/TestTracer.js';
|
|
27
|
+
import type { AnySpanBuffer } from '../types.js';
|
|
28
|
+
import { createTestTracerOptions } from './test-helpers.js';
|
|
29
|
+
|
|
30
|
+
function extractRows(
|
|
31
|
+
table: ReturnType<typeof convertSpanTreeToArrowTable>,
|
|
32
|
+
columns: readonly string[],
|
|
33
|
+
): Array<Record<string, unknown>> {
|
|
34
|
+
return Array.from({ length: table.numRows }, (_, rowIndex) => {
|
|
35
|
+
const row: Record<string, unknown> = {};
|
|
36
|
+
for (const columnName of columns) {
|
|
37
|
+
const column = table.getChild(columnName);
|
|
38
|
+
if (column) {
|
|
39
|
+
row[columnName] = column.get(rowIndex) as unknown;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return row;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
describe('Nested Library Tasks', () => {
|
|
47
|
+
describe('4-level nesting WITHOUT library prefixes (regular module contexts)', () => {
|
|
48
|
+
/**
|
|
49
|
+
* Test scenario: App -> Module1.op -> Module2.op -> Module3.op -> Module4.op
|
|
50
|
+
* All modules use the same schema (no prefixing)
|
|
51
|
+
* Verifies tree structure and Arrow conversion
|
|
52
|
+
*/
|
|
53
|
+
it('should create proper parent-child hierarchy with 4 levels of nesting', async () => {
|
|
54
|
+
// Shared schema for all modules
|
|
55
|
+
const sharedSchema = defineLogSchema({
|
|
56
|
+
userId: S.category(),
|
|
57
|
+
operation: S.enum(['CREATE', 'READ', 'UPDATE', 'DELETE']),
|
|
58
|
+
depth: S.number(),
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Create op context factory with the shared schema
|
|
62
|
+
const opContext = defineOpContext({
|
|
63
|
+
logSchema: sharedSchema,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const { defineOp } = opContext;
|
|
67
|
+
const { trace } = new TestTracer(opContext, { ...createTestTracerOptions() });
|
|
68
|
+
|
|
69
|
+
// Capture buffers for verification
|
|
70
|
+
let rootBuffer: AnySpanBuffer | undefined;
|
|
71
|
+
let level2Buffer: AnySpanBuffer | undefined;
|
|
72
|
+
let level3Buffer: AnySpanBuffer | undefined;
|
|
73
|
+
let level4Buffer: AnySpanBuffer | undefined;
|
|
74
|
+
|
|
75
|
+
// Level 4 op (deepest)
|
|
76
|
+
const level4Op = defineOp('level4-op', async (ctx) => {
|
|
77
|
+
level4Buffer = ctx.buffer;
|
|
78
|
+
ctx.tag.depth(4);
|
|
79
|
+
ctx.tag.operation('DELETE');
|
|
80
|
+
return ctx.ok('level4-done');
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Level 3 op
|
|
84
|
+
const level3Op = defineOp('level3-op', async (ctx) => {
|
|
85
|
+
level3Buffer = ctx.buffer;
|
|
86
|
+
ctx.tag.depth(3);
|
|
87
|
+
ctx.tag.operation('UPDATE');
|
|
88
|
+
|
|
89
|
+
// Call level 4 op
|
|
90
|
+
await ctx.span('level4-op', level4Op);
|
|
91
|
+
|
|
92
|
+
return ctx.ok('level3-done');
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Level 2 op
|
|
96
|
+
const level2Op = defineOp('level2-op', async (ctx) => {
|
|
97
|
+
level2Buffer = ctx.buffer;
|
|
98
|
+
ctx.tag.depth(2);
|
|
99
|
+
ctx.tag.operation('READ');
|
|
100
|
+
|
|
101
|
+
// Call level 3 op
|
|
102
|
+
await ctx.span('level3-op', level3Op);
|
|
103
|
+
|
|
104
|
+
return ctx.ok('level2-done');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Root op (level 1)
|
|
108
|
+
const rootOp = defineOp('root-op', async (ctx) => {
|
|
109
|
+
rootBuffer = ctx.buffer;
|
|
110
|
+
ctx.tag.userId('user-123');
|
|
111
|
+
ctx.tag.depth(1);
|
|
112
|
+
ctx.tag.operation('CREATE');
|
|
113
|
+
|
|
114
|
+
// Call level 2 op
|
|
115
|
+
await ctx.span('level2-op', level2Op);
|
|
116
|
+
|
|
117
|
+
return ctx.ok('root-done');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// Execute the nested op chain
|
|
121
|
+
const result = await trace('root-op', rootOp);
|
|
122
|
+
|
|
123
|
+
// Verify result
|
|
124
|
+
expect(result.success).toBe(true);
|
|
125
|
+
|
|
126
|
+
// Verify all buffers were captured
|
|
127
|
+
expect(rootBuffer).toBeDefined();
|
|
128
|
+
expect(level2Buffer).toBeDefined();
|
|
129
|
+
expect(level3Buffer).toBeDefined();
|
|
130
|
+
expect(level4Buffer).toBeDefined();
|
|
131
|
+
|
|
132
|
+
// Verify parent-child relationships
|
|
133
|
+
// Root has no parent
|
|
134
|
+
expect(rootBuffer?._parent).toBeUndefined();
|
|
135
|
+
|
|
136
|
+
// Level 2's parent is root
|
|
137
|
+
expect(level2Buffer?._parent).toBe(rootBuffer);
|
|
138
|
+
|
|
139
|
+
// Level 3's parent is level 2
|
|
140
|
+
expect(level3Buffer?._parent).toBe(level2Buffer);
|
|
141
|
+
|
|
142
|
+
// Level 4's parent is level 3
|
|
143
|
+
expect(level4Buffer?._parent).toBe(level3Buffer);
|
|
144
|
+
|
|
145
|
+
// Verify children array
|
|
146
|
+
expect(rootBuffer?._children).toContain(level2Buffer);
|
|
147
|
+
expect(level2Buffer?._children).toContain(level3Buffer);
|
|
148
|
+
expect(level3Buffer?._children).toContain(level4Buffer);
|
|
149
|
+
expect(level4Buffer?._children.length).toBe(0);
|
|
150
|
+
|
|
151
|
+
// Verify all share the same traceId
|
|
152
|
+
const traceId = rootBuffer?.trace_id;
|
|
153
|
+
expect(level2Buffer?.trace_id).toBe(traceId);
|
|
154
|
+
expect(level3Buffer?.trace_id).toBe(traceId);
|
|
155
|
+
expect(level4Buffer?.trace_id).toBe(traceId);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('should convert 4-level nested tree to Arrow table with correct parent-child relationships', async () => {
|
|
159
|
+
const sharedSchema = defineLogSchema({
|
|
160
|
+
level: S.number(),
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
const opContext = defineOpContext({
|
|
164
|
+
logSchema: sharedSchema,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const { defineOp } = opContext;
|
|
168
|
+
const { trace } = new TestTracer(opContext, { ...createTestTracerOptions() });
|
|
169
|
+
|
|
170
|
+
let rootBuffer: AnySpanBuffer | undefined;
|
|
171
|
+
|
|
172
|
+
const level4Op = defineOp('level4', async (ctx) => {
|
|
173
|
+
ctx.tag.level(4);
|
|
174
|
+
return ctx.ok('done');
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
const level3Op = defineOp('level3', async (ctx) => {
|
|
178
|
+
ctx.tag.level(3);
|
|
179
|
+
await ctx.span('level4', level4Op);
|
|
180
|
+
return ctx.ok('done');
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
const level2Op = defineOp('level2', async (ctx) => {
|
|
184
|
+
ctx.tag.level(2);
|
|
185
|
+
await ctx.span('level3', level3Op);
|
|
186
|
+
return ctx.ok('done');
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
const rootOp = defineOp('root', async (ctx) => {
|
|
190
|
+
rootBuffer = ctx.buffer;
|
|
191
|
+
ctx.tag.level(1);
|
|
192
|
+
await ctx.span('level2', level2Op);
|
|
193
|
+
return ctx.ok('done');
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
await trace('root', rootOp);
|
|
197
|
+
|
|
198
|
+
expect(rootBuffer).toBeDefined();
|
|
199
|
+
if (!rootBuffer) throw new Error('rootBuffer is undefined');
|
|
200
|
+
|
|
201
|
+
// Convert to Arrow table
|
|
202
|
+
const table = convertSpanTreeToArrowTable(rootBuffer);
|
|
203
|
+
|
|
204
|
+
// Should have rows for all 4 levels (span-start + span-ok for each = 8 rows)
|
|
205
|
+
expect(table.numRows).toBeGreaterThanOrEqual(8);
|
|
206
|
+
|
|
207
|
+
// Extract all rows for verification
|
|
208
|
+
const rows = extractRows(table, [
|
|
209
|
+
'entry_type',
|
|
210
|
+
'message',
|
|
211
|
+
'span_id',
|
|
212
|
+
'parent_span_id',
|
|
213
|
+
'trace_id',
|
|
214
|
+
'http_status',
|
|
215
|
+
'db_status',
|
|
216
|
+
'process_status',
|
|
217
|
+
]);
|
|
218
|
+
|
|
219
|
+
// Find span-start entries for each level
|
|
220
|
+
const spanStarts = rows.filter((r) => r?.entry_type === 'span-start');
|
|
221
|
+
|
|
222
|
+
// Should have 4 span-start entries (one per level)
|
|
223
|
+
expect(spanStarts.length).toBe(4);
|
|
224
|
+
|
|
225
|
+
// Verify parent-child relationships in Arrow output
|
|
226
|
+
const rootSpan = spanStarts.find((r) => r?.message === 'root');
|
|
227
|
+
const level2Span = spanStarts.find((r) => r?.message === 'level2');
|
|
228
|
+
const level3Span = spanStarts.find((r) => r?.message === 'level3');
|
|
229
|
+
const level4Span = spanStarts.find((r) => r?.message === 'level4');
|
|
230
|
+
|
|
231
|
+
expect(rootSpan).toBeDefined();
|
|
232
|
+
expect(level2Span).toBeDefined();
|
|
233
|
+
expect(level3Span).toBeDefined();
|
|
234
|
+
expect(level4Span).toBeDefined();
|
|
235
|
+
|
|
236
|
+
// Root has no parent (null in Arrow)
|
|
237
|
+
expect(rootSpan?.parent_span_id).toBeNull();
|
|
238
|
+
|
|
239
|
+
// Level 2's parent is root
|
|
240
|
+
expect(level2Span?.parent_span_id).toBe(rootSpan?.span_id);
|
|
241
|
+
|
|
242
|
+
// Level 3's parent is level 2
|
|
243
|
+
expect(level3Span?.parent_span_id).toBe(level2Span?.span_id);
|
|
244
|
+
|
|
245
|
+
// Level 4's parent is level 3
|
|
246
|
+
expect(level4Span?.parent_span_id).toBe(level3Span?.span_id);
|
|
247
|
+
|
|
248
|
+
// All have same trace_id
|
|
249
|
+
expect(level2Span?.trace_id).toBe(rootSpan?.trace_id);
|
|
250
|
+
expect(level3Span?.trace_id).toBe(rootSpan?.trace_id);
|
|
251
|
+
expect(level4Span?.trace_id).toBe(rootSpan?.trace_id);
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
describe('4-level nesting WITH library prefixes (separate defineOpContext per library)', () => {
|
|
256
|
+
/**
|
|
257
|
+
* Test scenario: App -> HTTP lib op -> DB lib op -> Cache lib op -> Auth lib op
|
|
258
|
+
*
|
|
259
|
+
* Per specs/lmao/01e_library_integration_pattern.md:
|
|
260
|
+
* - Each library defines its OWN schema with clean names (status, query, key, userId)
|
|
261
|
+
* - Libraries are composed via deps with .prefix() for namespacing
|
|
262
|
+
* - Effective schema has prefixed columns (http_status, db_query, cache_key, auth_userId)
|
|
263
|
+
* - Library code writes to UNPREFIXED names, stored in PREFIXED columns via remapping
|
|
264
|
+
*
|
|
265
|
+
* This is the CORRECT pattern - 4 separate defineOpContext calls, composed via deps.
|
|
266
|
+
*/
|
|
267
|
+
|
|
268
|
+
// =====================================
|
|
269
|
+
// LIBRARY DEFINITIONS (separate packages in real code)
|
|
270
|
+
// =====================================
|
|
271
|
+
|
|
272
|
+
// Auth library - deepest level (level 4)
|
|
273
|
+
const authSchema = defineLogSchema({
|
|
274
|
+
userId: S.category(),
|
|
275
|
+
role: S.category(),
|
|
276
|
+
});
|
|
277
|
+
const authContext = defineOpContext({ logSchema: authSchema });
|
|
278
|
+
const authOps = authContext.defineOps({
|
|
279
|
+
checkAuth: async (ctx) => {
|
|
280
|
+
// Library writes to unprefixed names
|
|
281
|
+
ctx.tag.userId('user-456').role('admin');
|
|
282
|
+
return ctx.ok({ authorized: true });
|
|
283
|
+
},
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
// Cache library - level 3 (depends on auth)
|
|
287
|
+
const cacheSchema = defineLogSchema({
|
|
288
|
+
key: S.category(),
|
|
289
|
+
hit: S.boolean(),
|
|
290
|
+
});
|
|
291
|
+
const cacheContext = defineOpContext({
|
|
292
|
+
logSchema: cacheSchema,
|
|
293
|
+
deps: { auth: authOps.prefix('auth') },
|
|
294
|
+
});
|
|
295
|
+
const cacheOps = cacheContext.defineOps({
|
|
296
|
+
lookup: async (ctx) => {
|
|
297
|
+
ctx.tag.key('session:user-456').hit(true);
|
|
298
|
+
// Call auth library via deps
|
|
299
|
+
|
|
300
|
+
await ctx.span('auth-check', ctx.deps.auth.checkAuth);
|
|
301
|
+
return ctx.ok({ cached: true });
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
// DB library - level 2 (depends on cache)
|
|
306
|
+
const dbSchema = defineLogSchema({
|
|
307
|
+
query: S.text(),
|
|
308
|
+
rowCount: S.number(),
|
|
309
|
+
});
|
|
310
|
+
const dbContext = defineOpContext({
|
|
311
|
+
logSchema: dbSchema,
|
|
312
|
+
deps: { cache: cacheOps.prefix('cache') },
|
|
313
|
+
});
|
|
314
|
+
const dbOps = dbContext.defineOps({
|
|
315
|
+
execute: async (ctx) => {
|
|
316
|
+
ctx.tag.query('SELECT * FROM users').rowCount(1);
|
|
317
|
+
// Call cache library via deps
|
|
318
|
+
|
|
319
|
+
await ctx.span('cache-lookup', ctx.deps.cache.lookup);
|
|
320
|
+
return ctx.ok({ rows: [] });
|
|
321
|
+
},
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
// HTTP library - level 1 (depends on db)
|
|
325
|
+
const httpSchema = defineLogSchema({
|
|
326
|
+
status: S.number(),
|
|
327
|
+
method: S.enum(['GET', 'POST', 'PUT', 'DELETE']),
|
|
328
|
+
});
|
|
329
|
+
const httpContext = defineOpContext({
|
|
330
|
+
logSchema: httpSchema,
|
|
331
|
+
deps: { db: dbOps.prefix('db') },
|
|
332
|
+
});
|
|
333
|
+
const httpOps = httpContext.defineOps({
|
|
334
|
+
request: async (ctx) => {
|
|
335
|
+
ctx.tag.status(200).method('GET');
|
|
336
|
+
// Call DB library via deps
|
|
337
|
+
|
|
338
|
+
await ctx.span('db-query', ctx.deps.db.execute);
|
|
339
|
+
return ctx.ok({ response: 'ok' });
|
|
340
|
+
},
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
// =====================================
|
|
344
|
+
// APP (root level, composes all libraries)
|
|
345
|
+
// =====================================
|
|
346
|
+
const appSchema = defineLogSchema({
|
|
347
|
+
requestId: S.category(),
|
|
348
|
+
});
|
|
349
|
+
const appContext = defineOpContext({
|
|
350
|
+
logSchema: appSchema,
|
|
351
|
+
deps: {
|
|
352
|
+
http: httpOps.prefix('http'),
|
|
353
|
+
db: dbOps.prefix('db'),
|
|
354
|
+
cache: cacheOps.prefix('cache'),
|
|
355
|
+
auth: authOps.prefix('auth'),
|
|
356
|
+
},
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
it('should compose 4 separate library contexts with prefixed columns', async () => {
|
|
360
|
+
const { defineOp } = appContext;
|
|
361
|
+
|
|
362
|
+
const { trace } = new TestTracer(appContext, { ...createTestTracerOptions() });
|
|
363
|
+
|
|
364
|
+
let rootBuffer: AnySpanBuffer | undefined;
|
|
365
|
+
|
|
366
|
+
const appOp = defineOp('handle-request', async (ctx) => {
|
|
367
|
+
rootBuffer = ctx.buffer;
|
|
368
|
+
ctx.tag.requestId('req-123');
|
|
369
|
+
// Call HTTP library via deps
|
|
370
|
+
|
|
371
|
+
await ctx.span('http-request', ctx.deps.http.request);
|
|
372
|
+
return ctx.ok({ handled: true });
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
const result = await trace('handle-request', appOp);
|
|
376
|
+
|
|
377
|
+
expect(result.success).toBe(true);
|
|
378
|
+
expect(rootBuffer).toBeDefined();
|
|
379
|
+
if (!rootBuffer) throw new Error('rootBuffer is undefined');
|
|
380
|
+
|
|
381
|
+
// Convert to Arrow table
|
|
382
|
+
const table = convertSpanTreeToArrowTable(rootBuffer);
|
|
383
|
+
|
|
384
|
+
// Should have rows for all 5 levels (app + 4 libraries)
|
|
385
|
+
// Each span has span-start + span-ok = 2 rows minimum
|
|
386
|
+
expect(table.numRows).toBeGreaterThanOrEqual(10);
|
|
387
|
+
|
|
388
|
+
// Verify prefixed columns exist in schema
|
|
389
|
+
const fieldNames = table.schema.fields.map((f) => f.name);
|
|
390
|
+
|
|
391
|
+
// App column
|
|
392
|
+
expect(fieldNames).toContain('requestId');
|
|
393
|
+
|
|
394
|
+
// HTTP library columns should be prefixed
|
|
395
|
+
expect(fieldNames).toContain('http_status');
|
|
396
|
+
expect(fieldNames).toContain('http_method');
|
|
397
|
+
|
|
398
|
+
// DB library columns should be prefixed
|
|
399
|
+
expect(fieldNames).toContain('db_query');
|
|
400
|
+
expect(fieldNames).toContain('db_rowCount');
|
|
401
|
+
|
|
402
|
+
// Cache library columns should be prefixed
|
|
403
|
+
expect(fieldNames).toContain('cache_key');
|
|
404
|
+
expect(fieldNames).toContain('cache_hit');
|
|
405
|
+
|
|
406
|
+
// Auth library columns should be prefixed
|
|
407
|
+
expect(fieldNames).toContain('auth_userId');
|
|
408
|
+
expect(fieldNames).toContain('auth_role');
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
it('should maintain correct tree structure with 4 levels of library tasks', async () => {
|
|
412
|
+
const { defineOp } = appContext;
|
|
413
|
+
|
|
414
|
+
const { trace } = new TestTracer(appContext, { ...createTestTracerOptions() });
|
|
415
|
+
|
|
416
|
+
let appBuffer: AnySpanBuffer | undefined;
|
|
417
|
+
|
|
418
|
+
const appOp = defineOp('handle-request', async (ctx) => {
|
|
419
|
+
appBuffer = ctx.buffer;
|
|
420
|
+
ctx.tag.requestId('req-123');
|
|
421
|
+
await ctx.span('http-request', ctx.deps.http.request);
|
|
422
|
+
return ctx.ok({ handled: true });
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
await trace('handle-request', appOp);
|
|
426
|
+
|
|
427
|
+
// Verify root buffer captured
|
|
428
|
+
expect(appBuffer).toBeDefined();
|
|
429
|
+
if (!appBuffer) throw new Error('appBuffer is undefined');
|
|
430
|
+
|
|
431
|
+
// Walk tree to collect all buffers
|
|
432
|
+
const allBuffers: AnySpanBuffer[] = [];
|
|
433
|
+
const collectBuffers = (buf: AnySpanBuffer) => {
|
|
434
|
+
allBuffers.push(buf);
|
|
435
|
+
for (const child of buf._children) {
|
|
436
|
+
collectBuffers(child);
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
collectBuffers(appBuffer);
|
|
440
|
+
|
|
441
|
+
// Should have 5 buffers: app, http, db, cache, auth
|
|
442
|
+
expect(allBuffers.length).toBe(5);
|
|
443
|
+
|
|
444
|
+
// Verify parent-child chain
|
|
445
|
+
const httpBuffer = allBuffers.find((b) => b._children.length > 0 && b !== appBuffer);
|
|
446
|
+
expect(httpBuffer).toBeDefined();
|
|
447
|
+
expect(httpBuffer?._parent).toBe(appBuffer);
|
|
448
|
+
|
|
449
|
+
// All should share same traceId
|
|
450
|
+
for (const buf of allBuffers) {
|
|
451
|
+
expect(buf.trace_id).toBe(appBuffer.trace_id);
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
describe('Mixed nesting (some with prefix, some without)', () => {
|
|
457
|
+
/**
|
|
458
|
+
* Test scenario: App -> regularModule.op -> httpModule.op (prefixed) ->
|
|
459
|
+
* regularModule2.op -> dbModule.op (prefixed)
|
|
460
|
+
*/
|
|
461
|
+
it('should handle mixed nesting with both prefixed and non-prefixed modules', async () => {
|
|
462
|
+
// Combined schema with both prefixed and non-prefixed columns
|
|
463
|
+
const combinedSchema = defineLogSchema({
|
|
464
|
+
// Regular module columns (no prefix)
|
|
465
|
+
requestId: S.category(),
|
|
466
|
+
step: S.category(),
|
|
467
|
+
// HTTP library columns (prefixed)
|
|
468
|
+
http_status: S.number(),
|
|
469
|
+
http_url: S.text(),
|
|
470
|
+
// DB library columns (prefixed)
|
|
471
|
+
db_query: S.text(),
|
|
472
|
+
db_table: S.category(),
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
const opContext = defineOpContext({
|
|
476
|
+
logSchema: combinedSchema,
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
const { defineOp } = opContext;
|
|
480
|
+
const { trace } = new TestTracer(opContext, { ...createTestTracerOptions() });
|
|
481
|
+
|
|
482
|
+
let rootBuffer: AnySpanBuffer | undefined;
|
|
483
|
+
|
|
484
|
+
// DB op (deepest - level 4, prefixed)
|
|
485
|
+
const dbOp = defineOp('db-query', async (ctx) => {
|
|
486
|
+
ctx.tag.db_query('INSERT INTO logs').db_table('logs');
|
|
487
|
+
return ctx.ok('inserted');
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
// Regular module 2 op (level 3, no prefix)
|
|
491
|
+
const processorOp = defineOp('process', async (ctx) => {
|
|
492
|
+
ctx.tag.step('validation');
|
|
493
|
+
await ctx.span('db-query', dbOp);
|
|
494
|
+
return ctx.ok('processed');
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
// HTTP library op (level 2, prefixed)
|
|
498
|
+
const httpOp = defineOp('fetch', async (ctx) => {
|
|
499
|
+
ctx.tag.http_status(200).http_url('/api/process');
|
|
500
|
+
await ctx.span('process', processorOp);
|
|
501
|
+
return ctx.ok('fetched');
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
// Root op (level 1, no prefix)
|
|
505
|
+
const rootOp = defineOp('handle-request', async (ctx) => {
|
|
506
|
+
rootBuffer = ctx.buffer;
|
|
507
|
+
ctx.tag.requestId('req-123');
|
|
508
|
+
ctx.tag.step('start');
|
|
509
|
+
await ctx.span('fetch', httpOp);
|
|
510
|
+
return ctx.ok('handled');
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
const result = await trace('handle-request', rootOp);
|
|
514
|
+
|
|
515
|
+
expect(result.success).toBe(true);
|
|
516
|
+
expect(rootBuffer).toBeDefined();
|
|
517
|
+
if (!rootBuffer) throw new Error('rootBuffer is undefined');
|
|
518
|
+
|
|
519
|
+
// Convert to Arrow table
|
|
520
|
+
const table = convertSpanTreeToArrowTable(rootBuffer);
|
|
521
|
+
|
|
522
|
+
// Verify both prefixed and non-prefixed columns exist
|
|
523
|
+
const fieldNames = table.schema.fields.map((f) => f.name);
|
|
524
|
+
|
|
525
|
+
// Non-prefixed columns from regular modules
|
|
526
|
+
expect(fieldNames).toContain('requestId');
|
|
527
|
+
expect(fieldNames).toContain('step');
|
|
528
|
+
|
|
529
|
+
// Prefixed columns from libraries
|
|
530
|
+
expect(fieldNames).toContain('http_status');
|
|
531
|
+
expect(fieldNames).toContain('http_url');
|
|
532
|
+
expect(fieldNames).toContain('db_query');
|
|
533
|
+
expect(fieldNames).toContain('db_table');
|
|
534
|
+
|
|
535
|
+
// Extract rows
|
|
536
|
+
const rows = extractRows(table, ['entry_type', 'message', 'span_id', 'parent_span_id', 'trace_id']);
|
|
537
|
+
const spanStarts = rows.filter((r) => r?.entry_type === 'span-start');
|
|
538
|
+
|
|
539
|
+
// Should have 4 span-start entries
|
|
540
|
+
expect(spanStarts.length).toBe(4);
|
|
541
|
+
|
|
542
|
+
// Verify correct nesting order
|
|
543
|
+
const handleRequest = spanStarts.find((r) => r?.message === 'handle-request');
|
|
544
|
+
const fetch = spanStarts.find((r) => r?.message === 'fetch');
|
|
545
|
+
const process = spanStarts.find((r) => r?.message === 'process');
|
|
546
|
+
const dbQuery = spanStarts.find((r) => r?.message === 'db-query');
|
|
547
|
+
|
|
548
|
+
expect(handleRequest?.parent_span_id).toBeNull();
|
|
549
|
+
expect(fetch?.parent_span_id).toBe(handleRequest?.span_id);
|
|
550
|
+
expect(process?.parent_span_id).toBe(fetch?.span_id);
|
|
551
|
+
expect(dbQuery?.parent_span_id).toBe(process?.span_id);
|
|
552
|
+
});
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
describe('Column isolation test (same column name with different prefixes)', () => {
|
|
556
|
+
/**
|
|
557
|
+
* Per specs/lmao/01e_library_integration_pattern.md:
|
|
558
|
+
* - Multiple libraries can define the same attribute name
|
|
559
|
+
* - Prefixes resolve to different columns (http_status, db_status)
|
|
560
|
+
* - No collision, correct data in Arrow output
|
|
561
|
+
*/
|
|
562
|
+
it('should isolate columns with same name using different prefixes', async () => {
|
|
563
|
+
// All libraries have a "status" column concept, but with different prefixes
|
|
564
|
+
const combinedSchema = defineLogSchema({
|
|
565
|
+
http_status: S.number(),
|
|
566
|
+
db_status: S.category(),
|
|
567
|
+
process_status: S.enum(['running', 'stopped', 'failed']),
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
const opContext = defineOpContext({
|
|
571
|
+
logSchema: combinedSchema,
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
const { defineOp } = opContext;
|
|
575
|
+
const { trace } = new TestTracer(opContext, { ...createTestTracerOptions() });
|
|
576
|
+
|
|
577
|
+
let rootBuffer: AnySpanBuffer | undefined;
|
|
578
|
+
|
|
579
|
+
const processOp = defineOp('run-process', async (ctx) => {
|
|
580
|
+
ctx.tag.process_status('running');
|
|
581
|
+
return ctx.ok('done');
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
const dbOp = defineOp('db-connect', async (ctx) => {
|
|
585
|
+
ctx.tag.db_status('connected');
|
|
586
|
+
await ctx.span('run-process', processOp);
|
|
587
|
+
return ctx.ok('done');
|
|
588
|
+
});
|
|
589
|
+
|
|
590
|
+
const httpOp = defineOp('http-request', async (ctx) => {
|
|
591
|
+
rootBuffer = ctx.buffer;
|
|
592
|
+
ctx.tag.http_status(200);
|
|
593
|
+
await ctx.span('db-connect', dbOp);
|
|
594
|
+
return ctx.ok('done');
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
await trace('http-request', httpOp);
|
|
598
|
+
|
|
599
|
+
expect(rootBuffer).toBeDefined();
|
|
600
|
+
if (!rootBuffer) throw new Error('rootBuffer is undefined');
|
|
601
|
+
|
|
602
|
+
// Convert to Arrow table
|
|
603
|
+
const table = convertSpanTreeToArrowTable(rootBuffer);
|
|
604
|
+
|
|
605
|
+
// Verify all three prefixed status columns exist
|
|
606
|
+
const fieldNames = table.schema.fields.map((f) => f.name);
|
|
607
|
+
expect(fieldNames).toContain('http_status');
|
|
608
|
+
expect(fieldNames).toContain('db_status');
|
|
609
|
+
expect(fieldNames).toContain('process_status');
|
|
610
|
+
|
|
611
|
+
const rows = extractRows(table, ['http_status', 'db_status', 'process_status']);
|
|
612
|
+
|
|
613
|
+
const httpRow = rows.find((r) => r.http_status === 200);
|
|
614
|
+
const dbRow = rows.find((r) => r.db_status === 'connected');
|
|
615
|
+
const processRow = rows.find((r) => r.process_status === 'running');
|
|
616
|
+
|
|
617
|
+
expect(httpRow).toBeDefined();
|
|
618
|
+
expect(dbRow).toBeDefined();
|
|
619
|
+
expect(processRow).toBeDefined();
|
|
620
|
+
|
|
621
|
+
// Verify no cross-contamination - each task only wrote to its own status column.
|
|
622
|
+
expect(httpRow?.db_status).toBeNull();
|
|
623
|
+
expect(httpRow?.process_status).toBeNull();
|
|
624
|
+
|
|
625
|
+
expect(dbRow?.http_status).toBeNull();
|
|
626
|
+
expect(dbRow?.process_status).toBeNull();
|
|
627
|
+
|
|
628
|
+
expect(processRow?.http_status).toBeNull();
|
|
629
|
+
expect(processRow?.db_status).toBeNull();
|
|
630
|
+
});
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
describe('Tree traversal verification (walkSpanTree)', () => {
|
|
634
|
+
/**
|
|
635
|
+
* Per specs/lmao/01k_tree_walker_and_arrow_conversion.md:
|
|
636
|
+
* - walkSpanTree visits all buffers including children
|
|
637
|
+
* - Visits overflow chains (buffer._overflow)
|
|
638
|
+
* - Depth-first pre-order traversal
|
|
639
|
+
*/
|
|
640
|
+
it('should visit all buffers in tree during Arrow conversion', async () => {
|
|
641
|
+
const schema = defineLogSchema({
|
|
642
|
+
nodeId: S.category(),
|
|
643
|
+
});
|
|
644
|
+
|
|
645
|
+
const opContext = defineOpContext({
|
|
646
|
+
logSchema: schema,
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
const { defineOp } = opContext;
|
|
650
|
+
const { trace } = new TestTracer(opContext, { ...createTestTracerOptions() });
|
|
651
|
+
|
|
652
|
+
let rootBuffer: AnySpanBuffer | undefined;
|
|
653
|
+
|
|
654
|
+
// Create a tree with multiple children at each level
|
|
655
|
+
const leafOp = defineOp('leaf', async (ctx) => {
|
|
656
|
+
ctx.tag.nodeId('leaf');
|
|
657
|
+
return ctx.ok('done');
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
const child2Op = defineOp('child2', async (ctx) => {
|
|
661
|
+
ctx.tag.nodeId('child2');
|
|
662
|
+
await ctx.span('leaf', leafOp); // child2 -> leaf
|
|
663
|
+
return ctx.ok('done');
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
const child1Op = defineOp('child1', async (ctx) => {
|
|
667
|
+
ctx.tag.nodeId('child1');
|
|
668
|
+
await ctx.span('leaf', leafOp); // child1 -> leaf (another leaf)
|
|
669
|
+
return ctx.ok('done');
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
const rootOp = defineOp('root', async (ctx) => {
|
|
673
|
+
rootBuffer = ctx.buffer;
|
|
674
|
+
ctx.tag.nodeId('root');
|
|
675
|
+
await ctx.span('child1', child1Op);
|
|
676
|
+
await ctx.span('child2', child2Op);
|
|
677
|
+
return ctx.ok('done');
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
await trace('root', rootOp);
|
|
681
|
+
|
|
682
|
+
expect(rootBuffer).toBeDefined();
|
|
683
|
+
if (!rootBuffer) throw new Error('rootBuffer is undefined');
|
|
684
|
+
|
|
685
|
+
// Convert to Arrow table
|
|
686
|
+
const table = convertSpanTreeToArrowTable(rootBuffer);
|
|
687
|
+
|
|
688
|
+
// Should have all nodes: root, child1, child2, leaf, leaf (2 leaves)
|
|
689
|
+
// Each span has span-start + span-ok = 2 rows
|
|
690
|
+
// Total: 5 spans * 2 = 10 rows
|
|
691
|
+
expect(table.numRows).toBe(10);
|
|
692
|
+
|
|
693
|
+
// Extract rows
|
|
694
|
+
const rows = extractRows(table, ['entry_type', 'message', 'nodeId']);
|
|
695
|
+
const spanStarts = rows.filter((r) => r?.entry_type === 'span-start');
|
|
696
|
+
|
|
697
|
+
// Should have 5 span-start entries
|
|
698
|
+
expect(spanStarts.length).toBe(5);
|
|
699
|
+
|
|
700
|
+
// Verify all nodes are present
|
|
701
|
+
const nodeIds = spanStarts.map((r) => r?.nodeId);
|
|
702
|
+
expect(nodeIds).toContain('root');
|
|
703
|
+
expect(nodeIds).toContain('child1');
|
|
704
|
+
expect(nodeIds).toContain('child2');
|
|
705
|
+
// Should have 2 leaf nodes
|
|
706
|
+
expect(nodeIds.filter((id) => id === 'leaf').length).toBe(2);
|
|
707
|
+
});
|
|
708
|
+
|
|
709
|
+
it('should correctly traverse tree with proper parent-child order', async () => {
|
|
710
|
+
const schema = defineLogSchema({
|
|
711
|
+
order: S.number(),
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
const opContext = defineOpContext({
|
|
715
|
+
logSchema: schema,
|
|
716
|
+
});
|
|
717
|
+
|
|
718
|
+
const { defineOp } = opContext;
|
|
719
|
+
const { trace } = new TestTracer(opContext, { ...createTestTracerOptions() });
|
|
720
|
+
|
|
721
|
+
let rootBuffer: AnySpanBuffer | undefined;
|
|
722
|
+
let order = 0;
|
|
723
|
+
|
|
724
|
+
const deepOp = defineOp('deep', async (ctx) => {
|
|
725
|
+
ctx.tag.order(++order);
|
|
726
|
+
return ctx.ok('done');
|
|
727
|
+
});
|
|
728
|
+
|
|
729
|
+
const middleOp = defineOp('middle', async (ctx) => {
|
|
730
|
+
ctx.tag.order(++order);
|
|
731
|
+
await ctx.span('deep', deepOp);
|
|
732
|
+
return ctx.ok('done');
|
|
733
|
+
});
|
|
734
|
+
|
|
735
|
+
const rootOp = defineOp('root', async (ctx) => {
|
|
736
|
+
rootBuffer = ctx.buffer;
|
|
737
|
+
ctx.tag.order(++order);
|
|
738
|
+
await ctx.span('middle', middleOp);
|
|
739
|
+
return ctx.ok('done');
|
|
740
|
+
});
|
|
741
|
+
|
|
742
|
+
await trace('root', rootOp);
|
|
743
|
+
|
|
744
|
+
expect(rootBuffer).toBeDefined();
|
|
745
|
+
if (!rootBuffer) throw new Error('rootBuffer is undefined');
|
|
746
|
+
|
|
747
|
+
// Convert to Arrow table
|
|
748
|
+
const table = convertSpanTreeToArrowTable(rootBuffer);
|
|
749
|
+
|
|
750
|
+
// Extract span-start rows in table order
|
|
751
|
+
const rows = extractRows(table, ['entry_type', 'message', 'order']);
|
|
752
|
+
const spanStarts = rows.filter((r) => r?.entry_type === 'span-start');
|
|
753
|
+
|
|
754
|
+
// Per specs/lmao/01k - depth-first pre-order: parent before children
|
|
755
|
+
// Order should be: root(1), middle(2), deep(3)
|
|
756
|
+
expect(spanStarts[0]?.order).toBe(1); // root
|
|
757
|
+
expect(spanStarts[0]?.message).toBe('root');
|
|
758
|
+
|
|
759
|
+
expect(spanStarts[1]?.order).toBe(2); // middle
|
|
760
|
+
expect(spanStarts[1]?.message).toBe('middle');
|
|
761
|
+
|
|
762
|
+
expect(spanStarts[2]?.order).toBe(3); // deep
|
|
763
|
+
expect(spanStarts[2]?.message).toBe('deep');
|
|
764
|
+
});
|
|
765
|
+
});
|
|
766
|
+
|
|
767
|
+
describe('Scope inheritance across nested library tasks', () => {
|
|
768
|
+
/**
|
|
769
|
+
* Per specs/lmao/01i_span_scope_attributes.md:
|
|
770
|
+
* - Scoped attributes propagate to child spans
|
|
771
|
+
* - Child spans inherit parent's scoped attributes
|
|
772
|
+
*/
|
|
773
|
+
it('should propagate scoped attributes through 4 levels of nesting', async () => {
|
|
774
|
+
const schema = defineLogSchema({
|
|
775
|
+
requestId: S.category(),
|
|
776
|
+
userId: S.category(),
|
|
777
|
+
level: S.number(),
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
const opContext = defineOpContext({
|
|
781
|
+
logSchema: schema,
|
|
782
|
+
});
|
|
783
|
+
|
|
784
|
+
const { defineOp } = opContext;
|
|
785
|
+
const { trace } = new TestTracer(opContext, { ...createTestTracerOptions() });
|
|
786
|
+
|
|
787
|
+
let rootBuffer: AnySpanBuffer | undefined;
|
|
788
|
+
|
|
789
|
+
const level4Op = defineOp('level4', async (ctx) => {
|
|
790
|
+
ctx.tag.level(4);
|
|
791
|
+
// Log a message - should include inherited scoped attributes
|
|
792
|
+
ctx.log.info('at level 4');
|
|
793
|
+
return ctx.ok('done');
|
|
794
|
+
});
|
|
795
|
+
|
|
796
|
+
const level3Op = defineOp('level3', async (ctx) => {
|
|
797
|
+
ctx.tag.level(3);
|
|
798
|
+
ctx.log.info('at level 3');
|
|
799
|
+
await ctx.span('level4', level4Op);
|
|
800
|
+
return ctx.ok('done');
|
|
801
|
+
});
|
|
802
|
+
|
|
803
|
+
const level2Op = defineOp('level2', async (ctx) => {
|
|
804
|
+
// Add more scoped attributes
|
|
805
|
+
ctx.setScope({ userId: 'user-456' });
|
|
806
|
+
ctx.tag.level(2);
|
|
807
|
+
ctx.log.info('at level 2');
|
|
808
|
+
await ctx.span('level3', level3Op);
|
|
809
|
+
return ctx.ok('done');
|
|
810
|
+
});
|
|
811
|
+
|
|
812
|
+
const rootOp = defineOp('root', async (ctx) => {
|
|
813
|
+
rootBuffer = ctx.buffer;
|
|
814
|
+
// Set scoped attributes at root
|
|
815
|
+
ctx.setScope({ requestId: 'req-abc' });
|
|
816
|
+
ctx.tag.level(1);
|
|
817
|
+
ctx.log.info('at root');
|
|
818
|
+
await ctx.span('level2', level2Op);
|
|
819
|
+
return ctx.ok('done');
|
|
820
|
+
});
|
|
821
|
+
|
|
822
|
+
await trace('root', rootOp);
|
|
823
|
+
|
|
824
|
+
expect(rootBuffer).toBeDefined();
|
|
825
|
+
if (!rootBuffer) throw new Error('rootBuffer is undefined');
|
|
826
|
+
|
|
827
|
+
// Convert to Arrow table
|
|
828
|
+
const table = convertSpanTreeToArrowTable(rootBuffer);
|
|
829
|
+
|
|
830
|
+
// Extract info log entries
|
|
831
|
+
const rows = extractRows(table, ['entry_type', 'message', 'requestId', 'userId', 'scopeValue']);
|
|
832
|
+
const infoLogs = rows.filter((r) => r?.entry_type === 'info');
|
|
833
|
+
|
|
834
|
+
// All info logs should have requestId (scoped at root)
|
|
835
|
+
for (const log of infoLogs) {
|
|
836
|
+
expect(log?.requestId).toBe('req-abc');
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
// Logs at level 2 and below should also have userId
|
|
840
|
+
const level2Log = infoLogs.find((r) => r?.message === 'at level 2');
|
|
841
|
+
const level3Log = infoLogs.find((r) => r?.message === 'at level 3');
|
|
842
|
+
const level4Log = infoLogs.find((r) => r?.message === 'at level 4');
|
|
843
|
+
|
|
844
|
+
expect(level2Log?.userId).toBe('user-456');
|
|
845
|
+
expect(level3Log?.userId).toBe('user-456');
|
|
846
|
+
expect(level4Log?.userId).toBe('user-456');
|
|
847
|
+
});
|
|
848
|
+
});
|
|
849
|
+
});
|