@smoothbricks/lmao 0.1.4 → 0.2.0

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.
Files changed (49) hide show
  1. package/dist/cloudflare.d.ts +15 -0
  2. package/dist/cloudflare.d.ts.map +1 -0
  3. package/dist/cloudflare.js +14 -0
  4. package/dist/lib/cloudflare/classSplit.d.ts +73 -0
  5. package/dist/lib/cloudflare/classSplit.d.ts.map +1 -0
  6. package/dist/lib/cloudflare/classSplit.js +82 -0
  7. package/dist/lib/cloudflare/collectorClient.d.ts +69 -0
  8. package/dist/lib/cloudflare/collectorClient.d.ts.map +1 -0
  9. package/dist/lib/cloudflare/collectorClient.js +82 -0
  10. package/dist/lib/cloudflare/diagnosticDrain.d.ts +78 -0
  11. package/dist/lib/cloudflare/diagnosticDrain.d.ts.map +1 -0
  12. package/dist/lib/cloudflare/diagnosticDrain.js +120 -0
  13. package/dist/lib/cloudflare/traceRows.d.ts +19 -0
  14. package/dist/lib/cloudflare/traceRows.d.ts.map +1 -0
  15. package/dist/lib/cloudflare/traceRows.js +51 -0
  16. package/dist/lib/codegen/evaluatorGenerator.js +1 -1
  17. package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts +8 -0
  18. package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts.map +1 -1
  19. package/dist/lib/codegen/fixedPositionWriterGenerator.js +17 -1
  20. package/dist/lib/sqlite/sqlite-common.d.ts +2 -0
  21. package/dist/lib/sqlite/sqlite-common.d.ts.map +1 -1
  22. package/dist/lib/sqlite/sqlite-common.js +4 -0
  23. package/dist/lib/traceRoot.d.ts +5 -5
  24. package/dist/lib/traceRoot.es.js +1 -1
  25. package/dist/lib/traceRoot.js +1 -1
  26. package/dist/lib/traceRoot.node.d.ts +2 -2
  27. package/dist/lib/traceRoot.node.js +3 -3
  28. package/package.json +7 -1
  29. package/src/cloudflare.ts +35 -0
  30. package/src/lib/bufferStrategy.ts +2 -2
  31. package/src/lib/cloudflare/__tests__/classSplit.test.ts +171 -0
  32. package/src/lib/cloudflare/__tests__/collectorClient.test.ts +104 -0
  33. package/src/lib/cloudflare/__tests__/diagnosticDrain.test.ts +165 -0
  34. package/src/lib/cloudflare/classSplit.ts +139 -0
  35. package/src/lib/cloudflare/collectorClient.ts +117 -0
  36. package/src/lib/cloudflare/diagnosticDrain.ts +152 -0
  37. package/src/lib/cloudflare/traceRows.ts +60 -0
  38. package/src/lib/codegen/__tests__/fixedPositionWriter-uint64.test.ts +304 -0
  39. package/src/lib/codegen/evaluatorGenerator.ts +2 -2
  40. package/src/lib/codegen/fixedPositionWriterGenerator.ts +26 -1
  41. package/src/lib/schema/defineFeatureFlags.ts +2 -2
  42. package/src/lib/schema/evaluator.ts +2 -2
  43. package/src/lib/sqlite/sqlite-common.ts +5 -0
  44. package/src/lib/testing/__tests__/facts.test.ts +6 -6
  45. package/src/lib/traceRoot.es.ts +2 -2
  46. package/src/lib/traceRoot.node.ts +3 -3
  47. package/src/lib/traceRoot.ts +5 -5
  48. package/src/lib/tracers/ArrayQueueTracer.ts +2 -2
  49. package/src/lib/codegen/__tests__/__snapshots__/spanLoggerGenerator.test.ts.snap +0 -1965
