@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,598 @@
|
|
|
1
|
+
import type { Nanoseconds } from '@smoothbricks/arrow-builder';
|
|
2
|
+
import {
|
|
3
|
+
getResultWriterClass,
|
|
4
|
+
getTagWriterClass,
|
|
5
|
+
type ResultWriterConstructor,
|
|
6
|
+
type TagWriter,
|
|
7
|
+
type TagWriterConstructor,
|
|
8
|
+
type WriterState,
|
|
9
|
+
} from './codegen/fixedPositionWriterGenerator.js';
|
|
10
|
+
import {
|
|
11
|
+
createSpanLoggerClass,
|
|
12
|
+
type SpanLoggerConstructor,
|
|
13
|
+
type SpanLoggerImpl,
|
|
14
|
+
} from './codegen/spanLoggerGenerator.js';
|
|
15
|
+
import { resolveEnumLookupDescriptor, type SchemaEnumLookupDescriptor } from './enumMetadata.js';
|
|
16
|
+
import type { RemapDescriptor } from './logBinding.js';
|
|
17
|
+
import type { OpMetadata } from './opContext/opTypes.js';
|
|
18
|
+
import type { OpContext } from './opContext/types.js';
|
|
19
|
+
import { decodeVocabularyMessage, MAX_PACKED_MESSAGE_DENSE_INDEX } from './resolveMessage.js';
|
|
20
|
+
import {
|
|
21
|
+
isRuntimeHintAnalyzed,
|
|
22
|
+
type MessageLayoutFamily,
|
|
23
|
+
type MessagePhysicalLayout,
|
|
24
|
+
RUNTIME_HINT_CAPABILITIES_MASK,
|
|
25
|
+
RUNTIME_HINT_FF,
|
|
26
|
+
RUNTIME_HINT_FULL_CAPABILITIES,
|
|
27
|
+
RUNTIME_HINT_LOG,
|
|
28
|
+
RUNTIME_HINT_SCOPE,
|
|
29
|
+
RUNTIME_HINT_TAG,
|
|
30
|
+
runtimeHintInitialCapacity,
|
|
31
|
+
runtimeHintMessageLayoutFamily,
|
|
32
|
+
runtimeHintMessagePhysicalLayout,
|
|
33
|
+
} from './runtimeHint.js';
|
|
34
|
+
import type { LogSchema } from './schema/LogSchema.js';
|
|
35
|
+
import { ENTRY_TYPE_SPAN_EXCEPTION, ENTRY_TYPE_SPAN_START } from './schema/systemSchema.js';
|
|
36
|
+
import { getSpanBufferClass, type SpanBufferConstructor } from './spanBuffer.js';
|
|
37
|
+
import type { SpanContextClass } from './spanContext.js';
|
|
38
|
+
import { consumeSpanStartedAtAllocation, type TimestampAppendPrimitive } from './traceRoot.js';
|
|
39
|
+
import type { AnySpanBuffer } from './types.js';
|
|
40
|
+
import { getVocabularyGeneration, type VocabularyGeneration } from './vocabularyRegistry.js';
|
|
41
|
+
import { createWasmLayoutTemplate, type WasmLayoutTemplate } from './wasm/wasmPhysicalLayout.js';
|
|
42
|
+
|
|
43
|
+
export const PHYSICAL_LAYOUT_VERSION = 1;
|
|
44
|
+
|
|
45
|
+
/** Concrete backends may bind the same physical schema to distinct immutable plans. */
|
|
46
|
+
export type PhysicalBackendKind = 'strategy-selected' | 'js-heap' | 'wasm';
|
|
47
|
+
|
|
48
|
+
/** Canonical schema-ordered eager column selection for generated storage and cache identity. */
|
|
49
|
+
export interface EagerColumnDescriptor {
|
|
50
|
+
readonly names: readonly string[];
|
|
51
|
+
readonly words: readonly number[];
|
|
52
|
+
readonly key: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface ArrowExposurePlan {
|
|
56
|
+
readonly version: 1;
|
|
57
|
+
readonly primitiveStorage: 'borrowed-chunks' | 'owned-copy';
|
|
58
|
+
readonly dictionaryStorage: 'pinned-generation-prefix';
|
|
59
|
+
readonly entryTypeStorage: 'borrowed-u8' | 'derived-row-headers' | 'owned-copy';
|
|
60
|
+
readonly messageIdentityStorage: 'local-u16' | 'global-u32' | 'packed-row-headers';
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const JS_ARROW_EXPOSURE_BY_LAYOUT: Readonly<Record<MessagePhysicalLayout, ArrowExposurePlan>> = Object.freeze({
|
|
64
|
+
current: Object.freeze({
|
|
65
|
+
version: 1,
|
|
66
|
+
primitiveStorage: 'borrowed-chunks',
|
|
67
|
+
dictionaryStorage: 'pinned-generation-prefix',
|
|
68
|
+
entryTypeStorage: 'borrowed-u8',
|
|
69
|
+
messageIdentityStorage: 'local-u16',
|
|
70
|
+
}),
|
|
71
|
+
specialized: Object.freeze({
|
|
72
|
+
version: 1,
|
|
73
|
+
primitiveStorage: 'borrowed-chunks',
|
|
74
|
+
dictionaryStorage: 'pinned-generation-prefix',
|
|
75
|
+
entryTypeStorage: 'borrowed-u8',
|
|
76
|
+
messageIdentityStorage: 'global-u32',
|
|
77
|
+
}),
|
|
78
|
+
packed: Object.freeze({
|
|
79
|
+
version: 1,
|
|
80
|
+
primitiveStorage: 'borrowed-chunks',
|
|
81
|
+
dictionaryStorage: 'pinned-generation-prefix',
|
|
82
|
+
entryTypeStorage: 'derived-row-headers',
|
|
83
|
+
messageIdentityStorage: 'packed-row-headers',
|
|
84
|
+
}),
|
|
85
|
+
});
|
|
86
|
+
const WASM_ARROW_EXPOSURE_BY_LAYOUT: Readonly<Record<MessagePhysicalLayout, ArrowExposurePlan>> = Object.freeze({
|
|
87
|
+
current: Object.freeze({
|
|
88
|
+
version: 1,
|
|
89
|
+
primitiveStorage: 'owned-copy',
|
|
90
|
+
dictionaryStorage: 'pinned-generation-prefix',
|
|
91
|
+
entryTypeStorage: 'owned-copy',
|
|
92
|
+
messageIdentityStorage: 'local-u16',
|
|
93
|
+
}),
|
|
94
|
+
specialized: Object.freeze({
|
|
95
|
+
version: 1,
|
|
96
|
+
primitiveStorage: 'owned-copy',
|
|
97
|
+
dictionaryStorage: 'pinned-generation-prefix',
|
|
98
|
+
entryTypeStorage: 'owned-copy',
|
|
99
|
+
messageIdentityStorage: 'global-u32',
|
|
100
|
+
}),
|
|
101
|
+
packed: Object.freeze({
|
|
102
|
+
version: 1,
|
|
103
|
+
primitiveStorage: 'owned-copy',
|
|
104
|
+
dictionaryStorage: 'pinned-generation-prefix',
|
|
105
|
+
entryTypeStorage: 'derived-row-headers',
|
|
106
|
+
messageIdentityStorage: 'packed-row-headers',
|
|
107
|
+
}),
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const EMPTY_EAGER_COLUMNS: EagerColumnDescriptor = Object.freeze({
|
|
111
|
+
names: Object.freeze([]),
|
|
112
|
+
words: Object.freeze([]),
|
|
113
|
+
key: '',
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
export function resolveEagerColumns(schema: LogSchema, requestedNames: readonly string[] = []): EagerColumnDescriptor {
|
|
117
|
+
if (requestedNames.length === 0) return EMPTY_EAGER_COLUMNS;
|
|
118
|
+
const requested = new Set(requestedNames);
|
|
119
|
+
const names: string[] = [];
|
|
120
|
+
const words = new Array<number>(Math.ceil(schema._columnNames.length / 32)).fill(0);
|
|
121
|
+
for (let columnIndex = 0; columnIndex < schema._columnNames.length; columnIndex++) {
|
|
122
|
+
const name = schema._columnNames[columnIndex];
|
|
123
|
+
if (!requested.delete(name)) continue;
|
|
124
|
+
names.push(name);
|
|
125
|
+
const wordIndex = columnIndex >>> 5;
|
|
126
|
+
words[wordIndex] = (words[wordIndex] | (1 << (columnIndex & 31))) >>> 0;
|
|
127
|
+
}
|
|
128
|
+
if (requested.size !== 0) {
|
|
129
|
+
throw new TypeError(`Unknown eager column${requested.size === 1 ? '' : 's'}: ${[...requested].join(', ')}`);
|
|
130
|
+
}
|
|
131
|
+
while (words.length !== 0 && words[words.length - 1] === 0) words.pop();
|
|
132
|
+
const frozenWords = Object.freeze(words);
|
|
133
|
+
return Object.freeze({
|
|
134
|
+
names: Object.freeze(names),
|
|
135
|
+
words: frozenWords,
|
|
136
|
+
key: frozenWords.map((word) => word.toString(16).padStart(8, '0')).join(''),
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export interface PhysicalClock {
|
|
141
|
+
readonly kind: 'trace-root';
|
|
142
|
+
now(buffer: AnySpanBuffer): Nanoseconds;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface PhysicalAppenders {
|
|
146
|
+
writeSpanStart(buffer: AnySpanBuffer, name: string | number): void;
|
|
147
|
+
writeSpanEnd(buffer: AnySpanBuffer, entryType: number): void;
|
|
148
|
+
writeLogEntry(buffer: AnySpanBuffer, entryType: number): number;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export interface PhysicalLayoutPlan<T extends LogSchema = LogSchema, Ctx extends OpContext<T> = OpContext<T>> {
|
|
152
|
+
readonly version: typeof PHYSICAL_LAYOUT_VERSION;
|
|
153
|
+
readonly backendKind: PhysicalBackendKind;
|
|
154
|
+
readonly schema: T;
|
|
155
|
+
readonly runtimeHint: number;
|
|
156
|
+
readonly capabilities: number;
|
|
157
|
+
readonly messageLayoutFamily: MessageLayoutFamily;
|
|
158
|
+
readonly messagePhysicalLayout: MessagePhysicalLayout;
|
|
159
|
+
readonly eagerColumns: EagerColumnDescriptor;
|
|
160
|
+
/** Immutable schema-order enum metadata shared by every plan and generated writer. */
|
|
161
|
+
readonly enumLookup: SchemaEnumLookupDescriptor;
|
|
162
|
+
/** Fixed transformer tier, or undefined to retain adaptive strategy capacity. */
|
|
163
|
+
readonly capacityTier: number | undefined;
|
|
164
|
+
/** Canonical user-context key layout used by the generated context constructor. */
|
|
165
|
+
readonly contextLayoutKey: string;
|
|
166
|
+
/** Exact constructor selected at startup for this plan's capability/layout signature. */
|
|
167
|
+
readonly SpanContextClass: SpanContextClass<Ctx>;
|
|
168
|
+
readonly SpanBufferClass: SpanBufferConstructor<T>;
|
|
169
|
+
readonly SpanLoggerClass: SpanLoggerConstructor<T> | undefined;
|
|
170
|
+
readonly TagWriterClass: TagWriterConstructor<T> | undefined;
|
|
171
|
+
readonly ResultWriterClass: ResultWriterConstructor;
|
|
172
|
+
readonly clock: PhysicalClock;
|
|
173
|
+
readonly appenders: PhysicalAppenders;
|
|
174
|
+
readonly appendLogEntry: TimestampAppendPrimitive;
|
|
175
|
+
/** Immutable global vocabulary generation used by dense row identities in this plan. */
|
|
176
|
+
readonly vocabularyGeneration: VocabularyGeneration;
|
|
177
|
+
/** Startup-fixed ownership policy used by leased Arrow conversion. */
|
|
178
|
+
/** Current-mode local ID minus one maps to a global vocabulary dense index. */
|
|
179
|
+
readonly localMessageDictionary: readonly number[];
|
|
180
|
+
readonly arrowExposure: ArrowExposurePlan;
|
|
181
|
+
/** Allocation-free hot lookup from global dense identity to 1-based local ID. */
|
|
182
|
+
readonly encodeLocalMessage: (globalDenseIndex: number) => number;
|
|
183
|
+
/** Reserved immutable ownership slot; buffer pooling is a later task. */
|
|
184
|
+
readonly poolRef: null;
|
|
185
|
+
readonly remapDescriptor: RemapDescriptor | null;
|
|
186
|
+
readonly newCtx0: (parent: object) => object;
|
|
187
|
+
readonly newCtx1: (parent: object, overrides: object) => object;
|
|
188
|
+
readonly newSpanLogger: ((state: WriterState) => SpanLoggerImpl<T>) | undefined;
|
|
189
|
+
readonly newTagWriter: ((state: WriterState) => TagWriter<T>) | undefined;
|
|
190
|
+
readonly wasmLayout: WasmLayoutTemplate;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** Fully resolved immutable operands for one operation callsite. */
|
|
194
|
+
export interface CallsitePlan<T extends LogSchema = LogSchema, Ctx extends OpContext<T> = OpContext<T>>
|
|
195
|
+
extends PhysicalLayoutPlan<T, Ctx> {
|
|
196
|
+
readonly metadata: OpMetadata;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export function sealCallsitePlan<T extends LogSchema, Ctx extends OpContext<T>>(
|
|
200
|
+
physicalLayoutPlan: PhysicalLayoutPlan<T, Ctx>,
|
|
201
|
+
metadata: OpMetadata,
|
|
202
|
+
): CallsitePlan<T, Ctx> {
|
|
203
|
+
return Object.freeze({ ...physicalLayoutPlan, metadata });
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const newCtx0 = (parent: object): object => parent;
|
|
207
|
+
|
|
208
|
+
function createNewCtx1(contextLayoutKey: string): (parent: object, overrides: object) => object {
|
|
209
|
+
const keys = contextLayoutKey === '' ? [] : contextLayoutKey.split('\u0000');
|
|
210
|
+
return (parent: object, overrides: object): object => {
|
|
211
|
+
const context: Record<string, unknown> = {};
|
|
212
|
+
for (const key of keys) {
|
|
213
|
+
context[key] = Object.hasOwn(overrides, key) ? Reflect.get(overrides, key) : Reflect.get(parent, key);
|
|
214
|
+
}
|
|
215
|
+
return context;
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const TRACE_ROOT_CLOCK: PhysicalClock = Object.freeze({
|
|
220
|
+
kind: 'trace-root' as const,
|
|
221
|
+
now(buffer: AnySpanBuffer): Nanoseconds {
|
|
222
|
+
const traceRoot = buffer._traceRoot;
|
|
223
|
+
return traceRoot._timestampNow(traceRoot);
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
const SPLIT_APPEND_LOG_ENTRY: TimestampAppendPrimitive = (traceRoot, buffer, entryType) =>
|
|
228
|
+
traceRoot._appendLogEntry(traceRoot, buffer, entryType);
|
|
229
|
+
|
|
230
|
+
const PACKED_APPEND_LOG_ENTRY: TimestampAppendPrimitive = (traceRoot, buffer, entryType) => {
|
|
231
|
+
const row = buffer._writeIndex;
|
|
232
|
+
const headers = buffer._rowHeaders;
|
|
233
|
+
if (headers === undefined) throw new TypeError('Packed layout is missing row headers');
|
|
234
|
+
buffer.timestamp[row] = traceRoot._timestampNow(traceRoot);
|
|
235
|
+
headers[row] = entryType;
|
|
236
|
+
buffer._writeIndex = row + 1;
|
|
237
|
+
return row;
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
const CURRENT_BASE_APPENDERS = {
|
|
241
|
+
writeSpanEnd(buffer: AnySpanBuffer, entryType: number): void {
|
|
242
|
+
const traceRoot = buffer._traceRoot;
|
|
243
|
+
traceRoot._writeSpanEnd(traceRoot, buffer, entryType);
|
|
244
|
+
},
|
|
245
|
+
writeLogEntry(buffer: AnySpanBuffer, entryType: number): number {
|
|
246
|
+
return SPLIT_APPEND_LOG_ENTRY(buffer._traceRoot, buffer, entryType);
|
|
247
|
+
},
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
function initializeCurrentSpan(buffer: AnySpanBuffer): Uint8Array {
|
|
251
|
+
const entryTypes = buffer.entry_type;
|
|
252
|
+
if (entryTypes === undefined) throw new TypeError('Current layout is missing entry types');
|
|
253
|
+
if (!consumeSpanStartedAtAllocation(buffer)) {
|
|
254
|
+
const traceRoot = buffer._traceRoot;
|
|
255
|
+
buffer.timestamp[0] = traceRoot._timestampNow(traceRoot);
|
|
256
|
+
entryTypes[0] = ENTRY_TYPE_SPAN_START;
|
|
257
|
+
entryTypes[1] = ENTRY_TYPE_SPAN_EXCEPTION;
|
|
258
|
+
buffer.timestamp[1] = 0n;
|
|
259
|
+
buffer._writeIndex = 2;
|
|
260
|
+
}
|
|
261
|
+
return entryTypes;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const CURRENT_MIXED_APPENDERS: PhysicalAppenders = Object.freeze({
|
|
265
|
+
...CURRENT_BASE_APPENDERS,
|
|
266
|
+
writeSpanStart(buffer: AnySpanBuffer, name: string | number): void {
|
|
267
|
+
initializeCurrentSpan(buffer);
|
|
268
|
+
if (typeof name === 'string') {
|
|
269
|
+
buffer.message(0, name);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
const localId = buffer._opMetadata._physicalLayoutPlan?.encodeLocalMessage(name) ?? 0;
|
|
273
|
+
if (localId === 0) {
|
|
274
|
+
const rawMessages = buffer.message_values;
|
|
275
|
+
if (rawMessages === undefined) throw new TypeError('Current mixed layout is missing raw message storage');
|
|
276
|
+
rawMessages[0] = decodeVocabularyMessage(buffer._vocabularyGeneration, name);
|
|
277
|
+
} else {
|
|
278
|
+
const messageIds = buffer._messageIds;
|
|
279
|
+
if (messageIds === undefined) throw new TypeError('Current mixed layout is missing local message storage');
|
|
280
|
+
messageIds[0] = localId;
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
const CURRENT_STATIC_APPENDERS: PhysicalAppenders = Object.freeze({
|
|
286
|
+
...CURRENT_BASE_APPENDERS,
|
|
287
|
+
writeSpanStart(buffer: AnySpanBuffer, name: string | number): void {
|
|
288
|
+
initializeCurrentSpan(buffer);
|
|
289
|
+
if (typeof name === 'string') {
|
|
290
|
+
buffer._spanName = name;
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
const localId = buffer._opMetadata._physicalLayoutPlan?.encodeLocalMessage(name) ?? 0;
|
|
294
|
+
if (localId === 0) {
|
|
295
|
+
buffer._spanName = name;
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
const messageIds = buffer._messageIds;
|
|
299
|
+
if (messageIds === undefined) throw new TypeError('Current static layout is missing local message storage');
|
|
300
|
+
messageIds[0] = localId;
|
|
301
|
+
},
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
const CURRENT_DYNAMIC_APPENDERS: PhysicalAppenders = Object.freeze({
|
|
305
|
+
...CURRENT_BASE_APPENDERS,
|
|
306
|
+
writeSpanStart(buffer: AnySpanBuffer, name: string | number): void {
|
|
307
|
+
initializeCurrentSpan(buffer);
|
|
308
|
+
buffer._spanName = name;
|
|
309
|
+
},
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
const SPLIT_MIXED_APPENDERS: PhysicalAppenders = Object.freeze({
|
|
313
|
+
writeSpanStart(buffer: AnySpanBuffer, name: string | number): void {
|
|
314
|
+
if (typeof name === 'number') {
|
|
315
|
+
const entryTypes = buffer.entry_type;
|
|
316
|
+
const headers = buffer._logHeaders;
|
|
317
|
+
if (entryTypes === undefined || headers === undefined) throw new TypeError('Split mixed layout is incomplete');
|
|
318
|
+
if (!consumeSpanStartedAtAllocation(buffer)) {
|
|
319
|
+
const traceRoot = buffer._traceRoot;
|
|
320
|
+
buffer.timestamp[0] = traceRoot._timestampNow(traceRoot);
|
|
321
|
+
entryTypes[0] = ENTRY_TYPE_SPAN_START;
|
|
322
|
+
entryTypes[1] = ENTRY_TYPE_SPAN_EXCEPTION;
|
|
323
|
+
buffer.timestamp[1] = 0n;
|
|
324
|
+
buffer._writeIndex = 2;
|
|
325
|
+
}
|
|
326
|
+
headers[0] = name + 1;
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
const traceRoot = buffer._traceRoot;
|
|
330
|
+
traceRoot._writeSpanStart(traceRoot, buffer, name);
|
|
331
|
+
},
|
|
332
|
+
writeSpanEnd(buffer: AnySpanBuffer, entryType: number): void {
|
|
333
|
+
const traceRoot = buffer._traceRoot;
|
|
334
|
+
traceRoot._writeSpanEnd(traceRoot, buffer, entryType);
|
|
335
|
+
},
|
|
336
|
+
writeLogEntry(buffer: AnySpanBuffer, entryType: number): number {
|
|
337
|
+
return SPLIT_APPEND_LOG_ENTRY(buffer._traceRoot, buffer, entryType);
|
|
338
|
+
},
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
const SPLIT_STATIC_APPENDERS: PhysicalAppenders = Object.freeze({
|
|
342
|
+
...SPLIT_MIXED_APPENDERS,
|
|
343
|
+
writeSpanStart(buffer: AnySpanBuffer, name: string | number): void {
|
|
344
|
+
const entryTypes = buffer.entry_type;
|
|
345
|
+
const headers = buffer._logHeaders;
|
|
346
|
+
if (entryTypes === undefined || headers === undefined) throw new TypeError('Split static layout is incomplete');
|
|
347
|
+
if (!consumeSpanStartedAtAllocation(buffer)) {
|
|
348
|
+
const traceRoot = buffer._traceRoot;
|
|
349
|
+
buffer.timestamp[0] = traceRoot._timestampNow(traceRoot);
|
|
350
|
+
entryTypes[0] = ENTRY_TYPE_SPAN_START;
|
|
351
|
+
entryTypes[1] = ENTRY_TYPE_SPAN_EXCEPTION;
|
|
352
|
+
buffer.timestamp[1] = 0n;
|
|
353
|
+
buffer._writeIndex = 2;
|
|
354
|
+
}
|
|
355
|
+
if (typeof name === 'number') {
|
|
356
|
+
headers[0] = name + 1;
|
|
357
|
+
} else {
|
|
358
|
+
buffer._spanName = name;
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
const SPLIT_DYNAMIC_APPENDERS: PhysicalAppenders = Object.freeze({
|
|
364
|
+
...SPLIT_MIXED_APPENDERS,
|
|
365
|
+
writeSpanStart(buffer: AnySpanBuffer, name: string | number): void {
|
|
366
|
+
const entryTypes = buffer.entry_type;
|
|
367
|
+
if (entryTypes === undefined) throw new TypeError('Split dynamic layout is missing entry types');
|
|
368
|
+
if (!consumeSpanStartedAtAllocation(buffer)) {
|
|
369
|
+
const traceRoot = buffer._traceRoot;
|
|
370
|
+
buffer.timestamp[0] = traceRoot._timestampNow(traceRoot);
|
|
371
|
+
entryTypes[0] = ENTRY_TYPE_SPAN_START;
|
|
372
|
+
entryTypes[1] = ENTRY_TYPE_SPAN_EXCEPTION;
|
|
373
|
+
buffer.timestamp[1] = 0n;
|
|
374
|
+
buffer._writeIndex = 2;
|
|
375
|
+
}
|
|
376
|
+
buffer._spanName = name;
|
|
377
|
+
},
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
function packedAppenders(messageLayoutFamily: MessageLayoutFamily): PhysicalAppenders {
|
|
381
|
+
return Object.freeze({
|
|
382
|
+
writeSpanStart(buffer: AnySpanBuffer, name: string | number): void {
|
|
383
|
+
const headers = buffer._rowHeaders;
|
|
384
|
+
if (headers === undefined) throw new TypeError('Packed layout is missing row headers');
|
|
385
|
+
const startedAtAllocation = consumeSpanStartedAtAllocation(buffer);
|
|
386
|
+
if (!startedAtAllocation) buffer.timestamp[0] = buffer._traceRoot._timestampNow(buffer._traceRoot);
|
|
387
|
+
if (typeof name === 'number') {
|
|
388
|
+
if (name > MAX_PACKED_MESSAGE_DENSE_INDEX) throw new RangeError('Packed message dense index exceeds 0xFFFFFE');
|
|
389
|
+
headers[0] = (((name + 1) << 8) | ENTRY_TYPE_SPAN_START) >>> 0;
|
|
390
|
+
} else {
|
|
391
|
+
headers[0] = ENTRY_TYPE_SPAN_START;
|
|
392
|
+
if (messageLayoutFamily === 'static-only' || messageLayoutFamily === 'dynamic-only') {
|
|
393
|
+
buffer._spanName = name;
|
|
394
|
+
} else {
|
|
395
|
+
const rawMessages = buffer.message_values;
|
|
396
|
+
if (rawMessages === undefined) throw new TypeError('Packed mixed layout is missing raw message storage');
|
|
397
|
+
if (typeof name !== 'string') throw new TypeError('Packed mixed numeric span name was not encoded');
|
|
398
|
+
rawMessages[0] = name;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
if (!startedAtAllocation) {
|
|
402
|
+
headers[1] = ENTRY_TYPE_SPAN_EXCEPTION;
|
|
403
|
+
buffer.timestamp[1] = 0n;
|
|
404
|
+
buffer._writeIndex = 2;
|
|
405
|
+
}
|
|
406
|
+
},
|
|
407
|
+
writeSpanEnd(buffer: AnySpanBuffer, entryType: number): void {
|
|
408
|
+
const headers = buffer._rowHeaders;
|
|
409
|
+
if (headers === undefined) throw new TypeError('Packed layout is missing row headers');
|
|
410
|
+
const traceRoot = buffer._traceRoot;
|
|
411
|
+
buffer.timestamp[1] = traceRoot._timestampNow(traceRoot);
|
|
412
|
+
headers[1] = entryType;
|
|
413
|
+
buffer._sealStatsChain();
|
|
414
|
+
},
|
|
415
|
+
writeLogEntry(buffer: AnySpanBuffer, entryType: number): number {
|
|
416
|
+
return PACKED_APPEND_LOG_ENTRY(buffer._traceRoot, buffer, entryType);
|
|
417
|
+
},
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const APPENDERS_BY_MESSAGE_LAYOUT: Readonly<Record<string, PhysicalAppenders>> = Object.freeze({
|
|
422
|
+
'static-only:current': CURRENT_STATIC_APPENDERS,
|
|
423
|
+
'mixed:current': CURRENT_MIXED_APPENDERS,
|
|
424
|
+
'dynamic-only:current': CURRENT_DYNAMIC_APPENDERS,
|
|
425
|
+
'static-only:specialized': SPLIT_STATIC_APPENDERS,
|
|
426
|
+
'mixed:specialized': SPLIT_MIXED_APPENDERS,
|
|
427
|
+
'dynamic-only:specialized': SPLIT_DYNAMIC_APPENDERS,
|
|
428
|
+
'static-only:packed': packedAppenders('static-only'),
|
|
429
|
+
'mixed:packed': packedAppenders('mixed'),
|
|
430
|
+
'dynamic-only:packed': packedAppenders('dynamic-only'),
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
const EMPTY_LOCAL_MESSAGE_DICTIONARY: readonly number[] = Object.freeze([]);
|
|
434
|
+
const NO_LOCAL_MESSAGE = (_globalDenseIndex: number): number => 0;
|
|
435
|
+
|
|
436
|
+
function createLocalMessageEncoder(dictionary: readonly number[]): (globalDenseIndex: number) => number {
|
|
437
|
+
if (dictionary.length === 0) return NO_LOCAL_MESSAGE;
|
|
438
|
+
const localByDense = new Map<number, number>();
|
|
439
|
+
let localId = 1;
|
|
440
|
+
for (const globalDenseIndex of dictionary) localByDense.set(globalDenseIndex, localId++);
|
|
441
|
+
return (globalDenseIndex: number): number => localByDense.get(globalDenseIndex) ?? 0;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
const basePlans = new WeakMap<LogSchema, WeakMap<object, Map<string, object>>>();
|
|
445
|
+
const remappedPlans = new WeakMap<object, WeakMap<RemapDescriptor, object>>();
|
|
446
|
+
|
|
447
|
+
function createBasePlan<T extends LogSchema, Ctx extends OpContext<T>>(
|
|
448
|
+
SpanBufferClass: SpanBufferConstructor<T>,
|
|
449
|
+
runtimeHint: number,
|
|
450
|
+
backendKind: PhysicalBackendKind,
|
|
451
|
+
SpanContextClass: SpanContextClass<Ctx>,
|
|
452
|
+
contextLayoutKey: string,
|
|
453
|
+
vocabularyGeneration: VocabularyGeneration,
|
|
454
|
+
eagerColumns: EagerColumnDescriptor,
|
|
455
|
+
localMessageDictionary: readonly number[],
|
|
456
|
+
messagePhysicalLayout: MessagePhysicalLayout,
|
|
457
|
+
): PhysicalLayoutPlan<T, Ctx> {
|
|
458
|
+
const schema = SpanBufferClass.schema;
|
|
459
|
+
const enumLookup = resolveEnumLookupDescriptor(schema);
|
|
460
|
+
const messageLayoutFamily = runtimeHintMessageLayoutFamily(runtimeHint);
|
|
461
|
+
const PlannedSpanBufferClass = getSpanBufferClass(schema, messageLayoutFamily, messagePhysicalLayout, eagerColumns);
|
|
462
|
+
const capabilities = isRuntimeHintAnalyzed(runtimeHint)
|
|
463
|
+
? runtimeHint & RUNTIME_HINT_CAPABILITIES_MASK
|
|
464
|
+
: RUNTIME_HINT_FULL_CAPABILITIES;
|
|
465
|
+
const needsLogger = (capabilities & (RUNTIME_HINT_LOG | RUNTIME_HINT_FF | RUNTIME_HINT_SCOPE)) !== 0;
|
|
466
|
+
const SpanLoggerClass = needsLogger
|
|
467
|
+
? createSpanLoggerClass(schema, messageLayoutFamily, messagePhysicalLayout, eagerColumns.names, enumLookup)
|
|
468
|
+
: undefined;
|
|
469
|
+
const ResultWriterClass = getResultWriterClass(
|
|
470
|
+
schema,
|
|
471
|
+
messageLayoutFamily,
|
|
472
|
+
messagePhysicalLayout,
|
|
473
|
+
eagerColumns.names,
|
|
474
|
+
enumLookup,
|
|
475
|
+
);
|
|
476
|
+
const needsTag = (capabilities & RUNTIME_HINT_TAG) !== 0;
|
|
477
|
+
const TagWriterClass = needsTag ? getTagWriterClass(schema, eagerColumns.names, enumLookup) : undefined;
|
|
478
|
+
const newSpanLogger =
|
|
479
|
+
SpanLoggerClass === undefined ? undefined : (state: WriterState): SpanLoggerImpl<T> => new SpanLoggerClass(state);
|
|
480
|
+
const newTagWriter =
|
|
481
|
+
TagWriterClass === undefined ? undefined : (state: WriterState): TagWriter<T> => new TagWriterClass(state);
|
|
482
|
+
const wasmLayout = createWasmLayoutTemplate(schema, messageLayoutFamily, messagePhysicalLayout, eagerColumns);
|
|
483
|
+
|
|
484
|
+
return Object.freeze({
|
|
485
|
+
version: PHYSICAL_LAYOUT_VERSION,
|
|
486
|
+
backendKind,
|
|
487
|
+
schema,
|
|
488
|
+
runtimeHint,
|
|
489
|
+
capabilities,
|
|
490
|
+
messageLayoutFamily,
|
|
491
|
+
messagePhysicalLayout,
|
|
492
|
+
eagerColumns,
|
|
493
|
+
enumLookup,
|
|
494
|
+
encodeLocalMessage: createLocalMessageEncoder(localMessageDictionary),
|
|
495
|
+
contextLayoutKey,
|
|
496
|
+
SpanContextClass,
|
|
497
|
+
capacityTier: runtimeHintInitialCapacity(runtimeHint),
|
|
498
|
+
SpanBufferClass: PlannedSpanBufferClass,
|
|
499
|
+
SpanLoggerClass,
|
|
500
|
+
TagWriterClass,
|
|
501
|
+
ResultWriterClass,
|
|
502
|
+
clock: TRACE_ROOT_CLOCK,
|
|
503
|
+
appendLogEntry: messagePhysicalLayout === 'packed' ? PACKED_APPEND_LOG_ENTRY : SPLIT_APPEND_LOG_ENTRY,
|
|
504
|
+
appenders: APPENDERS_BY_MESSAGE_LAYOUT[`${messageLayoutFamily}:${messagePhysicalLayout}`],
|
|
505
|
+
localMessageDictionary,
|
|
506
|
+
vocabularyGeneration,
|
|
507
|
+
arrowExposure:
|
|
508
|
+
backendKind === 'wasm'
|
|
509
|
+
? WASM_ARROW_EXPOSURE_BY_LAYOUT[messagePhysicalLayout]
|
|
510
|
+
: JS_ARROW_EXPOSURE_BY_LAYOUT[messagePhysicalLayout],
|
|
511
|
+
poolRef: null,
|
|
512
|
+
remapDescriptor: null,
|
|
513
|
+
newCtx0,
|
|
514
|
+
newCtx1: createNewCtx1(contextLayoutKey),
|
|
515
|
+
newSpanLogger,
|
|
516
|
+
newTagWriter,
|
|
517
|
+
wasmLayout,
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
export function getPhysicalLayoutPlan<T extends LogSchema, Ctx extends OpContext<T>>(
|
|
522
|
+
SpanBufferClass: SpanBufferConstructor<T>,
|
|
523
|
+
runtimeHint: number,
|
|
524
|
+
SpanContextClass: SpanContextClass<Ctx>,
|
|
525
|
+
remapDescriptor?: RemapDescriptor,
|
|
526
|
+
backendKind: PhysicalBackendKind = 'strategy-selected',
|
|
527
|
+
contextLayoutKey = '',
|
|
528
|
+
eagerColumnNames: readonly string[] = [],
|
|
529
|
+
localMessageDictionary: readonly number[] = Object.freeze([]),
|
|
530
|
+
): PhysicalLayoutPlan<T, Ctx> {
|
|
531
|
+
const schema = SpanBufferClass.schema;
|
|
532
|
+
const eagerColumns = resolveEagerColumns(schema, eagerColumnNames);
|
|
533
|
+
const resolvedLocalMessageDictionary =
|
|
534
|
+
localMessageDictionary.length === 0
|
|
535
|
+
? EMPTY_LOCAL_MESSAGE_DICTIONARY
|
|
536
|
+
: Object.isFrozen(localMessageDictionary)
|
|
537
|
+
? localMessageDictionary
|
|
538
|
+
: Object.freeze([...localMessageDictionary]);
|
|
539
|
+
let byContextClass = basePlans.get(schema);
|
|
540
|
+
if (!byContextClass) {
|
|
541
|
+
byContextClass = new WeakMap();
|
|
542
|
+
basePlans.set(schema, byContextClass);
|
|
543
|
+
}
|
|
544
|
+
let byKey = byContextClass.get(SpanContextClass);
|
|
545
|
+
if (!byKey) {
|
|
546
|
+
byKey = new Map();
|
|
547
|
+
byContextClass.set(SpanContextClass, byKey);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
const vocabularyGeneration = getVocabularyGeneration();
|
|
551
|
+
const messageLayoutFamily = runtimeHintMessageLayoutFamily(runtimeHint);
|
|
552
|
+
const requestedPhysicalLayout = runtimeHintMessagePhysicalLayout(runtimeHint);
|
|
553
|
+
const messagePhysicalLayout =
|
|
554
|
+
requestedPhysicalLayout === 'packed' && vocabularyGeneration.ids.length - 1 > MAX_PACKED_MESSAGE_DENSE_INDEX
|
|
555
|
+
? 'specialized'
|
|
556
|
+
: requestedPhysicalLayout;
|
|
557
|
+
const key = `${PHYSICAL_LAYOUT_VERSION}:${backendKind}:${runtimeHint}:${messageLayoutFamily}:${messagePhysicalLayout}:${contextLayoutKey}:${vocabularyGeneration.generation}:${eagerColumns.key}:${resolvedLocalMessageDictionary.join(',')}`;
|
|
558
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- cache keys encode schema/context/runtime identity for this erased store.
|
|
559
|
+
let base = byKey.get(key) as PhysicalLayoutPlan<T, Ctx> | undefined;
|
|
560
|
+
if (!base) {
|
|
561
|
+
base = createBasePlan(
|
|
562
|
+
SpanBufferClass,
|
|
563
|
+
runtimeHint,
|
|
564
|
+
backendKind,
|
|
565
|
+
SpanContextClass,
|
|
566
|
+
contextLayoutKey,
|
|
567
|
+
vocabularyGeneration,
|
|
568
|
+
eagerColumns,
|
|
569
|
+
resolvedLocalMessageDictionary,
|
|
570
|
+
messagePhysicalLayout,
|
|
571
|
+
);
|
|
572
|
+
byKey.set(key, base);
|
|
573
|
+
} else if (
|
|
574
|
+
base.SpanBufferClass.messageLayoutFamily !== messageLayoutFamily ||
|
|
575
|
+
base.SpanBufferClass.messagePhysicalLayout !== messagePhysicalLayout
|
|
576
|
+
) {
|
|
577
|
+
throw new TypeError('Physical layout cache key resolved to a different message layout');
|
|
578
|
+
} else if (base.SpanContextClass !== SpanContextClass) {
|
|
579
|
+
throw new TypeError('Physical layout cache key resolved to a different SpanContext constructor');
|
|
580
|
+
}
|
|
581
|
+
if (!remapDescriptor) return base;
|
|
582
|
+
|
|
583
|
+
let bindings = remappedPlans.get(base);
|
|
584
|
+
if (!bindings) {
|
|
585
|
+
bindings = new WeakMap();
|
|
586
|
+
remappedPlans.set(base, bindings);
|
|
587
|
+
}
|
|
588
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- remapped plans are stored under the exact base+descriptor pair created below.
|
|
589
|
+
const cached = bindings.get(remapDescriptor) as PhysicalLayoutPlan<T, Ctx> | undefined;
|
|
590
|
+
if (cached) return cached;
|
|
591
|
+
|
|
592
|
+
const bound: PhysicalLayoutPlan<T, Ctx> = Object.freeze({
|
|
593
|
+
...base,
|
|
594
|
+
remapDescriptor,
|
|
595
|
+
});
|
|
596
|
+
bindings.set(remapDescriptor, bound);
|
|
597
|
+
return bound;
|
|
598
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { AnySpanBuffer } from './types.js';
|
|
2
|
+
import type { VocabularyGeneration } from './vocabularyRegistry.js';
|
|
3
|
+
|
|
4
|
+
const decoder = new TextDecoder('utf-8', { fatal: true });
|
|
5
|
+
const decodedGenerations = new WeakMap<VocabularyGeneration, (string | undefined)[]>();
|
|
6
|
+
export const MAX_PACKED_MESSAGE_DENSE_INDEX = 0x00fffffe;
|
|
7
|
+
|
|
8
|
+
export function decodeVocabularyMessage(generation: VocabularyGeneration, denseIndex: number): string {
|
|
9
|
+
if (denseIndex >= generation.ids.length) {
|
|
10
|
+
throw new Error(`Invalid vocabulary dense index ${denseIndex} for generation ${generation.generation}`);
|
|
11
|
+
}
|
|
12
|
+
let values = decodedGenerations.get(generation);
|
|
13
|
+
if (values === undefined) {
|
|
14
|
+
values = new Array<string | undefined>(generation.ids.length);
|
|
15
|
+
decodedGenerations.set(generation, values);
|
|
16
|
+
}
|
|
17
|
+
const cached = values[denseIndex];
|
|
18
|
+
if (cached !== undefined) return cached;
|
|
19
|
+
|
|
20
|
+
const start = generation.offsets[denseIndex];
|
|
21
|
+
const end = generation.offsets[denseIndex + 1];
|
|
22
|
+
const record = generation.records.subarray(start, end);
|
|
23
|
+
const textLength = new DataView(record.buffer, record.byteOffset, 4).getUint32(0, true);
|
|
24
|
+
const value = decoder.decode(record.subarray(4, 4 + textLength));
|
|
25
|
+
values[denseIndex] = value;
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Resolve one entry type from either split or packed physical storage. */
|
|
30
|
+
export function resolveEntryType(buffer: AnySpanBuffer, row: number): number {
|
|
31
|
+
const packed = buffer._rowHeaders;
|
|
32
|
+
if (packed !== undefined) return packed[row] & 0xff;
|
|
33
|
+
const split = buffer.entry_type;
|
|
34
|
+
if (split === undefined) throw new TypeError('Span buffer has no declared entry-type storage');
|
|
35
|
+
return split[row];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Resolve one dynamic or process-dense vocabulary message row. */
|
|
39
|
+
export function resolveMessage(buffer: AnySpanBuffer, row: number): string | undefined {
|
|
40
|
+
if (row === 0 && buffer._spanName !== undefined) {
|
|
41
|
+
return typeof buffer._spanName === 'number'
|
|
42
|
+
? decodeVocabularyMessage(buffer._vocabularyGeneration, buffer._spanName)
|
|
43
|
+
: buffer._spanName;
|
|
44
|
+
}
|
|
45
|
+
if (row === 1 && buffer._terminalMessage !== undefined) return buffer._terminalMessage;
|
|
46
|
+
|
|
47
|
+
if (buffer._messagePhysicalLayout === 'current') {
|
|
48
|
+
const localId = buffer._messageIds?.[row] ?? 0;
|
|
49
|
+
if (localId === 0) return buffer.message_values?.[row];
|
|
50
|
+
const denseIndex = buffer._opMetadata._physicalLayoutPlan?.localMessageDictionary[localId - 1];
|
|
51
|
+
if (denseIndex === undefined) throw new Error(`Missing local message dictionary entry ${localId}`);
|
|
52
|
+
return decodeVocabularyMessage(buffer._vocabularyGeneration, denseIndex);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const packed = buffer._rowHeaders;
|
|
56
|
+
if (packed !== undefined) {
|
|
57
|
+
const encodedDenseIndex = packed[row] >>> 8;
|
|
58
|
+
return encodedDenseIndex === 0
|
|
59
|
+
? buffer.message_values?.[row]
|
|
60
|
+
: decodeVocabularyMessage(buffer._vocabularyGeneration, encodedDenseIndex - 1);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const encodedDenseIndex = buffer._logHeaders?.[row] ?? 0;
|
|
64
|
+
return encodedDenseIndex === 0
|
|
65
|
+
? buffer.message_values?.[row]
|
|
66
|
+
: decodeVocabularyMessage(buffer._vocabularyGeneration, encodedDenseIndex - 1);
|
|
67
|
+
}
|