@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
|
+
//#region smoo/lmao!n/codegen-spanlogger.closure
|
|
2
|
+
/**
|
|
3
|
+
* Closure-composed (no-eval) materializer for state-bound SpanLogger classes.
|
|
4
|
+
*
|
|
5
|
+
* Production workerd forbids code generation from strings (EvalError), so the
|
|
6
|
+
* compiled renderer in spanLoggerGenerator.ts cannot run there. This module
|
|
7
|
+
* assembles the SAME class shape from per-field closures instead of source
|
|
8
|
+
* text, mirroring arrow-builder's closureMaterializers.ts:
|
|
9
|
+
* - one shared prototype per schema/config plan,
|
|
10
|
+
* - methods installed with { value, writable: true, configurable: true, enumerable: false },
|
|
11
|
+
* - accessors installed with { get, configurable: true, enumerable: false },
|
|
12
|
+
* - constructors assign instance properties in the same order (V8 hidden classes).
|
|
13
|
+
*
|
|
14
|
+
* Every closure body mirrors the compiled class member it replaces, including
|
|
15
|
+
* evaluation order (append -> message write -> fields), guard conditions, and
|
|
16
|
+
* thrown error messages that callers observe.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import type { SchemaType } from '@smoothbricks/arrow-builder';
|
|
20
|
+
import type { SchemaEnumLookupDescriptor } from '../enumMetadata.js';
|
|
21
|
+
import type { MessageLayoutFamily, MessagePhysicalLayout } from '../runtimeHint.js';
|
|
22
|
+
import {
|
|
23
|
+
ENTRY_TYPE_DEBUG,
|
|
24
|
+
ENTRY_TYPE_ERROR,
|
|
25
|
+
ENTRY_TYPE_FF_ACCESS,
|
|
26
|
+
ENTRY_TYPE_FF_USAGE,
|
|
27
|
+
ENTRY_TYPE_INFO,
|
|
28
|
+
ENTRY_TYPE_TRACE,
|
|
29
|
+
ENTRY_TYPE_WARN,
|
|
30
|
+
} from '../schema/systemSchema.js';
|
|
31
|
+
import type { VocabularyGeneration } from '../vocabularyRegistry.js';
|
|
32
|
+
|
|
33
|
+
// ============================================================================
|
|
34
|
+
// Plan (pure data) + injected singleton dependencies
|
|
35
|
+
// ============================================================================
|
|
36
|
+
|
|
37
|
+
/** Structural type of SPAN_LOGGER_HELPERS (kept local to avoid an import cycle). */
|
|
38
|
+
export interface SpanLoggerRuntimeHelpers {
|
|
39
|
+
normalizeOperationalTemplate: (template: string) => string;
|
|
40
|
+
setNullBit: (bitmap: Uint8Array, idx: number) => void;
|
|
41
|
+
decodeVocabularyMessage: (generation: VocabularyGeneration, denseIndex: number) => string;
|
|
42
|
+
fillNullBitmapRange: (bitmap: Uint8Array, startIdx: number, endIdx: number) => void;
|
|
43
|
+
fillBooleanBitmapRange: (bitmap: Uint8Array, startIdx: number, endIdx: number, value: boolean) => void;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* How a schema column's storage is allocated and guarded (mirrors
|
|
48
|
+
* arrow-builder's ColumnAccessMode for the state-bound writer surface):
|
|
49
|
+
* - eager: allocated in the buffer constructor, no null bitmap
|
|
50
|
+
* - preallocated: allocated in the buffer constructor WITH a null bitmap
|
|
51
|
+
* - lazy: allocated on first public-getter access
|
|
52
|
+
*/
|
|
53
|
+
export type SpanLoggerColumnMode = 'eager' | 'preallocated' | 'lazy';
|
|
54
|
+
|
|
55
|
+
/** One schema column of the SpanLogger plan. */
|
|
56
|
+
export interface SpanLoggerColumnPlan {
|
|
57
|
+
readonly name: string;
|
|
58
|
+
readonly schemaType: SchemaType | undefined;
|
|
59
|
+
readonly mode: SpanLoggerColumnMode;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Pure-data description of one generated SpanLogger class, shared by the
|
|
64
|
+
* compiled renderer and this closure materializer. `helpers`/`enumLookup` are
|
|
65
|
+
* the same stable singletons the compiled path injects via `new Function`
|
|
66
|
+
* parameters (extension.dependencies).
|
|
67
|
+
*/
|
|
68
|
+
export interface SpanLoggerPlan {
|
|
69
|
+
readonly columns: readonly SpanLoggerColumnPlan[];
|
|
70
|
+
readonly messageLayoutFamily: MessageLayoutFamily;
|
|
71
|
+
readonly messagePhysicalLayout: MessagePhysicalLayout;
|
|
72
|
+
readonly helpers: SpanLoggerRuntimeHelpers;
|
|
73
|
+
readonly enumLookup: SchemaEnumLookupDescriptor;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ============================================================================
|
|
77
|
+
// Structural views (generated members are schema-dynamic, typed unknown)
|
|
78
|
+
// ============================================================================
|
|
79
|
+
|
|
80
|
+
/** Span buffer view with schema-dynamic lanes visible for keyed access. */
|
|
81
|
+
interface SpanBufferView {
|
|
82
|
+
[key: string]: unknown;
|
|
83
|
+
_writeIndex: number;
|
|
84
|
+
_capacity: number;
|
|
85
|
+
_scopeValues?: Readonly<Record<string, unknown>>;
|
|
86
|
+
_vocabularyGeneration: VocabularyGeneration;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** The SpanContext-owned writer state every generated method dereferences. */
|
|
90
|
+
interface WriterStateView {
|
|
91
|
+
_buffer: SpanBufferView;
|
|
92
|
+
readonly _physicalLayoutPlan: { encodeLocalMessage(vocabularyIndex: number): number };
|
|
93
|
+
_appendWriterEntry(entryType: number): number;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Structural view of a closure-composed logger instance used by closures. */
|
|
97
|
+
interface LoggerInstance {
|
|
98
|
+
[key: string]: unknown;
|
|
99
|
+
_state: WriterStateView;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Anything a column write can index-assign into (TypedArray or JS Array). */
|
|
103
|
+
interface IndexWritable {
|
|
104
|
+
[pos: number]: unknown;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function isIndexWritable(value: unknown): value is IndexWritable {
|
|
108
|
+
return typeof value === 'object' && value !== null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function laneOf(value: unknown): IndexWritable {
|
|
112
|
+
if (isIndexWritable(value)) return value;
|
|
113
|
+
throw new TypeError('Expected an indexable column lane');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function bitmapOf(value: unknown): Uint8Array {
|
|
117
|
+
if (value instanceof Uint8Array) return value;
|
|
118
|
+
throw new TypeError('Expected a Uint8Array bitmap lane');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** Lane that supports range fill (TypedArray or JS Array). */
|
|
122
|
+
interface RangeFillable {
|
|
123
|
+
fill(value: unknown, start: number, end: number): unknown;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function isRangeFillable(value: unknown): value is RangeFillable {
|
|
127
|
+
return typeof value === 'object' && value !== null && typeof Reflect.get(value, 'fill') === 'function';
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function fillableOf(value: unknown): RangeFillable {
|
|
131
|
+
if (isRangeFillable(value)) return value;
|
|
132
|
+
throw new TypeError('Expected a fillable column lane');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Dynamic `this.with(...)` dispatch (the compiled methods call through `this`). */
|
|
136
|
+
function callFluentWith(self: LoggerInstance, attributes: unknown): void {
|
|
137
|
+
const withFn = self.with;
|
|
138
|
+
if (typeof withFn !== 'function') throw new TypeError('SpanLogger.with is not callable');
|
|
139
|
+
withFn.call(self, attributes);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const METHOD_DESCRIPTOR = { writable: true, configurable: true, enumerable: false } as const;
|
|
143
|
+
const ACCESSOR_DESCRIPTOR = { configurable: true, enumerable: false } as const;
|
|
144
|
+
|
|
145
|
+
type FluentMethod = (this: LoggerInstance, value: unknown) => LoggerInstance;
|
|
146
|
+
|
|
147
|
+
// ============================================================================
|
|
148
|
+
// Schema column fluent setters (state-bound mirror of the base ColumnWriter
|
|
149
|
+
// setters after the `this._buffer` -> `this._state._buffer` and
|
|
150
|
+
// `this._writeIndex` -> `(this._state._buffer._writeIndex - 1)` rewrites)
|
|
151
|
+
// ============================================================================
|
|
152
|
+
|
|
153
|
+
function makeStateBoundSetter(column: SpanLoggerColumnPlan): FluentMethod {
|
|
154
|
+
const { name, schemaType, mode } = column;
|
|
155
|
+
// Preallocated setters write through the raw backing properties; eager and
|
|
156
|
+
// lazy setters go through the buffer's public getters (which allocate lazy
|
|
157
|
+
// columns on first access).
|
|
158
|
+
const nullsKey = mode === 'preallocated' ? `_${name}_nulls` : `${name}_nulls`;
|
|
159
|
+
const valuesKey = mode === 'preallocated' ? `_${name}_values` : `${name}_values`;
|
|
160
|
+
const hasNulls = mode !== 'eager';
|
|
161
|
+
const lookupKey = `_${name}_enumLookup`;
|
|
162
|
+
const enumValuesKey = `${name}_enumValues`;
|
|
163
|
+
|
|
164
|
+
if (schemaType === 'boolean') {
|
|
165
|
+
if (hasNulls) {
|
|
166
|
+
return function (value) {
|
|
167
|
+
const buf = this._state._buffer;
|
|
168
|
+
const idx = buf._writeIndex - 1;
|
|
169
|
+
const byteIdx = idx >>> 3;
|
|
170
|
+
const bitMask = 1 << (idx & 7);
|
|
171
|
+
bitmapOf(buf[nullsKey])[byteIdx] |= bitMask;
|
|
172
|
+
const values = bitmapOf(buf[valuesKey]);
|
|
173
|
+
if (value) values[byteIdx] |= bitMask;
|
|
174
|
+
else values[byteIdx] &= ~bitMask;
|
|
175
|
+
return this;
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
return function (value) {
|
|
179
|
+
const buf = this._state._buffer;
|
|
180
|
+
const idx = buf._writeIndex - 1;
|
|
181
|
+
const byteIdx = idx >>> 3;
|
|
182
|
+
const bitMask = 1 << (idx & 7);
|
|
183
|
+
const values = bitmapOf(buf[valuesKey]);
|
|
184
|
+
if (value) values[byteIdx] |= bitMask;
|
|
185
|
+
else values[byteIdx] &= ~bitMask;
|
|
186
|
+
return this;
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (schemaType === 'enum') {
|
|
191
|
+
// Base enum setter. Reachable only for enum fields absent from
|
|
192
|
+
// enumLookup.ordered (the fluent enum overrides shadow it otherwise) —
|
|
193
|
+
// the compiled class throws there too because its constructor-built
|
|
194
|
+
// `_<name>_enumLookup` Maps were dropped with the state-bound rewrite.
|
|
195
|
+
const makeEnumWrite = (writeNulls: boolean): FluentMethod =>
|
|
196
|
+
function (value) {
|
|
197
|
+
const buf = this._state._buffer;
|
|
198
|
+
const idx = buf._writeIndex - 1;
|
|
199
|
+
const lookup = this[lookupKey];
|
|
200
|
+
if (!(lookup instanceof Map)) {
|
|
201
|
+
throw new TypeError(`Enum lookup ${lookupKey} is not initialized (buffer has no enumValues).`);
|
|
202
|
+
}
|
|
203
|
+
const enumIndex: unknown = lookup.get(value);
|
|
204
|
+
if (enumIndex === undefined) {
|
|
205
|
+
const enumValues = buf[enumValuesKey];
|
|
206
|
+
throw new Error(
|
|
207
|
+
`Invalid enum value "${value}" for field "${name}". Valid values: ${Array.isArray(enumValues) ? enumValues.join(', ') : ''}`,
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
if (writeNulls) bitmapOf(buf[nullsKey])[idx >>> 3] |= 1 << (idx & 7);
|
|
211
|
+
laneOf(buf[valuesKey])[idx] = enumIndex;
|
|
212
|
+
return this;
|
|
213
|
+
};
|
|
214
|
+
return makeEnumWrite(hasNulls);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (schemaType === 'binary') {
|
|
218
|
+
// Shallow-freeze binary payload objects (mirrors the compiled binary setter).
|
|
219
|
+
const freezeBinaryValue = (value: unknown): void => {
|
|
220
|
+
if (typeof value === 'object' && value !== null && !(value instanceof Uint8Array)) Object.freeze(value);
|
|
221
|
+
};
|
|
222
|
+
if (hasNulls) {
|
|
223
|
+
return function (value) {
|
|
224
|
+
const buf = this._state._buffer;
|
|
225
|
+
const idx = buf._writeIndex - 1;
|
|
226
|
+
freezeBinaryValue(value);
|
|
227
|
+
bitmapOf(buf[nullsKey])[idx >>> 3] |= 1 << (idx & 7);
|
|
228
|
+
laneOf(buf[valuesKey])[idx] = value;
|
|
229
|
+
return this;
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
return function (value) {
|
|
233
|
+
const buf = this._state._buffer;
|
|
234
|
+
const idx = buf._writeIndex - 1;
|
|
235
|
+
freezeBinaryValue(value);
|
|
236
|
+
laneOf(buf[valuesKey])[idx] = value;
|
|
237
|
+
return this;
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (hasNulls) {
|
|
242
|
+
return function (value) {
|
|
243
|
+
const buf = this._state._buffer;
|
|
244
|
+
const idx = buf._writeIndex - 1;
|
|
245
|
+
bitmapOf(buf[nullsKey])[idx >>> 3] |= 1 << (idx & 7);
|
|
246
|
+
laneOf(buf[valuesKey])[idx] = value;
|
|
247
|
+
return this;
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
return function (value) {
|
|
251
|
+
const buf = this._state._buffer;
|
|
252
|
+
const idx = buf._writeIndex - 1;
|
|
253
|
+
laneOf(buf[valuesKey])[idx] = value;
|
|
254
|
+
return this;
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// ============================================================================
|
|
259
|
+
// SpanLogger materializer
|
|
260
|
+
// ============================================================================
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Materialize a state-bound SpanLogger class from a plan without string
|
|
264
|
+
* codegen. Same observable behavior as the compiled renderer. Returned as
|
|
265
|
+
* `unknown` to flow through the same constructor type guard as the compiled
|
|
266
|
+
* factory (isSpanLoggerConstructor).
|
|
267
|
+
*/
|
|
268
|
+
export function materializeSpanLoggerClass(plan: SpanLoggerPlan): unknown {
|
|
269
|
+
const { helpers, enumLookup } = plan;
|
|
270
|
+
const family = plan.messageLayoutFamily;
|
|
271
|
+
const physical = plan.messagePhysicalLayout;
|
|
272
|
+
|
|
273
|
+
class GeneratedSpanLogger {
|
|
274
|
+
[key: string]: unknown;
|
|
275
|
+
|
|
276
|
+
declare _state: WriterStateView;
|
|
277
|
+
|
|
278
|
+
constructor(state: WriterStateView) {
|
|
279
|
+
this._state = state;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const proto = GeneratedSpanLogger.prototype;
|
|
284
|
+
const defineMethod = (name: string, value: unknown): void => {
|
|
285
|
+
Object.defineProperty(proto, name, { ...METHOD_DESCRIPTOR, value });
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
// --------------------------------------------------------------------------
|
|
289
|
+
// Message writes per layout family / physical layout
|
|
290
|
+
// --------------------------------------------------------------------------
|
|
291
|
+
|
|
292
|
+
/** Operational entry (info/warn/error): normalized message + optional fields. */
|
|
293
|
+
const makeOperationalLogMethod = (entryType: number) => {
|
|
294
|
+
if (family === 'static-only') {
|
|
295
|
+
return function (this: LoggerInstance): LoggerInstance {
|
|
296
|
+
this._state._appendWriterEntry(entryType);
|
|
297
|
+
throw new TypeError('Dynamic log write reached a static-only callsite plan');
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
return function (this: LoggerInstance, message: string, fields?: Record<string, unknown>): LoggerInstance {
|
|
301
|
+
const state = this._state;
|
|
302
|
+
const idx = state._appendWriterEntry(entryType);
|
|
303
|
+
laneOf(state._buffer.message_values)[idx] = helpers.normalizeOperationalTemplate(message);
|
|
304
|
+
if (fields !== undefined) {
|
|
305
|
+
callFluentWith(this, fields);
|
|
306
|
+
}
|
|
307
|
+
return this;
|
|
308
|
+
};
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
/** Plain entry (debug/trace): raw message, no fields argument. */
|
|
312
|
+
const makePlainLogMethod = (entryType: number) => {
|
|
313
|
+
if (family === 'static-only') {
|
|
314
|
+
return function (this: LoggerInstance): LoggerInstance {
|
|
315
|
+
this._state._appendWriterEntry(entryType);
|
|
316
|
+
throw new TypeError('Dynamic log write reached a static-only callsite plan');
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
return function (this: LoggerInstance, message: string): LoggerInstance {
|
|
320
|
+
const state = this._state;
|
|
321
|
+
const idx = state._appendWriterEntry(entryType);
|
|
322
|
+
laneOf(state._buffer.message_values)[idx] = message;
|
|
323
|
+
return this;
|
|
324
|
+
};
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
/** Static template entry (_infoTemplate & co.) per physical layout. */
|
|
328
|
+
const makeTemplateLogMethod = (entryType: number) => {
|
|
329
|
+
if (family === 'dynamic-only') {
|
|
330
|
+
return function (this: LoggerInstance): LoggerInstance {
|
|
331
|
+
this._state._appendWriterEntry(entryType);
|
|
332
|
+
throw new TypeError('Static log write reached a dynamic-only callsite plan');
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
switch (physical) {
|
|
336
|
+
case 'current':
|
|
337
|
+
return function (this: LoggerInstance, vocabularyIndex: number): LoggerInstance {
|
|
338
|
+
const state = this._state;
|
|
339
|
+
const idx = state._appendWriterEntry(entryType);
|
|
340
|
+
const localMessageId = state._physicalLayoutPlan.encodeLocalMessage(vocabularyIndex);
|
|
341
|
+
if (localMessageId === 0) {
|
|
342
|
+
laneOf(state._buffer.message_values)[idx] = helpers.decodeVocabularyMessage(
|
|
343
|
+
state._buffer._vocabularyGeneration,
|
|
344
|
+
vocabularyIndex,
|
|
345
|
+
);
|
|
346
|
+
} else {
|
|
347
|
+
laneOf(state._buffer._messageIds)[idx] = localMessageId;
|
|
348
|
+
}
|
|
349
|
+
return this;
|
|
350
|
+
};
|
|
351
|
+
case 'specialized':
|
|
352
|
+
return function (this: LoggerInstance, vocabularyIndex: number): LoggerInstance {
|
|
353
|
+
const state = this._state;
|
|
354
|
+
const idx = state._appendWriterEntry(entryType);
|
|
355
|
+
laneOf(state._buffer._logHeaders)[idx] = vocabularyIndex + 1;
|
|
356
|
+
return this;
|
|
357
|
+
};
|
|
358
|
+
case 'packed':
|
|
359
|
+
return function (this: LoggerInstance, vocabularyIndex: number): LoggerInstance {
|
|
360
|
+
const state = this._state;
|
|
361
|
+
const idx = state._appendWriterEntry(entryType);
|
|
362
|
+
if (vocabularyIndex > 0x00fffffe) throw new RangeError('Packed message dense index exceeds 0xFFFFFE');
|
|
363
|
+
laneOf(state._buffer._rowHeaders)[idx] = (((vocabularyIndex + 1) << 8) | entryType) >>> 0;
|
|
364
|
+
return this;
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
/** Row-lane setter for fixed system columns (line, error_code, ...). */
|
|
370
|
+
const makeRowLaneSetter = (valuesKey: string, nullsKey: string): FluentMethod =>
|
|
371
|
+
function (value) {
|
|
372
|
+
const buf = this._state._buffer;
|
|
373
|
+
const idx = buf._writeIndex - 1;
|
|
374
|
+
const values = buf[valuesKey];
|
|
375
|
+
if (values) {
|
|
376
|
+
laneOf(values)[idx] = value;
|
|
377
|
+
const nulls = buf[nullsKey];
|
|
378
|
+
if (nulls) {
|
|
379
|
+
helpers.setNullBit(bitmapOf(nulls), idx);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
return this;
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
// --------------------------------------------------------------------------
|
|
386
|
+
// Prototype assembly — SAME member order as the compiled class body, so
|
|
387
|
+
// name collisions shadow identically (schema setters first, extension
|
|
388
|
+
// methods next, enum fluent overrides last).
|
|
389
|
+
// --------------------------------------------------------------------------
|
|
390
|
+
|
|
391
|
+
for (const column of plan.columns) {
|
|
392
|
+
defineMethod(column.name, makeStateBoundSetter(column));
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
defineMethod('info', makeOperationalLogMethod(ENTRY_TYPE_INFO));
|
|
396
|
+
defineMethod('_infoTemplate', makeTemplateLogMethod(ENTRY_TYPE_INFO));
|
|
397
|
+
defineMethod('debug', makePlainLogMethod(ENTRY_TYPE_DEBUG));
|
|
398
|
+
defineMethod('_debugTemplate', makeTemplateLogMethod(ENTRY_TYPE_DEBUG));
|
|
399
|
+
defineMethod('warn', makeOperationalLogMethod(ENTRY_TYPE_WARN));
|
|
400
|
+
defineMethod('_warnTemplate', makeTemplateLogMethod(ENTRY_TYPE_WARN));
|
|
401
|
+
defineMethod('error', makeOperationalLogMethod(ENTRY_TYPE_ERROR));
|
|
402
|
+
defineMethod('_errorTemplate', makeTemplateLogMethod(ENTRY_TYPE_ERROR));
|
|
403
|
+
defineMethod('trace', makePlainLogMethod(ENTRY_TYPE_TRACE));
|
|
404
|
+
defineMethod('_traceTemplate', makeTemplateLogMethod(ENTRY_TYPE_TRACE));
|
|
405
|
+
|
|
406
|
+
defineMethod('with', function (this: LoggerInstance, attributes: Record<string, unknown>): LoggerInstance {
|
|
407
|
+
for (const key in attributes) {
|
|
408
|
+
const value = attributes[key];
|
|
409
|
+
if (value === null || value === undefined) {
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
const setter = this[key];
|
|
413
|
+
if (typeof setter === 'function') {
|
|
414
|
+
setter.call(this, value);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
return this;
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
defineMethod(
|
|
421
|
+
'ffAccess',
|
|
422
|
+
family === 'static-only'
|
|
423
|
+
? function (this: LoggerInstance): void {
|
|
424
|
+
this._state._appendWriterEntry(ENTRY_TYPE_FF_ACCESS);
|
|
425
|
+
throw new TypeError('Feature flag write reached a static-only callsite plan');
|
|
426
|
+
}
|
|
427
|
+
: function (this: LoggerInstance, flagName: string, value: unknown): void {
|
|
428
|
+
const state = this._state;
|
|
429
|
+
const idx = state._appendWriterEntry(ENTRY_TYPE_FF_ACCESS);
|
|
430
|
+
laneOf(state._buffer.message_values)[idx] = flagName;
|
|
431
|
+
const ffValues = state._buffer.ff_value_values;
|
|
432
|
+
if (ffValues) {
|
|
433
|
+
const strValue = value === null || value === undefined ? 'null' : String(value);
|
|
434
|
+
laneOf(ffValues)[idx] = strValue;
|
|
435
|
+
const ffNulls = state._buffer.ff_value_nulls;
|
|
436
|
+
if (ffNulls) {
|
|
437
|
+
helpers.setNullBit(bitmapOf(ffNulls), idx);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
},
|
|
441
|
+
);
|
|
442
|
+
|
|
443
|
+
defineMethod(
|
|
444
|
+
'ffUsage',
|
|
445
|
+
family === 'static-only'
|
|
446
|
+
? function (this: LoggerInstance): LoggerInstance {
|
|
447
|
+
this._state._appendWriterEntry(ENTRY_TYPE_FF_USAGE);
|
|
448
|
+
throw new TypeError('Feature flag write reached a static-only callsite plan');
|
|
449
|
+
}
|
|
450
|
+
: function (this: LoggerInstance, flagName: string, context: unknown): LoggerInstance {
|
|
451
|
+
const state = this._state;
|
|
452
|
+
const idx = state._appendWriterEntry(ENTRY_TYPE_FF_USAGE);
|
|
453
|
+
laneOf(state._buffer.message_values)[idx] = flagName;
|
|
454
|
+
if (context) {
|
|
455
|
+
callFluentWith(this, context);
|
|
456
|
+
}
|
|
457
|
+
return this;
|
|
458
|
+
},
|
|
459
|
+
);
|
|
460
|
+
|
|
461
|
+
defineMethod('line', makeRowLaneSetter('line_values', 'line_nulls'));
|
|
462
|
+
defineMethod('error_code', makeRowLaneSetter('error_code_values', 'error_code_nulls'));
|
|
463
|
+
defineMethod('exception_stack', makeRowLaneSetter('exception_stack_values', 'exception_stack_nulls'));
|
|
464
|
+
defineMethod('ff_value', makeRowLaneSetter('ff_value_values', 'ff_value_nulls'));
|
|
465
|
+
defineMethod('uint64_value', makeRowLaneSetter('uint64_value_values', 'uint64_value_nulls'));
|
|
466
|
+
|
|
467
|
+
Object.defineProperty(proto, 'scope', {
|
|
468
|
+
...ACCESSOR_DESCRIPTOR,
|
|
469
|
+
get(this: LoggerInstance) {
|
|
470
|
+
return this._state._buffer._scopeValues;
|
|
471
|
+
},
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
defineMethod('_setScope', function (this: LoggerInstance, attributes: Record<string, unknown>): void {
|
|
475
|
+
const buf = this._state._buffer;
|
|
476
|
+
const current = buf._scopeValues || {};
|
|
477
|
+
const next: Record<string, unknown> = { ...current };
|
|
478
|
+
|
|
479
|
+
for (const key of Object.keys(attributes)) {
|
|
480
|
+
const value = attributes[key];
|
|
481
|
+
if (value === null) {
|
|
482
|
+
delete next[key];
|
|
483
|
+
} else if (value !== undefined) {
|
|
484
|
+
next[key] = value;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
buf._scopeValues = Object.freeze(next);
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
defineMethod('_prefillScopedAttributesOn', makePrefillScopedAttributes(plan));
|
|
492
|
+
|
|
493
|
+
// Fluent enum overrides: convert the declared enum string to its
|
|
494
|
+
// schema-order index (shadow the base enum setters, exactly like the
|
|
495
|
+
// compiled class where they appear last in the class body).
|
|
496
|
+
for (const { fieldName } of enumLookup.ordered) {
|
|
497
|
+
const encode = enumLookup.byField[fieldName].encode;
|
|
498
|
+
defineMethod(fieldName, function (this: LoggerInstance, value: unknown): LoggerInstance {
|
|
499
|
+
const idx = encode(value);
|
|
500
|
+
const buf = this._state._buffer;
|
|
501
|
+
const write = buf[fieldName];
|
|
502
|
+
if (typeof write !== 'function') throw new TypeError(`Span buffer has no ${fieldName} setter method`);
|
|
503
|
+
write.call(buf, buf._writeIndex - 1, idx);
|
|
504
|
+
return this;
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
return GeneratedSpanLogger;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// ============================================================================
|
|
512
|
+
// Scoped attribute prefill (mirrors generatePrefillScopedAttributesMethod)
|
|
513
|
+
// ============================================================================
|
|
514
|
+
|
|
515
|
+
type ColumnPrefill = (buffer: SpanBufferView, startIdx: number, endIdx: number) => void;
|
|
516
|
+
|
|
517
|
+
function makeColumnPrefill(
|
|
518
|
+
column: SpanLoggerColumnPlan,
|
|
519
|
+
encode: ((value: unknown) => number) | undefined,
|
|
520
|
+
helpers: SpanLoggerRuntimeHelpers,
|
|
521
|
+
): ColumnPrefill | undefined {
|
|
522
|
+
const { name, schemaType } = column;
|
|
523
|
+
|
|
524
|
+
// Binary columns are not scope-fillable (object payloads can't be bulk-filled)
|
|
525
|
+
if (schemaType === 'binary') return undefined;
|
|
526
|
+
|
|
527
|
+
const rawValuesKey = `_${name}_values`;
|
|
528
|
+
const valuesKey = `${name}_values`;
|
|
529
|
+
const nullsKey = `${name}_nulls`;
|
|
530
|
+
|
|
531
|
+
// Boolean uses bit-packed storage - bulk fill using helper
|
|
532
|
+
if (schemaType === 'boolean') {
|
|
533
|
+
return (buffer, startIdx, endIdx) => {
|
|
534
|
+
const scopeValue = buffer._scopeValues?.[name];
|
|
535
|
+
if (scopeValue !== null && scopeValue !== undefined && buffer[rawValuesKey] !== undefined) {
|
|
536
|
+
helpers.fillBooleanBitmapRange(bitmapOf(buffer[valuesKey]), startIdx, endIdx, Boolean(scopeValue));
|
|
537
|
+
helpers.fillNullBitmapRange(bitmapOf(buffer[nullsKey]), startIdx, endIdx);
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// For string arrays (category/text), use manual loop instead of fill()
|
|
543
|
+
if (schemaType === 'category' || schemaType === 'text') {
|
|
544
|
+
return (buffer, startIdx, endIdx) => {
|
|
545
|
+
const scopeValue = buffer._scopeValues?.[name];
|
|
546
|
+
if (scopeValue !== null && scopeValue !== undefined && buffer[rawValuesKey] !== undefined) {
|
|
547
|
+
const values = laneOf(buffer[valuesKey]);
|
|
548
|
+
for (let i = startIdx; i < endIdx; i++) {
|
|
549
|
+
values[i] = scopeValue;
|
|
550
|
+
}
|
|
551
|
+
helpers.fillNullBitmapRange(bitmapOf(buffer[nullsKey]), startIdx, endIdx);
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// Enum values are encoded to their schema-order index before filling
|
|
557
|
+
if (schemaType === 'enum' && encode !== undefined) {
|
|
558
|
+
return (buffer, startIdx, endIdx) => {
|
|
559
|
+
const scopeValue = buffer._scopeValues?.[name];
|
|
560
|
+
if (scopeValue !== null && scopeValue !== undefined && buffer[rawValuesKey] !== undefined) {
|
|
561
|
+
fillableOf(buffer[valuesKey]).fill(encode(scopeValue), startIdx, endIdx);
|
|
562
|
+
helpers.fillNullBitmapRange(bitmapOf(buffer[nullsKey]), startIdx, endIdx);
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
return (buffer, startIdx, endIdx) => {
|
|
568
|
+
const scopeValue = buffer._scopeValues?.[name];
|
|
569
|
+
if (scopeValue !== null && scopeValue !== undefined && buffer[rawValuesKey] !== undefined) {
|
|
570
|
+
fillableOf(buffer[valuesKey]).fill(scopeValue, startIdx, endIdx);
|
|
571
|
+
helpers.fillNullBitmapRange(bitmapOf(buffer[nullsKey]), startIdx, endIdx);
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
function makePrefillScopedAttributes(plan: SpanLoggerPlan): (this: LoggerInstance, buffer: SpanBufferView) => void {
|
|
577
|
+
const { helpers, enumLookup } = plan;
|
|
578
|
+
const orderedEnumFields = new Set(enumLookup.ordered.map(({ fieldName }) => fieldName));
|
|
579
|
+
const prefills: ColumnPrefill[] = [];
|
|
580
|
+
|
|
581
|
+
for (const column of plan.columns) {
|
|
582
|
+
const encode = orderedEnumFields.has(column.name) ? enumLookup.byField[column.name].encode : undefined;
|
|
583
|
+
const prefill = makeColumnPrefill(column, encode, helpers);
|
|
584
|
+
if (prefill !== undefined) prefills.push(prefill);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// Initial buffer: rows 0-1 reserved for span-start/end, data starts at _writeIndex=2
|
|
588
|
+
// Overflow buffer: no reserved rows, data starts at _writeIndex=0
|
|
589
|
+
// Use buffer._writeIndex as startIdx to handle both cases correctly
|
|
590
|
+
return (buffer) => {
|
|
591
|
+
const startIdx = buffer._writeIndex;
|
|
592
|
+
const endIdx = buffer._capacity;
|
|
593
|
+
for (let i = 0; i < prefills.length; i++) {
|
|
594
|
+
prefills[i](buffer, startIdx, endIdx);
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
//#endregion smoo/lmao!n/codegen-spanlogger.closure
|