@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/library.js
CHANGED
|
@@ -4,58 +4,30 @@
|
|
|
4
4
|
* WHY: Libraries need to write clean, domain-focused code (ctx.tag.status(200))
|
|
5
5
|
* while avoiding naming conflicts when composed with other libraries.
|
|
6
6
|
*
|
|
7
|
-
* HOW: At composition time (cold path), we
|
|
8
|
-
*
|
|
7
|
+
* HOW: At composition time (cold path), we create immutable Arrow remap descriptors.
|
|
8
|
+
* Child buffers retain canonical schema/layout.
|
|
9
9
|
*
|
|
10
10
|
* Per specs/lmao/01e_library_integration_pattern.md:
|
|
11
11
|
* - Libraries define clean schemas without prefixes (status, method, url)
|
|
12
12
|
* - Prefixing happens at composition time (http_status, http_method, http_url)
|
|
13
|
-
* - Zero hot path overhead -
|
|
13
|
+
* - Zero hot path overhead - remapping is composed at module creation
|
|
14
14
|
*
|
|
15
|
-
* WHAT: This module provides
|
|
16
|
-
*
|
|
17
|
-
* - createPrefixMapping() - Build clean→prefixed name mapping
|
|
18
|
-
* - generateRemappedBufferViewClass() - Generate view for Arrow conversion
|
|
19
|
-
* - generateRemappedSpanLoggerClass() - Generate class with clean methods, prefixed writes
|
|
20
|
-
* - createRemappedSpanLoggerClass() - Compile and cache SpanLogger classes
|
|
15
|
+
* WHAT: This module provides schema/prefix mapping utilities and immutable remap
|
|
16
|
+
* descriptors for cold Arrow conversion.
|
|
21
17
|
*/
|
|
22
18
|
import { isRecord } from '@smoothbricks/validation';
|
|
23
|
-
import { ENTRY_TYPE_DEBUG, ENTRY_TYPE_ERROR, ENTRY_TYPE_INFO, ENTRY_TYPE_TRACE, ENTRY_TYPE_WARN, } from './schema/systemSchema.js';
|
|
24
|
-
import { getEnumValues, getSchemaType } from './schema/typeGuards.js';
|
|
25
19
|
import { LogSchema } from './schema/types.js';
|
|
26
20
|
function isSchemaField(value) {
|
|
27
21
|
return isRecord(value);
|
|
28
22
|
}
|
|
29
|
-
function isRemappedBufferViewClass(value) {
|
|
30
|
-
if (typeof value !== 'function') {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
const prototype = Reflect.get(value, 'prototype');
|
|
34
|
-
return (typeof prototype === 'object' &&
|
|
35
|
-
prototype !== null &&
|
|
36
|
-
typeof Reflect.get(prototype, 'getColumnIfAllocated') === 'function' &&
|
|
37
|
-
typeof Reflect.get(prototype, 'getNullsIfAllocated') === 'function');
|
|
38
|
-
}
|
|
39
|
-
function isRemappedSpanLoggerClass(value) {
|
|
40
|
-
if (typeof value !== 'function') {
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
43
|
-
const prototype = Reflect.get(value, 'prototype');
|
|
44
|
-
return (typeof prototype === 'object' &&
|
|
45
|
-
prototype !== null &&
|
|
46
|
-
typeof Reflect.get(prototype, 'with') === 'function' &&
|
|
47
|
-
typeof Reflect.get(prototype, 'info') === 'function' &&
|
|
48
|
-
typeof Reflect.get(prototype, 'error') === 'function');
|
|
49
|
-
}
|
|
50
|
-
//#region smoo/lmao!n/codegen-prefixed-remap
|
|
51
23
|
/**
|
|
52
24
|
* Prefix a tag attribute schema
|
|
53
25
|
* Renames all fields with a prefix to avoid conflicts
|
|
54
26
|
*
|
|
55
27
|
* 01j "Library Compilation (Prefixed)": a library defines clean field names
|
|
56
|
-
* (status, method); the consumer applies a prefix (http) at wire time.
|
|
57
|
-
*
|
|
58
|
-
*
|
|
28
|
+
* (status, method); the consumer applies a prefix (http) at wire time. The utilities
|
|
29
|
+
* below create the prefixed schema, clean-to-prefixed mapping, and immutable Arrow
|
|
30
|
+
* remap descriptor.
|
|
59
31
|
*
|
|
60
32
|
* Example:
|
|
61
33
|
* - Input: { status: S.number(), method: S.enum(['GET', 'POST']) }
|
|
@@ -79,8 +51,8 @@ export function prefixSchema(schema, prefix) {
|
|
|
79
51
|
/**
|
|
80
52
|
* Create a mapping from clean field names to prefixed column names
|
|
81
53
|
*
|
|
82
|
-
* WHY: This mapping
|
|
83
|
-
*
|
|
54
|
+
* WHY: This mapping exposes the relationship between clean library field names and
|
|
55
|
+
* their prefixed column names.
|
|
84
56
|
*
|
|
85
57
|
* @param schema - Clean schema (LogSchema instance)
|
|
86
58
|
* @param prefix - Prefix to apply (e.g., 'http')
|
|
@@ -99,497 +71,32 @@ export function createPrefixMapping(schema, prefix) {
|
|
|
99
71
|
}
|
|
100
72
|
return mapping;
|
|
101
73
|
}
|
|
102
|
-
// ============================================================================
|
|
103
|
-
// RemappedBufferView - Maps prefixed column names to unprefixed for tree traversal
|
|
104
|
-
// ============================================================================
|
|
105
|
-
/**
|
|
106
|
-
* Cache for generated RemappedBufferView classes.
|
|
107
|
-
* Key is a stable string representation of the mapping.
|
|
108
|
-
* This avoids regenerating classes for the same mapping.
|
|
109
|
-
*/
|
|
110
|
-
const remappedBufferViewClassCache = new Map();
|
|
111
|
-
/**
|
|
112
|
-
* Cache for generated RemappedSpanLogger classes.
|
|
113
|
-
* Key is a stable string representation of schema fields + prefix mapping.
|
|
114
|
-
*/
|
|
115
|
-
const remappedSpanLoggerClassCache = new Map();
|
|
116
|
-
/**
|
|
117
|
-
* Create a stable cache key from a prefix mapping.
|
|
118
|
-
* Sorts keys to ensure consistent ordering.
|
|
119
|
-
*/
|
|
120
|
-
function createMappingCacheKey(mapping) {
|
|
121
|
-
const sortedEntries = Object.entries(mapping).sort(([a], [b]) => a.localeCompare(b));
|
|
122
|
-
return JSON.stringify(sortedEntries);
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Create a stable cache key from schema and prefix mapping.
|
|
126
|
-
* Combines schema fields with sorted prefix mapping for consistent keys.
|
|
127
|
-
*/
|
|
128
|
-
function createSchemaAndMappingCacheKey(schema, mapping) {
|
|
129
|
-
const schemaKey = JSON.stringify(schema.fields);
|
|
130
|
-
const mappingKey = createMappingCacheKey(mapping);
|
|
131
|
-
return `${schemaKey}:${mappingKey}`;
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Generate a RemappedBufferView class for library prefix support.
|
|
135
|
-
*
|
|
136
|
-
* WHY: Libraries write to unprefixed columns (status, method) but Arrow conversion
|
|
137
|
-
* iterates using prefixed names from the root schema (http_status, http_method).
|
|
138
|
-
* RemappedBufferView bridges this gap for tree traversal during cold-path Arrow conversion.
|
|
139
|
-
*
|
|
140
|
-
* HOW: Uses new Function() to generate a class at library composition time (cold path).
|
|
141
|
-
* The generated class wraps a SpanBuffer and remaps getColumnIfAllocated/getNullsIfAllocated
|
|
142
|
-
* calls from prefixed names to unprefixed names.
|
|
143
|
-
*
|
|
144
|
-
* WHAT: Returns a class constructor that:
|
|
145
|
-
* - Passes through tree traversal properties (children, next)
|
|
146
|
-
* - Passes through system columns (timestamps, operations, message, etc.)
|
|
147
|
-
* - Passes through identity properties (traceId, spanId, etc.)
|
|
148
|
-
* - Remaps getColumnIfAllocated() and getNullsIfAllocated() from prefixed→unprefixed
|
|
149
|
-
*
|
|
150
|
-
* Per specs/lmao/01e_library_integration_pattern.md:
|
|
151
|
-
* - Hot path: Library writes directly to unprefixed columns (zero overhead)
|
|
152
|
-
* - Cold path: Arrow conversion uses RemappedBufferView to access via prefixed names
|
|
153
|
-
*
|
|
154
|
-
* @param prefixToUnprefixedMapping - Maps prefixed names to unprefixed names
|
|
155
|
-
* e.g., { 'http_status': 'status', 'http_method': 'method' }
|
|
156
|
-
* NOTE: The mapping is prefixed→unprefixed (reverse of createPrefixMapping output)
|
|
157
|
-
*
|
|
158
|
-
* @returns Constructor for RemappedBufferView class
|
|
159
|
-
*
|
|
160
|
-
* @example
|
|
161
|
-
* ```typescript
|
|
162
|
-
* // Create mapping (prefixed → unprefixed)
|
|
163
|
-
* const mapping = { 'http_status': 'status', 'http_method': 'method' };
|
|
164
|
-
* const ViewClass = generateRemappedBufferViewClass(mapping);
|
|
165
|
-
*
|
|
166
|
-
* // Wrap library buffer
|
|
167
|
-
* const view = new ViewClass(libraryBuffer);
|
|
168
|
-
*
|
|
169
|
-
* // Access via prefixed name returns unprefixed column
|
|
170
|
-
* view.getColumnIfAllocated('http_status'); // Returns buffer.getColumnIfAllocated('status')
|
|
171
|
-
* ```
|
|
172
|
-
*/
|
|
173
|
-
export function generateRemappedBufferViewClass(prefixToUnprefixedMapping) {
|
|
174
|
-
// Check cache first
|
|
175
|
-
const cacheKey = createMappingCacheKey(prefixToUnprefixedMapping);
|
|
176
|
-
const cached = remappedBufferViewClassCache.get(cacheKey);
|
|
177
|
-
if (cached) {
|
|
178
|
-
return cached;
|
|
179
|
-
}
|
|
180
|
-
const mappingCode = JSON.stringify(prefixToUnprefixedMapping);
|
|
181
|
-
// Generate the class code
|
|
182
|
-
// Uses IIFE wrapper for clean scope, similar to generateRemappedSpanLoggerClass
|
|
183
|
-
const code = `(function() {
|
|
184
|
-
'use strict';
|
|
185
|
-
const mapping = ${mappingCode};
|
|
186
|
-
|
|
187
|
-
class RemappedBufferView {
|
|
188
|
-
constructor(buffer) {
|
|
189
|
-
this._buffer = buffer;
|
|
190
|
-
// Build _columns with prefixed names from mapping
|
|
191
|
-
// mapping is { prefixedName: unprefixedName }
|
|
192
|
-
// _logSchema may be undefined in tests using mock buffers
|
|
193
|
-
const baseFields = buffer._logSchema?.fields ?? {};
|
|
194
|
-
this._columns = [];
|
|
195
|
-
for (const prefixedName in mapping) {
|
|
196
|
-
const unprefixedName = mapping[prefixedName];
|
|
197
|
-
const schema = baseFields[unprefixedName];
|
|
198
|
-
if (schema) this._columns.push([prefixedName, schema]);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// Tree traversal (pass-through)
|
|
203
|
-
get _children() { return this._buffer._children; }
|
|
204
|
-
get _parent() { return this._buffer._parent; }
|
|
205
|
-
get _overflow() { return this._buffer._overflow; }
|
|
206
|
-
|
|
207
|
-
// Row count
|
|
208
|
-
get _writeIndex() { return this._buffer._writeIndex; }
|
|
209
|
-
|
|
210
|
-
// System columns (NOT remapped - same in all buffers)
|
|
211
|
-
get timestamp() { return this._buffer.timestamp; }
|
|
212
|
-
get entry_type() { return this._buffer.entry_type; }
|
|
213
|
-
get message_values() { return this._buffer.message_values; }
|
|
214
|
-
get message_nulls() { return this._buffer.message_nulls; }
|
|
215
|
-
get line_values() { return this._buffer.line_values; }
|
|
216
|
-
get line_nulls() { return this._buffer.line_nulls; }
|
|
217
|
-
get error_code_values() { return this._buffer.error_code_values; }
|
|
218
|
-
get error_code_nulls() { return this._buffer.error_code_nulls; }
|
|
219
|
-
get exception_stack_values() { return this._buffer.exception_stack_values; }
|
|
220
|
-
get exception_stack_nulls() { return this._buffer.exception_stack_nulls; }
|
|
221
|
-
get ff_value_values() { return this._buffer.ff_value_values; }
|
|
222
|
-
get ff_value_nulls() { return this._buffer.ff_value_nulls; }
|
|
223
|
-
|
|
224
|
-
// Identity (pass-through)
|
|
225
|
-
get trace_id() { return this._buffer.trace_id; }
|
|
226
|
-
get thread_id() { return this._buffer.thread_id; }
|
|
227
|
-
get span_id() { return this._buffer.span_id; }
|
|
228
|
-
get parent_span_id() { return this._buffer.parent_span_id; }
|
|
229
|
-
get parent_thread_id() { return this._buffer.parent_thread_id; }
|
|
230
|
-
get _identity() { return this._buffer._identity; }
|
|
231
|
-
|
|
232
|
-
// Metadata (pass-through)
|
|
233
|
-
get module() { return this._buffer._module; }
|
|
234
|
-
get _opMetadata() { return this._buffer._opMetadata; }
|
|
235
|
-
get _callsiteMetadata() { return this._buffer._callsiteMetadata; }
|
|
236
|
-
// Remapped column access (for Arrow conversion iteration)
|
|
237
|
-
// Maps prefixed name → unprefixed name before calling underlying buffer
|
|
238
|
-
getColumnIfAllocated(name) {
|
|
239
|
-
const unprefixedName = mapping[name] ?? name;
|
|
240
|
-
return this._buffer.getColumnIfAllocated(unprefixedName);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
getNullsIfAllocated(name) {
|
|
244
|
-
const unprefixedName = mapping[name] ?? name;
|
|
245
|
-
return this._buffer.getNullsIfAllocated(unprefixedName);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
return RemappedBufferView;
|
|
250
|
-
})()`;
|
|
251
|
-
const GeneratedClass = new Function(`return ${code}`)();
|
|
252
|
-
if (!isRemappedBufferViewClass(GeneratedClass)) {
|
|
253
|
-
throw new TypeError('Generated remapped buffer view is missing column remapping methods');
|
|
254
|
-
}
|
|
255
|
-
// Cache for future use
|
|
256
|
-
remappedBufferViewClassCache.set(cacheKey, GeneratedClass);
|
|
257
|
-
return GeneratedClass;
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* Generate enum value mapping code for remapped class
|
|
261
|
-
* Creates a switch-case statement for compile-time enum mapping
|
|
262
|
-
*
|
|
263
|
-
* WHY: Enums need compile-time mapping to Uint8 values for 1-byte storage
|
|
264
|
-
*/
|
|
265
|
-
function generateEnumMapping(fieldName, enumValues) {
|
|
266
|
-
const cases = enumValues.map((value, index) => ` case ${JSON.stringify(value)}: return ${index};`).join('\n');
|
|
267
|
-
return `
|
|
268
|
-
function getEnumIndex_${fieldName}(value) {
|
|
269
|
-
switch(value) {
|
|
270
|
-
${cases}
|
|
271
|
-
default: return 0;
|
|
272
|
-
}
|
|
273
|
-
}`;
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* Generate attribute writer method for remapped SpanLogger
|
|
277
|
-
*
|
|
278
|
-
* WHY: Each method must write to the PREFIXED column while being called by CLEAN name
|
|
279
|
-
* HOW: Method name is cleanName, but buffer access uses prefixedColumnName
|
|
280
|
-
*
|
|
281
|
-
* @param cleanName - Clean method name (e.g., 'status')
|
|
282
|
-
* @param prefixedColumnName - Prefixed column name (e.g., 'http_status')
|
|
283
|
-
* @param schema - Field schema for type-specific handling
|
|
284
|
-
* @param hasEnumMapping - Whether enum mapping function exists
|
|
285
|
-
*/
|
|
286
|
-
function generateRemappedAttributeWriter(cleanName, prefixedColumnName, schema, hasEnumMapping) {
|
|
287
|
-
const columnName = prefixedColumnName;
|
|
288
|
-
const lmaoType = getSchemaType(schema);
|
|
289
|
-
// For enums, use pre-generated mapping function (uses cleanName for function)
|
|
290
|
-
// Generated code: ALWAYS writes to row 0 (span-start) with overwrite semantics
|
|
291
|
-
// Maps clean method name to prefixed column, marks value as non-null (bit 0)
|
|
292
|
-
if (lmaoType === 'enum' && hasEnumMapping) {
|
|
293
|
-
return `
|
|
294
|
-
${cleanName}(value) {
|
|
295
|
-
const idx = 0;
|
|
296
|
-
const enumIndex = getEnumIndex_${cleanName}(value);
|
|
297
|
-
this._buffer.${columnName}_values[idx] = enumIndex;
|
|
298
|
-
this._buffer.${columnName}_nulls[0] |= 1;
|
|
299
|
-
return this;
|
|
300
|
-
}`;
|
|
301
|
-
}
|
|
302
|
-
// For categories, store strings directly
|
|
303
|
-
// Generated code: writes to row 0, stores string directly, marks non-null
|
|
304
|
-
if (lmaoType === 'category') {
|
|
305
|
-
return `
|
|
306
|
-
${cleanName}(value) {
|
|
307
|
-
const idx = 0;
|
|
308
|
-
if (value === null || value === undefined) {
|
|
309
|
-
this._buffer.${columnName}_nulls[0] &= ~1;
|
|
310
|
-
return this;
|
|
311
|
-
}
|
|
312
|
-
this._buffer.${columnName}_values[idx] = value;
|
|
313
|
-
this._buffer.${columnName}_nulls[0] |= 1;
|
|
314
|
-
return this;
|
|
315
|
-
}`;
|
|
316
|
-
}
|
|
317
|
-
// For text, store strings directly
|
|
318
|
-
// Generated code: writes to row 0, handles null/undefined by clearing bit and returning early,
|
|
319
|
-
// stores string directly, marks non-null
|
|
320
|
-
if (lmaoType === 'text') {
|
|
321
|
-
return `
|
|
322
|
-
${cleanName}(value) {
|
|
323
|
-
const idx = 0;
|
|
324
|
-
if (value === null || value === undefined) {
|
|
325
|
-
this._buffer.${columnName}_nulls[0] &= ~1;
|
|
326
|
-
return this;
|
|
327
|
-
}
|
|
328
|
-
this._buffer.${columnName}_values[idx] = value;
|
|
329
|
-
this._buffer.${columnName}_nulls[0] |= 1;
|
|
330
|
-
return this;
|
|
331
|
-
}`;
|
|
332
|
-
}
|
|
333
|
-
// Boolean: bit-packed storage (8 values per byte)
|
|
334
|
-
// Generated code: writes to row 0, bit 0 of byte 0 is index 0,
|
|
335
|
-
// sets or clears value bit, marks non-null
|
|
336
|
-
if (lmaoType === 'boolean') {
|
|
337
|
-
return `
|
|
338
|
-
${cleanName}(value) {
|
|
339
|
-
if (value) {
|
|
340
|
-
this._buffer.${columnName}_values[0] |= 1;
|
|
341
|
-
} else {
|
|
342
|
-
this._buffer.${columnName}_values[0] &= ~1;
|
|
343
|
-
}
|
|
344
|
-
this._buffer.${columnName}_nulls[0] |= 1;
|
|
345
|
-
return this;
|
|
346
|
-
}`;
|
|
347
|
-
}
|
|
348
|
-
// Generic writer for other types (number)
|
|
349
|
-
// Generated code: writes to row 0, direct value assignment, marks non-null
|
|
350
|
-
return `
|
|
351
|
-
${cleanName}(value) {
|
|
352
|
-
const idx = 0;
|
|
353
|
-
this._buffer.${columnName}_values[idx] = value;
|
|
354
|
-
this._buffer.${columnName}_nulls[0] |= 1;
|
|
355
|
-
return this;
|
|
356
|
-
}`;
|
|
357
|
-
}
|
|
358
74
|
/**
|
|
359
|
-
*
|
|
360
|
-
*
|
|
361
|
-
* WHY: Library authors write clean code (ctx.tag.status(200)) but buffers use prefixed
|
|
362
|
-
* columns (http_status). This function generates a class at module creation time
|
|
363
|
-
* (cold path) that exposes clean method names but writes to prefixed columns.
|
|
364
|
-
*
|
|
365
|
-
* HOW: Uses new Function() to generate optimized JavaScript code. The generated class
|
|
366
|
-
* has methods named after clean schema fields but writes to prefixed buffer columns.
|
|
75
|
+
* Create immutable output-to-source metadata for cold Arrow traversal.
|
|
367
76
|
*
|
|
368
|
-
*
|
|
369
|
-
*
|
|
370
|
-
*
|
|
371
|
-
* - Full support for enum/category/text type handling
|
|
372
|
-
* - Method chaining support
|
|
373
|
-
*
|
|
374
|
-
* @param cleanSchema - Original clean schema (without prefix)
|
|
375
|
-
* @param prefixMapping - Mapping from clean names to prefixed names
|
|
376
|
-
* @param className - Name for the generated class
|
|
377
|
-
* @returns Executable JavaScript code string
|
|
378
|
-
*
|
|
379
|
-
* @example
|
|
380
|
-
* const code = generateRemappedSpanLoggerClass(
|
|
381
|
-
* { status: S.number(), method: S.enum(['GET', 'POST']) },
|
|
382
|
-
* { status: 'http_status', method: 'http_method' },
|
|
383
|
-
* 'HttpSpanLogger'
|
|
384
|
-
* );
|
|
385
|
-
* // Generated class has .status() method that writes to http_status
|
|
77
|
+
* The mapping is already fully composed by OpGroup prefix/map operations. Keeping
|
|
78
|
+
* both the frozen lookup and output schema entries avoids wrapping child buffers
|
|
79
|
+
* or reconstructing schema metadata during each traversal.
|
|
386
80
|
*/
|
|
387
|
-
export function
|
|
388
|
-
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
81
|
+
export function createRemapDescriptor(sourceSchema, outputToSourceMapping) {
|
|
82
|
+
const sourceNames = {};
|
|
83
|
+
const columns = [];
|
|
84
|
+
for (const [outputName, sourceName] of Object.entries(outputToSourceMapping)) {
|
|
85
|
+
sourceNames[outputName] = sourceName;
|
|
86
|
+
const fieldSchema = sourceSchema.fields[sourceName];
|
|
87
|
+
if (fieldSchema !== undefined) {
|
|
88
|
+
const column = Object.freeze([
|
|
89
|
+
outputName,
|
|
90
|
+
sourceName,
|
|
91
|
+
fieldSchema,
|
|
92
|
+
`${sourceName}_values`,
|
|
93
|
+
`${sourceName}_nulls`,
|
|
94
|
+
]);
|
|
95
|
+
columns.push(column);
|
|
399
96
|
}
|
|
400
97
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
return generateRemappedAttributeWriter(cleanName, prefixedName, fieldSchema, enumFieldNames.has(cleanName));
|
|
98
|
+
return Object.freeze({
|
|
99
|
+
sourceNames: Object.freeze(sourceNames),
|
|
100
|
+
columns: Object.freeze(columns),
|
|
405
101
|
});
|
|
406
|
-
// Create schema type map for runtime type detection in scope()
|
|
407
|
-
const schemaTypeMap = Object.fromEntries(schemaFields.map(([fieldName, fieldSchema]) => {
|
|
408
|
-
return [fieldName, getSchemaType(fieldSchema) || 'unknown'];
|
|
409
|
-
}));
|
|
410
|
-
// Create clean-to-prefixed mapping for with() and scope() methods
|
|
411
|
-
const prefixMappingJson = JSON.stringify(prefixMapping);
|
|
412
|
-
// Entry type constants (imported from lmao.ts at module level, used here for code gen)
|
|
413
|
-
// These values are inlined into the generated code string below
|
|
414
|
-
// Generate the complete class
|
|
415
|
-
// Generated code: IIFE wrapper for clean scope
|
|
416
|
-
const classCode = `(function() {
|
|
417
|
-
'use strict';
|
|
418
|
-
` +
|
|
419
|
-
// Generated code: getTimestampNanos - platform-aware timestamp function
|
|
420
|
-
// Node.js: uses process.hrtime.bigint() for true nanosecond precision
|
|
421
|
-
// Browser: uses performance.timeOrigin + performance.now() for microsecond precision
|
|
422
|
-
`const getTimestampNanos = (typeof process !== 'undefined' && process.hrtime)
|
|
423
|
-
? (() => {
|
|
424
|
-
const anchorEpochNanos = BigInt(Date.now()) * 1000000n;
|
|
425
|
-
const anchorHrtime = process.hrtime.bigint();
|
|
426
|
-
return () => anchorEpochNanos + (process.hrtime.bigint() - anchorHrtime);
|
|
427
|
-
})()
|
|
428
|
-
: () => {
|
|
429
|
-
const epochMicros = Math.round((performance.timeOrigin + performance.now()) * 1000);
|
|
430
|
-
return BigInt(epochMicros) * 1000n;
|
|
431
|
-
};
|
|
432
|
-
` +
|
|
433
|
-
// Generated code: enum mapping functions (getEnumIndex_${fieldName})
|
|
434
|
-
enumMappings.join('\n') +
|
|
435
|
-
`
|
|
436
|
-
` +
|
|
437
|
-
// Generated code: SCHEMA_TYPES - maps clean field names to lmao types for runtime type detection
|
|
438
|
-
`const SCHEMA_TYPES = ${JSON.stringify(schemaTypeMap)};
|
|
439
|
-
` +
|
|
440
|
-
// Generated code: PREFIX_MAPPING - maps clean names to prefixed column names
|
|
441
|
-
`const PREFIX_MAPPING = ${prefixMappingJson};
|
|
442
|
-
|
|
443
|
-
class ${className} {
|
|
444
|
-
` +
|
|
445
|
-
// Generated code: constructor stores buffer, createOverflowBuffer function, and scoped attributes
|
|
446
|
-
`constructor(buffer, createOverflowBuffer, initialScopedAttributes = {}) {
|
|
447
|
-
this._buffer = buffer;
|
|
448
|
-
this._createOverflowBuffer = createOverflowBuffer;
|
|
449
|
-
this._scopedAttributes = initialScopedAttributes;
|
|
450
|
-
}
|
|
451
|
-
` +
|
|
452
|
-
// Generated code: tag getter returns this for chainable API (writes to row 0 = span-start)
|
|
453
|
-
`get tag() {
|
|
454
|
-
return this;
|
|
455
|
-
}
|
|
456
|
-
` +
|
|
457
|
-
// Generated code: with() bulk attribute setting - maps clean names to prefixed columns,
|
|
458
|
-
// stores values directly (strings stored as-is), marks non-null (bit 0)
|
|
459
|
-
`with(attributes) {
|
|
460
|
-
const idx = 0;
|
|
461
|
-
for (const [cleanKey, value] of Object.entries(attributes)) {
|
|
462
|
-
const prefixedKey = PREFIX_MAPPING[cleanKey] || cleanKey;
|
|
463
|
-
const columnName = prefixedKey;
|
|
464
|
-
const column = this._buffer[columnName + '_values'];
|
|
465
|
-
if (column && value !== null && value !== undefined) {
|
|
466
|
-
column[idx] = value;
|
|
467
|
-
const nullBitmap = this._buffer[columnName + '_nulls'];
|
|
468
|
-
if (nullBitmap) {
|
|
469
|
-
nullBitmap[0] |= 1;
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
return this;
|
|
474
|
-
}
|
|
475
|
-
` +
|
|
476
|
-
// Generated code: individual attribute setters (one per schema field)
|
|
477
|
-
attributeWriters.join('\n') +
|
|
478
|
-
`
|
|
479
|
-
` +
|
|
480
|
-
// Generated code: scope() stores values in _scopedAttributes,
|
|
481
|
-
// then pre-fills remaining buffer capacity so future log entries inherit these values
|
|
482
|
-
`scope(attributes) {
|
|
483
|
-
for (const [cleanKey, value] of Object.entries(attributes)) {
|
|
484
|
-
if (value !== null && value !== undefined) {
|
|
485
|
-
this._scopedAttributes[cleanKey] = value;
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
const startIdx = this._buffer._writeIndex;
|
|
489
|
-
const endIdx = this._buffer._capacity;
|
|
490
|
-
for (let idx = startIdx; idx < endIdx; idx++) {
|
|
491
|
-
for (const [cleanKey, value] of Object.entries(this._scopedAttributes)) {
|
|
492
|
-
const prefixedKey = PREFIX_MAPPING[cleanKey] || cleanKey;
|
|
493
|
-
const columnName = prefixedKey;
|
|
494
|
-
const column = this._buffer[columnName + '_values'];
|
|
495
|
-
if (column) {
|
|
496
|
-
column[idx] = value;
|
|
497
|
-
const nullBitmap = this._buffer[columnName + '_nulls'];
|
|
498
|
-
if (nullBitmap) {
|
|
499
|
-
const byteIndex = Math.floor(idx / 8);
|
|
500
|
-
const bitOffset = idx % 8;
|
|
501
|
-
nullBitmap[byteIndex] |= (1 << bitOffset);
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
` +
|
|
508
|
-
// Generated code: _writeMessage() writes a log entry - ensures buffer has space,
|
|
509
|
-
// writes entry type + timestamp + message, applies scoped attributes
|
|
510
|
-
`_writeMessage(entryType, message) {
|
|
511
|
-
// Check if buffer is full and create overflow buffer if needed
|
|
512
|
-
if (this._buffer._writeIndex >= this._buffer._capacity) {
|
|
513
|
-
const oldBuffer = this._buffer;
|
|
514
|
-
this._buffer = this._createOverflowBuffer(oldBuffer);
|
|
515
|
-
oldBuffer._overflow = this._buffer;
|
|
516
|
-
}
|
|
517
|
-
const idx = this._buffer._writeIndex;
|
|
518
|
-
this._buffer.entry_type[idx] = entryType;
|
|
519
|
-
this._buffer.timestamp[idx] = getTimestampNanos(this._buffer._traceRoot.anchorEpochNanos, this._buffer._traceRoot.anchorPerfNow);
|
|
520
|
-
const messageColumn = this._buffer.message_values;
|
|
521
|
-
if (messageColumn) {
|
|
522
|
-
messageColumn[idx] = message;
|
|
523
|
-
const nullBitmap = this._buffer.message_nulls;
|
|
524
|
-
if (nullBitmap) {
|
|
525
|
-
const byteIndex = Math.floor(idx / 8);
|
|
526
|
-
const bitOffset = idx % 8;
|
|
527
|
-
nullBitmap[byteIndex] |= (1 << bitOffset);
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
for (const [cleanKey, value] of Object.entries(this._scopedAttributes)) {
|
|
531
|
-
const prefixedKey = PREFIX_MAPPING[cleanKey] || cleanKey;
|
|
532
|
-
const columnName = prefixedKey;
|
|
533
|
-
const column = this._buffer[columnName + '_values'];
|
|
534
|
-
if (column) {
|
|
535
|
-
column[idx] = value;
|
|
536
|
-
const nullBitmap = this._buffer[columnName + '_nulls'];
|
|
537
|
-
if (nullBitmap) {
|
|
538
|
-
const byteIndex = Math.floor(idx / 8);
|
|
539
|
-
const bitOffset = idx % 8;
|
|
540
|
-
nullBitmap[byteIndex] |= (1 << bitOffset);
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
this._buffer._writeIndex++;
|
|
545
|
-
}
|
|
546
|
-
` +
|
|
547
|
-
// Generated code: message() generic logging with level string mapping to entry type constants
|
|
548
|
-
`message(level, message) {
|
|
549
|
-
const entryTypeMap = {
|
|
550
|
-
'info': ${ENTRY_TYPE_INFO},
|
|
551
|
-
'debug': ${ENTRY_TYPE_DEBUG},
|
|
552
|
-
'warn': ${ENTRY_TYPE_WARN},
|
|
553
|
-
'error': ${ENTRY_TYPE_ERROR},
|
|
554
|
-
'trace': ${ENTRY_TYPE_TRACE}
|
|
555
|
-
};
|
|
556
|
-
this._writeMessage(entryTypeMap[level] || ${ENTRY_TYPE_INFO}, message);
|
|
557
|
-
}
|
|
558
|
-
` +
|
|
559
|
-
// Generated code: convenience logging methods - each calls _writeMessage with entry type constant
|
|
560
|
-
`info(message) { this._writeMessage(${ENTRY_TYPE_INFO}, message); }
|
|
561
|
-
debug(message) { this._writeMessage(${ENTRY_TYPE_DEBUG}, message); }
|
|
562
|
-
warn(message) { this._writeMessage(${ENTRY_TYPE_WARN}, message); }
|
|
563
|
-
error(message) { this._writeMessage(${ENTRY_TYPE_ERROR}, message); }
|
|
564
|
-
trace(message) { this._writeMessage(${ENTRY_TYPE_TRACE}, message); }
|
|
565
|
-
}
|
|
566
|
-
return ${className};
|
|
567
|
-
})()`;
|
|
568
|
-
return classCode;
|
|
569
|
-
}
|
|
570
|
-
/**
|
|
571
|
-
* Create a remapped SpanLogger class constructor from clean schema and prefix mapping
|
|
572
|
-
*
|
|
573
|
-
* WHY: This is the cold-path function called at module creation time. It compiles
|
|
574
|
-
* the generated class code once and caches the constructor.
|
|
575
|
-
*
|
|
576
|
-
* @param cleanSchema - Clean schema (without prefix)
|
|
577
|
-
* @param prefixMapping - Mapping from clean names to prefixed names
|
|
578
|
-
* @returns Constructor for the remapped SpanLogger class
|
|
579
|
-
*/
|
|
580
|
-
export function createRemappedSpanLoggerClass(cleanSchema, prefixMapping) {
|
|
581
|
-
// Check cache first
|
|
582
|
-
const cacheKey = createSchemaAndMappingCacheKey(cleanSchema, prefixMapping);
|
|
583
|
-
const cached = remappedSpanLoggerClassCache.get(cacheKey);
|
|
584
|
-
if (cached && isRemappedSpanLoggerClass(cached)) {
|
|
585
|
-
return cached;
|
|
586
|
-
}
|
|
587
|
-
const classCode = generateRemappedSpanLoggerClass(cleanSchema, prefixMapping).trim();
|
|
588
|
-
const GeneratedClass = new Function(`return ${classCode}`)();
|
|
589
|
-
if (!isRemappedSpanLoggerClass(GeneratedClass)) {
|
|
590
|
-
throw new TypeError('Generated remapped span logger is missing required logging methods');
|
|
591
|
-
}
|
|
592
|
-
remappedSpanLoggerClassCache.set(cacheKey, GeneratedClass);
|
|
593
|
-
return GeneratedClass;
|
|
594
102
|
}
|
|
595
|
-
//#endregion smoo/lmao!n/codegen-prefixed-remap
|
package/dist/lib/logBinding.d.ts
CHANGED
|
@@ -12,22 +12,24 @@
|
|
|
12
12
|
* - 01e_library_integration_pattern.md - Library prefix/remapping support
|
|
13
13
|
*/
|
|
14
14
|
import type { LogSchema } from './schema/LogSchema.js';
|
|
15
|
-
|
|
15
|
+
/** Dense cold-path remap entry with schema and canonical storage property metadata. */
|
|
16
|
+
export type RemappedColumn = readonly [
|
|
17
|
+
outputName: string,
|
|
18
|
+
sourceName: string,
|
|
19
|
+
schema: unknown,
|
|
20
|
+
valuesProperty: `${string}_values`,
|
|
21
|
+
nullsProperty: `${string}_nulls`
|
|
22
|
+
];
|
|
16
23
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* Generated at module composition time (cold path) by `generateRemappedBufferViewClass()`.
|
|
20
|
-
* Used by prefixed modules to wrap SpanBuffer instances for Arrow conversion when
|
|
21
|
-
* the module's schema columns have been renamed with a prefix.
|
|
22
|
-
*
|
|
23
|
-
* The constructor takes a raw SpanBuffer and returns a view that remaps column access
|
|
24
|
-
* from prefixed names to unprefixed names for tree traversal during Arrow conversion.
|
|
25
|
-
*
|
|
26
|
-
* Per specs/lmao/01e_library_integration_pattern.md:
|
|
27
|
-
* - Hot path: Library writes directly to unprefixed columns (zero overhead)
|
|
28
|
-
* - Cold path: Arrow conversion uses RemappedBufferView to access via prefixed names
|
|
24
|
+
* Immutable metadata interpreted only by cold Arrow conversion.
|
|
25
|
+
* Child SpanBuffers retain their canonical schema and storage layout.
|
|
29
26
|
*/
|
|
30
|
-
export
|
|
27
|
+
export interface RemapDescriptor {
|
|
28
|
+
/** Fully composed output-name to canonical source-name lookup. */
|
|
29
|
+
readonly sourceNames: Readonly<Record<string, string>>;
|
|
30
|
+
/** Dense output/source/schema entries in deterministic composition order. */
|
|
31
|
+
readonly columns: readonly RemappedColumn[];
|
|
32
|
+
}
|
|
31
33
|
/**
|
|
32
34
|
* LogBinding - Everything needed for a group of ops to write logs.
|
|
33
35
|
*
|
|
@@ -42,22 +44,14 @@ export type RemappedViewConstructor = new (buffer: SpanBuffer) => SpanBuffer;
|
|
|
42
44
|
* - 01b2_buffer_self_tuning.md - Self-tuning via SpanBufferClass.stats
|
|
43
45
|
* - 01e_library_integration_pattern.md - Library prefix/remapping support
|
|
44
46
|
*
|
|
45
|
-
* @property
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* @property remappedViewClass - Optional RemappedBufferView class for prefixed/remapped buffers.
|
|
50
|
-
* - When present: the module's ops write to unprefixed columns, but buffers must be wrapped
|
|
51
|
-
* in this view for Arrow conversion to access them by prefixed names
|
|
52
|
-
* - When absent: buffers can be used directly without remapping
|
|
53
|
-
* - Set during module composition when prefix() or mapColumns() is applied (cold path)
|
|
54
|
-
* - Used when registering child spans to parent's tree (see op.ts)
|
|
47
|
+
* @property remapDescriptor - Optional immutable output-to-source metadata for
|
|
48
|
+
* prefixed/remapped buffers. Ops attach the descriptor pointer to raw child
|
|
49
|
+
* buffers; cold Arrow traversal interprets it without wrapping the buffer.
|
|
55
50
|
*/
|
|
56
51
|
export interface LogBinding<T extends LogSchema = LogSchema> {
|
|
57
52
|
/** The unprefixed schema defining what columns exist */
|
|
58
53
|
readonly logSchema: T;
|
|
59
|
-
/** Optional
|
|
60
|
-
readonly
|
|
54
|
+
/** Optional immutable remapping metadata for cold Arrow conversion. */
|
|
55
|
+
readonly remapDescriptor?: RemapDescriptor;
|
|
61
56
|
}
|
|
62
|
-
export {};
|
|
63
57
|
//# sourceMappingURL=logBinding.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logBinding.d.ts","sourceRoot":"","sources":["../../src/lib/logBinding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"logBinding.d.ts","sourceRoot":"","sources":["../../src/lib/logBinding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,uFAAuF;AACvF,MAAM,MAAM,cAAc,GAAG,SAAS;IACpC,UAAU,EAAE,MAAM;IAClB,UAAU,EAAE,MAAM;IAClB,MAAM,EAAE,OAAO;IACf,cAAc,EAAE,GAAG,MAAM,SAAS;IAClC,aAAa,EAAE,GAAG,MAAM,QAAQ;CACjC,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACvD,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;CAC7C;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS;IACzD,wDAAwD;IACxD,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;IAEtB,uEAAuE;IACvE,QAAQ,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC;CAC5C"}
|