@@ -48,6 +48,10 @@ export type TagWriter<T extends LogSchema> = {
48
48
  * Bulk set multiple attributes at once.
49
49
  */
50
50
  with(attributes: Partial<InferSchema<T>>): TagWriter<T>;
51
+ /**
52
+ * Set the reserved `uint64_value` column for this span-start row.
53
+ */
54
+ uint64_value(value: bigint): TagWriter<T>;
51
55
  } & {
52
56
  [K in keyof InferSchema<T>]: (value: InferSchema<T>[K]) => TagWriter<T>;
53
57
  };
@@ -81,6 +85,10 @@ export type ResultWriter<T extends LogSchema, R = unknown, E = unknown> = {
81
85
  * Set the result-row source line (row 1).
82
86
  */
83
87
  line(lineNumber: number): ResultWriter<T, R, E>;
88
+ /**
89
+ * Set the reserved `uint64_value` column for this result row.
90
+ */
91
+ uint64_value(value: bigint): ResultWriter<T, R, E>;
84
92
  } & {
85
93
  [K in keyof InferSchema<T>]: (value: InferSchema<T>[K]) => ResultWriter<T, R, E>;
86
94
  };
@@ -1 +1 @@
1
- {"version":3,"file":"fixedPositionWriterGenerator.d.ts","sourceRoot":"","sources":["../../../src/lib/codegen/fixedPositionWriterGenerator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fixedPositionWriterGenerator.d.ts","sourceRoot":"","sources":["../../../src/lib/codegen/fixedPositionWriterGenerator.ts"],"names":[],"mappings":"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"}
@@ -171,12 +171,23 @@ const resultWriterClassCache = new WeakMap();
171
171
  // ============================================================================
172
172
  // TagWriter API
173
173
  // ============================================================================
174
+ /**
175
+ * TagWriter extension - adds the reserved system `uint64_value` writer (row 0).
176
+ */
177
+ const tagWriterExtension = {
178
+ methods: `
179
+ uint64_value(value) {
180
+ this._buffer.uint64_value(this._pos, value);
181
+ return this;
182
+ }
183
+ `,
184
+ };
174
185
  /**
175
186
  * Generate TagWriter class code for a schema.
176
187
  * TagWriter writes to position 0 (span-start row).
177
188
  */
178
189
  export function generateTagWriterClass(schema) {
179
- return generateFixedPositionWriterClass(schema, 0, 'GeneratedTagWriter');
190
+ return generateFixedPositionWriterClass(schema, 0, 'GeneratedTagWriter', tagWriterExtension);
180
191
  }
181
192
  /**
182
193
  * Get or create a cached TagWriter class for a schema.
@@ -243,6 +254,11 @@ line(lineNumber) {
243
254
  this._buffer.line(this._pos, lineNumber);
244
255
  return this;
245
256
  }
257
+
258
+ uint64_value(value) {
259
+ this._buffer.uint64_value(this._pos, value);
260
+ return this;
261
+ }
246
262
  `,
247
263
  };
248
264
  /**
@@ -33,5 +33,7 @@ export declare function getMissingSchemaColumns(schema: LogSchema, knownColumns:
33
33
  export declare function getActiveUserFields(schema: LogSchema, knownColumns: ReadonlySet<string>): string[];
34
34
  export declare function getInsertStatementCacheKey(activeUserFields: readonly string[]): string;
35
35
  export declare function buildInsertSql(activeUserFields: readonly string[]): string;
36
+ /** Read a user schema field for one buffer row, falling back to the buffer's scope values. */
37
+ export declare function readSpanFieldValue(buffer: AnySpanBuffer, fieldName: string, row: number): unknown;
36
38
  export declare function buildInsertParams(segment: SpanSegment, row: number, activeUserFields: readonly string[]): unknown[];
37
39
  //# sourceMappingURL=sqlite-common.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite-common.d.ts","sourceRoot":"","sources":["../../../src/lib/sqlite/sqlite-common.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,eAAO,MAAM,oBAAoB,sdAchC,CAAC;AAEF,eAAO,MAAM,oBAAoB,6BAA6B,CAAC;AAI/D,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAqID,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKvD;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,sBAAsB,GAAG,MAAM,CAExE;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAMxF;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,SAAS,sBAAsB,EAAE,EAC1C,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,GAChC,sBAAsB,EAAE,CAQ1B;AAED,wBAAgB,iCAAiC,CAAC,OAAO,EAAE,SAAS,kBAAkB,EAAE,GAAG,sBAAsB,EAAE,CAKlH;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,SAAS,OAAO,EAAE,EACxB,QAAQ,SAA6B,GACpC,kBAAkB,EAAE,CAEtB;AA8BD,wBAAiB,gBAAgB,CAAC,UAAU,EAAE,aAAa,GAAG,SAAS,CAAC,WAAW,CAAC,CAEnF;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,SAAS,EACjB,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,GAChC,sBAAsB,EAAE,CAW1B;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAElG;AAED,wBAAgB,0BAA0B,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAEtF;AAED,wBAAgB,cAAc,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAS1E;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,EAAE,CAgBnH"}
1
+ {"version":3,"file":"sqlite-common.d.ts","sourceRoot":"","sources":["../../../src/lib/sqlite/sqlite-common.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,eAAO,MAAM,oBAAoB,sdAchC,CAAC;AAEF,eAAO,MAAM,oBAAoB,6BAA6B,CAAC;AAI/D,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAqID,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKvD;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,sBAAsB,GAAG,MAAM,CAExE;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAMxF;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,SAAS,sBAAsB,EAAE,EAC1C,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,GAChC,sBAAsB,EAAE,CAQ1B;AAED,wBAAgB,iCAAiC,CAAC,OAAO,EAAE,SAAS,kBAAkB,EAAE,GAAG,sBAAsB,EAAE,CAKlH;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,SAAS,OAAO,EAAE,EACxB,QAAQ,SAA6B,GACpC,kBAAkB,EAAE,CAEtB;AA8BD,wBAAiB,gBAAgB,CAAC,UAAU,EAAE,aAAa,GAAG,SAAS,CAAC,WAAW,CAAC,CAEnF;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,SAAS,EACjB,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,GAChC,sBAAsB,EAAE,CAW1B;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAElG;AAED,wBAAgB,0BAA0B,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAEtF;AAED,wBAAgB,cAAc,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAS1E;AAED,8FAA8F;AAC9F,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAEjG;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,EAAE,CAgBnH"}
@@ -194,6 +194,10 @@ export function buildInsertSql(activeUserFields) {
194
194
  return `INSERT INTO spans (trace_id, span_id, parent_span_id, row_index, entry_type, timestamp_ns, message${userColsSql})
195
195
  VALUES (?, ?, ?, ?, ?, ?, ?${userPlaceholders})`;
196
196
  }
197
+ /** Read a user schema field for one buffer row, falling back to the buffer's scope values. */
198
+ export function readSpanFieldValue(buffer, fieldName, row) {
199
+ return readUserValue(buffer, fieldName, row) ?? readScopeValue(buffer, fieldName);
200
+ }
197
201
  export function buildInsertParams(segment, row, activeUserFields) {
198
202
  const { buffer, traceId, spanId, parentSpanId, rowOffset } = segment;
199
203
  const entryType = buffer.entry_type[row];
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * Platform-specific implementations:
10
10
  * - TraceRoot.es.ts: Browser - uses performance.now() for timing
11
- * - TraceRoot.node.ts: Node.js - delegates to NAPI addon for optimized writes
11
+ * - TraceRoot.node.ts: Node.js - process.hrtime.bigint(), pure-JS writes to SpanBuffer state
12
12
  *
13
13
  * @module traceRoot
14
14
  */
@@ -47,7 +47,7 @@ export interface TracerLifecycleHooks {
47
47
  *
48
48
  * Total: 17 + trace_id.length bytes
49
49
  *
50
- * This layout enables NAPI/WASM to read anchors directly without BigInt extraction.
50
+ * This layout enables the WASM path to read anchors directly without BigInt extraction.
51
51
  */
52
52
  export declare const TRACE_ROOT_ANCHOR_EPOCH_OFFSET = 0;
53
53
  export declare const TRACE_ROOT_ANCHOR_PERF_OFFSET = 8;
@@ -58,7 +58,7 @@ export declare const TRACE_ROOT_TRACE_ID_OFFSET = 17;
58
58
  *
59
59
  * Each implementation handles timestamp calculation and span writes differently:
60
60
  * - Browser: Pure JS with performance.now()
61
- * - Node.js: NAPI addon with mach_absolute_time() / clock_gettime()
61
+ * - Node.js: process.hrtime.bigint() (pure JS; a NAPI addon was benchmarked slower than WASM and removed)
62
62
  */
63
63
  /**
64
64
  * Factory function type for creating platform-specific TraceRoot instances.
@@ -70,7 +70,7 @@ export type TraceRootFactory = (trace_id: string, tracer: TracerLifecycleHooks)
70
70
  export interface ITraceRoot {
71
71
  /**
72
72
  * Raw backing buffer containing anchor timestamps and trace_id.
73
- * NAPI/WASM can read this directly without BigInt extraction.
73
+ * The WASM path can read this directly without BigInt extraction.
74
74
  */
75
75
  readonly _system: ArrayBuffer;
76
76
  /**
@@ -89,7 +89,7 @@ export interface ITraceRoot {
89
89
  /**
90
90
  * High-resolution timer anchor when trace was created.
91
91
  * Browser: performance.now() value (number)
92
- * Node.js: stored as number for NAPI compatibility, but represents hrtime
92
+ * Node.js: stored as number in the shared layout (WASM-readable), but represents hrtime
93
93
  */
94
94
  readonly anchorPerfNow: number;
95
95
  /**
@@ -1,4 +1,4 @@
1
- //#region corpos/billing!n/audit-pricing-metering.lmao-es-trace-root
1
+ //#region smoo/lmao!n/es-trace-root
2
2
  /**
3
3
  * TraceRoot - Browser/ES implementation.
4
4
  *
@@ -12,7 +12,7 @@ export { createTraceId, extractSpanIdentity, generateTraceId, isValidTraceId, MA
12
12
  *
13
13
  * Total: 17 + trace_id.length bytes
14
14
  *
15
- * This layout enables NAPI/WASM to read anchors directly without BigInt extraction.
15
+ * This layout enables the WASM path to read anchors directly without BigInt extraction.
16
16
  */
17
17
  //#region smoo/lmao!n/trace-root-timestamps #contract
18
18
  export const TRACE_ROOT_ANCHOR_EPOCH_OFFSET = 0;
@@ -30,8 +30,8 @@ export declare class TraceRoot implements ITraceRoot {
30
30
  private readonly _epochView;
31
31
  private readonly _perfView;
32
32
  /**
33
- * Cached anchor hrtime as BigInt for JS timestamp fallback.
34
- * Only used if NAPI addon is not available.
33
+ * Cached anchor hrtime as the exact BigInt, so the JS timestamp delta stays
34
+ * correct after the f64 `anchorPerfNow` loses integer precision (~104 days uptime).
35
35
  */
36
36
  private readonly _anchorHrtimeBigInt;
37
37
  constructor(trace_id: TraceId, anchorEpochNanos: bigint, anchorPerfNow: number, anchorHrtimeBigInt: bigint, tracer: TracerLifecycleHooks);
@@ -36,8 +36,8 @@ export class TraceRoot {
36
36
  _epochView;
37
37
  _perfView;
38
38
  /**
39
- * Cached anchor hrtime as BigInt for JS timestamp fallback.
40
- * Only used if NAPI addon is not available.
39
+ * Cached anchor hrtime as the exact BigInt, so the JS timestamp delta stays
40
+ * correct after the f64 `anchorPerfNow` loses integer precision (~104 days uptime).
41
41
  */
42
42
  _anchorHrtimeBigInt;
43
43
  constructor(trace_id, anchorEpochNanos, anchorPerfNow, anchorHrtimeBigInt, tracer) {
@@ -128,7 +128,7 @@ export class TraceRoot {
128
128
  export function createTraceRoot(trace_id, tracer) {
129
129
  const anchorEpochNanos = BigInt(Date.now()) * 1000000n;
130
130
  const anchorHrtimeBigInt = process.hrtime.bigint();
131
- // Store as number for NAPI to read as f64
131
+ // Also store as f64 in the shared _system layout (WASM reads it without BigInt extraction)
132
132
  const anchorPerfNow = Number(anchorHrtimeBigInt);
133
133
  return new TraceRoot(createTraceId(trace_id), anchorEpochNanos, anchorPerfNow, anchorHrtimeBigInt, tracer);
134
134
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smoothbricks/lmao",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -26,6 +26,12 @@
26
26
  "import": "./dist/es.js",
27
27
  "default": "./dist/es.js"
28
28
  },
29
+ "./cloudflare": {
30
+ "types": "./dist/cloudflare.d.ts",
31
+ "development": "./src/cloudflare.ts",
32
+ "import": "./dist/cloudflare.js",
33
+ "default": "./dist/cloudflare.js"
34
+ },
29
35
  "./tracers": {
30
36
  "types": "./dist/lib/tracers/index.d.ts",
31
37
  "development": "./src/lib/tracers/index.ts",
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Cloudflare trace-sink adapters (specs/lmao/01u_cloudflare_trace_segments.md).
3
+ *
4
+ * Two delivery lanes over the base Tracer lifecycle, no Cloudflare types required — every
5
+ * platform binding (Pipelines stream send, Queues producer, collector shard) is injected
6
+ * structurally:
7
+ * - billing-grade: CollectorClient (awaited within the request; ack = DO storage commit)
8
+ * - diagnostic: DiagnosticDrainTracer + transports (waitUntil, fire-and-forget)
9
+ * - both: ClassSplitTracer routes rows per delivery class via an injected classifier
10
+ */
11
+
12
+ export {
13
+ type ClassSplitOptions,
14
+ ClassSplitTracer,
15
+ type DeliveryClass,
16
+ type DeliveryClassifier,
17
+ } from './lib/cloudflare/classSplit.js';
18
+ export {
19
+ COLLECTOR_ACK,
20
+ type CollectorAck,
21
+ type CollectorClient,
22
+ type CollectorSendFailure,
23
+ FakeCollectorClient,
24
+ } from './lib/cloudflare/collectorClient.js';
25
+ export {
26
+ type DiagnosticDrainOptions,
27
+ DiagnosticDrainTracer,
28
+ type DiagnosticTransport,
29
+ type PipelinesStreamSend,
30
+ PipelinesStreamTransport,
31
+ type QueuesFallbackOptions,
32
+ QueuesFallbackTransport,
33
+ type TraceChunkQueueMessage,
34
+ } from './lib/cloudflare/diagnosticDrain.js';
35
+ export { spanBufferToTraceRows, type TraceRow, type TraceRowValue } from './lib/cloudflare/traceRows.js';
@@ -1,4 +1,4 @@
1
- //#region corpos/billing!n/audit-pricing-metering.lmao-buffer-strategy
1
+ //#region smoo/lmao!n/buffer-strategy
2
2
  /**
3
3
  * BufferStrategy - Abstraction for SpanBuffer memory management and Arrow conversion.
4
4
  *
@@ -105,4 +105,4 @@ export interface BufferStrategy<T extends LogSchema = LogSchema> {
105
105
  */
106
106
  releaseBuffer(buffer: AnySpanBuffer): void;
107
107
  }
108
- //#endregion corpos/billing!n/audit-pricing-metering.lmao-buffer-strategy
108
+ //#endregion smoo/lmao!n/buffer-strategy
@@ -0,0 +1,171 @@
1
+ // Configure Node.js timestamp implementation - MUST be first import
2
+ import '../../__tests__/test-helpers.js';
3
+
4
+ import { describe, expect, it } from 'bun:test';
5
+ import { createTestTracerOptions } from '../../__tests__/test-helpers.js';
6
+ import { defineLogSchema, defineOpContext, S } from '../../defineOpContext.js';
7
+ import { Err, Ok } from '../../result.js';
8
+ import { ClassSplitTracer, type DeliveryClassifier } from '../classSplit.js';
9
+ import { type CollectorSendFailure, FakeCollectorClient } from '../collectorClient.js';
10
+ import type { TraceRow } from '../traceRows.js';
11
+
12
+ const testSchema = defineLogSchema({
13
+ lane: S.category(),
14
+ });
15
+
16
+ const opContext = defineOpContext({ logSchema: testSchema });
17
+ const { defineOp } = opContext;
18
+
19
+ // Injected classifier seam — here: a row is billing-grade iff it carries the billing lane tag.
20
+ const classifyByLane: DeliveryClassifier = (row) => (row.lane === 'billing' ? 'billing-grade' : 'diagnostic');
21
+
22
+ const billableOp = defineOp('billable', (ctx) => {
23
+ ctx.tag.lane('billing');
24
+ return ctx.ok('charged');
25
+ });
26
+
27
+ const diagnosticOp = defineOp('diagnostic', (ctx) => ctx.ok('observed'));
28
+
29
+ interface Harness {
30
+ tracer: ClassSplitTracer<typeof opContext>;
31
+ collector: FakeCollectorClient;
32
+ diagnosticBatches: (readonly TraceRow[])[];
33
+ diagnosticErrors: unknown[];
34
+ lateFailures: CollectorSendFailure[];
35
+ }
36
+
37
+ function makeHarness(options?: { diagnosticsFail?: boolean }): Harness {
38
+ const collector = new FakeCollectorClient();
39
+ const diagnosticBatches: (readonly TraceRow[])[] = [];
40
+ const diagnosticErrors: unknown[] = [];
41
+ const lateFailures: CollectorSendFailure[] = [];
42
+ const tracer = new ClassSplitTracer(opContext, {
43
+ ...createTestTracerOptions(),
44
+ collector,
45
+ diagnostics: {
46
+ send: async (rows) => {
47
+ if (options?.diagnosticsFail) throw new Error('diagnostic lane down');
48
+ diagnosticBatches.push(rows);
49
+ },
50
+ },
51
+ classify: classifyByLane,
52
+ onDiagnosticSendError: (error) => {
53
+ diagnosticErrors.push(error);
54
+ },
55
+ onLateBillableSendFailure: (failure) => {
56
+ lateFailures.push(failure);
57
+ },
58
+ });
59
+ return { tracer, collector, diagnosticBatches, diagnosticErrors, lateFailures };
60
+ }
61
+
62
+ function tick(): Promise<void> {
63
+ return new Promise((resolve) => setTimeout(resolve, 0));
64
+ }
65
+
66
+ describe('ClassSplitTracer', () => {
67
+ describe('settleBillable (awaited within the request)', () => {
68
+ it('returns Ok(null) when the request produced no billing-grade rows', async () => {
69
+ const { tracer, collector, diagnosticBatches } = makeHarness();
70
+ await tracer.trace('req', diagnosticOp);
71
+
72
+ const settled = await tracer.settleBillable();
73
+ expect(settled).toBeInstanceOf(Ok);
74
+ if (settled instanceof Ok) expect(settled.value).toBeNull();
75
+ expect(collector.acked).toHaveLength(0);
76
+ // Diagnostic rows are staged, not sent yet — that is flush()'s lazy job.
77
+ expect(diagnosticBatches).toHaveLength(0);
78
+ });
79
+
80
+ it('sends billing-grade rows to the collector and resolves only on its ack', async () => {
81
+ const { tracer, collector } = makeHarness();
82
+ collector.holdSends();
83
+ await tracer.trace('req', billableOp);
84
+
85
+ let settledFlag = false;
86
+ const pending = tracer.settleBillable().then((result) => {
87
+ settledFlag = true;
88
+ return result;
89
+ });
90
+
91
+ await tick();
92
+ // Send-before-response: the request must still be blocked here.
93
+ expect(settledFlag).toBe(false);
94
+ expect(collector.pendingCount).toBe(1);
95
+
96
+ collector.ackNext();
97
+ const settled = await pending;
98
+ expect(settled).toBeInstanceOf(Ok);
99
+ expect(collector.acked).toHaveLength(1);
100
+ expect(collector.acked[0].every((row) => row.lane === 'billing')).toBe(true);
101
+ // No billing-grade rows may remain buffered in the isolate.
102
+ expect(tracer.queue).toHaveLength(0);
103
+ });
104
+
105
+ it('returns Err when the collector is unavailable — the billable request must fail', async () => {
106
+ const { tracer, collector } = makeHarness();
107
+ collector.failNext({ code: 'collector-unavailable', message: 'shard down' });
108
+ await tracer.trace('req', billableOp);
109
+
110
+ const settled = await tracer.settleBillable();
111
+ expect(settled).toBeInstanceOf(Err);
112
+ if (settled instanceof Err) expect(settled.error.code).toBe('collector-unavailable');
113
+ });
114
+
115
+ it('routes rows of one trace to both lanes per the injected classifier', async () => {
116
+ const { tracer, collector, diagnosticBatches } = makeHarness();
117
+ await tracer.trace('req', billableOp);
118
+ await tracer.trace('req', diagnosticOp);
119
+
120
+ const settled = await tracer.settleBillable();
121
+ expect(settled).toBeInstanceOf(Ok);
122
+ expect(collector.acked).toHaveLength(1);
123
+
124
+ await tracer.flush();
125
+ expect(diagnosticBatches).toHaveLength(1);
126
+ const diagnosticRows = diagnosticBatches[0];
127
+ expect(diagnosticRows.length).toBeGreaterThan(0);
128
+ expect(diagnosticRows.every((row) => row.lane !== 'billing')).toBe(true);
129
+ });
130
+ });
131
+
132
+ describe('flush (lazy, waitUntil-schedulable)', () => {
133
+ it('sends staged + newly drained diagnostic rows and never rejects on transport failure', async () => {
134
+ const { tracer, diagnosticErrors } = makeHarness({ diagnosticsFail: true });
135
+ await tracer.trace('req', diagnosticOp);
136
+
137
+ await tracer.flush();
138
+ expect(diagnosticErrors).toHaveLength(1);
139
+ expect(diagnosticErrors[0]).toBeInstanceOf(Error);
140
+ });
141
+
142
+ it('still delivers billing rows found at flush time (settle skipped), awaited', async () => {
143
+ const { tracer, collector, lateFailures } = makeHarness();
144
+ await tracer.trace('req', billableOp);
145
+
146
+ await tracer.flush();
147
+ expect(collector.acked).toHaveLength(1);
148
+ expect(lateFailures).toHaveLength(0);
149
+ });
150
+
151
+ it('escalates late billable send failures via onLateBillableSendFailure without rejecting', async () => {
152
+ const { tracer, collector, lateFailures } = makeHarness();
153
+ collector.failNext({ code: 'collector-rejected', message: 'commit failed' });
154
+ await tracer.trace('req', billableOp);
155
+
156
+ await tracer.flush();
157
+ expect(lateFailures).toHaveLength(1);
158
+ expect(lateFailures[0].code).toBe('collector-rejected');
159
+ });
160
+
161
+ it('does not resend diagnostic rows on a second flush', async () => {
162
+ const { tracer, diagnosticBatches } = makeHarness();
163
+ await tracer.trace('req', diagnosticOp);
164
+
165
+ await tracer.settleBillable();
166
+ await tracer.flush();
167
+ await tracer.flush();
168
+ expect(diagnosticBatches).toHaveLength(1);
169
+ });
170
+ });
171
+ });
@@ -0,0 +1,104 @@
1
+ // Configure Node.js timestamp implementation - MUST be first import
2
+ import '../../__tests__/test-helpers.js';
3
+
4
+ import { describe, expect, it } from 'bun:test';
5
+ import { Err, Ok } from '../../result.js';
6
+ import { COLLECTOR_ACK, FakeCollectorClient } from '../collectorClient.js';
7
+ import type { TraceRow } from '../traceRows.js';
8
+
9
+ const rows: TraceRow[] = [
10
+ {
11
+ trace_id: 't1',
12
+ span_id: 1,
13
+ parent_span_id: 0,
14
+ row_index: 0,
15
+ entry_type: 1,
16
+ timestamp_ns: 1_000_000,
17
+ message: 'op',
18
+ },
19
+ ];
20
+
21
+ function tick(): Promise<void> {
22
+ return new Promise((resolve) => setTimeout(resolve, 0));
23
+ }
24
+
25
+ describe('CollectorClient contract (via FakeCollectorClient)', () => {
26
+ describe('ack semantics', () => {
27
+ it('resolves Ok with the durability ack and records the batch', async () => {
28
+ const client = new FakeCollectorClient();
29
+ const result = await client.send(rows);
30
+
31
+ expect(result).toBeInstanceOf(Ok);
32
+ if (result instanceof Ok) expect(result.value).toBe(COLLECTOR_ACK);
33
+ expect(client.acked).toEqual([rows]);
34
+ });
35
+
36
+ it('send resolves ONLY when the collector acks (durability point)', async () => {
37
+ const client = new FakeCollectorClient();
38
+ client.holdSends();
39
+
40
+ let settled = false;
41
+ const pending = client.send(rows).then((result) => {
42
+ settled = true;
43
+ return result;
44
+ });
45
+
46
+ await tick();
47
+ // No ack yet — the send-before-response contract means the caller is still blocked here.
48
+ expect(settled).toBe(false);
49
+ expect(client.pendingCount).toBe(1);
50
+ expect(client.acked).toHaveLength(0);
51
+
52
+ client.ackNext();
53
+ const result = await pending;
54
+ expect(settled).toBe(true);
55
+ expect(result).toBeInstanceOf(Ok);
56
+ expect(client.acked).toEqual([rows]);
57
+ });
58
+
59
+ it('supports injected ack latency', async () => {
60
+ const client = new FakeCollectorClient();
61
+ client.setLatency(20);
62
+
63
+ const start = Date.now();
64
+ const result = await client.send(rows);
65
+ expect(result).toBeInstanceOf(Ok);
66
+ expect(Date.now() - start).toBeGreaterThanOrEqual(15);
67
+ });
68
+ });
69
+
70
+ describe('failure semantics', () => {
71
+ it('returns Err (never throws) on injected failure — the billable request must fail', async () => {
72
+ const client = new FakeCollectorClient();
73
+ client.failNext({ code: 'collector-unavailable', message: 'shard down' });
74
+
75
+ const result = await client.send(rows);
76
+ expect(result).toBeInstanceOf(Err);
77
+ if (result instanceof Err) expect(result.error.code).toBe('collector-unavailable');
78
+ // A failed send is NOT durable — nothing may be recorded as acked.
79
+ expect(client.acked).toHaveLength(0);
80
+ });
81
+
82
+ it('held sends can be rejected with an operational failure', async () => {
83
+ const client = new FakeCollectorClient();
84
+ client.holdSends();
85
+
86
+ const pending = client.send(rows);
87
+ client.rejectNext({ code: 'collector-rejected', message: 'storage commit failed' });
88
+
89
+ const result = await pending;
90
+ expect(result).toBeInstanceOf(Err);
91
+ if (result instanceof Err) expect(result.error.code).toBe('collector-rejected');
92
+ expect(client.acked).toHaveLength(0);
93
+ });
94
+
95
+ it('recovers after a failure: subsequent sends ack normally', async () => {
96
+ const client = new FakeCollectorClient();
97
+ client.failNext({ code: 'collector-unavailable', message: 'blip' });
98
+
99
+ expect(await client.send(rows)).toBeInstanceOf(Err);
100
+ expect(await client.send(rows)).toBeInstanceOf(Ok);
101
+ expect(client.acked).toEqual([rows]);
102
+ });
103
+ });
104
+ });