@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
package/dist/lib/spanBuffer.js
CHANGED
|
@@ -24,16 +24,16 @@
|
|
|
24
24
|
*
|
|
25
25
|
* @module spanBuffer
|
|
26
26
|
*/
|
|
27
|
-
import { DEFAULT_BUFFER_CAPACITY, getColumnBufferClass } from '@smoothbricks/arrow-builder';
|
|
27
|
+
import { activeMaterializerMode, DEFAULT_BUFFER_CAPACITY, getColumnBufferClass, } from '@smoothbricks/arrow-builder';
|
|
28
28
|
import { checkCapacityTuning } from './capacityTuning.js';
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
29
|
+
import { LogSchema } from './schema/LogSchema.js';
|
|
30
|
+
import { copyThreadIdTo, getThreadId } from './threadId.js';
|
|
31
|
+
import { getVocabularyGeneration } from './vocabularyRegistry.js';
|
|
31
32
|
/**
|
|
32
33
|
* Empty frozen scope object - shared singleton to avoid allocations.
|
|
33
34
|
* Used as default _scopeValues for all buffers until setScope() is called.
|
|
34
35
|
*/
|
|
35
36
|
export const EMPTY_SCOPE = Object.freeze({});
|
|
36
|
-
const traceIdDecoder = new TextDecoder();
|
|
37
37
|
// ============================================================================
|
|
38
38
|
// Thread-local state (generated once per process/worker)
|
|
39
39
|
// These are used by the generated class code via the constructorPreamble
|
|
@@ -91,6 +91,8 @@ function isGeneratedSpanBufferClass(ctor) {
|
|
|
91
91
|
return false;
|
|
92
92
|
}
|
|
93
93
|
return (typeof Reflect.get(prototype, 'getOrCreateOverflow') === 'function' &&
|
|
94
|
+
typeof Reflect.get(prototype, '_sealStats') === 'function' &&
|
|
95
|
+
typeof Reflect.get(prototype, '_sealStatsChain') === 'function' &&
|
|
94
96
|
typeof Reflect.get(prototype, 'isParentOf') === 'function' &&
|
|
95
97
|
typeof Reflect.get(prototype, 'isChildOf') === 'function');
|
|
96
98
|
}
|
|
@@ -106,21 +108,396 @@ function getSpanBufferConstructorForBuffer(buffer) {
|
|
|
106
108
|
}
|
|
107
109
|
return ctor;
|
|
108
110
|
}
|
|
109
|
-
function createSpanBufferConstructor(schema, generatedClass) {
|
|
110
|
-
|
|
111
|
-
schema,
|
|
111
|
+
function createSpanBufferConstructor(schema, messageLayoutFamily, messagePhysicalLayout, generatedClass, eagerColumns) {
|
|
112
|
+
Object.defineProperties(generatedClass, {
|
|
113
|
+
schema: { value: schema, enumerable: true },
|
|
114
|
+
messageLayoutFamily: { value: messageLayoutFamily, enumerable: true },
|
|
115
|
+
messagePhysicalLayout: { value: messagePhysicalLayout, enumerable: true },
|
|
116
|
+
eagerColumns: { value: eagerColumns, enumerable: true },
|
|
112
117
|
stats: {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
118
|
+
value: {
|
|
119
|
+
capacity: DEFAULT_BUFFER_CAPACITY,
|
|
120
|
+
totalWrites: 0,
|
|
121
|
+
spansCreated: 0,
|
|
122
|
+
},
|
|
123
|
+
enumerable: true,
|
|
116
124
|
},
|
|
117
125
|
});
|
|
126
|
+
if (!isSpanBufferConstructorForSchema(generatedClass, schema)) {
|
|
127
|
+
throw new TypeError('Generated column buffer constructor initialization failed');
|
|
128
|
+
}
|
|
129
|
+
return generatedClass;
|
|
118
130
|
}
|
|
119
131
|
/**
|
|
120
132
|
* Cache for generated SpanBuffer classes per schema.
|
|
121
133
|
* Key is the schema object reference (WeakMap for GC).
|
|
122
134
|
*/
|
|
123
135
|
const spanBufferClassCache = new WeakMap();
|
|
136
|
+
const messageStorageSchemas = new WeakMap();
|
|
137
|
+
const EMPTY_EAGER_COLUMNS = Object.freeze({
|
|
138
|
+
names: Object.freeze([]),
|
|
139
|
+
words: Object.freeze([]),
|
|
140
|
+
key: '',
|
|
141
|
+
});
|
|
142
|
+
function resolveCompiledEagerColumns(schema, requestedNames) {
|
|
143
|
+
if (requestedNames.length === 0)
|
|
144
|
+
return EMPTY_EAGER_COLUMNS;
|
|
145
|
+
const requested = new Set(requestedNames);
|
|
146
|
+
const names = [];
|
|
147
|
+
const words = new Array(Math.ceil(schema._columnNames.length / 32)).fill(0);
|
|
148
|
+
for (let columnIndex = 0; columnIndex < schema._columnNames.length; columnIndex++) {
|
|
149
|
+
const name = schema._columnNames[columnIndex];
|
|
150
|
+
if (!requested.delete(name))
|
|
151
|
+
continue;
|
|
152
|
+
names.push(name);
|
|
153
|
+
const wordIndex = columnIndex >>> 5;
|
|
154
|
+
words[wordIndex] = (words[wordIndex] | (1 << (columnIndex & 31))) >>> 0;
|
|
155
|
+
}
|
|
156
|
+
if (requested.size !== 0) {
|
|
157
|
+
throw new TypeError(`Unknown compiled eager column${requested.size === 1 ? '' : 's'}: ${[...requested].join(', ')}`);
|
|
158
|
+
}
|
|
159
|
+
while (words.length !== 0 && words[words.length - 1] === 0)
|
|
160
|
+
words.pop();
|
|
161
|
+
const frozenWords = Object.freeze(words);
|
|
162
|
+
return Object.freeze({
|
|
163
|
+
names: Object.freeze(names),
|
|
164
|
+
words: frozenWords,
|
|
165
|
+
key: frozenWords.map((word) => word.toString(16).padStart(8, '0')).join(''),
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
function getStorageSchema(schema, messageLayoutFamily, messagePhysicalLayout) {
|
|
169
|
+
let byLayout = messageStorageSchemas.get(schema);
|
|
170
|
+
const key = `${messageLayoutFamily}:${messagePhysicalLayout}`;
|
|
171
|
+
let storageSchema = byLayout?.get(key);
|
|
172
|
+
if (storageSchema === undefined) {
|
|
173
|
+
const fields = {};
|
|
174
|
+
for (const [name, field] of schema._columns) {
|
|
175
|
+
if (name !== 'message')
|
|
176
|
+
fields[name] = field;
|
|
177
|
+
}
|
|
178
|
+
storageSchema = new LogSchema(fields);
|
|
179
|
+
byLayout ??= new Map();
|
|
180
|
+
byLayout.set(key, storageSchema);
|
|
181
|
+
messageStorageSchemas.set(schema, byLayout);
|
|
182
|
+
}
|
|
183
|
+
return storageSchema;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Canonicalize a ttsc-emitted SpanBuffer class into the same schema/layout cache
|
|
187
|
+
* used by the dynamic fallback. The factory is lazy so an already materialized
|
|
188
|
+
* class wins without allocating a duplicate constructor.
|
|
189
|
+
*/
|
|
190
|
+
export function materializeCompiledSpanBufferClass(schema, messageLayoutFamily, messagePhysicalLayout, eagerColumnNames, factory) {
|
|
191
|
+
const eagerColumns = resolveCompiledEagerColumns(schema, eagerColumnNames);
|
|
192
|
+
// Mode-prefixed like arrow-builder's class caches: the materializer mode is fixed for a process,
|
|
193
|
+
// but the parity suite flips it via override and must never see the other mode's class.
|
|
194
|
+
const cacheKey = `${activeMaterializerMode()}:${messageLayoutFamily}:${messagePhysicalLayout}:${eagerColumns.key}`;
|
|
195
|
+
let familyClasses = spanBufferClassCache.get(schema);
|
|
196
|
+
const cached = familyClasses?.get(cacheKey);
|
|
197
|
+
if (isSpanBufferConstructorForSchema(cached, schema) &&
|
|
198
|
+
cached.messageLayoutFamily === messageLayoutFamily &&
|
|
199
|
+
cached.messagePhysicalLayout === messagePhysicalLayout) {
|
|
200
|
+
return cached;
|
|
201
|
+
}
|
|
202
|
+
const compiledClass = factory();
|
|
203
|
+
if (!isGeneratedSpanBufferClass(compiledClass)) {
|
|
204
|
+
throw new TypeError('Compiled SpanBuffer class is missing the required buffer contract');
|
|
205
|
+
}
|
|
206
|
+
const SpanBufferClass = createSpanBufferConstructor(schema, messageLayoutFamily, messagePhysicalLayout, compiledClass, eagerColumns);
|
|
207
|
+
familyClasses ??= new Map();
|
|
208
|
+
familyClasses.set(cacheKey, SpanBufferClass);
|
|
209
|
+
spanBufferClassCache.set(schema, familyClasses);
|
|
210
|
+
return SpanBufferClass;
|
|
211
|
+
}
|
|
212
|
+
function isSpanBufferConstructorValue(value) {
|
|
213
|
+
return typeof value === 'function';
|
|
214
|
+
}
|
|
215
|
+
function spanBufferStatics(self) {
|
|
216
|
+
const ctor = self.constructor;
|
|
217
|
+
if (!isSpanBufferConstructorValue(ctor))
|
|
218
|
+
throw new TypeError('SpanBuffer constructor is not initialized');
|
|
219
|
+
return ctor;
|
|
220
|
+
}
|
|
221
|
+
/** Constructor arguments arrive untyped through the materializer; every real buffer/traceRoot is an object. */
|
|
222
|
+
function isSpanBufferValue(value) {
|
|
223
|
+
return typeof value === 'object' && value !== null;
|
|
224
|
+
}
|
|
225
|
+
function isTraceRootValue(value) {
|
|
226
|
+
return typeof value === 'object' && value !== null;
|
|
227
|
+
}
|
|
228
|
+
function requireParent(parent) {
|
|
229
|
+
if (parent === undefined)
|
|
230
|
+
throw new TypeError('Chained/child SpanBuffer construction requires a parent buffer');
|
|
231
|
+
return parent;
|
|
232
|
+
}
|
|
233
|
+
/** Every runtime SpanBuffer instance satisfies the typed SpanBuffer contract (dynamic column lanes included). */
|
|
234
|
+
function isTypedSpanBuffer(value) {
|
|
235
|
+
return typeof value === 'object' && value !== null;
|
|
236
|
+
}
|
|
237
|
+
/** Mirrors the generated `_sealStats` body (shared with getOrCreateOverflow). */
|
|
238
|
+
function sealStatsFor(self) {
|
|
239
|
+
if (self._statsSealed)
|
|
240
|
+
return;
|
|
241
|
+
const completedRows = self._writeIndex - self._statsReservedRows;
|
|
242
|
+
if (completedRows > 0)
|
|
243
|
+
spanBufferStatics(self).stats.totalWrites += completedRows;
|
|
244
|
+
self._statsSealed = true;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* No-eval counterpart of the extension `constructorPreamble` (and its
|
|
248
|
+
* `constructorParams` signature): identical buffer-type branches (root /
|
|
249
|
+
* child / chained), identical physical system layout math, identical
|
|
250
|
+
* property-assignment order (V8 in-object slots).
|
|
251
|
+
*/
|
|
252
|
+
function createSpanBufferClosureInit(messageLayoutFamily, messagePhysicalLayout) {
|
|
253
|
+
return (self, requestedCapacity, ctorArgs) => {
|
|
254
|
+
// ctorArgs mirror constructorParams: stats, parent, isChained, callsiteMetadata, opMetadata, traceRoot, vocabularyGeneration
|
|
255
|
+
const parent = isSpanBufferValue(ctorArgs[1]) ? ctorArgs[1] : undefined;
|
|
256
|
+
const isChained = Boolean(ctorArgs[2]);
|
|
257
|
+
const callsiteMetadata = ctorArgs[3];
|
|
258
|
+
const opMetadata = ctorArgs[4];
|
|
259
|
+
const traceRootArg = ctorArgs[5];
|
|
260
|
+
if (!isTraceRootValue(traceRootArg))
|
|
261
|
+
throw new TypeError('SpanBuffer construction requires a traceRoot');
|
|
262
|
+
const traceRoot = traceRootArg;
|
|
263
|
+
const vocabularyGeneration = ctorArgs[6];
|
|
264
|
+
// Thread-local span counter (per-process/worker, see threadId.ts docs)
|
|
265
|
+
globalThis.globalSpanCounter = (globalThis.globalSpanCounter ?? 0) + 1;
|
|
266
|
+
const spanId = globalThis.globalSpanCounter;
|
|
267
|
+
const threadId = isChained ? requireParent(parent).thread_id : getThreadId();
|
|
268
|
+
// Calculate exact physical system storage (same math as the preamble variants).
|
|
269
|
+
let systemSize;
|
|
270
|
+
let rowHeaderOffset = 0;
|
|
271
|
+
let messageIdOffset = 0;
|
|
272
|
+
let logHeaderOffset = 0;
|
|
273
|
+
if (messagePhysicalLayout === 'packed') {
|
|
274
|
+
rowHeaderOffset = requestedCapacity * 8;
|
|
275
|
+
systemSize = (requestedCapacity * 12 + 7) & ~7;
|
|
276
|
+
}
|
|
277
|
+
else if (messageLayoutFamily === 'dynamic-only') {
|
|
278
|
+
systemSize = (requestedCapacity * 9 + 7) & ~7;
|
|
279
|
+
}
|
|
280
|
+
else if (messagePhysicalLayout === 'current') {
|
|
281
|
+
messageIdOffset = (requestedCapacity * 9 + 1) & ~1;
|
|
282
|
+
systemSize = (messageIdOffset + requestedCapacity * 2 + 7) & ~7;
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
logHeaderOffset = (requestedCapacity * 9 + 3) & ~3;
|
|
286
|
+
systemSize = (logHeaderOffset + requestedCapacity * 4 + 7) & ~7;
|
|
287
|
+
}
|
|
288
|
+
// CHAINED: shares parent._identity; CHILD: identity without traceId; ROOT: identity with traceId bytes.
|
|
289
|
+
let systemBuffer;
|
|
290
|
+
let identityView;
|
|
291
|
+
if (isChained) {
|
|
292
|
+
systemBuffer = new ArrayBuffer(systemSize);
|
|
293
|
+
identityView = requireParent(parent)._identity;
|
|
294
|
+
}
|
|
295
|
+
else if (parent) {
|
|
296
|
+
const identitySize = 12;
|
|
297
|
+
systemBuffer = new ArrayBuffer(systemSize + identitySize);
|
|
298
|
+
identityView = new Uint8Array(systemBuffer, systemSize, identitySize);
|
|
299
|
+
copyThreadIdTo(identityView, 0);
|
|
300
|
+
identityView[8] = spanId;
|
|
301
|
+
identityView[9] = spanId >>> 8;
|
|
302
|
+
identityView[10] = spanId >>> 16;
|
|
303
|
+
identityView[11] = spanId >>> 24;
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
const traceIdBytes = traceRoot._traceIdBytes;
|
|
307
|
+
const identitySize = 13 + traceIdBytes.length;
|
|
308
|
+
systemBuffer = new ArrayBuffer(systemSize + identitySize);
|
|
309
|
+
identityView = new Uint8Array(systemBuffer, systemSize, identitySize);
|
|
310
|
+
copyThreadIdTo(identityView, 0);
|
|
311
|
+
identityView[8] = spanId;
|
|
312
|
+
identityView[9] = spanId >>> 8;
|
|
313
|
+
identityView[10] = spanId >>> 16;
|
|
314
|
+
identityView[11] = spanId >>> 24;
|
|
315
|
+
identityView[12] = traceIdBytes.length;
|
|
316
|
+
identityView.set(traceIdBytes, 13);
|
|
317
|
+
}
|
|
318
|
+
// Assign properties in the optimal V8 in-object slot order (same as the preamble).
|
|
319
|
+
self._writeIndex = 0;
|
|
320
|
+
self._capacity = requestedCapacity;
|
|
321
|
+
self._overflow = undefined;
|
|
322
|
+
self.timestamp = new BigInt64Array(systemBuffer, 0, requestedCapacity);
|
|
323
|
+
if (messagePhysicalLayout === 'packed') {
|
|
324
|
+
self._rowHeaders = new Uint32Array(systemBuffer, rowHeaderOffset, requestedCapacity);
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
self.entry_type = new Uint8Array(systemBuffer, requestedCapacity * 8, requestedCapacity);
|
|
328
|
+
if (messageLayoutFamily !== 'dynamic-only') {
|
|
329
|
+
if (messagePhysicalLayout === 'current') {
|
|
330
|
+
self._messageIds = new Uint16Array(systemBuffer, messageIdOffset, requestedCapacity);
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
self._logHeaders = new Uint32Array(systemBuffer, logHeaderOffset, requestedCapacity);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
self._vocabularyGeneration = vocabularyGeneration;
|
|
338
|
+
if (messageLayoutFamily === 'static-only') {
|
|
339
|
+
self._spanName = undefined;
|
|
340
|
+
self._terminalMessage = undefined;
|
|
341
|
+
}
|
|
342
|
+
else if (messageLayoutFamily === 'dynamic-only') {
|
|
343
|
+
self._spanName = undefined;
|
|
344
|
+
}
|
|
345
|
+
self._nodeIndex = 4294967295;
|
|
346
|
+
self._topologyGeneration = 0;
|
|
347
|
+
self._parent = isChained ? requireParent(parent)._parent : parent;
|
|
348
|
+
self._traceRoot = traceRoot;
|
|
349
|
+
self._scopeValues = parent ? parent._scopeValues : EMPTY_SCOPE;
|
|
350
|
+
self._threadId = threadId;
|
|
351
|
+
self._identity = identityView;
|
|
352
|
+
self._system = systemBuffer;
|
|
353
|
+
self._callsiteMetadata = callsiteMetadata;
|
|
354
|
+
self._opMetadata = opMetadata;
|
|
355
|
+
self._statsSealed = false;
|
|
356
|
+
self._statsReservedRows = isChained ? 0 : 2;
|
|
357
|
+
if (messageLayoutFamily !== 'static-only') {
|
|
358
|
+
self.message_values = new Array(requestedCapacity);
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* No-eval counterpart of the extension `methods` string: same members, same
|
|
364
|
+
* kinds (getter vs method), installed after the generated per-column members
|
|
365
|
+
* so same-named members override exactly like the compiled class body.
|
|
366
|
+
*/
|
|
367
|
+
function createSpanBufferClosureMethods(messageLayoutFamily) {
|
|
368
|
+
return (prototype) => {
|
|
369
|
+
const defineMethod = (name, value) => {
|
|
370
|
+
Object.defineProperty(prototype, name, { value, writable: true, configurable: true, enumerable: false });
|
|
371
|
+
};
|
|
372
|
+
const defineGetter = (name, get) => {
|
|
373
|
+
Object.defineProperty(prototype, name, { get, configurable: true, enumerable: false });
|
|
374
|
+
};
|
|
375
|
+
defineGetter('span_id', function () {
|
|
376
|
+
const b = this._identity;
|
|
377
|
+
return b ? (b[8] | (b[9] << 8) | (b[10] << 16) | (b[11] << 24)) >>> 0 : 0;
|
|
378
|
+
});
|
|
379
|
+
defineGetter('thread_id', function () {
|
|
380
|
+
return this._threadId;
|
|
381
|
+
});
|
|
382
|
+
defineGetter('trace_id', function () {
|
|
383
|
+
return this._traceRoot.trace_id;
|
|
384
|
+
});
|
|
385
|
+
defineGetter('_spanStartTime', function () {
|
|
386
|
+
return this.timestamp[0];
|
|
387
|
+
});
|
|
388
|
+
defineGetter('_lastLoggedTime', function () {
|
|
389
|
+
const chain = [];
|
|
390
|
+
let current = this;
|
|
391
|
+
while (current) {
|
|
392
|
+
chain.push(current);
|
|
393
|
+
current = current._overflow;
|
|
394
|
+
}
|
|
395
|
+
for (let i = chain.length - 1; i >= 0; i--) {
|
|
396
|
+
const buffer = chain[i];
|
|
397
|
+
for (let row = buffer._writeIndex - 1; row >= 0; row--) {
|
|
398
|
+
const ts = buffer.timestamp[row];
|
|
399
|
+
if (ts !== 0n) {
|
|
400
|
+
return ts;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
return null;
|
|
405
|
+
});
|
|
406
|
+
defineGetter('_hasParent', function () {
|
|
407
|
+
return this._parent !== undefined;
|
|
408
|
+
});
|
|
409
|
+
defineGetter('parent_span_id', function () {
|
|
410
|
+
return this._parent?.span_id ?? 0;
|
|
411
|
+
});
|
|
412
|
+
defineGetter('parent_thread_id', function () {
|
|
413
|
+
return this._parent?.thread_id ?? 0n;
|
|
414
|
+
});
|
|
415
|
+
defineMethod('isParentOf', function (other) {
|
|
416
|
+
return this === other._parent;
|
|
417
|
+
});
|
|
418
|
+
defineMethod('isChildOf', function (other) {
|
|
419
|
+
return this._parent === other;
|
|
420
|
+
});
|
|
421
|
+
defineMethod('copyThreadIdTo', function (dest, offset) {
|
|
422
|
+
const source = this._identity;
|
|
423
|
+
if (source) {
|
|
424
|
+
dest[offset] = source[0];
|
|
425
|
+
dest[offset + 1] = source[1];
|
|
426
|
+
dest[offset + 2] = source[2];
|
|
427
|
+
dest[offset + 3] = source[3];
|
|
428
|
+
dest[offset + 4] = source[4];
|
|
429
|
+
dest[offset + 5] = source[5];
|
|
430
|
+
dest[offset + 6] = source[6];
|
|
431
|
+
dest[offset + 7] = source[7];
|
|
432
|
+
}
|
|
433
|
+
else {
|
|
434
|
+
dest.fill(0, offset, offset + 8);
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
defineMethod('copyParentThreadIdTo', function (dest, offset) {
|
|
438
|
+
if (this._parent)
|
|
439
|
+
this._parent.copyThreadIdTo(dest, offset);
|
|
440
|
+
else
|
|
441
|
+
dest.fill(0, offset, offset + 8);
|
|
442
|
+
});
|
|
443
|
+
defineGetter('_logSchema', function () {
|
|
444
|
+
return spanBufferStatics(this).schema;
|
|
445
|
+
});
|
|
446
|
+
defineGetter('_messageLayoutFamily', function () {
|
|
447
|
+
return spanBufferStatics(this).messageLayoutFamily;
|
|
448
|
+
});
|
|
449
|
+
defineGetter('_messagePhysicalLayout', function () {
|
|
450
|
+
return spanBufferStatics(this).messagePhysicalLayout;
|
|
451
|
+
});
|
|
452
|
+
defineGetter('_columns', function () {
|
|
453
|
+
return spanBufferStatics(this).schema._columns;
|
|
454
|
+
});
|
|
455
|
+
defineGetter('_stats', function () {
|
|
456
|
+
return spanBufferStatics(this).stats;
|
|
457
|
+
});
|
|
458
|
+
defineMethod('_sealStats', function () {
|
|
459
|
+
sealStatsFor(this);
|
|
460
|
+
});
|
|
461
|
+
defineMethod('_sealStatsChain', function () {
|
|
462
|
+
let current = this;
|
|
463
|
+
while (current) {
|
|
464
|
+
sealStatsFor(current);
|
|
465
|
+
current = current._overflow;
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
defineMethod('getOrCreateOverflow', function () {
|
|
469
|
+
if (this._overflow)
|
|
470
|
+
return this._overflow;
|
|
471
|
+
sealStatsFor(this);
|
|
472
|
+
const tracer = this._traceRoot.tracer;
|
|
473
|
+
tracer.onStatsWillResetFor(this);
|
|
474
|
+
checkCapacityTuning(spanBufferStatics(this).stats);
|
|
475
|
+
if (!isTypedSpanBuffer(this))
|
|
476
|
+
throw new TypeError('SpanBuffer instance is not initialized');
|
|
477
|
+
return tracer.bufferStrategy.createOverflowBuffer(this);
|
|
478
|
+
});
|
|
479
|
+
if (messageLayoutFamily === 'static-only') {
|
|
480
|
+
defineMethod('message', function (pos, val) {
|
|
481
|
+
if (pos === 0)
|
|
482
|
+
this._spanName = val;
|
|
483
|
+
else if (pos === 1)
|
|
484
|
+
this._terminalMessage = val;
|
|
485
|
+
else
|
|
486
|
+
throw new RangeError('Static-only buffers only accept raw system messages at rows 0 and 1');
|
|
487
|
+
return this;
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
else {
|
|
491
|
+
defineMethod('message', function (pos, val) {
|
|
492
|
+
const lane = this.message_values;
|
|
493
|
+
if (!Array.isArray(lane))
|
|
494
|
+
throw new TypeError('message_values lane is not allocated');
|
|
495
|
+
lane[pos] = val;
|
|
496
|
+
return this;
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
};
|
|
500
|
+
}
|
|
124
501
|
/**
|
|
125
502
|
* Get or create a SpanBuffer class for the given schema.
|
|
126
503
|
*
|
|
@@ -134,9 +511,13 @@ const spanBufferClassCache = new WeakMap();
|
|
|
134
511
|
* @returns SpanBufferConstructor with static schema and stats properties
|
|
135
512
|
*/
|
|
136
513
|
//#region smoo/lmao!n/spanbuffer-layout.constructor
|
|
137
|
-
export function getSpanBufferClass(schema) {
|
|
138
|
-
const
|
|
139
|
-
|
|
514
|
+
export function getSpanBufferClass(schema, messageLayoutFamily = 'mixed', messagePhysicalLayout = 'current', eagerColumns = EMPTY_EAGER_COLUMNS) {
|
|
515
|
+
const cacheKey = `${activeMaterializerMode()}:${messageLayoutFamily}:${messagePhysicalLayout}:${eagerColumns.key}`;
|
|
516
|
+
let familyClasses = spanBufferClassCache.get(schema);
|
|
517
|
+
const cached = familyClasses?.get(cacheKey);
|
|
518
|
+
if (isSpanBufferConstructorForSchema(cached, schema) &&
|
|
519
|
+
cached.messageLayoutFamily === messageLayoutFamily &&
|
|
520
|
+
cached.messagePhysicalLayout === messagePhysicalLayout) {
|
|
140
521
|
return cached;
|
|
141
522
|
}
|
|
142
523
|
// ==========================================================================
|
|
@@ -159,21 +540,27 @@ export function getSpanBufferClass(schema) {
|
|
|
159
540
|
// 2. _capacity - compared on EVERY write (overflow check)
|
|
160
541
|
// 3. _overflow - checked when overflow occurs
|
|
161
542
|
// 4. timestamp/entry_type - TypedArray refs accessed on EVERY write
|
|
162
|
-
// 5.
|
|
543
|
+
// 5. _nodeIndex/_parent - modified/accessed during span creation
|
|
163
544
|
// 6. _traceRoot - accessed for timestamp anchors on EVERY write
|
|
164
545
|
// 7. _identity/_logBinding - accessed during span operations
|
|
165
546
|
// 8-N. Cold properties - only accessed during Arrow conversion
|
|
166
547
|
// ==========================================================================
|
|
167
548
|
// Define extension for arrow-builder's class generator
|
|
168
549
|
const extension = {
|
|
169
|
-
|
|
550
|
+
preallocatedColumns: eagerColumns.names,
|
|
551
|
+
constructorParams: 'stats, parent, isChained, callsiteMetadata, opMetadata, traceRoot, vocabularyGeneration',
|
|
170
552
|
dependencies: {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
textEncoder,
|
|
553
|
+
copyThreadIdTo,
|
|
554
|
+
getThreadId,
|
|
174
555
|
EMPTY_SCOPE,
|
|
175
556
|
checkCapacityTuning,
|
|
176
557
|
},
|
|
558
|
+
// No-eval counterparts consumed by arrow-builder's closure-composed
|
|
559
|
+
// materializer on runtimes without string codegen (workerd). They MUST
|
|
560
|
+
// mirror constructorPreamble/methods below exactly — see the factories
|
|
561
|
+
// above and spanbuffer-materializer-parity.test.ts.
|
|
562
|
+
closureInit: createSpanBufferClosureInit(messageLayoutFamily, messagePhysicalLayout),
|
|
563
|
+
closureMethods: createSpanBufferClosureMethods(messageLayoutFamily),
|
|
177
564
|
// ==========================================================================
|
|
178
565
|
// GENERATED CONSTRUCTOR PREAMBLE
|
|
179
566
|
// ==========================================================================
|
|
@@ -199,12 +586,11 @@ export function getSpanBufferClass(schema) {
|
|
|
199
586
|
// V8 IN-OBJECT PROPERTY OPTIMIZATION:
|
|
200
587
|
// Property assignment order determines which properties get fast in-object slots.
|
|
201
588
|
// First ~10-12 properties are stored directly on the object (fastest access).
|
|
202
|
-
// Slots
|
|
203
|
-
// Slots
|
|
204
|
-
// Slots
|
|
205
|
-
// Slots
|
|
206
|
-
// Slots
|
|
207
|
-
// Slots 12+: COLD (Arrow conversion only) - _callsiteMetadata, _opMetadata
|
|
589
|
+
// Slots 0-2: HOTTEST (every log entry) - _writeIndex, _capacity, _overflow
|
|
590
|
+
// Slots 3-6: HOT (storage refs) - timestamp, entry_type/header, message identity, vocabulary
|
|
591
|
+
// Slots 7-10: WARM (tree structure) - _nodeIndex, _topologyGeneration, _parent, _traceRoot
|
|
592
|
+
// Slots 11-14: WARM (context/identity) - _scopeValues, _threadId, _identity, _system
|
|
593
|
+
// Slots 15+: COLD (Arrow/stats/raw message) - metadata, stats, message_values
|
|
208
594
|
// ==========================================================================
|
|
209
595
|
constructorPreamble:
|
|
210
596
|
// Thread-local span counter (per-process/worker, see threadId.ts docs)
|
|
@@ -212,84 +598,133 @@ export function getSpanBufferClass(schema) {
|
|
|
212
598
|
globalThis.globalSpanCounter = 0;
|
|
213
599
|
}
|
|
214
600
|
const spanId = ++globalThis.globalSpanCounter;
|
|
601
|
+
const threadId = isChained ? parent.thread_id : getThreadId();
|
|
215
602
|
` +
|
|
216
|
-
// Calculate
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
const systemSize = (
|
|
603
|
+
// Calculate exact physical system storage once for the generated class.
|
|
604
|
+
(messagePhysicalLayout === 'packed'
|
|
605
|
+
? `const rowHeaderOffset = requestedCapacity * 8;
|
|
606
|
+
const systemSize = (requestedCapacity * 12 + 7) & ~7;
|
|
220
607
|
let systemBuffer;
|
|
221
608
|
let identityView;
|
|
222
|
-
`
|
|
609
|
+
`
|
|
610
|
+
: messageLayoutFamily === 'dynamic-only'
|
|
611
|
+
? `const systemSize = (requestedCapacity * 9 + 7) & ~7;
|
|
612
|
+
let systemBuffer;
|
|
613
|
+
let identityView;
|
|
614
|
+
`
|
|
615
|
+
: messagePhysicalLayout === 'current'
|
|
616
|
+
? `const messageIdOffset = (requestedCapacity * 9 + 1) & ~1;
|
|
617
|
+
const systemSize = (messageIdOffset + requestedCapacity * 2 + 7) & ~7;
|
|
618
|
+
let systemBuffer;
|
|
619
|
+
let identityView;
|
|
620
|
+
`
|
|
621
|
+
: `const logHeaderOffset = (requestedCapacity * 9 + 3) & ~3;
|
|
622
|
+
const systemSize = (logHeaderOffset + requestedCapacity * 4 + 7) & ~7;
|
|
623
|
+
let systemBuffer;
|
|
624
|
+
let identityView;
|
|
625
|
+
`) +
|
|
223
626
|
// CHAINED BUFFER: overflow storage for same logical span - shares parent identity
|
|
224
627
|
`if (isChained) {
|
|
225
628
|
systemBuffer = new ArrayBuffer(systemSize);
|
|
226
629
|
identityView = parent._identity;
|
|
227
630
|
}` +
|
|
228
631
|
// CHILD BUFFER: new span in existing trace - gets identity without traceId
|
|
229
|
-
// (traceId accessed via parent chain walk in trace_id getter)
|
|
230
632
|
` else if (parent) {
|
|
231
633
|
const identitySize = 12;
|
|
232
634
|
systemBuffer = new ArrayBuffer(systemSize + identitySize);
|
|
233
635
|
identityView = new Uint8Array(systemBuffer, systemSize, identitySize);
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
636
|
+
copyThreadIdTo(identityView, 0);
|
|
637
|
+
identityView[8] = spanId;
|
|
638
|
+
identityView[9] = spanId >>> 8;
|
|
639
|
+
identityView[10] = spanId >>> 16;
|
|
640
|
+
identityView[11] = spanId >>> 24;
|
|
237
641
|
}` +
|
|
238
|
-
// ROOT BUFFER: new trace -
|
|
642
|
+
// ROOT BUFFER: new trace - copies the trace-owned canonical bytes once into its public identity.
|
|
239
643
|
` else {
|
|
240
|
-
const
|
|
241
|
-
const identitySize = 13 +
|
|
644
|
+
const traceIdBytes = traceRoot._traceIdBytes;
|
|
645
|
+
const identitySize = 13 + traceIdBytes.length;
|
|
242
646
|
systemBuffer = new ArrayBuffer(systemSize + identitySize);
|
|
243
647
|
identityView = new Uint8Array(systemBuffer, systemSize, identitySize);
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
identityView[
|
|
249
|
-
identityView.
|
|
648
|
+
copyThreadIdTo(identityView, 0);
|
|
649
|
+
identityView[8] = spanId;
|
|
650
|
+
identityView[9] = spanId >>> 8;
|
|
651
|
+
identityView[10] = spanId >>> 16;
|
|
652
|
+
identityView[11] = spanId >>> 24;
|
|
653
|
+
identityView[12] = traceIdBytes.length;
|
|
654
|
+
identityView.set(traceIdBytes, 13);
|
|
250
655
|
}
|
|
251
656
|
` +
|
|
252
|
-
// Create
|
|
253
|
-
|
|
657
|
+
// Create exact physical views. Packed classes never create split entry/header views.
|
|
658
|
+
(messagePhysicalLayout === 'packed'
|
|
659
|
+
? `const timestampView = new BigInt64Array(systemBuffer, 0, requestedCapacity);
|
|
660
|
+
const rowHeaderView = new Uint32Array(systemBuffer, rowHeaderOffset, requestedCapacity);
|
|
661
|
+
`
|
|
662
|
+
: `const timestampView = new BigInt64Array(systemBuffer, 0, requestedCapacity);
|
|
254
663
|
const entryTypeView = new Uint8Array(systemBuffer, requestedCapacity * 8, requestedCapacity);
|
|
255
|
-
timestampView.fill(0n);
|
|
256
|
-
entryTypeView.fill(0);
|
|
257
664
|
` +
|
|
258
|
-
|
|
665
|
+
(messageLayoutFamily === 'dynamic-only'
|
|
666
|
+
? ''
|
|
667
|
+
: messagePhysicalLayout === 'current'
|
|
668
|
+
? ` const messageIdView = new Uint16Array(systemBuffer, messageIdOffset, requestedCapacity);
|
|
669
|
+
`
|
|
670
|
+
: ` const logHeaderView = new Uint32Array(systemBuffer, logHeaderOffset, requestedCapacity);
|
|
671
|
+
`)) +
|
|
672
|
+
// Assign properties in optimal order for V8 in-object slots.
|
|
259
673
|
`this._writeIndex = 0;
|
|
260
674
|
this._capacity = requestedCapacity;
|
|
261
675
|
this._overflow = undefined;
|
|
262
676
|
this.timestamp = timestampView;
|
|
263
|
-
|
|
264
|
-
|
|
677
|
+
` +
|
|
678
|
+
(messagePhysicalLayout === 'packed'
|
|
679
|
+
? ` this._rowHeaders = rowHeaderView;
|
|
680
|
+
`
|
|
681
|
+
: ` this.entry_type = entryTypeView;
|
|
682
|
+
` +
|
|
683
|
+
(messageLayoutFamily === 'dynamic-only'
|
|
684
|
+
? ''
|
|
685
|
+
: messagePhysicalLayout === 'current'
|
|
686
|
+
? ` this._messageIds = messageIdView;
|
|
687
|
+
`
|
|
688
|
+
: ` this._logHeaders = logHeaderView;
|
|
689
|
+
`)) +
|
|
690
|
+
` this._vocabularyGeneration = vocabularyGeneration;
|
|
691
|
+
` +
|
|
692
|
+
(messageLayoutFamily === 'static-only'
|
|
693
|
+
? ` this._spanName = undefined;
|
|
694
|
+
this._terminalMessage = undefined;
|
|
695
|
+
`
|
|
696
|
+
: messageLayoutFamily === 'dynamic-only'
|
|
697
|
+
? ` this._spanName = undefined;
|
|
698
|
+
`
|
|
699
|
+
: '') +
|
|
700
|
+
` this._nodeIndex = 4294967295;
|
|
701
|
+
this._topologyGeneration = 0;
|
|
265
702
|
this._parent = isChained ? parent._parent : parent;
|
|
266
703
|
this._traceRoot = traceRoot;
|
|
267
704
|
this._scopeValues = parent ? parent._scopeValues : EMPTY_SCOPE;
|
|
705
|
+
this._threadId = threadId;
|
|
268
706
|
this._identity = identityView;
|
|
269
707
|
this._system = systemBuffer;
|
|
270
708
|
this._callsiteMetadata = callsiteMetadata;
|
|
271
709
|
this._opMetadata = opMetadata;
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
710
|
+
this._statsSealed = false;
|
|
711
|
+
this._statsReservedRows = isChained ? 0 : 2;
|
|
712
|
+
` +
|
|
713
|
+
(messageLayoutFamily === 'static-only'
|
|
714
|
+
? ''
|
|
715
|
+
: ` this.message_values = new Array(requestedCapacity);
|
|
716
|
+
`) +
|
|
717
|
+
' ',
|
|
718
|
+
// Generated identity methods use canonical primitives/direct offsets without temporary views.
|
|
280
719
|
methods: `get span_id() {
|
|
281
|
-
|
|
720
|
+
const b = this._identity;
|
|
721
|
+
return b ? (b[8] | (b[9] << 8) | (b[10] << 16) | (b[11] << 24)) >>> 0 : 0;
|
|
282
722
|
}
|
|
283
723
|
get thread_id() {
|
|
284
|
-
return this.
|
|
724
|
+
return this._threadId;
|
|
285
725
|
}
|
|
286
726
|
get trace_id() {
|
|
287
|
-
|
|
288
|
-
while (current._parent) { current = current._parent; }
|
|
289
|
-
if (!current._identity) { return undefined; }
|
|
290
|
-
const len = current._identity[12];
|
|
291
|
-
const traceIdBytes = current._identity.subarray(13, 13 + len);
|
|
292
|
-
return textDecoder.decode(traceIdBytes);
|
|
727
|
+
return this._traceRoot.trace_id;
|
|
293
728
|
}
|
|
294
729
|
get _spanStartTime() {
|
|
295
730
|
return this.timestamp[0];
|
|
@@ -318,39 +753,78 @@ export function getSpanBufferClass(schema) {
|
|
|
318
753
|
isParentOf(other) { return this === other._parent; }
|
|
319
754
|
isChildOf(other) { return this._parent === other; }
|
|
320
755
|
copyThreadIdTo(dest, offset) {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
756
|
+
const source = this._identity;
|
|
757
|
+
if (source) {
|
|
758
|
+
dest[offset] = source[0];
|
|
759
|
+
dest[offset + 1] = source[1];
|
|
760
|
+
dest[offset + 2] = source[2];
|
|
761
|
+
dest[offset + 3] = source[3];
|
|
762
|
+
dest[offset + 4] = source[4];
|
|
763
|
+
dest[offset + 5] = source[5];
|
|
764
|
+
dest[offset + 6] = source[6];
|
|
765
|
+
dest[offset + 7] = source[7];
|
|
325
766
|
} else {
|
|
326
|
-
|
|
767
|
+
dest.fill(0, offset, offset + 8);
|
|
327
768
|
}
|
|
328
769
|
}
|
|
329
770
|
copyParentThreadIdTo(dest, offset) {
|
|
330
|
-
this._parent
|
|
771
|
+
if (this._parent) this._parent.copyThreadIdTo(dest, offset);
|
|
772
|
+
else dest.fill(0, offset, offset + 8);
|
|
331
773
|
}
|
|
332
774
|
get _logSchema() { return this.constructor.schema; }
|
|
775
|
+
get _messageLayoutFamily() { return this.constructor.messageLayoutFamily; }
|
|
776
|
+
get _messagePhysicalLayout() { return this.constructor.messagePhysicalLayout; }
|
|
333
777
|
get _columns() { return this.constructor.schema._columns; }
|
|
334
778
|
get _stats() { return this.constructor.stats; }
|
|
779
|
+
_sealStats() {
|
|
780
|
+
if (this._statsSealed) return;
|
|
781
|
+
const completedRows = this._writeIndex - this._statsReservedRows;
|
|
782
|
+
if (completedRows > 0) this.constructor.stats.totalWrites += completedRows;
|
|
783
|
+
this._statsSealed = true;
|
|
784
|
+
}
|
|
785
|
+
_sealStatsChain() {
|
|
786
|
+
let current = this;
|
|
787
|
+
while (current) {
|
|
788
|
+
current._sealStats();
|
|
789
|
+
current = current._overflow;
|
|
790
|
+
}
|
|
791
|
+
}
|
|
335
792
|
getOrCreateOverflow() {
|
|
336
793
|
if (this._overflow) return this._overflow;
|
|
794
|
+
this._sealStats();
|
|
337
795
|
const tracer = this._traceRoot.tracer;
|
|
338
796
|
tracer.onStatsWillResetFor(this);
|
|
339
797
|
checkCapacityTuning(this.constructor.stats);
|
|
340
798
|
return tracer.bufferStrategy.createOverflowBuffer(this);
|
|
341
799
|
}
|
|
800
|
+
${messageLayoutFamily === 'static-only'
|
|
801
|
+
? `message(pos, val) {
|
|
802
|
+
if (pos === 0) this._spanName = val;
|
|
803
|
+
else if (pos === 1) this._terminalMessage = val;
|
|
804
|
+
else throw new RangeError('Static-only buffers only accept raw system messages at rows 0 and 1');
|
|
805
|
+
return this;
|
|
806
|
+
}`
|
|
807
|
+
: `message(pos, val) {
|
|
808
|
+
this.message_values[pos] = val;
|
|
809
|
+
return this;
|
|
810
|
+
}`}
|
|
342
811
|
`,
|
|
343
812
|
};
|
|
813
|
+
// Storage schema identity partitions source schema/family/physical classes; the extension cache key
|
|
814
|
+
// partitions eager-column selections without adding another dedicated cache object.
|
|
815
|
+
const storageSchema = getStorageSchema(schema, messageLayoutFamily, messagePhysicalLayout);
|
|
344
816
|
// Generate class with arrow-builder
|
|
345
|
-
const generatedClass = getColumnBufferClass(
|
|
817
|
+
const generatedClass = getColumnBufferClass(storageSchema, extension, storageSchema);
|
|
346
818
|
if (!isGeneratedSpanBufferClass(generatedClass)) {
|
|
347
819
|
throw new TypeError('Generated column buffer is missing SpanBuffer methods');
|
|
348
820
|
}
|
|
349
|
-
//
|
|
350
|
-
//
|
|
351
|
-
const SpanBufferClass = createSpanBufferConstructor(schema, generatedClass);
|
|
821
|
+
// Initialize immutable static discriminators before publishing the constructor in the LMAO cache.
|
|
822
|
+
// The mutable stats object remains shared by every instance of this exact class dimension.
|
|
823
|
+
const SpanBufferClass = createSpanBufferConstructor(schema, messageLayoutFamily, messagePhysicalLayout, generatedClass, eagerColumns);
|
|
352
824
|
// Cache for future use
|
|
353
|
-
|
|
825
|
+
familyClasses ??= new Map();
|
|
826
|
+
familyClasses.set(cacheKey, SpanBufferClass);
|
|
827
|
+
spanBufferClassCache.set(schema, familyClasses);
|
|
354
828
|
return SpanBufferClass;
|
|
355
829
|
}
|
|
356
830
|
//#endregion smoo/lmao!n/spanbuffer-layout.constructor
|
|
@@ -369,22 +843,35 @@ export function getSpanBufferClass(schema) {
|
|
|
369
843
|
*
|
|
370
844
|
* @returns SpanBuffer with typed setters for schema fields
|
|
371
845
|
*/
|
|
372
|
-
const
|
|
846
|
+
export const MIN_ADAPTIVE_BUFFER_CAPACITY = 8;
|
|
847
|
+
export function resolveSpanBufferCapacity(explicitCapacity, adaptiveCapacity) {
|
|
848
|
+
if (explicitCapacity === undefined)
|
|
849
|
+
return Math.max(MIN_ADAPTIVE_BUFFER_CAPACITY, adaptiveCapacity);
|
|
850
|
+
if (!Number.isSafeInteger(explicitCapacity) || explicitCapacity < 2) {
|
|
851
|
+
throw new RangeError('Explicit span buffer capacity must be a safe integer of at least 2');
|
|
852
|
+
}
|
|
853
|
+
return explicitCapacity;
|
|
854
|
+
}
|
|
373
855
|
//#region smoo/lmao!n/spanbuffer-layout.create-root
|
|
374
|
-
export function createSpanBuffer(schema, traceRoot, opMetadata, capacity) {
|
|
375
|
-
const
|
|
856
|
+
export function createSpanBuffer(schema, traceRoot, opMetadata, capacity, plannedClass) {
|
|
857
|
+
const metadataPlan = opMetadata._physicalLayoutPlan;
|
|
858
|
+
const metadataSpanBufferClass = metadataPlan?.SpanBufferClass;
|
|
859
|
+
if (metadataSpanBufferClass !== undefined && !isSpanBufferConstructorForSchema(metadataSpanBufferClass, schema)) {
|
|
860
|
+
throw new TypeError('Planned SpanBuffer class does not match schema');
|
|
861
|
+
}
|
|
862
|
+
const plannedSpanBufferClass = plannedClass ?? metadataSpanBufferClass;
|
|
863
|
+
const SpanBufferClass = plannedSpanBufferClass ?? getSpanBufferClass(schema);
|
|
376
864
|
const stats = SpanBufferClass.stats;
|
|
377
|
-
//
|
|
378
|
-
const actualCapacity =
|
|
865
|
+
// Compiler-planned capacities are validated when the runtime hint is decoded. Keep direct external calls strict.
|
|
866
|
+
const actualCapacity = plannedSpanBufferClass === undefined
|
|
867
|
+
? resolveSpanBufferCapacity(capacity, stats.capacity)
|
|
868
|
+
: (capacity ?? Math.max(MIN_ADAPTIVE_BUFFER_CAPACITY, stats.capacity));
|
|
379
869
|
// Track non-chained buffer creation for capacity tuning
|
|
380
870
|
stats.spansCreated++;
|
|
381
|
-
// Create root buffer (no parent)
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
opMetadata, // callsiteMetadata for row 0
|
|
386
|
-
opMetadata, // opMetadata for rows 1+ (same as callsite for root)
|
|
387
|
-
traceRoot);
|
|
871
|
+
// Create root buffer (no parent), then register its stable logical node.
|
|
872
|
+
const buffer = new SpanBufferClass(actualCapacity, stats, undefined, false, opMetadata, opMetadata, traceRoot, metadataPlan?.vocabularyGeneration ?? getVocabularyGeneration());
|
|
873
|
+
traceRoot._topology.registerRoot(buffer);
|
|
874
|
+
return buffer;
|
|
388
875
|
}
|
|
389
876
|
//#endregion smoo/lmao!n/spanbuffer-layout.create-root
|
|
390
877
|
/**
|
|
@@ -407,9 +894,11 @@ export function createOverflowBuffer(buffer) {
|
|
|
407
894
|
// Pass buffer as parent - used for identity sharing; _parent set to buffer._parent in constructor
|
|
408
895
|
const nextBuffer = new SpanBufferClass(capacity, stats, buffer, // Used for identity sharing, _parent set to buffer._parent in constructor
|
|
409
896
|
true, // isChained
|
|
410
|
-
buffer._callsiteMetadata, buffer._opMetadata, buffer._traceRoot
|
|
897
|
+
buffer._callsiteMetadata, buffer._opMetadata, buffer._traceRoot, // traceRoot from parent
|
|
898
|
+
buffer._vocabularyGeneration);
|
|
411
899
|
// Link current buffer to next
|
|
412
900
|
buffer._overflow = nextBuffer;
|
|
901
|
+
buffer._traceRoot._topology.adoptOverflow(buffer, nextBuffer);
|
|
413
902
|
return nextBuffer;
|
|
414
903
|
}
|
|
415
904
|
//#endregion smoo/lmao!n/spanbuffer-layout.create-overflow
|
|
@@ -432,7 +921,8 @@ export function createOverflowBuffer(buffer) {
|
|
|
432
921
|
//#region smoo/lmao!n/spanbuffer-layout.create-child
|
|
433
922
|
export function createChildSpanBuffer(parentBuffer, SpanBufferClass, callsiteMetadata, opMetadata, capacity) {
|
|
434
923
|
const stats = SpanBufferClass.stats;
|
|
435
|
-
|
|
924
|
+
// Child capacities arrive through a validated callsite plan; preserve exact values including 2..7.
|
|
925
|
+
const actualCapacity = capacity ?? Math.max(MIN_ADAPTIVE_BUFFER_CAPACITY, stats.capacity);
|
|
436
926
|
// Track non-chained buffer creation for capacity tuning
|
|
437
927
|
stats.spansCreated++;
|
|
438
928
|
// Create child buffer with parent reference
|
|
@@ -440,7 +930,9 @@ export function createChildSpanBuffer(parentBuffer, SpanBufferClass, callsiteMet
|
|
|
440
930
|
false, // not chained
|
|
441
931
|
callsiteMetadata, // callsiteMetadata - CALLER's op metadata (for row 0)
|
|
442
932
|
opMetadata, // opMetadata - EXECUTING op metadata (for rows 1+)
|
|
443
|
-
parentBuffer._traceRoot
|
|
933
|
+
parentBuffer._traceRoot, // traceRoot from parent
|
|
934
|
+
opMetadata._physicalLayoutPlan?.vocabularyGeneration ?? getVocabularyGeneration());
|
|
935
|
+
parentBuffer._traceRoot._topology.registerChild(parentBuffer, childBuffer);
|
|
444
936
|
return childBuffer;
|
|
445
937
|
}
|
|
446
938
|
//#endregion smoo/lmao!n/spanbuffer-layout.create-child
|