@smoothbricks/lmao 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/allocator.wasm +0 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/lib/JsBufferStrategy.d.ts +4 -3
- package/dist/lib/JsBufferStrategy.d.ts.map +1 -1
- package/dist/lib/JsBufferStrategy.js +18 -11
- package/dist/lib/arrow/lease.d.ts +10 -0
- package/dist/lib/arrow/lease.d.ts.map +1 -0
- package/dist/lib/arrow/lease.js +33 -0
- package/dist/lib/arrow/utils.d.ts +3 -4
- package/dist/lib/arrow/utils.d.ts.map +1 -1
- package/dist/lib/arrow/utils.js +12 -13
- package/dist/lib/arrow/vocabularyDictionary.d.ts +21 -0
- package/dist/lib/arrow/vocabularyDictionary.d.ts.map +1 -0
- package/dist/lib/arrow/vocabularyDictionary.js +95 -0
- package/dist/lib/bufferStrategy.d.ts +3 -2
- package/dist/lib/bufferStrategy.d.ts.map +1 -1
- package/dist/lib/cloudflare/traceRows.d.ts.map +1 -1
- package/dist/lib/cloudflare/traceRows.js +3 -2
- package/dist/lib/codegen/evaluatorGenerator.d.ts.map +1 -1
- package/dist/lib/codegen/evaluatorGenerator.js +12 -11
- package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts +44 -82
- package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts.map +1 -1
- package/dist/lib/codegen/fixedPositionWriterGenerator.js +223 -162
- package/dist/lib/codegen/spanLoggerClosureMaterializer.d.ts +63 -0
- package/dist/lib/codegen/spanLoggerClosureMaterializer.d.ts.map +1 -0
- package/dist/lib/codegen/spanLoggerClosureMaterializer.js +447 -0
- package/dist/lib/codegen/spanLoggerGenerator.d.ts +36 -19
- package/dist/lib/codegen/spanLoggerGenerator.d.ts.map +1 -1
- package/dist/lib/codegen/spanLoggerGenerator.js +164 -158
- package/dist/lib/convertToArrow.d.ts +7 -2
- package/dist/lib/convertToArrow.d.ts.map +1 -1
- package/dist/lib/convertToArrow.js +499 -285
- package/dist/lib/defineOpContext.js +1 -1
- package/dist/lib/enumMetadata.d.ts +19 -0
- package/dist/lib/enumMetadata.d.ts.map +1 -0
- package/dist/lib/enumMetadata.js +86 -0
- package/dist/lib/flushScheduler.d.ts.map +1 -1
- package/dist/lib/flushScheduler.js +13 -4
- package/dist/lib/library.d.ts +16 -98
- package/dist/lib/library.d.ts.map +1 -1
- package/dist/lib/library.js +32 -525
- package/dist/lib/logBinding.d.ts +21 -27
- package/dist/lib/logBinding.d.ts.map +1 -1
- package/dist/lib/op.d.ts +30 -30
- package/dist/lib/op.d.ts.map +1 -1
- package/dist/lib/op.js +15 -22
- package/dist/lib/opContext/createOpGroup.d.ts +1 -1
- package/dist/lib/opContext/createOpGroup.d.ts.map +1 -1
- package/dist/lib/opContext/createOpGroup.js +22 -29
- package/dist/lib/opContext/defineOp.d.ts +4 -4
- package/dist/lib/opContext/defineOp.d.ts.map +1 -1
- package/dist/lib/opContext/defineOp.js +53 -10
- package/dist/lib/opContext/opGroupTypes.d.ts +2 -2
- package/dist/lib/opContext/opTypes.d.ts +1 -1
- package/dist/lib/opContext/opTypes.d.ts.map +1 -1
- package/dist/lib/opContext/spanContextTypes.d.ts +29 -14
- package/dist/lib/opContext/spanContextTypes.d.ts.map +1 -1
- package/dist/lib/opContext/types.d.ts +4 -4
- package/dist/lib/opContext/types.d.ts.map +1 -1
- package/dist/lib/physicalLayoutPlan.d.ts +89 -0
- package/dist/lib/physicalLayoutPlan.d.ts.map +1 -0
- package/dist/lib/physicalLayoutPlan.js +442 -0
- package/dist/lib/resolveMessage.d.ts +9 -0
- package/dist/lib/resolveMessage.d.ts.map +1 -0
- package/dist/lib/resolveMessage.js +63 -0
- package/dist/lib/result.d.ts +5 -7
- package/dist/lib/result.d.ts.map +1 -1
- package/dist/lib/result.js +19 -26
- package/dist/lib/runtimeHint.d.ts +35 -0
- package/dist/lib/runtimeHint.d.ts.map +1 -0
- package/dist/lib/runtimeHint.js +79 -0
- package/dist/lib/schema/types.d.ts +1 -1
- package/dist/lib/schema/types.d.ts.map +1 -1
- package/dist/lib/span-buffer/aot/v1.d.ts +2 -0
- package/dist/lib/span-buffer/aot/v1.d.ts.map +1 -0
- package/dist/lib/span-buffer/aot/v1.js +24 -0
- package/dist/lib/spanBuffer.d.ts +33 -4
- package/dist/lib/spanBuffer.d.ts.map +1 -1
- package/dist/lib/spanBuffer.js +583 -91
- package/dist/lib/spanBufferStats.d.ts +1 -1
- package/dist/lib/spanBufferStats.d.ts.map +1 -1
- package/dist/lib/spanContext.d.ts +27 -51
- package/dist/lib/spanContext.d.ts.map +1 -1
- package/dist/lib/spanContext.js +822 -344
- package/dist/lib/sqlite/sqlite-common.d.ts.map +1 -1
- package/dist/lib/sqlite/sqlite-common.js +20 -21
- package/dist/lib/testing/bun-harness.d.ts +8 -3
- package/dist/lib/testing/bun-harness.d.ts.map +1 -1
- package/dist/lib/testing/bun-harness.js +30 -18
- package/dist/lib/testing/extractFacts.d.ts +1 -1
- package/dist/lib/testing/extractFacts.d.ts.map +1 -1
- package/dist/lib/testing/extractFacts.js +55 -63
- package/dist/lib/testing/facts.d.ts +1 -1
- package/dist/lib/testing/facts.d.ts.map +1 -1
- package/dist/lib/testing/queryable-span.d.ts +1 -1
- package/dist/lib/testing/queryable-span.d.ts.map +1 -1
- package/dist/lib/testing/queryable-span.js +26 -28
- package/dist/lib/testing/span-query.d.ts.map +1 -1
- package/dist/lib/testing/span-query.js +19 -22
- package/dist/lib/testing/stdio-replay.d.ts.map +1 -1
- package/dist/lib/testing/stdio-replay.js +19 -8
- package/dist/lib/threadId.d.ts.map +1 -1
- package/dist/lib/threadId.js +6 -3
- package/dist/lib/traceRoot.d.ts +30 -8
- package/dist/lib/traceRoot.d.ts.map +1 -1
- package/dist/lib/traceRoot.es.d.ts +17 -15
- package/dist/lib/traceRoot.es.d.ts.map +1 -1
- package/dist/lib/traceRoot.es.js +68 -34
- package/dist/lib/traceRoot.js +11 -0
- package/dist/lib/traceRoot.node.d.ts +17 -19
- package/dist/lib/traceRoot.node.d.ts.map +1 -1
- package/dist/lib/traceRoot.node.js +66 -38
- package/dist/lib/traceTopology.d.ts +42 -0
- package/dist/lib/traceTopology.d.ts.map +1 -0
- package/dist/lib/traceTopology.js +260 -0
- package/dist/lib/tracer.d.ts +9 -5
- package/dist/lib/tracer.d.ts.map +1 -1
- package/dist/lib/tracer.js +65 -71
- package/dist/lib/tracers/ArrayQueueTracer.d.ts +1 -1
- package/dist/lib/tracers/ArrayQueueTracer.js +1 -1
- package/dist/lib/tracers/StdioTracer.d.ts.map +1 -1
- package/dist/lib/tracers/StdioTracer.js +15 -13
- package/dist/lib/tracers/TestTracer.d.ts +4 -6
- package/dist/lib/tracers/TestTracer.d.ts.map +1 -1
- package/dist/lib/tracers/TestTracer.js +6 -8
- package/dist/lib/types.d.ts +49 -32
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/vocabularyRegistry.d.ts +25 -0
- package/dist/lib/vocabularyRegistry.d.ts.map +1 -0
- package/dist/lib/vocabularyRegistry.js +372 -0
- package/dist/lib/wasm/WasmBufferStrategy.d.ts +6 -10
- package/dist/lib/wasm/WasmBufferStrategy.d.ts.map +1 -1
- package/dist/lib/wasm/WasmBufferStrategy.js +44 -37
- package/dist/lib/wasm/wasmAllocator.d.ts +27 -22
- package/dist/lib/wasm/wasmAllocator.d.ts.map +1 -1
- package/dist/lib/wasm/wasmAllocator.js +66 -44
- package/dist/lib/wasm/wasmPhysicalLayout.d.ts +67 -0
- package/dist/lib/wasm/wasmPhysicalLayout.d.ts.map +1 -0
- package/dist/lib/wasm/wasmPhysicalLayout.js +179 -0
- package/dist/lib/wasm/wasmSpanBuffer.d.ts +79 -31
- package/dist/lib/wasm/wasmSpanBuffer.d.ts.map +1 -1
- package/dist/lib/wasm/wasmSpanBuffer.js +442 -272
- package/dist/lib/wasm/wasmTraceRoot.d.ts +24 -22
- package/dist/lib/wasm/wasmTraceRoot.d.ts.map +1 -1
- package/dist/lib/wasm/wasmTraceRoot.js +110 -71
- package/dist/vocabulary/register/v1.d.ts +2 -0
- package/dist/vocabulary/register/v1.d.ts.map +1 -0
- package/dist/vocabulary/register/v1.js +1 -0
- package/dist/wasm.d.ts +5 -0
- package/dist/wasm.d.ts.map +1 -0
- package/dist/wasm.js +4 -0
- package/package.json +54 -6
- package/src/index.ts +1 -0
- package/src/lib/JsBufferStrategy.ts +27 -9
- package/src/lib/__tests__/arrow-builder-integration/arrow-conversion.test.ts +335 -37
- package/src/lib/__tests__/arrow-builder-integration/binary-arrow-conversion.test.ts +97 -26
- package/src/lib/__tests__/arrow-builder-integration/binary-comparison.test.ts +75 -15
- package/src/lib/__tests__/arrow-builder-integration/binary-format-compliance.test.ts +30 -6
- package/src/lib/__tests__/arrow-builder-integration/buffer-chaining.test.ts +18 -21
- package/src/lib/__tests__/arrow-builder-integration/foundation.test.ts +5 -2
- package/src/lib/__tests__/arrow-builder-integration/integration.test.ts +25 -7
- package/src/lib/__tests__/arrow-builder-integration/lazy-columns.test.ts +3 -2
- package/src/lib/__tests__/buffer-overflow.test.ts +24 -18
- package/src/lib/__tests__/capability-span-context.test.ts +505 -0
- package/src/lib/__tests__/capacity-tuning.test.ts +5 -3
- package/src/lib/__tests__/eager-columns.test.ts +345 -0
- package/src/lib/__tests__/enum-metadata-aot.test.ts +153 -0
- package/src/lib/__tests__/enum-metadata.test.ts +177 -0
- package/src/lib/__tests__/fixtures/empty-vocabulary-runtime.fixture.ts +15 -0
- package/src/lib/__tests__/flushScheduler.test.ts +5 -1
- package/src/lib/__tests__/identity-view.property.test.ts +179 -0
- package/src/lib/__tests__/library.test.ts +19 -235
- package/src/lib/__tests__/message-buffer-families.test.ts +878 -0
- package/src/lib/__tests__/nested-library-tasks.test.ts +14 -15
- package/src/lib/__tests__/op-metadata.test.ts +1 -1
- package/src/lib/__tests__/op-type-safety.test.ts +5 -16
- package/src/lib/__tests__/physical-layout-plan.test.ts +333 -0
- package/src/lib/__tests__/remap-descriptor-integration.test.ts +381 -0
- package/src/lib/__tests__/root-context-construction.test.ts +414 -0
- package/src/lib/__tests__/span-auto-runtime.test.ts +386 -0
- package/src/lib/__tests__/span-buffer-segment-stats.test.ts +221 -0
- package/src/lib/__tests__/span-lifecycle.test.ts +53 -25
- package/src/lib/__tests__/spanbuffer-materializer-parity.test.ts +266 -0
- package/src/lib/__tests__/sync-async-trace.test.ts +24 -23
- package/src/lib/__tests__/tag-writer-aot.test.ts +214 -0
- package/src/lib/__tests__/test-helpers.ts +67 -12
- package/src/lib/__tests__/threadId.test.ts +62 -0
- package/src/lib/__tests__/timestamp.test.ts +221 -93
- package/src/lib/__tests__/traceTopology.property.test.ts +383 -0
- package/src/lib/__tests__/type-narrowing.test.ts +63 -0
- package/src/lib/__tests__/vocabulary-dense-decoding.test.ts +405 -0
- package/src/lib/__tests__/vocabularyRegistry.test.ts +313 -0
- package/src/lib/arrow/lease.ts +43 -0
- package/src/lib/arrow/utils.ts +10 -14
- package/src/lib/arrow/vocabularyDictionary.ts +123 -0
- package/src/lib/bufferStrategy.ts +9 -1
- package/src/lib/cloudflare/traceRows.ts +3 -2
- package/src/lib/codegen/__tests__/evaluatorGenerator.test.ts +21 -141
- package/src/lib/codegen/__tests__/fixedPositionWriter-parity.test.ts +273 -0
- package/src/lib/codegen/__tests__/fixedPositionWriter-uint64.test.ts +61 -34
- package/src/lib/codegen/__tests__/nullBitmap.test.ts +33 -37
- package/src/lib/codegen/__tests__/spanLoggerGenerator.test.ts +34 -18
- package/src/lib/codegen/__tests__/spanLoggerMaterializerParity.test.ts +503 -0
- package/src/lib/codegen/evaluatorGenerator.ts +18 -13
- package/src/lib/codegen/fixedPositionWriterGenerator.ts +329 -245
- package/src/lib/codegen/spanLoggerClosureMaterializer.ts +598 -0
- package/src/lib/codegen/spanLoggerGenerator.ts +241 -177
- package/src/lib/convertToArrow.ts +598 -311
- package/src/lib/defineOpContext.ts +1 -1
- package/src/lib/enumMetadata.ts +121 -0
- package/src/lib/flushScheduler.ts +11 -5
- package/src/lib/library.ts +37 -595
- package/src/lib/logBinding.ts +21 -27
- package/src/lib/op.ts +75 -18
- package/src/lib/opContext/__tests__/retry.test.ts +27 -21
- package/src/lib/opContext/createOpGroup.ts +33 -31
- package/src/lib/opContext/defineOp.ts +88 -11
- package/src/lib/opContext/opGroupTypes.ts +2 -2
- package/src/lib/opContext/opTypes.ts +1 -1
- package/src/lib/opContext/spanContextTypes.ts +98 -17
- package/src/lib/opContext/types.ts +7 -3
- package/src/lib/physicalLayoutPlan.ts +598 -0
- package/src/lib/resolveMessage.ts +67 -0
- package/src/lib/result.ts +20 -33
- package/src/lib/runtimeHint.ts +98 -0
- package/src/lib/schema/__tests__/featureFlags.test.ts +2 -1
- package/src/lib/schema/builder.ts +1 -1
- package/src/lib/schema/types.ts +1 -1
- package/src/lib/span-buffer/aot/v1.ts +26 -0
- package/src/lib/spanBuffer.ts +658 -92
- package/src/lib/spanBufferStats.ts +1 -1
- package/src/lib/spanContext.ts +1350 -861
- package/src/lib/sqlite/sqlite-common.ts +20 -31
- package/src/lib/testing/__tests__/topology-traversal.test.ts +174 -0
- package/src/lib/testing/__tests__/vitest-harness.test.ts +2 -1
- package/src/lib/testing/bun-harness.ts +94 -43
- package/src/lib/testing/extractFacts.ts +64 -78
- package/src/lib/testing/facts.ts +1 -1
- package/src/lib/testing/queryable-span.ts +23 -30
- package/src/lib/testing/span-query.ts +16 -20
- package/src/lib/testing/stdio-replay.ts +25 -8
- package/src/lib/testing/vitest-harness.ts +1 -1
- package/src/lib/threadId.ts +6 -3
- package/src/lib/traceRoot.es.ts +77 -42
- package/src/lib/traceRoot.node.ts +75 -46
- package/src/lib/traceRoot.ts +41 -14
- package/src/lib/traceTopology.ts +279 -0
- package/src/lib/tracer.ts +109 -98
- package/src/lib/tracers/ArrayQueueTracer.ts +1 -1
- package/src/lib/tracers/StdioTracer.ts +15 -13
- package/src/lib/tracers/TestTracer.ts +6 -8
- package/src/lib/tracers/__tests__/ArrayQueueTracer.test.ts +15 -10
- package/src/lib/tracers/__tests__/TestTracer.test.ts +23 -13
- package/src/lib/types.ts +64 -33
- package/src/lib/vocabularyRegistry.ts +439 -0
- package/src/lib/wasm/WasmBufferStrategy.ts +56 -48
- package/src/lib/wasm/__tests__/WasmBufferStrategy.test.ts +215 -11
- package/src/lib/wasm/__tests__/allocatorFreeBlockClamp.test.ts +86 -0
- package/src/lib/wasm/__tests__/wasm-identity-view.test.ts +311 -0
- package/src/lib/wasm/__tests__/wasm-integration.test.ts +417 -44
- package/src/lib/wasm/__tests__/wasm-message-buffer-families.test.ts +588 -0
- package/src/lib/wasm/__tests__/wasmAllocator.test.ts +100 -668
- package/src/lib/wasm/__tests__/wasmSpanBuffer.test.ts +419 -63
- package/src/lib/wasm/__tests__/wasmTraceRoot.test.ts +24 -29
- package/src/lib/wasm/__tests__/wasmTracer.test.ts.disabled +2 -2
- package/src/lib/wasm/wasmAllocator.ts +131 -96
- package/src/lib/wasm/wasmPhysicalLayout.ts +309 -0
- package/src/lib/wasm/wasmSpanBuffer.ts +597 -341
- package/src/lib/wasm/wasmTraceRoot.ts +140 -78
- package/src/vocabulary/register/v1.ts +1 -0
- package/src/wasm.ts +19 -0
- package/src/lib/__tests__/remapped-buffer-view-integration.test.ts +0 -319
- package/src/lib/__tests__/remapped-buffer-view.test.ts +0 -635
- package/src/lib/wasm/allocator.zig +0 -948
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
import { describe, expect, it } from 'bun:test';
|
|
2
|
+
import fc from 'fast-check';
|
|
3
|
+
import { defineOpContext } from '../defineOpContext.js';
|
|
4
|
+
import type { OpContext, OpContextOf, SpanContext } from '../opContext/types.js';
|
|
5
|
+
import { resolveEntryType, resolveMessage } from '../resolveMessage.js';
|
|
6
|
+
import { defineCodeError, Ok } from '../result.js';
|
|
7
|
+
import {
|
|
8
|
+
RUNTIME_HINT_ANALYZED_VALID,
|
|
9
|
+
RUNTIME_HINT_CAPABILITIES_MASK,
|
|
10
|
+
RUNTIME_HINT_DEPS,
|
|
11
|
+
RUNTIME_HINT_FF,
|
|
12
|
+
RUNTIME_HINT_FULL_CAPABILITIES,
|
|
13
|
+
RUNTIME_HINT_LOG,
|
|
14
|
+
RUNTIME_HINT_RESERVED_MASK,
|
|
15
|
+
RUNTIME_HINT_RESULT,
|
|
16
|
+
RUNTIME_HINT_SCOPE,
|
|
17
|
+
RUNTIME_HINT_SPAN,
|
|
18
|
+
RUNTIME_HINT_TAG,
|
|
19
|
+
} from '../runtimeHint.js';
|
|
20
|
+
import { S } from '../schema/builder.js';
|
|
21
|
+
import { defineFeatureFlags } from '../schema/defineFeatureFlags.js';
|
|
22
|
+
import { defineLogSchema } from '../schema/defineLogSchema.js';
|
|
23
|
+
import { InMemoryFlagEvaluator, type SpanContextWithoutFf } from '../schema/evaluator.js';
|
|
24
|
+
import { TestTracer } from '../tracers/TestTracer.js';
|
|
25
|
+
import { iterateSpanChildren } from '../traceTopology.js';
|
|
26
|
+
import { createTestTracerOptions } from './test-helpers.js';
|
|
27
|
+
|
|
28
|
+
const schema = defineLogSchema({ marker: S.category() });
|
|
29
|
+
const flags = defineFeatureFlags({ enabled: S.boolean().default(false).sync() });
|
|
30
|
+
const context = defineOpContext({
|
|
31
|
+
logSchema: schema,
|
|
32
|
+
flags: flags.schema,
|
|
33
|
+
ctx: { requestId: 'default-request', tenant: { region: 'iad' } },
|
|
34
|
+
});
|
|
35
|
+
type Context = OpContextOf<typeof context>;
|
|
36
|
+
type CapturedContext = SpanContext<Context>;
|
|
37
|
+
|
|
38
|
+
const TEST_FAILURE = defineCodeError('TEST_FAILURE')<{ reason: string }>();
|
|
39
|
+
const CAPABILITY_NAMES = ['tag', 'log', 'ff', 'span', 'spanSync', 'ok', 'err', 'setScope', 'deps'];
|
|
40
|
+
const RESULT_ONLY_KEYS = [
|
|
41
|
+
'_spanBuffer',
|
|
42
|
+
'_buffer',
|
|
43
|
+
'_appendLogEntry',
|
|
44
|
+
'_schema',
|
|
45
|
+
'_logBinding',
|
|
46
|
+
'_physicalLayoutPlan',
|
|
47
|
+
'requestId',
|
|
48
|
+
'tenant',
|
|
49
|
+
'ok',
|
|
50
|
+
'err',
|
|
51
|
+
];
|
|
52
|
+
const LOG_RESULT_KEYS = [
|
|
53
|
+
'_spanBuffer',
|
|
54
|
+
'_buffer',
|
|
55
|
+
'_appendLogEntry',
|
|
56
|
+
'_schema',
|
|
57
|
+
'_logBinding',
|
|
58
|
+
'_physicalLayoutPlan',
|
|
59
|
+
'_spanLogger',
|
|
60
|
+
'log',
|
|
61
|
+
'requestId',
|
|
62
|
+
'tenant',
|
|
63
|
+
'ok',
|
|
64
|
+
'err',
|
|
65
|
+
];
|
|
66
|
+
const LOG_SPAN_RESULT_KEYS = [
|
|
67
|
+
'_spanBuffer',
|
|
68
|
+
'_buffer',
|
|
69
|
+
'_appendLogEntry',
|
|
70
|
+
'_schema',
|
|
71
|
+
'_logBinding',
|
|
72
|
+
'_physicalLayoutPlan',
|
|
73
|
+
'_spanLogger',
|
|
74
|
+
'log',
|
|
75
|
+
'requestId',
|
|
76
|
+
'tenant',
|
|
77
|
+
'ok',
|
|
78
|
+
'err',
|
|
79
|
+
'span',
|
|
80
|
+
'spanSync',
|
|
81
|
+
];
|
|
82
|
+
const FULL_FALLBACK_KEYS = [
|
|
83
|
+
'_spanBuffer',
|
|
84
|
+
'_buffer',
|
|
85
|
+
'_appendLogEntry',
|
|
86
|
+
'_schema',
|
|
87
|
+
'_logBinding',
|
|
88
|
+
'_physicalLayoutPlan',
|
|
89
|
+
'_spanLogger',
|
|
90
|
+
'tag',
|
|
91
|
+
'log',
|
|
92
|
+
'deps',
|
|
93
|
+
'ff',
|
|
94
|
+
'requestId',
|
|
95
|
+
'tenant',
|
|
96
|
+
'setScope',
|
|
97
|
+
'ok',
|
|
98
|
+
'err',
|
|
99
|
+
'span',
|
|
100
|
+
'spanSync',
|
|
101
|
+
];
|
|
102
|
+
|
|
103
|
+
function requireCaptured(value: CapturedContext | undefined, label: string): CapturedContext {
|
|
104
|
+
if (!value) throw new Error(`missing ${label} context`);
|
|
105
|
+
return value;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function requireObject(value: unknown, label: string): object {
|
|
109
|
+
if ((typeof value !== 'object' && typeof value !== 'function') || value === null) {
|
|
110
|
+
throw new TypeError(`${label} must be an object`);
|
|
111
|
+
}
|
|
112
|
+
return value;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function expectContextWriterState(ctx: CapturedContext): void {
|
|
116
|
+
expect(Object.hasOwn(ctx, '_spanBuffer')).toBe(true);
|
|
117
|
+
expect(Object.hasOwn(ctx, '_buffer')).toBe(true);
|
|
118
|
+
expect(Object.hasOwn(ctx, '_appendLogEntry')).toBe(true);
|
|
119
|
+
expect(Object.hasOwn(ctx, '_physicalLayoutPlan')).toBe(true);
|
|
120
|
+
expect(Object.hasOwn(ctx, '_state')).toBe(false);
|
|
121
|
+
expect(Object.hasOwn(ctx, '_traceRoot')).toBe(false);
|
|
122
|
+
expect(Object.hasOwn(ctx, '_appendWriterEntry')).toBe(false);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function expectThinWriter(writer: object, state: CapturedContext): void {
|
|
126
|
+
expect(Reflect.ownKeys(writer)).toEqual(['_state']);
|
|
127
|
+
expect(Reflect.get(writer, '_state')).toBe(state);
|
|
128
|
+
for (const duplicatedField of ['_buffer', '_spanBuffer', '_traceRoot', '_appendLogEntry', '_physicalLayoutPlan']) {
|
|
129
|
+
expect(Object.hasOwn(writer, duplicatedField)).toBe(false);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function constructorOf(value: object): (...args: never[]) => unknown {
|
|
134
|
+
const prototype = Object.getPrototypeOf(value);
|
|
135
|
+
const ctor = Reflect.get(prototype, 'constructor');
|
|
136
|
+
if (typeof ctor !== 'function') throw new Error('context prototype has no constructor');
|
|
137
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Reflect.get only proves Function; callers only compare constructor identity.
|
|
138
|
+
return ctor as (...args: never[]) => unknown;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async function captureRoot(runtimeHint: number, name: string): Promise<CapturedContext> {
|
|
142
|
+
let captured: CapturedContext | undefined;
|
|
143
|
+
const op = context.defineOp(
|
|
144
|
+
name,
|
|
145
|
+
(ctx) => {
|
|
146
|
+
captured = ctx;
|
|
147
|
+
return new Ok(name);
|
|
148
|
+
},
|
|
149
|
+
undefined,
|
|
150
|
+
{ runtimeHint },
|
|
151
|
+
);
|
|
152
|
+
const tracer = new TestTracer(context, createTestTracerOptions());
|
|
153
|
+
await tracer.trace(name, { requestId: `${name}-request` }, op);
|
|
154
|
+
return requireCaptured(captured, name);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function expectedCapabilityNames(mask: number): string[] {
|
|
158
|
+
const names: string[] = [];
|
|
159
|
+
if ((mask & RUNTIME_HINT_TAG) !== 0) names.push('tag');
|
|
160
|
+
if ((mask & RUNTIME_HINT_LOG) !== 0) names.push('log');
|
|
161
|
+
if ((mask & RUNTIME_HINT_FF) !== 0) names.push('ff');
|
|
162
|
+
if ((mask & RUNTIME_HINT_SPAN) !== 0) names.push('span', 'spanSync');
|
|
163
|
+
if ((mask & RUNTIME_HINT_RESULT) !== 0) names.push('ok', 'err');
|
|
164
|
+
if ((mask & RUNTIME_HINT_SCOPE) !== 0) names.push('setScope');
|
|
165
|
+
if ((mask & RUNTIME_HINT_DEPS) !== 0) names.push('deps');
|
|
166
|
+
return names;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function capabilitySnapshot(ctx: CapturedContext): string[] {
|
|
170
|
+
return CAPABILITY_NAMES.filter((name) => Object.hasOwn(ctx, name));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function bufferSnapshot(tracer: TestTracer<typeof context>) {
|
|
174
|
+
const root = tracer.rootBuffers[0];
|
|
175
|
+
if (!root) throw new Error('missing completed root buffer');
|
|
176
|
+
const [child] = iterateSpanChildren(root);
|
|
177
|
+
if (!child) throw new Error('missing completed child buffer');
|
|
178
|
+
return {
|
|
179
|
+
rootEntryTypes: Array.from({ length: root._writeIndex }, (_, row) => resolveEntryType(root, row)),
|
|
180
|
+
rootMessages: Array.from({ length: root._writeIndex }, (_, row) => resolveMessage(root, row)),
|
|
181
|
+
rootMarkers: root.marker_values.slice(0, root._writeIndex),
|
|
182
|
+
rootErrorCodes: root.error_code_values.slice(0, root._writeIndex),
|
|
183
|
+
childEntryTypes: Array.from({ length: child._writeIndex }, (_, row) => resolveEntryType(child, row)),
|
|
184
|
+
childMessages: Array.from({ length: child._writeIndex }, (_, row) => resolveMessage(child, row)),
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
describe('capability-specialized SpanContext shapes', () => {
|
|
189
|
+
it('reuses constructors and exact own-key order for identical analyzed signatures', async () => {
|
|
190
|
+
const hint = RUNTIME_HINT_ANALYZED_VALID | RUNTIME_HINT_RESULT | 4;
|
|
191
|
+
const first = await captureRoot(hint, 'same-a');
|
|
192
|
+
const second = await captureRoot(hint | 31, 'same-b');
|
|
193
|
+
|
|
194
|
+
expect(constructorOf(first)).toBe(constructorOf(second));
|
|
195
|
+
expect(Reflect.ownKeys(first)).toEqual(RESULT_ONLY_KEYS);
|
|
196
|
+
expect(Reflect.ownKeys(second)).toEqual(RESULT_ONLY_KEYS);
|
|
197
|
+
expect(capabilitySnapshot(first)).toEqual(['ok', 'err']);
|
|
198
|
+
expect(capabilitySnapshot(second)).toEqual(['ok', 'err']);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('creates distinct constructors and own shapes for distinct capability masks', async () => {
|
|
202
|
+
const resultOnly = await captureRoot(RUNTIME_HINT_ANALYZED_VALID | RUNTIME_HINT_RESULT | 2, 'result-only');
|
|
203
|
+
const loggingResult = await captureRoot(
|
|
204
|
+
RUNTIME_HINT_ANALYZED_VALID | RUNTIME_HINT_LOG | RUNTIME_HINT_RESULT | 2,
|
|
205
|
+
'logging-result',
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
expect(constructorOf(resultOnly)).not.toBe(constructorOf(loggingResult));
|
|
209
|
+
expect(Reflect.ownKeys(resultOnly)).toEqual(RESULT_ONLY_KEYS);
|
|
210
|
+
expect(Reflect.ownKeys(loggingResult)).toEqual(LOG_RESULT_KEYS);
|
|
211
|
+
expect(capabilitySnapshot(resultOnly)).toEqual(['ok', 'err']);
|
|
212
|
+
expect(capabilitySnapshot(loggingResult)).toEqual(['log', 'ok', 'err']);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it('covers every capability mask without allocating unused capability properties', async () => {
|
|
216
|
+
const everyMask = Array.from({ length: 0x80 }, (_, maskIndex) => maskIndex);
|
|
217
|
+
await fc.assert(
|
|
218
|
+
fc.asyncProperty(
|
|
219
|
+
fc.shuffledSubarray(everyMask, { minLength: everyMask.length, maxLength: everyMask.length }),
|
|
220
|
+
async (maskIndexes) => {
|
|
221
|
+
for (const maskIndex of maskIndexes) {
|
|
222
|
+
const mask = maskIndex << 16;
|
|
223
|
+
const captured = await captureRoot(RUNTIME_HINT_ANALYZED_VALID | mask | 2, `mask-${maskIndex}`);
|
|
224
|
+
expect(capabilitySnapshot(captured)).toEqual(expectedCapabilityNames(mask));
|
|
225
|
+
expectContextWriterState(captured);
|
|
226
|
+
const needsLogger = (mask & (RUNTIME_HINT_LOG | RUNTIME_HINT_FF | RUNTIME_HINT_SCOPE)) !== 0;
|
|
227
|
+
expect(Object.hasOwn(captured, '_spanLogger')).toBe(needsLogger);
|
|
228
|
+
if (needsLogger) {
|
|
229
|
+
expectThinWriter(requireObject(Reflect.get(captured, '_spanLogger'), 'capability logger'), captured);
|
|
230
|
+
}
|
|
231
|
+
if ((mask & RUNTIME_HINT_TAG) !== 0) expectThinWriter(captured.tag, captured);
|
|
232
|
+
expect(mask & ~RUNTIME_HINT_CAPABILITIES_MASK).toBe(0);
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
),
|
|
236
|
+
{ numRuns: 1 },
|
|
237
|
+
);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('uses one full canonical fallback constructor for every invalid or unanalysed hint', async () => {
|
|
241
|
+
const fallbacks: CapturedContext[] = [];
|
|
242
|
+
for (const [index, hint] of [
|
|
243
|
+
0,
|
|
244
|
+
RUNTIME_HINT_RESULT,
|
|
245
|
+
RUNTIME_HINT_ANALYZED_VALID | RUNTIME_HINT_RESERVED_MASK,
|
|
246
|
+
-1,
|
|
247
|
+
0x1_0000_0000,
|
|
248
|
+
RUNTIME_HINT_ANALYZED_VALID + 0.5,
|
|
249
|
+
].entries()) {
|
|
250
|
+
fallbacks.push(await captureRoot(hint, `fallback-${index}`));
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const first = fallbacks[0];
|
|
254
|
+
if (!first) throw new Error('missing canonical fallback');
|
|
255
|
+
for (const fallback of fallbacks) {
|
|
256
|
+
expect(constructorOf(fallback)).toBe(constructorOf(first));
|
|
257
|
+
expect(Reflect.ownKeys(fallback)).toEqual(FULL_FALLBACK_KEYS);
|
|
258
|
+
expect(capabilitySnapshot(fallback)).toEqual(CAPABILITY_NAMES);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it('preserves inferred overrides while reusing the Op CallsitePlan', async () => {
|
|
263
|
+
const capturedRequests: string[] = [];
|
|
264
|
+
const capturedRegions: string[] = [];
|
|
265
|
+
const capturedContexts: CapturedContext[] = [];
|
|
266
|
+
const op = context.defineOp(
|
|
267
|
+
'typed-user-context',
|
|
268
|
+
(ctx) => {
|
|
269
|
+
capturedContexts.push(ctx);
|
|
270
|
+
capturedRequests.push(ctx.requestId.toUpperCase());
|
|
271
|
+
capturedRegions.push(ctx.tenant.region.toUpperCase());
|
|
272
|
+
return ctx.ok(null);
|
|
273
|
+
},
|
|
274
|
+
undefined,
|
|
275
|
+
{ runtimeHint: RUNTIME_HINT_ANALYZED_VALID | RUNTIME_HINT_RESULT | 2 },
|
|
276
|
+
);
|
|
277
|
+
const plan = op.callsitePlan;
|
|
278
|
+
const tracer = new TestTracer(context, createTestTracerOptions());
|
|
279
|
+
await tracer.trace('typed-user-context-1', { requestId: 'request-7', tenant: { region: 'ord' } }, op);
|
|
280
|
+
await tracer.trace('typed-user-context-2', { requestId: 'request-8', tenant: { region: 'dfw' } }, op);
|
|
281
|
+
|
|
282
|
+
expect(capturedRequests).toEqual(['REQUEST-7', 'REQUEST-8']);
|
|
283
|
+
expect(capturedRegions).toEqual(['ORD', 'DFW']);
|
|
284
|
+
expect(op.callsitePlan).toBe(plan);
|
|
285
|
+
expect(capturedContexts).toHaveLength(2);
|
|
286
|
+
for (const captured of capturedContexts) {
|
|
287
|
+
expect(captured).toBeInstanceOf(plan.SpanContextClass);
|
|
288
|
+
expect(Reflect.ownKeys(captured)).toEqual(RESULT_ONLY_KEYS);
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
describe('specialized SpanContext runtime semantics', () => {
|
|
294
|
+
class CapturingEvaluator extends InMemoryFlagEvaluator {
|
|
295
|
+
readonly contexts: SpanContextWithoutFf<OpContext>[] = [];
|
|
296
|
+
|
|
297
|
+
override getSync<K extends string>(ctx: SpanContextWithoutFf<OpContext>, flag: K) {
|
|
298
|
+
this.contexts.push(ctx);
|
|
299
|
+
return super.getSync(ctx, flag);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
it('reuses one context-owned WriterState across logger, tag, and result chains', async () => {
|
|
304
|
+
function inspectWriters(ctx: CapturedContext, label: string): void {
|
|
305
|
+
expectContextWriterState(ctx);
|
|
306
|
+
expect(Reflect.get(ctx, '_spanBuffer')).toBe(Reflect.get(ctx, '_buffer'));
|
|
307
|
+
|
|
308
|
+
const tag = ctx.tag;
|
|
309
|
+
expectThinWriter(tag, ctx);
|
|
310
|
+
expect(tag.marker(`${label}-tag`)).toBe(tag);
|
|
311
|
+
|
|
312
|
+
const logger = ctx.log;
|
|
313
|
+
expectThinWriter(logger, ctx);
|
|
314
|
+
expect(Object.is(logger.info(`${label}-log`).marker(`${label}-log-marker`), logger)).toBe(true);
|
|
315
|
+
|
|
316
|
+
const ok = ctx.ok({ label });
|
|
317
|
+
expect(Reflect.get(ok, '_state')).toBe(ctx);
|
|
318
|
+
expect(Object.hasOwn(ok, '_writer')).toBe(false);
|
|
319
|
+
expect(ok.with({ marker: `${label}-ok` })).toBe(ok);
|
|
320
|
+
const okWriter = requireObject(Reflect.get(ok, '_writer'), `${label} Ok writer`);
|
|
321
|
+
expectThinWriter(okWriter, ctx);
|
|
322
|
+
expect(ok.message(`${label} ok`).line(101)).toBe(ok);
|
|
323
|
+
expect(Reflect.get(ok, '_writer')).toBe(okWriter);
|
|
324
|
+
|
|
325
|
+
const err = ctx.err(TEST_FAILURE({ reason: label }));
|
|
326
|
+
expect(Reflect.get(err, '_state')).toBe(ctx);
|
|
327
|
+
expect(Object.hasOwn(err, '_writer')).toBe(false);
|
|
328
|
+
expect(err.with({ marker: `${label}-err` })).toBe(err);
|
|
329
|
+
const errWriter = requireObject(Reflect.get(err, '_writer'), `${label} Err writer`);
|
|
330
|
+
expectThinWriter(errWriter, ctx);
|
|
331
|
+
expect(err.message(`${label} error`).line(202)).toBe(err);
|
|
332
|
+
expect(Reflect.get(err, '_writer')).toBe(errWriter);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
async function run(runtimeHint: number, name: string): Promise<void> {
|
|
336
|
+
let rootContext: CapturedContext | undefined;
|
|
337
|
+
let childContext: CapturedContext | undefined;
|
|
338
|
+
const child = context.defineOp(
|
|
339
|
+
`${name}-child`,
|
|
340
|
+
(ctx) => {
|
|
341
|
+
childContext = ctx;
|
|
342
|
+
inspectWriters(ctx, `${name}-child`);
|
|
343
|
+
return ctx.ok('child');
|
|
344
|
+
},
|
|
345
|
+
undefined,
|
|
346
|
+
{ runtimeHint },
|
|
347
|
+
);
|
|
348
|
+
const root = context.defineOp(
|
|
349
|
+
name,
|
|
350
|
+
async (ctx) => {
|
|
351
|
+
rootContext = ctx;
|
|
352
|
+
inspectWriters(ctx, `${name}-root`);
|
|
353
|
+
const childResult = await ctx.span(`${name}-child`, child);
|
|
354
|
+
if (!childResult.success) throw new Error(`${name} child failed`);
|
|
355
|
+
return ctx.ok('root');
|
|
356
|
+
},
|
|
357
|
+
undefined,
|
|
358
|
+
{ runtimeHint },
|
|
359
|
+
);
|
|
360
|
+
const tracer = new TestTracer(context, createTestTracerOptions());
|
|
361
|
+
const result = await tracer.trace(name, root);
|
|
362
|
+
|
|
363
|
+
expect(result.success).toBe(true);
|
|
364
|
+
const capturedRoot = requireCaptured(rootContext, `${name} root`);
|
|
365
|
+
const capturedChild = requireCaptured(childContext, `${name} child`);
|
|
366
|
+
expect(capturedRoot).not.toBe(capturedChild);
|
|
367
|
+
expect(Reflect.get(capturedRoot, '_spanBuffer')).not.toBe(Reflect.get(capturedChild, '_spanBuffer'));
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
await run(RUNTIME_HINT_ANALYZED_VALID | RUNTIME_HINT_FULL_CAPABILITIES | 8, 'shared-state-specialized');
|
|
371
|
+
await run(0, 'shared-state-fallback');
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
it('binds repeated feature evaluations to contexts created by one CallsitePlan', async () => {
|
|
375
|
+
const evaluator = new CapturingEvaluator(flags.schema, { enabled: true });
|
|
376
|
+
const childContexts: CapturedContext[] = [];
|
|
377
|
+
const child = context.defineOp(
|
|
378
|
+
'flag-child',
|
|
379
|
+
(ctx) => {
|
|
380
|
+
childContexts.push(ctx);
|
|
381
|
+
const enabled = ctx.ff.enabled;
|
|
382
|
+
if (!enabled) throw new Error('enabled feature flag was not bound');
|
|
383
|
+
expect(enabled.value).toBe(true);
|
|
384
|
+
return ctx.ok('child');
|
|
385
|
+
},
|
|
386
|
+
undefined,
|
|
387
|
+
{
|
|
388
|
+
runtimeHint: RUNTIME_HINT_ANALYZED_VALID | RUNTIME_HINT_FF | RUNTIME_HINT_RESULT | 2,
|
|
389
|
+
},
|
|
390
|
+
);
|
|
391
|
+
const plan = child.callsitePlan;
|
|
392
|
+
const parent = context.defineOp(
|
|
393
|
+
'flag-parent',
|
|
394
|
+
async (ctx) => {
|
|
395
|
+
await ctx.span('flag-child-1', child);
|
|
396
|
+
await ctx.span('flag-child-2', child);
|
|
397
|
+
return ctx.ok('parent');
|
|
398
|
+
},
|
|
399
|
+
undefined,
|
|
400
|
+
{
|
|
401
|
+
runtimeHint: RUNTIME_HINT_ANALYZED_VALID | RUNTIME_HINT_SPAN | RUNTIME_HINT_RESULT | 2,
|
|
402
|
+
},
|
|
403
|
+
);
|
|
404
|
+
const tracer = new TestTracer(context, { ...createTestTracerOptions(), flagEvaluator: evaluator });
|
|
405
|
+
await tracer.trace('flag-parent', parent);
|
|
406
|
+
|
|
407
|
+
expect(child.callsitePlan).toBe(plan);
|
|
408
|
+
expect(childContexts).toHaveLength(2);
|
|
409
|
+
expect(childContexts.every((captured) => captured instanceof plan.SpanContextClass)).toBe(true);
|
|
410
|
+
expect(evaluator.contexts).toEqual(childContexts);
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
it('keeps exact own-key order stable across root, child, and overflowing contexts', async () => {
|
|
414
|
+
const hint = RUNTIME_HINT_ANALYZED_VALID | RUNTIME_HINT_LOG | RUNTIME_HINT_SPAN | RUNTIME_HINT_RESULT | 3;
|
|
415
|
+
let childContext: CapturedContext | undefined;
|
|
416
|
+
const child = context.defineOp(
|
|
417
|
+
'overflow-child',
|
|
418
|
+
(ctx) => {
|
|
419
|
+
childContext = ctx;
|
|
420
|
+
ctx.log.info('first');
|
|
421
|
+
ctx.log.info('second');
|
|
422
|
+
return ctx.ok('child');
|
|
423
|
+
},
|
|
424
|
+
undefined,
|
|
425
|
+
{ runtimeHint: hint },
|
|
426
|
+
);
|
|
427
|
+
let rootContext: CapturedContext | undefined;
|
|
428
|
+
const root = context.defineOp(
|
|
429
|
+
'overflow-root',
|
|
430
|
+
async (ctx) => {
|
|
431
|
+
rootContext = ctx;
|
|
432
|
+
ctx.log.info('root-first');
|
|
433
|
+
ctx.log.info('root-second');
|
|
434
|
+
ctx.log.info('root-third');
|
|
435
|
+
ctx.log.info('root-fourth');
|
|
436
|
+
ctx.log.info('root-fifth');
|
|
437
|
+
ctx.log.info('root-sixth');
|
|
438
|
+
ctx.log.info('root-seventh');
|
|
439
|
+
await ctx.span('overflow-child', child);
|
|
440
|
+
return ctx.ok('root');
|
|
441
|
+
},
|
|
442
|
+
undefined,
|
|
443
|
+
{ runtimeHint: hint },
|
|
444
|
+
);
|
|
445
|
+
const tracer = new TestTracer(context, createTestTracerOptions());
|
|
446
|
+
await tracer.trace('overflow-root', root);
|
|
447
|
+
|
|
448
|
+
const capturedRoot = requireCaptured(rootContext, 'root');
|
|
449
|
+
const capturedChild = requireCaptured(childContext, 'overflow child');
|
|
450
|
+
const repeated = await captureRoot(hint, 'overflow-repeat');
|
|
451
|
+
expect(Reflect.ownKeys(capturedRoot)).toEqual(LOG_SPAN_RESULT_KEYS);
|
|
452
|
+
expect(Reflect.ownKeys(capturedChild)).toEqual(LOG_SPAN_RESULT_KEYS);
|
|
453
|
+
expect(Reflect.ownKeys(repeated)).toEqual(LOG_SPAN_RESULT_KEYS);
|
|
454
|
+
expect(constructorOf(capturedRoot)).toBe(constructorOf(capturedChild));
|
|
455
|
+
expect(constructorOf(capturedChild)).toBe(constructorOf(repeated));
|
|
456
|
+
const overflowRoot = tracer.rootBuffers[0];
|
|
457
|
+
if (!overflowRoot) throw new Error('missing overflow root buffer');
|
|
458
|
+
const [overflowChild] = iterateSpanChildren(overflowRoot);
|
|
459
|
+
if (!overflowChild) throw new Error('missing overflow child buffer');
|
|
460
|
+
expect(overflowChild._overflow).toBeDefined();
|
|
461
|
+
expectContextWriterState(capturedRoot);
|
|
462
|
+
expectContextWriterState(capturedChild);
|
|
463
|
+
expectThinWriter(capturedRoot.log, capturedRoot);
|
|
464
|
+
expectThinWriter(capturedChild.log, capturedChild);
|
|
465
|
+
expect(capturedRoot).not.toBe(capturedChild);
|
|
466
|
+
expect(Reflect.get(capturedRoot, '_spanBuffer')).toBe(overflowRoot);
|
|
467
|
+
expect(Reflect.get(capturedRoot, '_buffer')).toBe(overflowRoot._overflow);
|
|
468
|
+
expect(Reflect.get(capturedChild, '_spanBuffer')).toBe(overflowChild);
|
|
469
|
+
expect(Reflect.get(capturedChild, '_buffer')).toBe(overflowChild._overflow);
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
it('matches ok, err, log, tag, span, and scope semantics between specialized and fallback contexts', async () => {
|
|
473
|
+
async function run(runtimeHint: number, name: string) {
|
|
474
|
+
let childSucceeded = false;
|
|
475
|
+
const op = context.defineOp(
|
|
476
|
+
name,
|
|
477
|
+
async (ctx) => {
|
|
478
|
+
ctx.setScope({ marker: 'scoped' });
|
|
479
|
+
ctx.tag.marker('tagged');
|
|
480
|
+
ctx.log.info('logged');
|
|
481
|
+
const ok = ctx.ok('probe');
|
|
482
|
+
expect(ok.success).toBe(true);
|
|
483
|
+
const child = await ctx.span('nested', (childCtx) => childCtx.ok('child'));
|
|
484
|
+
childSucceeded = child.success;
|
|
485
|
+
return ctx.err(TEST_FAILURE({ reason: 'expected' }));
|
|
486
|
+
},
|
|
487
|
+
undefined,
|
|
488
|
+
{ runtimeHint },
|
|
489
|
+
);
|
|
490
|
+
const tracer = new TestTracer(context, createTestTracerOptions());
|
|
491
|
+
const result = await tracer.trace(name, op);
|
|
492
|
+
if (result.success) throw new Error(`${name} unexpectedly succeeded`);
|
|
493
|
+
return {
|
|
494
|
+
childSucceeded,
|
|
495
|
+
errorCode: result.error.code,
|
|
496
|
+
errorReason: result.error.reason,
|
|
497
|
+
buffer: bufferSnapshot(tracer),
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
const specialized = await run(RUNTIME_HINT_ANALYZED_VALID | RUNTIME_HINT_FULL_CAPABILITIES | 8, 'semantic-parity');
|
|
502
|
+
const fallback = await run(0, 'semantic-parity');
|
|
503
|
+
expect(specialized).toEqual(fallback);
|
|
504
|
+
});
|
|
505
|
+
});
|
|
@@ -2,7 +2,6 @@ import { beforeEach, describe, expect, it } from 'bun:test';
|
|
|
2
2
|
import { DEFAULT_BUFFER_CAPACITY } from '@smoothbricks/arrow-builder';
|
|
3
3
|
import fc from 'fast-check';
|
|
4
4
|
import { shouldTuneCapacity } from '../capacityTuning.js';
|
|
5
|
-
import { createSpanLogger } from '../codegen/spanLoggerGenerator.js';
|
|
6
5
|
import { DEFAULT_METADATA } from '../opContext/defineOp.js';
|
|
7
6
|
import { S } from '../schema/builder.js';
|
|
8
7
|
import { LogSchema } from '../schema/LogSchema.js';
|
|
@@ -10,7 +9,7 @@ import { mergeWithSystemSchema } from '../schema/systemSchema.js';
|
|
|
10
9
|
import { createSpanBuffer, getSpanBufferClass } from '../spanBuffer.js';
|
|
11
10
|
import type { SpanBufferStats } from '../spanBufferStats.js';
|
|
12
11
|
|
|
13
|
-
import { createTestTraceRoot, createTestTracerOptions } from './test-helpers.js';
|
|
12
|
+
import { createTestSpanContext, createTestTraceRoot, createTestTracerOptions } from './test-helpers.js';
|
|
14
13
|
|
|
15
14
|
/**
|
|
16
15
|
* Create mock SpanBufferStats for testing capacity tuning.
|
|
@@ -489,12 +488,15 @@ describe('Capacity Tuning Algorithm', () => {
|
|
|
489
488
|
DEFAULT_METADATA,
|
|
490
489
|
undefined,
|
|
491
490
|
);
|
|
492
|
-
const
|
|
491
|
+
const ctx = createTestSpanContext(integrationSchema, buffer);
|
|
492
|
+
ctx._buffer._writeIndex = 2;
|
|
493
|
+
const logger = ctx._spanLogger;
|
|
493
494
|
|
|
494
495
|
// Write 10 entries per span (160% utilization of 6 usable rows)
|
|
495
496
|
for (let i = 0; i < 10; i++) {
|
|
496
497
|
logger.info(`message ${i}`);
|
|
497
498
|
}
|
|
499
|
+
buffer._sealStatsChain();
|
|
498
500
|
}
|
|
499
501
|
|
|
500
502
|
// After 12 spans with 10 writes each = 120 writes
|