@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,647 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Arrow format correctness tests
|
|
3
|
+
*
|
|
4
|
+
* This test suite verifies that LMAO produces valid Arrow IPC format that can be:
|
|
5
|
+
* 1. Serialized to IPC binary format
|
|
6
|
+
* 2. Deserialized back to identical data
|
|
7
|
+
* 3. Read by any Arrow-compatible tool
|
|
8
|
+
*
|
|
9
|
+
* Per specs/lmao/01f_arrow_table_structure.md and 01b_columnar_buffer_architecture.md:
|
|
10
|
+
* - Zero-copy conversion MUST produce correct Arrow format
|
|
11
|
+
* - Dictionary encoding MUST work correctly
|
|
12
|
+
* - Null bitmaps MUST use Arrow format (1=valid, 0=null)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { describe, expect, it } from 'bun:test';
|
|
16
|
+
import { dictionary, type Table, tableFromColumns, tableFromIPC, tableToIPC, uint8, utf8 } from '@uwdata/flechette';
|
|
17
|
+
import { convertToArrowTable } from '../../convertToArrow.js';
|
|
18
|
+
import { DEFAULT_METADATA } from '../../opContext/defineOp.js';
|
|
19
|
+
import { S } from '../../schema/builder.js';
|
|
20
|
+
import { ENTRY_TYPE_SPAN_START } from '../../schema/systemSchema.js';
|
|
21
|
+
import { createSpanBuffer } from '../../spanBuffer.js';
|
|
22
|
+
import { callBufferWriter, requireColumn } from '../arrow-test-helpers.js';
|
|
23
|
+
|
|
24
|
+
import { createTestSchema, createTestTraceRoot } from '../test-helpers.js';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Round-trip test: serialize to IPC, deserialize, verify data matches
|
|
28
|
+
*/
|
|
29
|
+
const DICTIONARY_TYPE_ID = dictionary(utf8(), uint8()).typeId;
|
|
30
|
+
|
|
31
|
+
function verifyRoundTrip(table: Table, columnNames: string[]): Table {
|
|
32
|
+
const ipcColumns: Record<string, ReturnType<typeof getColumn>> = {};
|
|
33
|
+
for (const columnName of columnNames) {
|
|
34
|
+
const column = table.getChild(columnName);
|
|
35
|
+
if (!column) {
|
|
36
|
+
throw new Error(`Column not found for IPC round-trip: ${columnName}`);
|
|
37
|
+
}
|
|
38
|
+
ipcColumns[columnName] = column;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const ipcTable = tableFromColumns(ipcColumns);
|
|
42
|
+
|
|
43
|
+
// Serialize to IPC stream format
|
|
44
|
+
const ipcBytes = tableToIPC(ipcTable, { format: 'stream' });
|
|
45
|
+
if (!ipcBytes) {
|
|
46
|
+
throw new Error('Failed to serialize Arrow table');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Deserialize back
|
|
50
|
+
const roundTripped = tableFromIPC(ipcBytes);
|
|
51
|
+
|
|
52
|
+
// Verify schema matches
|
|
53
|
+
expect(roundTripped.schema.fields.length).toBe(ipcTable.schema.fields.length);
|
|
54
|
+
for (let i = 0; i < ipcTable.schema.fields.length; i++) {
|
|
55
|
+
expect(roundTripped.schema.fields[i].name).toBe(ipcTable.schema.fields[i].name);
|
|
56
|
+
expect(roundTripped.schema.fields[i].type.typeId).toBe(ipcTable.schema.fields[i].type.typeId);
|
|
57
|
+
expect(roundTripped.schema.fields[i].nullable).toBe(ipcTable.schema.fields[i].nullable);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Verify row count matches
|
|
61
|
+
expect(roundTripped.numRows).toBe(table.numRows);
|
|
62
|
+
|
|
63
|
+
return roundTripped;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function getColumn(table: Table, columnName: string) {
|
|
67
|
+
const column = table.getChild(columnName);
|
|
68
|
+
if (!column) {
|
|
69
|
+
throw new Error(`Column not found: ${columnName}`);
|
|
70
|
+
}
|
|
71
|
+
return column;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function getColumnValue(table: Table, columnName: string, rowIndex: number): unknown {
|
|
75
|
+
return getColumn(table, columnName).get(rowIndex);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function requireBigInt64Values(table: Table, columnName: string): BigInt64Array {
|
|
79
|
+
const column = requireColumn(table, columnName);
|
|
80
|
+
const batch = column.data[0];
|
|
81
|
+
if (!batch || !(batch.values instanceof BigInt64Array)) {
|
|
82
|
+
throw new Error(`Expected raw BigInt64Array values for column '${columnName}'`);
|
|
83
|
+
}
|
|
84
|
+
return batch.values;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function requireDictionaryLength(table: Table, columnName: string): number {
|
|
88
|
+
const column = requireColumn(table, columnName);
|
|
89
|
+
const batch = column.data[0];
|
|
90
|
+
const dictionary = batch ? Reflect.get(batch, 'dictionary') : undefined;
|
|
91
|
+
if (!(dictionary instanceof Object) || !('length' in dictionary) || typeof dictionary.length !== 'number') {
|
|
92
|
+
throw new Error(`Expected dictionary-encoded column '${columnName}'`);
|
|
93
|
+
}
|
|
94
|
+
return dictionary.length;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Set null bit at position (Arrow format: 1=valid, 0=null)
|
|
99
|
+
*/
|
|
100
|
+
function setNull(nullBitmap: Uint8Array, idx: number, isNull: boolean): void {
|
|
101
|
+
const byteIndex = Math.floor(idx / 8);
|
|
102
|
+
const bitOffset = idx % 8;
|
|
103
|
+
if (isNull) {
|
|
104
|
+
nullBitmap[byteIndex] &= ~(1 << bitOffset);
|
|
105
|
+
} else {
|
|
106
|
+
nullBitmap[byteIndex] |= 1 << bitOffset;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
describe('Arrow IPC Round-Trip', () => {
|
|
111
|
+
// No interners needed - direct string access is used
|
|
112
|
+
|
|
113
|
+
describe('serializes and deserializes correctly', () => {
|
|
114
|
+
it('number columns survive round-trip', () => {
|
|
115
|
+
const schema = createTestSchema({ value: S.number() });
|
|
116
|
+
|
|
117
|
+
const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
|
|
118
|
+
buffer._opMetadata = DEFAULT_METADATA;
|
|
119
|
+
|
|
120
|
+
// Write a fewbuffer._opMetadata = DEFAULT_METADATA;
|
|
121
|
+
|
|
122
|
+
const testValues = [1.5, 2.5, 3.5, Number.NaN, 5.5];
|
|
123
|
+
for (const value of testValues) {
|
|
124
|
+
const idx = buffer._writeIndex;
|
|
125
|
+
buffer.timestamp[idx] = 1000n;
|
|
126
|
+
buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
|
|
127
|
+
buffer.value(idx, value);
|
|
128
|
+
buffer._writeIndex++;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const table = convertToArrowTable(buffer);
|
|
132
|
+
const roundTripped = verifyRoundTrip(table, ['value']);
|
|
133
|
+
|
|
134
|
+
// Verify data values match
|
|
135
|
+
for (let i = 0; i < testValues.length; i++) {
|
|
136
|
+
const original = getColumnValue(table, 'value', i);
|
|
137
|
+
const restored = getColumnValue(roundTripped, 'value', i);
|
|
138
|
+
|
|
139
|
+
if (Number.isNaN(testValues[i])) {
|
|
140
|
+
expect(Number.isNaN(original)).toBe(true);
|
|
141
|
+
expect(Number.isNaN(restored)).toBe(true);
|
|
142
|
+
} else {
|
|
143
|
+
expect(restored).toBe(original);
|
|
144
|
+
expect(restored).toBe(testValues[i]);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('boolean columns survive round-trip', () => {
|
|
150
|
+
const schema = createTestSchema({ flag: S.boolean() });
|
|
151
|
+
|
|
152
|
+
const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, 16);
|
|
153
|
+
buffer._opMetadata = DEFAULT_METADATA;
|
|
154
|
+
|
|
155
|
+
// Write a fewbuffer._opMetadata = DEFAULT_METADATA;
|
|
156
|
+
|
|
157
|
+
const testValues = [true, false, true, false, true, false, true, false, true];
|
|
158
|
+
for (const value of testValues) {
|
|
159
|
+
const idx = buffer._writeIndex;
|
|
160
|
+
buffer.timestamp[idx] = 1000n;
|
|
161
|
+
buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
|
|
162
|
+
buffer.flag(idx, value);
|
|
163
|
+
buffer._writeIndex++;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const table = convertToArrowTable(buffer);
|
|
167
|
+
const roundTripped = verifyRoundTrip(table, ['flag']);
|
|
168
|
+
|
|
169
|
+
for (let i = 0; i < testValues.length; i++) {
|
|
170
|
+
expect(getColumnValue(roundTripped, 'flag', i)).toBe(testValues[i]);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('enum columns survive round-trip', () => {
|
|
175
|
+
const schema = createTestSchema({ status: S.enum(['pending', 'active', 'completed'] as const) });
|
|
176
|
+
|
|
177
|
+
const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
|
|
178
|
+
buffer._opMetadata = DEFAULT_METADATA;
|
|
179
|
+
|
|
180
|
+
// Write enum indices (0=pending, 1=active, 2=completed)
|
|
181
|
+
// Note: Buffer setters accept numeric indices for enum columns at runtime.
|
|
182
|
+
const testIndices = [0, 2, 1, 0, 2];
|
|
183
|
+
const expectedStrings = ['pending', 'completed', 'active', 'pending', 'completed'];
|
|
184
|
+
for (const enumIdx of testIndices) {
|
|
185
|
+
const idx = buffer._writeIndex;
|
|
186
|
+
buffer.timestamp[idx] = 1000n;
|
|
187
|
+
buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
|
|
188
|
+
callBufferWriter(buffer, 'status', idx, enumIdx);
|
|
189
|
+
buffer._writeIndex++;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const table = convertToArrowTable(buffer);
|
|
193
|
+
for (let i = 0; i < expectedStrings.length; i++) {
|
|
194
|
+
expect(getColumnValue(table, 'status', i)).toBe(expectedStrings[i]);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('category columns survive round-trip', () => {
|
|
199
|
+
const schema = createTestSchema({ userId: S.category() });
|
|
200
|
+
|
|
201
|
+
const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
|
|
202
|
+
buffer._opMetadata = DEFAULT_METADATA;
|
|
203
|
+
|
|
204
|
+
// Write a fewbuffer._opMetadata = DEFAULT_METADATA;
|
|
205
|
+
|
|
206
|
+
const testValues = ['user-123', 'user-456', 'user-789', 'user-123', 'user-456'];
|
|
207
|
+
for (const userId of testValues) {
|
|
208
|
+
const idx = buffer._writeIndex;
|
|
209
|
+
buffer.timestamp[idx] = 1000n;
|
|
210
|
+
buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
|
|
211
|
+
buffer.userId(idx, userId);
|
|
212
|
+
buffer._writeIndex++;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const table = convertToArrowTable(buffer);
|
|
216
|
+
const originalField = table.schema.fields.find((field) => field.name === 'userId');
|
|
217
|
+
expect(originalField?.type.typeId).toBe(DICTIONARY_TYPE_ID);
|
|
218
|
+
|
|
219
|
+
for (let i = 0; i < testValues.length; i++) {
|
|
220
|
+
expect(getColumnValue(table, 'userId', i)).toBe(testValues[i]);
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it('text columns survive round-trip', () => {
|
|
225
|
+
const schema = createTestSchema({ userMessage: S.text() });
|
|
226
|
+
|
|
227
|
+
const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
|
|
228
|
+
buffer._opMetadata = DEFAULT_METADATA;
|
|
229
|
+
|
|
230
|
+
// Write a fewbuffer._opMetadata = DEFAULT_METADATA;
|
|
231
|
+
|
|
232
|
+
const testValues = ['First message', 'Second message', 'Third message', 'Second message', 'First message'];
|
|
233
|
+
for (const value of testValues) {
|
|
234
|
+
const idx = buffer._writeIndex;
|
|
235
|
+
buffer.timestamp[idx] = 1000n;
|
|
236
|
+
buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
|
|
237
|
+
buffer.userMessage(idx, value);
|
|
238
|
+
buffer._writeIndex++;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const table = convertToArrowTable(buffer);
|
|
242
|
+
|
|
243
|
+
for (let i = 0; i < testValues.length; i++) {
|
|
244
|
+
expect(getColumnValue(table, 'userMessage', i)).toBe(testValues[i]);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it('nullable columns with nulls survive round-trip', () => {
|
|
249
|
+
const schema = createTestSchema({ value: S.number() });
|
|
250
|
+
|
|
251
|
+
const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
|
|
252
|
+
buffer._opMetadata = DEFAULT_METADATA;
|
|
253
|
+
|
|
254
|
+
// Write a fewbuffer._opMetadata = DEFAULT_METADATA;
|
|
255
|
+
|
|
256
|
+
const testValues = [1.0, null, 3.0, null, 5.0];
|
|
257
|
+
for (const value of testValues) {
|
|
258
|
+
const idx = buffer._writeIndex;
|
|
259
|
+
buffer.timestamp[idx] = 1000n;
|
|
260
|
+
buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
|
|
261
|
+
if (value !== null) {
|
|
262
|
+
buffer.value(idx, value);
|
|
263
|
+
} else {
|
|
264
|
+
// For null values, we need to explicitly mark as null in the bitmap
|
|
265
|
+
const nullBitmap = buffer.getNullsIfAllocated('value');
|
|
266
|
+
if (nullBitmap) {
|
|
267
|
+
setNull(nullBitmap, idx, true);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
buffer._writeIndex++;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const table = convertToArrowTable(buffer);
|
|
274
|
+
const roundTripped = verifyRoundTrip(table, ['value']);
|
|
275
|
+
|
|
276
|
+
for (let i = 0; i < testValues.length; i++) {
|
|
277
|
+
expect(getColumnValue(roundTripped, 'value', i)).toBe(testValues[i]);
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it('mixed column types survive round-trip', () => {
|
|
282
|
+
const schema = createTestSchema({
|
|
283
|
+
count: S.number(),
|
|
284
|
+
active: S.boolean(),
|
|
285
|
+
status: S.enum(['pending', 'active', 'completed'] as const),
|
|
286
|
+
userId: S.category(),
|
|
287
|
+
userMessage: S.text(),
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
|
|
291
|
+
buffer._opMetadata = DEFAULT_METADATA;
|
|
292
|
+
|
|
293
|
+
const testData = [
|
|
294
|
+
{ count: 42, active: true, status: 0, userId: 'user-123', userMessage: 'First message' },
|
|
295
|
+
{ count: 100, active: false, status: 1, userId: 'user-456', userMessage: 'Second message' },
|
|
296
|
+
{ count: null, active: true, status: 2, userId: 'user-123', userMessage: 'First message' },
|
|
297
|
+
];
|
|
298
|
+
for (const row of testData) {
|
|
299
|
+
const idx = buffer._writeIndex;
|
|
300
|
+
buffer.timestamp[idx] = 1000n;
|
|
301
|
+
buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
|
|
302
|
+
|
|
303
|
+
if (row.count !== null) {
|
|
304
|
+
buffer.count(idx, row.count);
|
|
305
|
+
} else {
|
|
306
|
+
const nullBitmap = buffer.getNullsIfAllocated('count');
|
|
307
|
+
if (nullBitmap) {
|
|
308
|
+
setNull(nullBitmap, idx, true);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
buffer.active(idx, row.active);
|
|
312
|
+
callBufferWriter(buffer, 'status', idx, row.status);
|
|
313
|
+
buffer.userId(idx, row.userId);
|
|
314
|
+
buffer.userMessage(idx, row.userMessage);
|
|
315
|
+
buffer._writeIndex++;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const table = convertToArrowTable(buffer);
|
|
319
|
+
const roundTripped = verifyRoundTrip(table, ['count', 'active']);
|
|
320
|
+
|
|
321
|
+
// Verify first row
|
|
322
|
+
expect(getColumnValue(roundTripped, 'count', 0)).toBe(42);
|
|
323
|
+
expect(getColumnValue(roundTripped, 'active', 0)).toBe(true);
|
|
324
|
+
expect(getColumnValue(table, 'status', 0)).toBe('pending');
|
|
325
|
+
expect(getColumnValue(table, 'userId', 0)).toBe('user-123');
|
|
326
|
+
expect(getColumnValue(table, 'userMessage', 0)).toBe('First message');
|
|
327
|
+
|
|
328
|
+
// Verify second row
|
|
329
|
+
expect(getColumnValue(roundTripped, 'count', 1)).toBe(100);
|
|
330
|
+
expect(getColumnValue(roundTripped, 'active', 1)).toBe(false);
|
|
331
|
+
expect(getColumnValue(table, 'status', 1)).toBe('active');
|
|
332
|
+
expect(getColumnValue(table, 'userId', 1)).toBe('user-456');
|
|
333
|
+
expect(getColumnValue(table, 'userMessage', 1)).toBe('Second message');
|
|
334
|
+
|
|
335
|
+
// Verify third row with null
|
|
336
|
+
expect(getColumnValue(roundTripped, 'count', 2)).toBeNull();
|
|
337
|
+
expect(getColumnValue(roundTripped, 'active', 2)).toBe(true);
|
|
338
|
+
expect(getColumnValue(table, 'status', 2)).toBe('completed');
|
|
339
|
+
expect(getColumnValue(table, 'userId', 2)).toBe('user-123');
|
|
340
|
+
expect(getColumnValue(table, 'userMessage', 2)).toBe('First message');
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
it('system columns survive round-trip', () => {
|
|
344
|
+
const schema = createTestSchema({});
|
|
345
|
+
|
|
346
|
+
const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
|
|
347
|
+
buffer._opMetadata = DEFAULT_METADATA;
|
|
348
|
+
|
|
349
|
+
// Write a few rows with timestamps (BigInt64Array stores nanoseconds)
|
|
350
|
+
const timestamps = [1000n, 1100n, 1200n];
|
|
351
|
+
for (let i = 0; i < 3; i++) {
|
|
352
|
+
const idx = buffer._writeIndex;
|
|
353
|
+
buffer.timestamp[idx] = timestamps[i];
|
|
354
|
+
buffer.entry_type[idx] = i;
|
|
355
|
+
buffer._writeIndex++;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const table = convertToArrowTable(buffer);
|
|
359
|
+
const roundTripped = verifyRoundTrip(table, [
|
|
360
|
+
'timestamp',
|
|
361
|
+
'thread_id',
|
|
362
|
+
'span_id',
|
|
363
|
+
'parent_thread_id',
|
|
364
|
+
'parent_span_id',
|
|
365
|
+
]);
|
|
366
|
+
|
|
367
|
+
// Verify system columns exist in source table
|
|
368
|
+
const sourceFieldNames = table.schema.fields.map((f) => f.name);
|
|
369
|
+
expect(sourceFieldNames).toContain('timestamp');
|
|
370
|
+
expect(sourceFieldNames).toContain('trace_id');
|
|
371
|
+
expect(sourceFieldNames).toContain('thread_id');
|
|
372
|
+
expect(sourceFieldNames).toContain('span_id');
|
|
373
|
+
expect(sourceFieldNames).toContain('parent_thread_id');
|
|
374
|
+
expect(sourceFieldNames).toContain('parent_span_id');
|
|
375
|
+
expect(sourceFieldNames).toContain('entry_type');
|
|
376
|
+
expect(sourceFieldNames).toContain('package_name');
|
|
377
|
+
expect(sourceFieldNames).toContain('package_file');
|
|
378
|
+
|
|
379
|
+
// Verify IPC round-tripped subset columns exist
|
|
380
|
+
const fieldNames = roundTripped.schema.fields.map((f) => f.name);
|
|
381
|
+
expect(fieldNames).toContain('timestamp');
|
|
382
|
+
expect(fieldNames).toContain('thread_id');
|
|
383
|
+
expect(fieldNames).toContain('span_id');
|
|
384
|
+
expect(fieldNames).toContain('parent_thread_id');
|
|
385
|
+
expect(fieldNames).toContain('parent_span_id');
|
|
386
|
+
|
|
387
|
+
// Verify timestamps round-tripped correctly
|
|
388
|
+
// Arrow's getter converts nanoseconds to a decimal, so access raw BigInt64Array
|
|
389
|
+
const timestampIndex = roundTripped.schema.fields.findIndex((f) => f.name === 'timestamp');
|
|
390
|
+
const timestampVector = roundTripped.getChildAt(timestampIndex);
|
|
391
|
+
if (!timestampVector) {
|
|
392
|
+
throw new Error('Timestamp vector not found');
|
|
393
|
+
}
|
|
394
|
+
const rawTimestamps = requireBigInt64Values(roundTripped, 'timestamp');
|
|
395
|
+
for (let i = 0; i < 3; i++) {
|
|
396
|
+
expect(rawTimestamps[i]).toBe(timestamps[i]);
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
describe('schema correctness', () => {
|
|
402
|
+
it('system columns have correct nullability', () => {
|
|
403
|
+
const schema = createTestSchema({ userAttr: S.number() });
|
|
404
|
+
|
|
405
|
+
const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
|
|
406
|
+
buffer._opMetadata = DEFAULT_METADATA;
|
|
407
|
+
|
|
408
|
+
const idx = buffer._writeIndex;
|
|
409
|
+
buffer.timestamp[idx] = 1000n;
|
|
410
|
+
buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
|
|
411
|
+
buffer._writeIndex++;
|
|
412
|
+
|
|
413
|
+
const table = convertToArrowTable(buffer);
|
|
414
|
+
|
|
415
|
+
// System columns must be present and match current conversion contract.
|
|
416
|
+
const expectedSystemColumns = [
|
|
417
|
+
'timestamp',
|
|
418
|
+
'trace_id',
|
|
419
|
+
'thread_id',
|
|
420
|
+
'span_id',
|
|
421
|
+
'entry_type',
|
|
422
|
+
'package_name',
|
|
423
|
+
'package_file',
|
|
424
|
+
];
|
|
425
|
+
for (const colName of expectedSystemColumns) {
|
|
426
|
+
const field = table.schema.fields.find((f) => f.name === colName);
|
|
427
|
+
expect(field).toBeDefined();
|
|
428
|
+
expect(field?.nullable).toBe(true);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// Columns that SHOULD be nullable
|
|
432
|
+
const nullableColumns = ['parent_thread_id', 'parent_span_id', 'userAttr'];
|
|
433
|
+
for (const colName of nullableColumns) {
|
|
434
|
+
const field = table.schema.fields.find((f) => f.name === colName);
|
|
435
|
+
expect(field).toBeDefined();
|
|
436
|
+
expect(field?.nullable).toBe(true);
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
it('dictionary columns have correct type', () => {
|
|
441
|
+
const schema = createTestSchema({
|
|
442
|
+
category: S.category(),
|
|
443
|
+
text: S.text(),
|
|
444
|
+
status: S.enum(['a', 'b'] as const),
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
|
|
448
|
+
buffer._opMetadata = DEFAULT_METADATA;
|
|
449
|
+
|
|
450
|
+
const idx = buffer._writeIndex;
|
|
451
|
+
buffer.timestamp[idx] = 1000n;
|
|
452
|
+
buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
|
|
453
|
+
buffer.category(idx, 'cat1');
|
|
454
|
+
buffer.text(idx, 'text1');
|
|
455
|
+
callBufferWriter(buffer, 'status', idx, 0);
|
|
456
|
+
buffer._writeIndex++;
|
|
457
|
+
|
|
458
|
+
const table = convertToArrowTable(buffer);
|
|
459
|
+
|
|
460
|
+
// Category and text should be Dictionary<Utf8, Uint32>
|
|
461
|
+
const categoryField = table.schema.fields.find((f) => f.name === 'category');
|
|
462
|
+
expect(categoryField?.type.typeId).toBe(DICTIONARY_TYPE_ID);
|
|
463
|
+
|
|
464
|
+
const textField = table.schema.fields.find((f) => f.name === 'text');
|
|
465
|
+
expect(textField?.type.typeId).toBe(DICTIONARY_TYPE_ID);
|
|
466
|
+
|
|
467
|
+
// Enum should be Dictionary<Utf8, Uint8>
|
|
468
|
+
const enumField = table.schema.fields.find((f) => f.name === 'status');
|
|
469
|
+
expect(enumField?.type.typeId).toBe(DICTIONARY_TYPE_ID);
|
|
470
|
+
});
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
describe('null bitmap format', () => {
|
|
474
|
+
it('uses Arrow format (1=valid, 0=null)', () => {
|
|
475
|
+
const schema = createTestSchema({ value: S.number() });
|
|
476
|
+
|
|
477
|
+
const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
|
|
478
|
+
buffer._opMetadata = DEFAULT_METADATA;
|
|
479
|
+
|
|
480
|
+
// Write pattern: valid, null, valid, null, valid, null, valid, null
|
|
481
|
+
const values = [1.0, null, 2.0, null, 3.0, null, 4.0, null];
|
|
482
|
+
for (const value of values) {
|
|
483
|
+
const idx = buffer._writeIndex;
|
|
484
|
+
buffer.timestamp[idx] = 1000n;
|
|
485
|
+
buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
|
|
486
|
+
if (value !== null) {
|
|
487
|
+
buffer.value(idx, value);
|
|
488
|
+
} else {
|
|
489
|
+
const nullBitmap = buffer.getNullsIfAllocated('value');
|
|
490
|
+
if (nullBitmap) {
|
|
491
|
+
setNull(nullBitmap, idx, true);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
buffer._writeIndex++;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
const table = convertToArrowTable(buffer);
|
|
498
|
+
|
|
499
|
+
// Extract value column
|
|
500
|
+
const valueColumnIndex = table.schema.fields.findIndex((f) => f.name === 'value');
|
|
501
|
+
const valueVector = table.getChildAt(valueColumnIndex);
|
|
502
|
+
if (!valueVector) {
|
|
503
|
+
throw new Error('Value vector not found');
|
|
504
|
+
}
|
|
505
|
+
const valueData = valueVector.data[0] as { nullCount: number; nullBitmap?: Uint8Array; validity?: Uint8Array };
|
|
506
|
+
|
|
507
|
+
// Verify null count
|
|
508
|
+
expect(valueData.nullCount).toBe(4);
|
|
509
|
+
|
|
510
|
+
// Verify null bitmap (1=valid, 0=null)
|
|
511
|
+
// Pattern: 01010101 = 0x55
|
|
512
|
+
const nullBitmap = valueData.nullBitmap ?? valueData.validity;
|
|
513
|
+
expect(nullBitmap).toBeDefined();
|
|
514
|
+
expect(nullBitmap?.[0]).toBe(0b01010101);
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
it('handles sparse nulls correctly', () => {
|
|
518
|
+
const schema = createTestSchema({ value: S.number() });
|
|
519
|
+
|
|
520
|
+
// Need capacity for 10 values
|
|
521
|
+
const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, 16);
|
|
522
|
+
buffer._opMetadata = DEFAULT_METADATA;
|
|
523
|
+
|
|
524
|
+
// Only one null in 10 values
|
|
525
|
+
const values = [1, 2, 3, null, 5, 6, 7, 8, 9, 10];
|
|
526
|
+
for (const value of values) {
|
|
527
|
+
const idx = buffer._writeIndex;
|
|
528
|
+
buffer.timestamp[idx] = 1000n;
|
|
529
|
+
buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
|
|
530
|
+
if (value !== null) {
|
|
531
|
+
buffer.value(idx, value);
|
|
532
|
+
} else {
|
|
533
|
+
const nullBitmap = buffer.getNullsIfAllocated('value');
|
|
534
|
+
if (nullBitmap) {
|
|
535
|
+
setNull(nullBitmap, idx, true);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
buffer._writeIndex++;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
const table = convertToArrowTable(buffer);
|
|
542
|
+
|
|
543
|
+
const valueColumnIndex = table.schema.fields.findIndex((f) => f.name === 'value');
|
|
544
|
+
const valueVector = table.getChildAt(valueColumnIndex);
|
|
545
|
+
if (!valueVector) {
|
|
546
|
+
throw new Error('Value vector not found');
|
|
547
|
+
}
|
|
548
|
+
const valueData = valueVector.data[0];
|
|
549
|
+
|
|
550
|
+
expect(valueData.nullCount).toBe(1);
|
|
551
|
+
|
|
552
|
+
// Verify all values round-trip correctly
|
|
553
|
+
for (let i = 0; i < values.length; i++) {
|
|
554
|
+
expect(getColumnValue(table, 'value', i)).toBe(values[i]);
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
it('omits null bitmap when no nulls', () => {
|
|
559
|
+
const schema = createTestSchema({ value: S.number() });
|
|
560
|
+
|
|
561
|
+
const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
|
|
562
|
+
buffer._opMetadata = DEFAULT_METADATA;
|
|
563
|
+
|
|
564
|
+
// No nulls - write all valid values
|
|
565
|
+
const values = [1, 2, 3, 4, 5];
|
|
566
|
+
for (const value of values) {
|
|
567
|
+
const idx = buffer._writeIndex;
|
|
568
|
+
buffer.timestamp[idx] = 1000n;
|
|
569
|
+
buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
|
|
570
|
+
buffer.value(idx, value);
|
|
571
|
+
buffer._writeIndex++;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
const table = convertToArrowTable(buffer);
|
|
575
|
+
|
|
576
|
+
const valueColumnIndex = table.schema.fields.findIndex((f) => f.name === 'value');
|
|
577
|
+
const valueVector = table.getChildAt(valueColumnIndex);
|
|
578
|
+
if (!valueVector) {
|
|
579
|
+
throw new Error('Value vector not found');
|
|
580
|
+
}
|
|
581
|
+
const valueData = valueVector.data[0];
|
|
582
|
+
|
|
583
|
+
expect(valueData.nullCount).toBe(0);
|
|
584
|
+
// When nullCount is 0, Arrow may or may not include a bitmap
|
|
585
|
+
// The important thing is nullCount is correct
|
|
586
|
+
});
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
describe('dictionary encoding', () => {
|
|
590
|
+
it('preserves dictionary values through round-trip', () => {
|
|
591
|
+
const schema = createTestSchema({ category: S.category() });
|
|
592
|
+
|
|
593
|
+
const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, undefined);
|
|
594
|
+
buffer._opMetadata = DEFAULT_METADATA;
|
|
595
|
+
|
|
596
|
+
// Write a fewbuffer._opMetadata = DEFAULT_METADATA;
|
|
597
|
+
|
|
598
|
+
const testValues = ['alpha', 'beta', 'zebra', 'alpha', 'beta'];
|
|
599
|
+
for (const category of testValues) {
|
|
600
|
+
const idx = buffer._writeIndex;
|
|
601
|
+
buffer.timestamp[idx] = 1000n;
|
|
602
|
+
buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
|
|
603
|
+
buffer.category(idx, category);
|
|
604
|
+
buffer._writeIndex++;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
const table = convertToArrowTable(buffer);
|
|
608
|
+
for (let i = 0; i < testValues.length; i++) {
|
|
609
|
+
expect(getColumnValue(table, 'category', i)).toBe(testValues[i]);
|
|
610
|
+
}
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
it('handles repeated values efficiently', () => {
|
|
614
|
+
const schema = createTestSchema({ userId: S.category() });
|
|
615
|
+
|
|
616
|
+
// Use capacity of 128 to hold 100 rows without overflow
|
|
617
|
+
const buffer = createSpanBuffer(schema, createTestTraceRoot('trace-123'), DEFAULT_METADATA, 128);
|
|
618
|
+
buffer._opMetadata = DEFAULT_METADATA;
|
|
619
|
+
|
|
620
|
+
// Write same value many times
|
|
621
|
+
const testValue = 'user-repeated';
|
|
622
|
+
for (let i = 0; i < 100; i++) {
|
|
623
|
+
const idx = buffer._writeIndex;
|
|
624
|
+
buffer.timestamp[idx] = 1000n;
|
|
625
|
+
buffer.entry_type[idx] = ENTRY_TYPE_SPAN_START;
|
|
626
|
+
buffer.userId(idx, testValue);
|
|
627
|
+
buffer._writeIndex++;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
const table = convertToArrowTable(buffer);
|
|
631
|
+
|
|
632
|
+
// Verify all 100 rows have the same value by accessing the column directly
|
|
633
|
+
const userIdIndex = table.schema.fields.findIndex((f) => f.name === 'userId');
|
|
634
|
+
const userIdVector = table.getChildAt(userIdIndex);
|
|
635
|
+
if (!userIdVector) {
|
|
636
|
+
throw new Error('UserId vector not found');
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
for (let i = 0; i < 100; i++) {
|
|
640
|
+
expect(userIdVector.get(i)).toBe(testValue);
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
// Dictionary should only have 1 unique value
|
|
644
|
+
expect(requireDictionaryLength(table, 'userId')).toBe(1);
|
|
645
|
+
});
|
|
646
|
+
});
|
|
647
|
+
});
|