@noego/telemetry 0.0.5 → 0.1.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.
- package/README.md +6 -0
- package/dist/browser/index.d.cts +6 -5
- package/dist/browser/index.d.ts +6 -5
- package/dist/{browser_telemetry_client-BSAMZ8Qb.d.cts → browser_telemetry_client-ClZl3awO.d.cts} +2 -2
- package/dist/{browser_telemetry_client-DPBU6NGw.d.ts → browser_telemetry_client-t4dPp8Ku.d.ts} +2 -2
- package/dist/cli/telemetry_bin.cjs +393 -35
- package/dist/cli/telemetry_bin.cjs.map +1 -1
- package/dist/cli/telemetry_bin.js +378 -20
- package/dist/cli/telemetry_bin.js.map +1 -1
- package/dist/cli/telemetry_cli.cjs +393 -35
- package/dist/cli/telemetry_cli.cjs.map +1 -1
- package/dist/cli/telemetry_cli.d.cts +35 -5
- package/dist/cli/telemetry_cli.d.ts +35 -5
- package/dist/cli/telemetry_cli.js +378 -20
- package/dist/cli/telemetry_cli.js.map +1 -1
- package/dist/{client_defaults-ShVYQYmn.d.ts → client_defaults-CZ8PysZX.d.ts} +2 -2
- package/dist/{client_defaults-Dk0MMzvx.d.cts → client_defaults-lDbWYWWK.d.cts} +2 -2
- package/dist/core/index.cjs +5 -1
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +15 -12
- package/dist/core/index.d.ts +15 -12
- package/dist/core/index.js +5 -1
- package/dist/core/index.js.map +1 -1
- package/dist/electron/index.d.cts +5 -4
- package/dist/electron/index.d.ts +5 -4
- package/dist/{envelope.types-rOLpWXRC.d.cts → envelope.types-DIvZD3xH.d.ts} +2 -6
- package/dist/{envelope.types-rOLpWXRC.d.ts → envelope.types-DyrlRG49.d.cts} +2 -6
- package/dist/{in_memory_batch_transport-DKW9EZnU.d.cts → in_memory_batch_transport-3T6gElXP.d.cts} +1 -1
- package/dist/{in_memory_batch_transport-oOwNxXnA.d.ts → in_memory_batch_transport-DpQU6JqM.d.ts} +1 -1
- package/dist/index.cjs +5 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -12
- package/dist/index.d.ts +14 -12
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/json.types-BqS77fcN.d.cts +7 -0
- package/dist/json.types-BqS77fcN.d.ts +7 -0
- package/dist/{maintenance_coordinator.types-C4ULi4A4.d.cts → maintenance_coordinator.types-Crhx9i9k.d.cts} +3 -3
- package/dist/{maintenance_coordinator.types-ikUrRXmO.d.ts → maintenance_coordinator.types-DprmgpVn.d.ts} +3 -3
- package/dist/metric.types-D8aOAnUm.d.ts +67 -0
- package/dist/metric.types-Dg4eZq6u.d.cts +67 -0
- package/dist/{metric_definition_contract-BYtnODhu.d.ts → metric_definition_contract-C6MERhJs.d.ts} +1 -1
- package/dist/{metric_definition_contract-DfhhmTZ1.d.cts → metric_definition_contract-DoAk7NOw.d.cts} +1 -1
- package/dist/node/index.cjs +5 -1
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.cts +11 -9
- package/dist/node/index.d.ts +11 -9
- package/dist/node/index.js +5 -1
- package/dist/node/index.js.map +1 -1
- package/dist/node/producer/index.d.cts +5 -4
- package/dist/node/producer/index.d.ts +5 -4
- package/dist/projector/index.cjs +1370 -0
- package/dist/projector/index.cjs.map +1 -0
- package/dist/projector/index.d.cts +246 -0
- package/dist/projector/index.d.ts +246 -0
- package/dist/projector/index.js +1328 -0
- package/dist/projector/index.js.map +1 -0
- package/dist/{query.types-DU5v7vM0.d.ts → query.types-CRqAsGTX.d.cts} +4 -66
- package/dist/{query.types-DuYWbFFe.d.cts → query.types-DnOMYXpC.d.ts} +4 -66
- package/dist/sqlite/index.cjs +5 -1
- package/dist/sqlite/index.cjs.map +1 -1
- package/dist/sqlite/index.d.cts +7 -5
- package/dist/sqlite/index.d.ts +7 -5
- package/dist/sqlite/index.js +5 -1
- package/dist/sqlite/index.js.map +1 -1
- package/dist/{storage.types-k7oElEB3.d.ts → storage.types-BKWoIOHp.d.ts} +3 -2
- package/dist/{storage.types-Bji_pWqr.d.cts → storage.types-DHbAm3j_.d.cts} +3 -2
- package/dist/{telemetry_client-BO5Pjp41.d.cts → telemetry_client-Bg5tbj5E.d.cts} +3 -2
- package/dist/{telemetry_client-D8uZ-mTL.d.ts → telemetry_client-DWKgufmc.d.ts} +3 -2
- package/dist/{telemetry_configuration_parser-BZ8Nvnle.d.ts → telemetry_configuration_parser-6BR3_dD_.d.ts} +2 -2
- package/dist/{telemetry_configuration_parser-CgSN7R6A.d.cts → telemetry_configuration_parser-ybeweUPE.d.cts} +2 -2
- package/dist/testing/index.d.cts +7 -5
- package/dist/testing/index.d.ts +7 -5
- package/dist/trace-adapter/index.d.cts +4 -3
- package/dist/trace-adapter/index.d.ts +4 -3
- package/dist/{transport.types-BAl_TRtU.d.cts → transport.types-C2dP-eed.d.cts} +1 -1
- package/dist/{transport.types-DDnZoKWi.d.ts → transport.types-SA8KpLiK.d.ts} +1 -1
- package/native/noego_telemetry_native.node +0 -0
- package/package.json +11 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/projector/trace_projection.types.ts","../../src/projector/trace_projector.ts","../../src/projector/trace_projector_process.ts","../../src/platform/node/telemetry_configuration_parser.ts","../../src/core/metric_definition_contract.ts","../../src/core/helper/canonical_json.ts","../../src/storage/helper/sqlite_table_names.ts","../../src/storage/telemetry_table_map.ts","../../src/platform/node/helper/telemetry_duration_parser.ts","../../src/platform/node/schema/telemetry_configuration_schema.ts","../../src/projector/telemetry_metrics_migration.ts"],"sourcesContent":["/**\n * Declarative trace projection definitions (spec 04 §6).\n *\n * A projection describes how raw trace events become historical time-series\n * observations. Definitions are immutable by (name, version) once historical\n * data exists: changing meaning requires a version bump.\n */\n\nexport type TraceAggregate = 'count' | 'sum' | 'min' | 'max' | 'avg' | 'last';\n\nexport type TraceMeasurement = {\n /** Numeric field read from the trace event's context. */\n field: string;\n aggregates: readonly TraceAggregate[];\n};\n\nexport type TraceCardinalityPolicy = {\n /** Bound on distinct dimension-value combinations per projection. */\n maxDimensionKeys?: number;\n /** At the bound: 'reject' records a projection failure; 'other' folds into an __other__ bucket. */\n overflow?: 'reject' | 'other';\n};\n\nexport type TraceProjection = {\n name: string;\n version: number;\n /**\n * Trace event name selector (TraceEvent.event). Exact match, or a glob:\n * `*` matches one dot-separated segment, `**` matches any remainder\n * (e.g. 'render-cycle.**' matches 'render-cycle.turns-changed').\n */\n event: string;\n /** Optional source filter (TraceEvent.source). */\n source?: string;\n /** Context fields promoted to bounded historical dimensions. */\n groupBy?: readonly string[];\n measurements: readonly TraceMeasurement[];\n /** Bucket resolutions in milliseconds (e.g. 60_000, 3_600_000). */\n resolutions: readonly number[];\n /**\n * Behavior when a measurement field is absent/non-numeric on a matching\n * event: 'record-failure' (default) records a bounded projection failure and\n * skips the event; 'skip' omits the field but still counts the event.\n */\n missingField?: 'skip' | 'record-failure';\n cardinality?: TraceCardinalityPolicy;\n};\n\nconst NAME_PATTERN = /^[a-z][a-z0-9_.-]*$/;\n\n/** Validates a projection definition, throwing on structural errors. */\nexport function validateTraceProjection(projection: TraceProjection): void {\n if (!NAME_PATTERN.test(projection.name)) {\n throw new Error(`TraceProjection: invalid name '${projection.name}'`);\n }\n if (!Number.isSafeInteger(projection.version) || projection.version < 1) {\n throw new Error(`TraceProjection '${projection.name}': version must be a positive integer`);\n }\n if (typeof projection.event !== 'string' || projection.event.trim().length === 0) {\n throw new Error(`TraceProjection '${projection.name}': event selector is required`);\n }\n if (projection.resolutions.length === 0) {\n throw new Error(`TraceProjection '${projection.name}': at least one resolution is required`);\n }\n for (const resolution of projection.resolutions) {\n if (!Number.isSafeInteger(resolution) || resolution < 1) {\n throw new Error(`TraceProjection '${projection.name}': resolutions must be positive integers`);\n }\n }\n // measurements may be empty: a count-only projection tracks bucket counts.\n for (const measurement of projection.measurements) {\n if (typeof measurement.field !== 'string' || measurement.field.trim().length === 0) {\n throw new Error(`TraceProjection '${projection.name}': measurement field is required`);\n }\n if (measurement.aggregates.length === 0) {\n throw new Error(\n `TraceProjection '${projection.name}': measurement '${measurement.field}' needs at least one aggregate`,\n );\n }\n }\n const dimensions = projection.groupBy ?? [];\n if (new Set(dimensions).size !== dimensions.length) {\n throw new Error(`TraceProjection '${projection.name}': duplicate groupBy dimension`);\n }\n}\n","import type { Database } from 'better-sqlite3';\nimport type {\n StoredTraceEvent,\n TraceCursor,\n TraceSource,\n TraceSourceDescription,\n} from '@noego/trace/sqlite';\nimport {\n validateTraceProjection,\n type TraceAggregate,\n type TraceProjection,\n} from './trace_projection.types';\n\nexport type TraceProjectorOptions = {\n /** Bounded reader over the raw trace store (owned by @noego/trace). */\n source: TraceSource;\n /** Historical SQL destination. Owned by telemetry; separate from raw traces. */\n destination: Database;\n projections: readonly TraceProjection[];\n /** Raw events read per page; default 500. */\n pageSize?: number;\n now?: () => number;\n};\n\n/**\n * Why a pass produced no bucket updates (spec 05 §5.4). A pass with buckets\n * reports `buckets-updated`; every other value names the reason so \"cursor\n * advancing, zero buckets\" can never be mistaken for health.\n */\nexport type TraceProjectorProgress =\n | 'buckets-updated'\n | 'caught-up-no-new-source'\n | 'new-source-no-selector-match'\n | 'matching-source-no-bucket';\n\n/** Why the durable cursor was discarded before this pass. */\nexport type TraceSourceReset = 'store-epoch-changed' | 'cursor-beyond-source';\n\nexport type TraceProjectorRunResult = {\n pages: number;\n eventsRead: number;\n /** Events that matched at least one projection selector. */\n selectorMatches: number;\n bucketsUpdated: number;\n failures: number;\n progress: TraceProjectorProgress;\n /** Cursor after the pass (rowid in the source store); null when nothing was ever projected. */\n cursorRowId: number | null;\n /** Newest source rowid at the start of the pass; null when the source cannot describe itself. */\n sourceHighRowId: number | null;\n sourceEpoch: string | null;\n sourceReset: TraceSourceReset | null;\n};\n\n/** Backfill reprojects a range; it never touches the forward cursor, so it reports only volume. */\nexport type TraceBackfillResult = Pick<\n TraceProjectorRunResult,\n 'pages' | 'eventsRead' | 'bucketsUpdated' | 'failures'\n>;\n\nexport type TraceBucketQuery = {\n projection: string;\n version: number;\n resolutionMs: number;\n fromMs?: number;\n toMs?: number;\n /** Exact-match dimension filter. */\n dimensions?: Record<string, string>;\n};\n\nexport type TraceBucketRow = {\n projection: string;\n version: number;\n resolutionMs: number;\n bucketStartMs: number;\n dimensions: Record<string, string>;\n count: number;\n values: Record<string, MeasurementState>;\n /** Computed views: avg per field where sum+count exist. */\n averages: Record<string, number>;\n};\n\ntype MeasurementState = {\n count: number;\n sum: number;\n min: number;\n max: number;\n /** Last observed value in projector processing order. */\n last: number;\n};\n\nconst SCAN_PROGRESS_KEY = '__scan__';\nconst OVERFLOW_DIMENSIONS: Record<string, string> = Object.freeze({ __overflow__: 'other' });\n\n/**\n * Downstream trace projector (spec 04): reads retained raw traces through the\n * TraceSource contract and materializes idempotent historical buckets in SQL.\n *\n * The projector is never part of trace ingestion. Buckets are keyed by\n * (projection, version, resolution, bucket start, dimensions) and bucketed by\n * the event's producer-assigned occurrence time — never by projector run time\n * or insert time. Each page commits bucket updates, failures, and the scan\n * cursor in one destination transaction, so a crash resumes exactly at the\n * durable cursor with no double counting. The insertion-ordered source cursor\n * means a late-delivered event is still observed and folded into its\n * historical occurrence-time bucket.\n */\nexport class TraceProjector {\n private readonly source: TraceSource;\n private readonly db: Database;\n private readonly projections: readonly TraceProjection[];\n private readonly pageSize: number;\n private readonly now: () => number;\n\n constructor(options: TraceProjectorOptions) {\n this.source = options.source;\n this.db = options.destination;\n this.projections = options.projections;\n this.pageSize = Math.max(1, options.pageSize ?? 500);\n this.now = options.now ?? Date.now;\n for (const projection of this.projections) {\n validateTraceProjection(projection);\n }\n this.initializeSchema();\n this.registerDefinitions();\n }\n\n /**\n * Drains all unprojected raw traces, page by page, committing progress per\n * page.\n *\n * The durable cursor is a source rowid, so it is only meaningful against\n * the store file it was taken from. When the source describes itself, a\n * cursor whose epoch differs from the store's — or that lies beyond the\n * store's newest row — belongs to a store that has since been recreated\n * (boot reset, manual deletion) and is discarded, restarting the scan at\n * row 0. 2026-09-03: the live projector sat at rowid 22.6M over a rebuilt\n * store holding rows 1–440k, reported \"caught up\" every minute, and wrote\n * no buckets for ten hours.\n */\n runOnce(): TraceProjectorRunResult {\n const description = this.source.describe?.() ?? null;\n const progress = this.loadProgress();\n const sourceReset = detectSourceReset(progress, description);\n let cursor: TraceCursor | null = sourceReset === null ? progress : null;\n const result: TraceProjectorRunResult = {\n pages: 0,\n eventsRead: 0,\n selectorMatches: 0,\n bucketsUpdated: 0,\n failures: 0,\n progress: 'caught-up-no-new-source',\n cursorRowId: cursor?.rowId ?? null,\n sourceHighRowId: description?.highRowId ?? null,\n sourceEpoch: description?.storeEpoch ?? null,\n sourceReset,\n };\n\n for (;;) {\n const page = this.source.readAfter(cursor, { limit: this.pageSize });\n if (page.events.length === 0) break;\n\n const apply = this.db.transaction(() => {\n for (const event of page.events) {\n let matched = false;\n for (const projection of this.projections) {\n if (!this.matches(projection, event)) continue;\n matched = true;\n const outcome = this.applyEvent(projection, event);\n result.bucketsUpdated += outcome.bucketsUpdated;\n result.failures += outcome.failures;\n }\n if (matched) result.selectorMatches += 1;\n }\n this.saveProgress(page.cursor, description?.storeEpoch ?? progress?.storeEpoch ?? null);\n });\n apply();\n\n cursor = page.cursor;\n result.pages += 1;\n result.eventsRead += page.events.length;\n }\n if (sourceReset !== null && result.pages === 0) {\n // Nothing to read from the new store yet; still forget the stale cursor\n // so the next pass does not re-detect the reset.\n this.saveProgress({ rowId: 0 }, description?.storeEpoch ?? null);\n }\n result.cursorRowId = cursor?.rowId ?? (sourceReset !== null ? 0 : null);\n result.progress = classifyProgress(result);\n return result;\n }\n\n /** Newest completed bucket start per projection at the given resolution — the freshness signal. */\n newestBucketStartMs(resolutionMs: number): number | null {\n const row = this.db.prepare(\n 'SELECT MAX(bucket_start_ms) AS newest FROM trace_metric_buckets WHERE resolution_ms = ?',\n ).get(resolutionMs) as { newest: number | null };\n return row.newest;\n }\n\n /**\n * Rebuilds one projection's derived buckets for an occurrence-time range\n * from retained raw traces (spec 04 §14–15): clears coverage for the range,\n * then reprojects every retained matching event. Uses the same extraction\n * code as forward projection; does not touch the forward scan cursor.\n */\n backfill(options: {\n projection: string;\n version: number;\n fromOccurredAtMs: number;\n toOccurredAtMs: number;\n }): TraceBackfillResult {\n const projection = this.projections.find(\n (candidate) => candidate.name === options.projection && candidate.version === options.version,\n );\n if (!projection) {\n throw new Error(`TraceProjector: unknown projection ${options.projection}@${options.version}`);\n }\n const result: TraceBackfillResult = { pages: 0, eventsRead: 0, bucketsUpdated: 0, failures: 0 };\n\n const run = this.db.transaction(() => {\n for (const resolution of projection.resolutions) {\n const firstBucket = bucketStart(options.fromOccurredAtMs, resolution);\n this.db.prepare(`\n DELETE FROM trace_metric_buckets\n WHERE projection_name = ? AND projection_version = ? AND resolution_ms = ?\n AND bucket_start_ms >= ? AND bucket_start_ms <= ?\n `).run(projection.name, projection.version, resolution, firstBucket, options.toOccurredAtMs);\n }\n\n let cursor: TraceCursor | null = null;\n for (;;) {\n const page = this.source.readAfter(cursor, {\n limit: this.pageSize,\n toOccurredAtMs: options.toOccurredAtMs,\n });\n if (page.events.length === 0) break;\n for (const event of page.events) {\n if (event.occurredAtMs < options.fromOccurredAtMs) continue;\n if (!this.matches(projection, event)) continue;\n const outcome = this.applyEvent(projection, event);\n result.bucketsUpdated += outcome.bucketsUpdated;\n result.failures += outcome.failures;\n result.eventsRead += 1;\n }\n cursor = page.cursor;\n result.pages += 1;\n }\n });\n run();\n return result;\n }\n\n /** Historical bucket query with explicit projection/version/resolution. */\n query(query: TraceBucketQuery): readonly TraceBucketRow[] {\n const clauses = [\n 'projection_name = @projection',\n 'projection_version = @version',\n 'resolution_ms = @resolutionMs',\n ];\n const params: Record<string, unknown> = {\n projection: query.projection,\n version: query.version,\n resolutionMs: query.resolutionMs,\n };\n if (query.fromMs !== undefined) { clauses.push('bucket_start_ms >= @fromMs'); params.fromMs = query.fromMs; }\n if (query.toMs !== undefined) { clauses.push('bucket_start_ms <= @toMs'); params.toMs = query.toMs; }\n if (query.dimensions !== undefined) {\n clauses.push('dimension_key = @dimensionKey');\n params.dimensionKey = dimensionKey(query.dimensions);\n }\n\n const rows = this.db.prepare(`\n SELECT * FROM trace_metric_buckets\n WHERE ${clauses.join(' AND ')}\n ORDER BY bucket_start_ms, dimension_key\n `).all(params) as BucketRow[];\n\n return rows.map((row) => {\n const values = JSON.parse(row.values_json) as Record<string, MeasurementState>;\n const averages: Record<string, number> = {};\n for (const [field, state] of Object.entries(values)) {\n if (state.count > 0) averages[field] = state.sum / state.count;\n }\n return {\n projection: row.projection_name,\n version: row.projection_version,\n resolutionMs: row.resolution_ms,\n bucketStartMs: row.bucket_start_ms,\n dimensions: JSON.parse(row.dimensions_json) as Record<string, string>,\n count: row.count,\n values,\n averages,\n };\n });\n }\n\n /** Bounded projection failures, newest first. */\n failures(limit = 100): readonly {\n projection: string;\n version: number;\n traceId: string;\n reason: string;\n }[] {\n const rows = this.db.prepare(`\n SELECT projection_name, projection_version, trace_id, reason\n FROM trace_projection_failures ORDER BY recorded_at_ms DESC LIMIT ?\n `).all(Math.max(1, limit)) as Array<{\n projection_name: string;\n projection_version: number;\n trace_id: string;\n reason: string;\n }>;\n return rows.map((row) => ({\n projection: row.projection_name,\n version: row.projection_version,\n traceId: row.trace_id,\n reason: row.reason,\n }));\n }\n\n private matches(projection: TraceProjection, event: StoredTraceEvent): boolean {\n if (!eventSelectorMatches(projection.event, event.event)) return false;\n if (projection.source !== undefined && event.source !== projection.source) return false;\n return true;\n }\n\n private applyEvent(\n projection: TraceProjection,\n event: StoredTraceEvent,\n ): { bucketsUpdated: number; failures: number } {\n const context = (event.context ?? {}) as Record<string, unknown>;\n\n let dimensions: Record<string, string> = {};\n for (const field of projection.groupBy ?? []) {\n const value = context[field];\n dimensions[field] = value === undefined || value === null ? '' : String(value);\n }\n\n const measured: Record<string, number> = {};\n for (const measurement of projection.measurements) {\n const value = context[measurement.field];\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n if ((projection.missingField ?? 'record-failure') === 'skip') {\n // Field omitted; the event still counts toward the bucket.\n continue;\n }\n this.recordFailure(projection, event, `measurement field '${measurement.field}' is not a finite number`);\n return { bucketsUpdated: 0, failures: 1 };\n }\n measured[measurement.field] = value;\n }\n\n if (!this.admitDimensions(projection, dimensions)) {\n if ((projection.cardinality?.overflow ?? 'reject') === 'other') {\n dimensions = { ...OVERFLOW_DIMENSIONS };\n } else {\n this.recordFailure(projection, event, 'dimension cardinality limit exceeded');\n return { bucketsUpdated: 0, failures: 1 };\n }\n }\n\n let bucketsUpdated = 0;\n for (const resolution of projection.resolutions) {\n this.updateBucket(projection, resolution, bucketStart(event.occurredAtMs, resolution), dimensions, measured);\n bucketsUpdated += 1;\n }\n return { bucketsUpdated, failures: 0 };\n }\n\n private admitDimensions(projection: TraceProjection, dimensions: Record<string, string>): boolean {\n const limit = projection.cardinality?.maxDimensionKeys;\n if (limit === undefined) return true;\n const key = dimensionKey(dimensions);\n const known = this.db.prepare(`\n SELECT 1 FROM trace_metric_buckets\n WHERE projection_name = ? AND projection_version = ? AND dimension_key = ?\n LIMIT 1\n `).get(projection.name, projection.version, key);\n if (known) return true;\n const row = this.db.prepare(`\n SELECT COUNT(DISTINCT dimension_key) AS n FROM trace_metric_buckets\n WHERE projection_name = ? AND projection_version = ?\n `).get(projection.name, projection.version) as { n: number };\n return row.n < limit;\n }\n\n private updateBucket(\n projection: TraceProjection,\n resolutionMs: number,\n bucketStartMs: number,\n dimensions: Record<string, string>,\n measured: Record<string, number>,\n ): void {\n const key = dimensionKey(dimensions);\n const existing = this.db.prepare(`\n SELECT count, values_json FROM trace_metric_buckets\n WHERE projection_name = ? AND projection_version = ? AND resolution_ms = ?\n AND bucket_start_ms = ? AND dimension_key = ?\n `).get(projection.name, projection.version, resolutionMs, bucketStartMs, key) as\n | { count: number; values_json: string }\n | undefined;\n\n const values: Record<string, MeasurementState> = existing\n ? JSON.parse(existing.values_json) as Record<string, MeasurementState>\n : {};\n for (const [field, value] of Object.entries(measured)) {\n const state = values[field] ?? {\n count: 0,\n sum: 0,\n min: Number.POSITIVE_INFINITY,\n max: Number.NEGATIVE_INFINITY,\n last: Number.NaN,\n };\n state.count += 1;\n state.sum += value;\n state.min = Math.min(state.min, value);\n state.max = Math.max(state.max, value);\n state.last = value;\n values[field] = state;\n }\n\n this.db.prepare(`\n INSERT INTO trace_metric_buckets (\n projection_name, projection_version, resolution_ms, bucket_start_ms,\n dimension_key, dimensions_json, count, values_json, updated_at_ms\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (projection_name, projection_version, resolution_ms, bucket_start_ms, dimension_key)\n DO UPDATE SET count = excluded.count, values_json = excluded.values_json, updated_at_ms = excluded.updated_at_ms\n `).run(\n projection.name,\n projection.version,\n resolutionMs,\n bucketStartMs,\n key,\n JSON.stringify(dimensions),\n (existing?.count ?? 0) + 1,\n JSON.stringify(values),\n this.now(),\n );\n }\n\n private recordFailure(projection: TraceProjection, event: StoredTraceEvent, reason: string): void {\n this.db.prepare(`\n INSERT INTO trace_projection_failures (\n projection_name, projection_version, trace_id, reason, occurred_at_ms, recorded_at_ms\n ) VALUES (?, ?, ?, ?, ?, ?)\n `).run(projection.name, projection.version, event.id, reason, event.occurredAtMs, this.now());\n }\n\n private loadProgress(): ScanProgress | null {\n const row = this.db.prepare(\n 'SELECT cursor_json FROM trace_projection_progress WHERE progress_key = ?'\n ).get(SCAN_PROGRESS_KEY) as { cursor_json: string } | undefined;\n if (!row) return null;\n const parsed = JSON.parse(row.cursor_json) as { rowId: number; storeEpoch?: string };\n return { rowId: parsed.rowId, storeEpoch: parsed.storeEpoch ?? null };\n }\n\n private saveProgress(cursor: TraceCursor | null, storeEpoch: string | null): void {\n if (cursor === null) return;\n const progress: ScanProgress = { rowId: cursor.rowId, storeEpoch };\n this.db.prepare(`\n INSERT INTO trace_projection_progress (progress_key, cursor_json, updated_at_ms)\n VALUES (?, ?, ?)\n ON CONFLICT (progress_key) DO UPDATE SET cursor_json = excluded.cursor_json, updated_at_ms = excluded.updated_at_ms\n `).run(SCAN_PROGRESS_KEY, JSON.stringify(progress), this.now());\n }\n\n private registerDefinitions(): void {\n for (const projection of this.projections) {\n const definitionJson = JSON.stringify(projection);\n const existing = this.db.prepare(`\n SELECT definition_json FROM trace_projection_definitions\n WHERE projection_name = ? AND projection_version = ?\n `).get(projection.name, projection.version) as { definition_json: string } | undefined;\n if (existing === undefined) {\n this.db.prepare(`\n INSERT INTO trace_projection_definitions (projection_name, projection_version, definition_json, registered_at_ms)\n VALUES (?, ?, ?, ?)\n `).run(projection.name, projection.version, definitionJson, this.now());\n } else if (existing.definition_json !== definitionJson) {\n // Definitions are immutable per (name, version): changing meaning\n // requires a version bump so historical data stays interpretable.\n throw new Error(\n `TraceProjector: projection ${projection.name}@${projection.version} differs from its registered definition; bump the version`,\n );\n }\n }\n }\n\n private initializeSchema(): void {\n this.db.pragma('journal_mode = WAL');\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS trace_projection_definitions (\n projection_name TEXT NOT NULL,\n projection_version INTEGER NOT NULL,\n definition_json TEXT NOT NULL,\n registered_at_ms INTEGER NOT NULL,\n PRIMARY KEY (projection_name, projection_version)\n );\n\n CREATE TABLE IF NOT EXISTS trace_projection_progress (\n progress_key TEXT NOT NULL PRIMARY KEY,\n cursor_json TEXT NOT NULL,\n updated_at_ms INTEGER NOT NULL\n );\n\n CREATE TABLE IF NOT EXISTS trace_metric_buckets (\n projection_name TEXT NOT NULL,\n projection_version INTEGER NOT NULL,\n resolution_ms INTEGER NOT NULL,\n bucket_start_ms INTEGER NOT NULL,\n dimension_key TEXT NOT NULL,\n dimensions_json TEXT NOT NULL,\n count INTEGER NOT NULL,\n values_json TEXT NOT NULL,\n updated_at_ms INTEGER NOT NULL,\n PRIMARY KEY (projection_name, projection_version, resolution_ms, bucket_start_ms, dimension_key)\n );\n\n CREATE INDEX IF NOT EXISTS trace_metric_buckets_time_idx\n ON trace_metric_buckets (projection_name, projection_version, resolution_ms, bucket_start_ms);\n\n CREATE TABLE IF NOT EXISTS trace_projection_failures (\n projection_name TEXT NOT NULL,\n projection_version INTEGER NOT NULL,\n trace_id TEXT NOT NULL,\n reason TEXT NOT NULL,\n occurred_at_ms INTEGER NOT NULL,\n recorded_at_ms INTEGER NOT NULL\n );\n `);\n }\n}\n\n/**\n * Matches a projection event selector against an event name. Exact match, or\n * glob where `*` matches exactly one dot-separated segment and a trailing\n * `**` matches any remainder (including empty).\n */\nexport function eventSelectorMatches(selector: string, eventName: string): boolean {\n if (selector === eventName) return true;\n if (!selector.includes('*')) return false;\n const selectorParts = selector.split('.');\n const eventParts = eventName.split('.');\n for (let i = 0; i < selectorParts.length; i++) {\n const part = selectorParts[i];\n if (part === '**') {\n // '**' must be terminal; matches any remainder including none.\n return i === selectorParts.length - 1;\n }\n if (i >= eventParts.length) return false;\n if (part !== '*' && part !== eventParts[i]) return false;\n }\n return selectorParts.length === eventParts.length;\n}\n\nfunction bucketStart(occurredAtMs: number, resolutionMs: number): number {\n return occurredAtMs - (occurredAtMs % resolutionMs);\n}\n\n/** Durable scan progress: the source rowid plus the epoch of the store it was read from. */\ntype ScanProgress = {\n rowId: number;\n /** Null for progress written before epochs existed; such a cursor is validated by extent only. */\n storeEpoch: string | null;\n};\n\n/**\n * Decide whether the persisted cursor still refers to the store in front of\n * us. Epoch mismatch is definitive. Without an epoch (legacy progress, or a\n * source that cannot describe itself) fall back to extent: a rowid beyond the\n * newest row cannot have been read from this store.\n */\nexport function detectSourceReset(\n progress: ScanProgress | null,\n description: TraceSourceDescription | null,\n): TraceSourceReset | null {\n if (progress === null || description === null) return null;\n if (progress.storeEpoch !== null && progress.storeEpoch !== description.storeEpoch) {\n return 'store-epoch-changed';\n }\n if (progress.rowId > description.highRowId) return 'cursor-beyond-source';\n return null;\n}\n\nfunction classifyProgress(result: TraceProjectorRunResult): TraceProjectorProgress {\n if (result.bucketsUpdated > 0) return 'buckets-updated';\n if (result.eventsRead === 0) return 'caught-up-no-new-source';\n if (result.selectorMatches === 0) return 'new-source-no-selector-match';\n return 'matching-source-no-bucket';\n}\n\nfunction dimensionKey(dimensions: Record<string, string>): string {\n const sorted = Object.keys(dimensions).sort().map((key) => [key, dimensions[key]]);\n return JSON.stringify(sorted);\n}\n\ntype BucketRow = {\n projection_name: string;\n projection_version: number;\n resolution_ms: number;\n bucket_start_ms: number;\n dimension_key: string;\n dimensions_json: string;\n count: number;\n values_json: string;\n updated_at_ms: number;\n};\n","import { mkdirSync } from 'node:fs';\nimport path from 'node:path';\nimport Database from 'better-sqlite3';\nimport { SqliteTraceStore } from '@noego/trace/sqlite';\nimport { NodeTelemetryConfigurationParser } from '../platform/node/telemetry_configuration_parser.js';\nimport { metricDefinitionsToTraceProjections } from './telemetry_metrics_migration';\nimport { TraceProjector, type TraceProjectorRunResult } from './trace_projector';\nimport type { TraceProjection } from './trace_projection.types';\n\nexport type TraceProjectorProcessOptions = {\n /** Path to the raw trace SQLite written by @noego/trace (traces.db). */\n tracesDbPath: string;\n /** Path to the historical projection SQLite destination. */\n destinationDbPath: string;\n /** Projection definitions; or use configurationPath to migrate legacy metrics. */\n projections?: readonly TraceProjection[];\n /** telemetry.config.yml whose metric definitions become projections. */\n configurationPath?: string;\n /** Raw events per page; default 500. */\n pageSize?: number;\n};\n\nexport type TraceProjectorProcess = {\n runOnce(): TraceProjectorRunResult;\n projector: TraceProjector;\n close(): void;\n};\n\n/**\n * Builds a runnable projector process over file-based stores (spec 04 §5).\n *\n * This is the separate-process execution mode: it opens the raw trace store\n * read-side and its own historical destination, resumes from the durable\n * cursor, and can be run continuously, on a schedule, or as an explicit\n * maintenance command. Its lifecycle never gates raw trace collection.\n */\nexport function createTraceProjectorProcess(\n options: TraceProjectorProcessOptions,\n): TraceProjectorProcess {\n let projections = options.projections ?? [];\n if (options.configurationPath !== undefined) {\n const parser = new NodeTelemetryConfigurationParser();\n const configuration = parser.parseFile(options.configurationPath, {\n storageBaseDirectory: path.dirname(options.destinationDbPath),\n });\n projections = [...projections, ...metricDefinitionsToTraceProjections(configuration.metrics)];\n }\n if (projections.length === 0) {\n throw new Error('TraceProjectorProcess: no projections configured');\n }\n\n const source = new SqliteTraceStore({ connection: new Database(options.tracesDbPath) });\n mkdirSync(path.dirname(options.destinationDbPath), { recursive: true });\n const destination = new Database(options.destinationDbPath);\n const projector = new TraceProjector({\n source,\n destination,\n projections,\n ...(options.pageSize !== undefined ? { pageSize: options.pageSize } : {}),\n });\n\n return {\n projector,\n runOnce: () => projector.runOnce(),\n close: () => {\n source.close();\n destination.close();\n },\n };\n}\n","import { dirname, resolve } from 'node:path';\nimport { readFileSync } from 'node:fs';\nimport { load as loadYaml } from 'js-yaml';\nimport { MetricDefinitionContract } from '../../core/metric_definition_contract.js';\nimport type {\n ResolvedTelemetryConfiguration,\n SqliteTableOverrides,\n SqliteTargetConfiguration,\n} from '../../core/types/configuration.types.js';\nimport type { MetricDefinition, MetricMeasurement } from '../../core/types/metric.types.js';\nimport { TelemetryTableMap } from '../../storage/telemetry_table_map.js';\nimport { TelemetryDurationParser } from './helper/telemetry_duration_parser.js';\nimport {\n TelemetryConfigurationDocumentSchema,\n type SerializedMetricDefinition,\n type SerializedSqliteTarget,\n} from './schema/telemetry_configuration_schema.js';\nimport type { NodeTelemetryConfigurationParseOptions } from './types/telemetry_configuration_parser.types.js';\n\nconst DEFAULT_LEASE_EXPIRY = '30s';\nconst DEFAULT_QUERY_RANGE = '365d';\nconst DEFAULT_QUERY_ROWS = 10_000;\nconst DEFAULT_QUERY_BUCKETS = 10_000;\nconst DEFAULT_QUERY_BYTES = 5_000_000;\nconst DEFAULT_RECLAIM_PAGES = 100;\n\nexport class TelemetryConfigurationError extends Error {\n constructor(\n message: string,\n readonly source: string,\n ) {\n super(`${source}: ${message}`);\n this.name = 'TelemetryConfigurationError';\n }\n}\n\nexport class NodeTelemetryConfigurationParser {\n constructor(\n private readonly durations = new TelemetryDurationParser(),\n private readonly metricContract = new MetricDefinitionContract(),\n ) {}\n\n parseFile(\n configurationPath: string,\n options: NodeTelemetryConfigurationParseOptions = {},\n ): ResolvedTelemetryConfiguration {\n const absolutePath = resolve(configurationPath);\n let source: string;\n try {\n source = readFileSync(absolutePath, 'utf8');\n } catch (cause) {\n throw new TelemetryConfigurationError(this.errorMessage(cause), absolutePath);\n }\n return this.parseYaml(source, {\n sourceName: options.sourceName ?? absolutePath,\n storageBaseDirectory: options.storageBaseDirectory ?? dirname(absolutePath),\n });\n }\n\n parseYaml(\n source: string,\n options: NodeTelemetryConfigurationParseOptions = {},\n ): ResolvedTelemetryConfiguration {\n const sourceName = options.sourceName ?? '<telemetry-configuration>';\n let document: unknown;\n try {\n document = loadYaml(source);\n } catch (cause) {\n throw new TelemetryConfigurationError(this.errorMessage(cause), sourceName);\n }\n const parsed = TelemetryConfigurationDocumentSchema.safeParse(document);\n if (!parsed.success) {\n throw new TelemetryConfigurationError(parsed.error.message, sourceName);\n }\n try {\n const baseDirectory =\n options.storageBaseDirectory === undefined\n ? dirname(resolve(sourceName))\n : resolve(options.storageBaseDirectory);\n return this.resolveDocument(parsed.data, baseDirectory);\n } catch (cause) {\n if (cause instanceof TelemetryConfigurationError) {\n throw cause;\n }\n throw new TelemetryConfigurationError(this.errorMessage(cause), sourceName);\n }\n }\n\n private resolveDocument(\n document: ReturnType<typeof TelemetryConfigurationDocumentSchema.parse>,\n baseDirectory: string,\n ): ResolvedTelemetryConfiguration {\n const telemetry = document.telemetry;\n this.validateRole(telemetry.role, telemetry.trace);\n const serializedTargets = telemetry.trace.storage?.targets ?? [];\n const targets = serializedTargets.map((target, index) =>\n this.resolveTarget(target, baseDirectory, index),\n );\n this.validateTargets(telemetry.role, targets, telemetry.trace.storage?.defaultTarget ?? null);\n const metrics = (telemetry.metrics ?? []).map((metric, index) =>\n this.resolveMetric(metric, targets, index),\n );\n this.validateMetricIdentities(metrics);\n return Object.freeze({\n version: telemetry.version ?? 1,\n role: telemetry.role,\n ingestionTransport: telemetry.trace.ingestionTransport ?? null,\n logTransport: telemetry.logs?.transport ?? null,\n defaultTargetId: telemetry.trace.storage?.defaultTarget ?? null,\n sqliteTargets: Object.freeze(targets),\n metrics: Object.freeze(metrics),\n });\n }\n\n private validateRole(\n role: 'producer' | 'collector' | 'combined',\n trace: Readonly<{\n ingestionTransport?: string | undefined;\n storage?: unknown;\n }>,\n ): void {\n const hasIngestion = trace.ingestionTransport !== undefined;\n const hasStorage = trace.storage !== undefined;\n if (role === 'producer' && (!hasIngestion || hasStorage)) {\n throw new Error('Producer telemetry requires ingestionTransport and forbids storage');\n }\n if (role === 'collector' && !hasStorage) {\n throw new Error('Collector telemetry requires storage targets');\n }\n if (role === 'combined' && (!hasIngestion || !hasStorage)) {\n throw new Error('Combined telemetry requires ingestionTransport and storage targets');\n }\n }\n\n private resolveTarget(\n target: SerializedSqliteTarget,\n baseDirectory: string,\n index: number,\n ): SqliteTargetConfiguration {\n const field = `telemetry.trace.storage.targets[${index}]`;\n const rawMs = this.durations.parse(target.retention.raw, `${field}.retention.raw`);\n const lateArrivalMs = this.durations.parse(\n target.retention.lateArrival ?? '0ms',\n `${field}.retention.lateArrival`,\n true,\n );\n const samplesMs =\n target.retention.samples === undefined\n ? rawMs + lateArrivalMs\n : this.durations.parse(target.retention.samples, `${field}.retention.samples`);\n const levelMs = this.resolveLevelRetention(target.retention.levels, field);\n const rollups = target.retention.rollups.map((tier, tierIndex) =>\n Object.freeze({\n resolutionMs: this.durations.parse(\n tier.resolution,\n `${field}.retention.rollups[${tierIndex}].resolution`,\n ),\n retainMs: this.durations.parse(\n tier.retain,\n `${field}.retention.rollups[${tierIndex}].retain`,\n ),\n }),\n );\n const tables = Object.freeze(\n Object.fromEntries(\n Object.entries(target.schema?.tables ?? {}).filter((entry) => entry[1] !== undefined),\n ),\n ) as SqliteTableOverrides;\n const schema = Object.freeze({\n tablePrefix: target.schema?.tablePrefix ?? null,\n tables,\n });\n const tableMap = TelemetryTableMap.create(schema);\n if (!tableMap.ok) {\n throw new Error(`${field}.schema: ${tableMap.error}`);\n }\n const resolved = Object.freeze({\n targetId: target.id,\n path: resolve(baseDirectory, target.path),\n delivery: target.delivery,\n schema,\n retention: Object.freeze({\n rawMs,\n lateArrivalMs,\n samplesMs,\n levelMs,\n rollups: Object.freeze(rollups),\n }),\n maintenance: Object.freeze({\n intervalMs: this.durations.parse(\n target.maintenance.interval,\n `${field}.maintenance.interval`,\n ),\n maxWorkMs: target.maintenance.maxWorkMs,\n maxReclaimPages: target.maintenance.maxReclaimPages ?? DEFAULT_RECLAIM_PAGES,\n }),\n leaseExpiryMs: this.durations.parse(\n target.leaseExpiry ?? DEFAULT_LEASE_EXPIRY,\n `${field}.leaseExpiry`,\n ),\n query: Object.freeze({\n maxRangeMs: this.durations.parse(\n target.query?.maxRange ?? DEFAULT_QUERY_RANGE,\n `${field}.query.maxRange`,\n ),\n maxRows: target.query?.maxRows ?? DEFAULT_QUERY_ROWS,\n maxBuckets: target.query?.maxBuckets ?? DEFAULT_QUERY_BUCKETS,\n maxResponseBytes: target.query?.maxResponseBytes ?? DEFAULT_QUERY_BYTES,\n }),\n });\n this.validateRetention(resolved, field);\n if (resolved.leaseExpiryMs < 1_000) {\n throw new Error(`${field}.leaseExpiry must be at least 1s`);\n }\n return resolved;\n }\n\n private resolveLevelRetention(\n levels: Readonly<Record<string, string>> | undefined,\n field: string,\n ): Readonly<Record<string, number>> {\n if (levels === undefined) {\n return Object.freeze({});\n }\n const resolved: Record<string, number> = {};\n for (const [level, duration] of Object.entries(levels)) {\n const normalized = level.trim().toLowerCase();\n if (normalized.length === 0) {\n throw new Error(`${field}.retention.levels contains an empty level name`);\n }\n if (resolved[normalized] !== undefined) {\n throw new Error(`${field}.retention.levels declares \"${normalized}\" more than once`);\n }\n resolved[normalized] = this.durations.parse(\n duration,\n `${field}.retention.levels.${normalized}`,\n );\n }\n return Object.freeze(resolved);\n }\n\n private validateRetention(target: SqliteTargetConfiguration, field: string): void {\n const retention = target.retention;\n const requiredSamplesMs = retention.rawMs + retention.lateArrivalMs;\n if (!Number.isSafeInteger(requiredSamplesMs) || retention.samplesMs < requiredSamplesMs) {\n throw new Error(`${field}.retention.samples must cover raw plus lateArrival`);\n }\n for (let index = 0; index < retention.rollups.length; index += 1) {\n const tier = retention.rollups[index];\n const previous = retention.rollups[index - 1];\n if (!tier || tier.retainMs < retention.rawMs) {\n throw new Error(`${field}.retention rollup retention cannot be shorter than raw retention`);\n }\n if (\n previous &&\n (tier.resolutionMs <= previous.resolutionMs || tier.retainMs <= previous.retainMs)\n ) {\n throw new Error(\n `${field}.retention rollup tiers must increase by resolution and retention`,\n );\n }\n }\n }\n\n private validateTargets(\n role: 'producer' | 'collector' | 'combined',\n targets: readonly SqliteTargetConfiguration[],\n defaultTargetId: string | null,\n ): void {\n if (role === 'producer') {\n return;\n }\n const targetIds = targets.map((target) => target.targetId);\n if (new Set(targetIds).size !== targetIds.length) {\n throw new Error('Telemetry storage target ids must be unique');\n }\n if (!targets.some((target) => target.delivery === 'required')) {\n throw new Error('Telemetry storage requires at least one required durable target');\n }\n if (defaultTargetId !== null && !targetIds.includes(defaultTargetId)) {\n throw new Error(`Unknown default telemetry target ${defaultTargetId}`);\n }\n }\n\n private resolveMetric(\n metric: SerializedMetricDefinition,\n targets: readonly SqliteTargetConfiguration[],\n index: number,\n ): MetricDefinition {\n if (metric.selector.endsWith('[*]') && (metric.groupBy?.length ?? 0) > 0) {\n throw new Error(`telemetry.metrics[${index}] selector [*] cannot declare groupBy`);\n }\n const targetIds = metric.targets ?? targets.map((target) => target.targetId);\n if (new Set(targetIds).size !== targetIds.length) {\n throw new Error(`telemetry.metrics[${index}] has duplicate target ids`);\n }\n const unknownTarget = targetIds.find(\n (targetId) => !targets.some((target) => target.targetId === targetId),\n );\n if (unknownTarget !== undefined) {\n throw new Error(`telemetry.metrics[${index}] references unknown target ${unknownTarget}`);\n }\n const resolutionsMs =\n metric.resolutions?.map((resolution, resolutionIndex) =>\n this.durations.parse(\n resolution,\n `telemetry.metrics[${index}].resolutions[${resolutionIndex}]`,\n ),\n ) ?? this.metricResolutions(targets, targetIds);\n this.validateMetricResolutions(resolutionsMs, targets, targetIds, index);\n const cardinality = Object.freeze(\n Object.fromEntries(\n Object.entries(metric.cardinality ?? {}).map(([field, rule]) => [\n field,\n Object.freeze({ ...rule }),\n ]),\n ),\n );\n const definition: MetricDefinition = {\n name: metric.name,\n version: metric.version ?? 1,\n selector: metric.selector,\n groupBy: Object.freeze([...(metric.groupBy ?? [])]),\n measurements: Object.freeze(\n metric.measurements.map((measurement) => this.resolveMeasurement(measurement)),\n ),\n cardinality,\n targetIds: Object.freeze([...targetIds]),\n resolutionsMs: Object.freeze(resolutionsMs),\n missingField: metric.missingField ?? 'record-failure',\n };\n const normalized = this.metricContract.normalize(definition);\n if (!normalized.ok) {\n throw new Error(`telemetry.metrics[${index}]: ${normalized.error}`);\n }\n this.validateNormalizedMetric(normalized.value, index);\n return normalized.value;\n }\n\n private validateNormalizedMetric(definition: MetricDefinition, index: number): void {\n const segments = definition.selector.split('.');\n const invalidSelector = segments.some(\n (segment) =>\n segment !== '*' && segment !== '**' && !/^[A-Za-z0-9_:-][A-Za-z0-9_:\\-]*$/.test(segment),\n );\n if (invalidSelector) {\n throw new Error(`telemetry.metrics[${index}] has an invalid dotted selector`);\n }\n const invalidGroupBy = definition.groupBy.find((field) => !this.isFieldPath(field));\n if (\n invalidGroupBy !== undefined ||\n new Set(definition.groupBy).size !== definition.groupBy.length\n ) {\n throw new Error(`telemetry.metrics[${index}] has invalid or duplicate groupBy fields`);\n }\n const extraCardinality = Object.keys(definition.cardinality).find(\n (field) => !definition.groupBy.includes(field),\n );\n if (extraCardinality !== undefined) {\n throw new Error(\n `telemetry.metrics[${index}] cardinality policy ${extraCardinality} is not a declared dimension`,\n );\n }\n const measurementKeys = definition.measurements.map((measurement) =>\n measurement.kind === 'count' ? 'count' : `field:${measurement.field}`,\n );\n const invalidField = definition.measurements.find(\n (measurement) => measurement.kind === 'field' && !this.isFieldPath(measurement.field),\n );\n if (invalidField !== undefined || new Set(measurementKeys).size !== measurementKeys.length) {\n throw new Error(`telemetry.metrics[${index}] has invalid or duplicate measurements`);\n }\n }\n\n private isFieldPath(value: string): boolean {\n return value.split('.').every((segment) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(segment));\n }\n\n private resolveMeasurement(\n measurement: SerializedMetricDefinition['measurements'][number],\n ): MetricMeasurement {\n if (measurement === 'count') {\n return Object.freeze({ kind: 'count' });\n }\n if (new Set(measurement.aggregate).size !== measurement.aggregate.length) {\n throw new Error(`Metric field ${measurement.field} has duplicate aggregates`);\n }\n return Object.freeze({\n kind: 'field',\n field: measurement.field,\n aggregates: Object.freeze([...measurement.aggregate]),\n });\n }\n\n private metricResolutions(\n targets: readonly SqliteTargetConfiguration[],\n targetIds: readonly string[],\n ): number[] {\n const selected = targets.filter((target) => targetIds.includes(target.targetId));\n const first = selected[0]?.retention.rollups.map((tier) => tier.resolutionMs) ?? [];\n return first\n .filter((resolution) =>\n selected.every((target) =>\n target.retention.rollups.some((tier) => tier.resolutionMs === resolution),\n ),\n )\n .sort((left, right) => left - right);\n }\n\n private validateMetricResolutions(\n resolutions: readonly number[],\n targets: readonly SqliteTargetConfiguration[],\n targetIds: readonly string[],\n metricIndex: number,\n ): void {\n for (const targetId of targetIds) {\n const target = targets.find((candidate) => candidate.targetId === targetId);\n const unavailable = resolutions.find(\n (resolution) => !target?.retention.rollups.some((tier) => tier.resolutionMs === resolution),\n );\n if (unavailable !== undefined) {\n throw new Error(\n `telemetry.metrics[${metricIndex}] resolution ${unavailable} is not configured for target ${targetId}`,\n );\n }\n }\n }\n\n private validateMetricIdentities(metrics: readonly MetricDefinition[]): void {\n const identities = metrics.map((metric) => `${metric.name}:${metric.version}`);\n if (new Set(identities).size !== identities.length) {\n throw new Error('Metric name/version identities must be unique');\n }\n }\n\n private errorMessage(cause: unknown): string {\n return cause instanceof Error ? cause.message : String(cause);\n }\n}\n","import type { MetricDefinition } from './types/metric.types.js';\nimport type { TelemetryResult } from './types/result.types.js';\n\nexport class MetricDefinitionContract {\n normalize(definition: MetricDefinition): TelemetryResult<MetricDefinition, string> {\n const parsedSelector = this.parseSelector(definition.selector);\n if (!parsedSelector.ok) {\n return parsedSelector;\n }\n\n const bracketGroupBy = parsedSelector.value.groupBy;\n const configuredGroupBy = definition.groupBy;\n const bothSpecifyDifferentGrouping = bracketGroupBy.length > 0\n && configuredGroupBy.length > 0\n && bracketGroupBy.join('.') !== configuredGroupBy.join('.');\n if (bothSpecifyDifferentGrouping) {\n return { ok: false, error: `Metric ${definition.name} has conflicting selector and groupBy declarations` };\n }\n const groupBy = configuredGroupBy.length > 0 ? configuredGroupBy : bracketGroupBy;\n\n const basicError = this.validateBasic(definition, parsedSelector.value.selector, groupBy);\n if (basicError !== null) {\n return { ok: false, error: basicError };\n }\n if (parsedSelector.value.wildcardUngrouped\n && definition.measurements.some((measurement) => measurement.kind !== 'count')) {\n return {\n ok: false,\n error: `Metric ${definition.name} uses [*] and may only declare count`,\n };\n }\n\n return {\n ok: true,\n value: Object.freeze({\n ...definition,\n selector: parsedSelector.value.selector,\n groupBy: Object.freeze([...groupBy]),\n resolutionsMs: Object.freeze([...definition.resolutionsMs].sort((left, right) => left - right)),\n measurements: Object.freeze([...definition.measurements]),\n targetIds: Object.freeze([...definition.targetIds]),\n cardinality: Object.freeze({ ...definition.cardinality }),\n }),\n };\n }\n\n matches(selector: string, label: string): boolean {\n const selectorSegments = selector.split('.');\n const labelSegments = label.split('.');\n return this.matchSegments(selectorSegments, labelSegments, 0, 0);\n }\n\n private parseSelector(selector: string): TelemetryResult<Readonly<{\n selector: string;\n groupBy: readonly string[];\n wildcardUngrouped: boolean;\n }>, string> {\n if (selector.startsWith('[')) {\n return { ok: false, error: 'A metric selector cannot omit its event label or glob' };\n }\n\n const bracketStart = selector.lastIndexOf('[');\n if (bracketStart < 0) {\n return { ok: true, value: { selector, groupBy: [], wildcardUngrouped: false } };\n }\n if (!selector.endsWith(']')) {\n return { ok: false, error: `Invalid metric selector ${selector}` };\n }\n\n const eventSelector = selector.slice(0, bracketStart);\n const bracket = selector.slice(bracketStart + 1, -1).trim();\n if (!eventSelector || !bracket) {\n return { ok: false, error: `Invalid metric selector ${selector}` };\n }\n // `[a, b]` groups by several bounded fields at once (e.g. routeKey and\n // visibility); each name is validated downstream like a `groupBy` entry.\n const groupBy = bracket === '*' ? [] : bracket.split(',').map((field) => field.trim());\n if (groupBy.some((field) => field.length === 0)) {\n return { ok: false, error: `Invalid metric selector ${selector}` };\n }\n return {\n ok: true,\n value: {\n selector: eventSelector,\n groupBy,\n wildcardUngrouped: bracket === '*',\n },\n };\n }\n\n private validateBasic(\n definition: MetricDefinition,\n selector: string,\n groupBy: readonly string[],\n ): string | null {\n if (!/^[A-Za-z0-9_*][A-Za-z0-9_.:*\\-]*$/.test(selector)) {\n return `Metric ${definition.name} has an invalid selector`;\n }\n if (!/^[A-Za-z][A-Za-z0-9_]*$/.test(definition.name)) {\n return `Metric name ${definition.name} is invalid`;\n }\n if (!Number.isInteger(definition.version) || definition.version <= 0) {\n return `Metric ${definition.name} must have a positive integer version`;\n }\n if (definition.measurements.length === 0) {\n return `Metric ${definition.name} must declare at least one measurement`;\n }\n const invalidResolution = definition.resolutionsMs.some(\n (resolution) => !Number.isInteger(resolution) || resolution <= 0,\n );\n const duplicateResolution = new Set(definition.resolutionsMs).size !== definition.resolutionsMs.length;\n if (invalidResolution || duplicateResolution || definition.resolutionsMs.length === 0) {\n return `Metric ${definition.name} has invalid or duplicate resolutions`;\n }\n const missingCardinality = groupBy.find((field) => definition.cardinality[field] === undefined);\n if (missingCardinality) {\n return `Metric ${definition.name} is missing cardinality policy for ${missingCardinality}`;\n }\n const invalidCardinality = Object.values(definition.cardinality).some(\n (rule) => !Number.isInteger(rule.maxValuesPerBucket) || rule.maxValuesPerBucket <= 0,\n );\n if (invalidCardinality) {\n return `Metric ${definition.name} has an invalid cardinality limit`;\n }\n return null;\n }\n\n private matchSegments(\n selector: readonly string[],\n label: readonly string[],\n selectorIndex: number,\n labelIndex: number,\n ): boolean {\n if (selectorIndex === selector.length) {\n return labelIndex === label.length;\n }\n const segment = selector[selectorIndex];\n if (segment === '**') {\n if (selectorIndex === selector.length - 1) {\n return true;\n }\n for (let next = labelIndex; next <= label.length; next += 1) {\n if (this.matchSegments(selector, label, selectorIndex + 1, next)) {\n return true;\n }\n }\n return false;\n }\n if (labelIndex >= label.length) {\n return false;\n }\n const segmentMatches = segment === '*' || segment === label[labelIndex];\n return segmentMatches\n && this.matchSegments(selector, label, selectorIndex + 1, labelIndex + 1);\n }\n}\n","const UTF8_ENCODER = new TextEncoder();\n\n/**\n * Canonical key order is UTF-8 byte order. This must stay byte-identical to\n * the native Rust collector, whose serde_json BTreeMap serialization sorts\n * object keys the same way; locale-aware comparisons (localeCompare) depend\n * on the ICU build and diverge from the Rust side, which invalidates every\n * cross-language checksum.\n */\nexport function compareCanonicalKeys(left: string, right: string): number {\n if (left === right) return 0;\n // Code-unit comparison equals UTF-8 byte order for ASCII-only keys.\n // eslint-disable-next-line no-control-regex\n if (/^[\\x00-\\x7f]*$/.test(left) && /^[\\x00-\\x7f]*$/.test(right)) {\n return left < right ? -1 : 1;\n }\n const leftBytes = UTF8_ENCODER.encode(left);\n const rightBytes = UTF8_ENCODER.encode(right);\n const length = Math.min(leftBytes.length, rightBytes.length);\n for (let index = 0; index < length; index += 1) {\n const difference = (leftBytes[index] ?? 0) - (rightBytes[index] ?? 0);\n if (difference !== 0) return difference;\n }\n return leftBytes.length - rightBytes.length;\n}\n\nexport function canonicalJson(value: unknown): string {\n if (value === null || typeof value === 'string' || typeof value === 'boolean') {\n return JSON.stringify(value);\n }\n if (typeof value === 'number') {\n if (!Number.isFinite(value)) {\n throw new Error('Canonical telemetry JSON cannot encode a non-finite number');\n }\n return JSON.stringify(value);\n }\n\n if (Array.isArray(value)) {\n const items = value.map((item) => canonicalJson(item));\n return `[${items.join(',')}]`;\n }\n\n if (typeof value !== 'object') {\n throw new Error(`Canonical telemetry JSON cannot encode ${typeof value}`);\n }\n\n const entries = Object.entries(value).sort(([left], [right]) => compareCanonicalKeys(left, right));\n const properties = entries.map(([key, item]) => `${JSON.stringify(key)}:${canonicalJson(item)}`);\n return `{${properties.join(',')}}`;\n}\n\nexport function telemetryUtf8Length(value: string): number {\n return new TextEncoder().encode(value).byteLength;\n}\n\nexport function telemetryChecksum(value: unknown): string {\n const bytes = new TextEncoder().encode(canonicalJson(value));\n let hash = 0xcbf29ce484222325n;\n const prime = 0x100000001b3n;\n\n for (const byte of bytes) {\n hash ^= BigInt(byte);\n hash = BigInt.asUintN(64, hash * prime);\n }\n\n return hash.toString(16).padStart(16, '0');\n}\n","import type { SqliteTableOverrides } from '../../core/types/configuration.types.js';\n\nexport const SQLITE_LOGICAL_TABLE_NAMES = [\n 'rawEvents',\n 'batchAcknowledgements',\n 'ingestWatermarks',\n 'metricDefinitions',\n 'metricSamples',\n 'metricRollups',\n 'rollupCompletions',\n 'extractionFailures',\n 'maintenanceRuns',\n 'readerLeases',\n 'committedDropCounters',\n 'migrationHistory',\n] as const satisfies readonly (keyof SqliteTableOverrides)[];\n\nexport const SQLITE_DEFAULT_TABLE_NAMES: Readonly<Record<(typeof SQLITE_LOGICAL_TABLE_NAMES)[number], string>> =\n Object.freeze({\n rawEvents: 'raw_events',\n batchAcknowledgements: 'batch_acknowledgements',\n ingestWatermarks: 'ingest_watermarks',\n metricDefinitions: 'metric_definitions',\n metricSamples: 'metric_samples',\n metricRollups: 'metric_rollups',\n rollupCompletions: 'rollup_completions',\n extractionFailures: 'extraction_failures',\n maintenanceRuns: 'maintenance_runs',\n readerLeases: 'reader_leases',\n committedDropCounters: 'committed_drop_counters',\n migrationHistory: 'migration_history',\n });\n\nexport const SQLITE_SCHEMA_MANIFEST_TABLE = 'telemetry_schema_manifest';\n","import type { SqliteSchemaConfiguration } from '../core/types/configuration.types.js';\nimport type { TelemetryResult } from '../core/types/result.types.js';\nimport { telemetryChecksum } from '../core/helper/canonical_json.js';\nimport {\n SQLITE_DEFAULT_TABLE_NAMES,\n SQLITE_LOGICAL_TABLE_NAMES,\n SQLITE_SCHEMA_MANIFEST_TABLE,\n} from './helper/sqlite_table_names.js';\nimport type {\n TelemetryLogicalTableName,\n TelemetryPhysicalTableMapping,\n} from './types/telemetry_table_map.types.js';\n\nexport class TelemetryTableMap {\n private readonly tokenMap: Readonly<Record<string, string>>;\n\n private constructor(\n private readonly mapping: TelemetryPhysicalTableMapping,\n readonly checksum: string,\n ) {\n this.tokenMap = Object.freeze({\n ...mapping,\n rawEventsOccurredIndex: this.indexName(mapping.rawEvents, 'occurred'),\n rawEventsConversationIndex: this.indexName(mapping.rawEvents, 'conversation'),\n rawEventsLabelIndex: this.indexName(mapping.rawEvents, 'label'),\n rawEventsLevelIndex: this.indexName(mapping.rawEvents, 'level'),\n metricSamplesTimeIndex: this.indexName(mapping.metricSamples, 'time'),\n metricSamplesEventIndex: this.indexName(mapping.metricSamples, 'event'),\n metricRollupsTimeIndex: this.indexName(mapping.metricRollups, 'time'),\n });\n }\n\n static create(configuration: SqliteSchemaConfiguration): TelemetryResult<TelemetryTableMap, string> {\n const prefixError = TelemetryTableMap.validateOptionalPrefix(configuration.tablePrefix);\n if (prefixError !== null) {\n return { ok: false, error: prefixError };\n }\n\n const entries = SQLITE_LOGICAL_TABLE_NAMES.map((logicalName) => {\n const override = configuration.tables[logicalName];\n const defaultName = SQLITE_DEFAULT_TABLE_NAMES[logicalName];\n const physicalName = override ?? (configuration.tablePrefix === null\n ? defaultName\n : `${configuration.tablePrefix}${defaultName}`);\n return [logicalName, physicalName] as const;\n });\n\n for (const [logicalName, physicalName] of entries) {\n const identifierError = TelemetryTableMap.validateIdentifier(physicalName);\n if (identifierError !== null) {\n return { ok: false, error: `${logicalName}: ${identifierError}` };\n }\n if (physicalName.toLowerCase() === SQLITE_SCHEMA_MANIFEST_TABLE) {\n return { ok: false, error: `${logicalName} cannot use the fixed schema manifest name` };\n }\n }\n\n const foldedNames = entries.map(([, physicalName]) => physicalName.toLowerCase());\n if (new Set(foldedNames).size !== foldedNames.length) {\n return { ok: false, error: 'Resolved telemetry table names must be unique after case folding' };\n }\n\n const mapping = Object.freeze(Object.fromEntries(entries)) as TelemetryPhysicalTableMapping;\n const checksum = telemetryChecksum(mapping);\n return { ok: true, value: new TelemetryTableMap(mapping, checksum) };\n }\n\n physical(logicalName: TelemetryLogicalTableName): string {\n return this.mapping[logicalName];\n }\n\n quoted(logicalName: TelemetryLogicalTableName): string {\n return this.quote(this.mapping[logicalName]);\n }\n\n manifestMapping(): TelemetryPhysicalTableMapping {\n return this.mapping;\n }\n\n substitute(sql: string): TelemetryResult<string, string> {\n const unknownTokens: string[] = [];\n const substituted = sql.replace(/\\{\\{([A-Za-z][A-Za-z0-9]*)\\}\\}/g, (_match, token: string) => {\n const identifier = this.tokenMap[token];\n if (identifier === undefined) {\n unknownTokens.push(token);\n return `{{${token}}}`;\n }\n return this.quote(identifier);\n });\n if (unknownTokens.length > 0 || substituted.includes('{{')) {\n return {\n ok: false,\n error: `Unknown telemetry migration identifier token(s): ${unknownTokens.join(', ') || 'malformed token'}`,\n };\n }\n return { ok: true, value: substituted };\n }\n\n private quote(identifier: string): string {\n return `\"${identifier.replaceAll('\"', '\"\"')}\"`;\n }\n\n private indexName(tableName: string, purpose: string): string {\n const raw = `${tableName}_${purpose}_idx`;\n if (raw.length <= 63) {\n return raw;\n }\n const suffix = telemetryChecksum(raw).slice(0, 8);\n return `${raw.slice(0, 54)}_${suffix}`;\n }\n\n private static validateOptionalPrefix(prefix: string | null): string | null {\n if (prefix === null) {\n return null;\n }\n return this.validateIdentifier(prefix);\n }\n\n private static validateIdentifier(identifier: string): string | null {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(identifier)) {\n return `Invalid SQLite identifier ${identifier}`;\n }\n if (identifier.length > 63) {\n return `SQLite identifier ${identifier} exceeds 63 characters`;\n }\n if (identifier.toLowerCase().startsWith('sqlite_')) {\n return `SQLite identifier ${identifier} uses the reserved sqlite_ prefix`;\n }\n return null;\n }\n}\n","export class TelemetryDurationParser {\n private static readonly MULTIPLIERS = Object.freeze({\n ms: 1,\n s: 1_000,\n m: 60_000,\n h: 60 * 60_000,\n d: 24 * 60 * 60_000,\n w: 7 * 24 * 60 * 60_000,\n y: 365 * 24 * 60 * 60_000,\n });\n\n parse(value: string, field: string, allowZero = false): number {\n const match = /^(0|[1-9][0-9]*)(ms|s|m|h|d|w|y)$/.exec(value);\n if (!match) {\n throw new Error(`${field} must be an integer duration using ms, s, m, h, d, w, or y`);\n }\n const amount = Number(match[1]);\n const unit = match[2] as keyof typeof TelemetryDurationParser.MULTIPLIERS;\n const milliseconds = amount * TelemetryDurationParser.MULTIPLIERS[unit];\n if (!Number.isSafeInteger(milliseconds) || (!allowZero && milliseconds <= 0)) {\n throw new Error(`${field} is outside the supported duration range`);\n }\n return milliseconds;\n }\n}\n","import { z } from 'zod';\n\nconst DurationSchema = z.string().min(1);\nconst NonEmptyStringSchema = z.string().trim().min(1);\nconst StableIdSchema = z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/);\n\nconst CardinalityRuleSchema = z\n .object({\n maxValuesPerBucket: z.number().int().positive(),\n overflow: z.enum(['other', 'drop', 'reject']),\n })\n .strict();\n\nconst MetricMeasurementSchema = z.union([\n z.literal('count'),\n z\n .object({\n field: z.string().min(1),\n aggregate: z.array(z.enum(['sum', 'min', 'max', 'last'])).min(1),\n })\n .strict(),\n]);\n\nconst MetricDefinitionSchema = z\n .object({\n name: z.string().min(1),\n version: z.number().int().positive().optional(),\n selector: z.string().min(1),\n groupBy: z.array(z.string().min(1)).optional(),\n measurements: z.array(MetricMeasurementSchema).min(1),\n cardinality: z.record(z.string(), CardinalityRuleSchema).optional(),\n targets: z.array(StableIdSchema).min(1).optional(),\n resolutions: z.array(DurationSchema).min(1).optional(),\n missingField: z.enum(['skip', 'record-failure']).optional(),\n })\n .strict();\n\nconst SqliteTablesSchema = z\n .object({\n rawEvents: NonEmptyStringSchema.optional(),\n batchAcknowledgements: NonEmptyStringSchema.optional(),\n ingestWatermarks: NonEmptyStringSchema.optional(),\n metricDefinitions: NonEmptyStringSchema.optional(),\n metricSamples: NonEmptyStringSchema.optional(),\n metricRollups: NonEmptyStringSchema.optional(),\n rollupCompletions: NonEmptyStringSchema.optional(),\n extractionFailures: NonEmptyStringSchema.optional(),\n maintenanceRuns: NonEmptyStringSchema.optional(),\n readerLeases: NonEmptyStringSchema.optional(),\n committedDropCounters: NonEmptyStringSchema.optional(),\n migrationHistory: NonEmptyStringSchema.optional(),\n })\n .strict();\n\nconst SqliteTargetSchema = z\n .object({\n id: StableIdSchema,\n transport: z.literal('sqlite'),\n delivery: z.enum(['required', 'best-effort']),\n path: z.string().min(1),\n schema: z\n .object({\n tablePrefix: NonEmptyStringSchema.nullable().optional(),\n tables: SqliteTablesSchema.optional(),\n })\n .strict()\n .optional(),\n retention: z\n .object({\n raw: DurationSchema,\n lateArrival: DurationSchema.optional(),\n samples: DurationSchema.optional(),\n levels: z.record(z.string().min(1), DurationSchema).optional(),\n rollups: z\n .array(\n z\n .object({\n resolution: DurationSchema,\n retain: DurationSchema,\n })\n .strict(),\n )\n .min(1),\n })\n .strict(),\n maintenance: z\n .object({\n interval: DurationSchema,\n maxWorkMs: z.number().int().positive(),\n reclaim: z.literal('incremental'),\n maxReclaimPages: z.number().int().positive().optional(),\n })\n .strict(),\n leaseExpiry: DurationSchema.optional(),\n query: z\n .object({\n maxRange: DurationSchema.optional(),\n maxRows: z.number().int().positive().optional(),\n maxBuckets: z.number().int().positive().optional(),\n maxResponseBytes: z.number().int().positive().optional(),\n })\n .strict()\n .optional(),\n })\n .strict();\n\nconst StorageSchema = z\n .object({\n defaultTarget: StableIdSchema.nullable().optional(),\n targets: z.array(SqliteTargetSchema).min(1),\n })\n .strict();\n\nconst TraceSchema = z\n .object({\n ingestionTransport: z.string().min(1).optional(),\n storage: StorageSchema.optional(),\n })\n .strict();\n\nexport const TelemetryConfigurationDocumentSchema = z\n .object({\n telemetry: z\n .object({\n version: z.literal(1).optional(),\n role: z.enum(['producer', 'collector', 'combined']),\n trace: TraceSchema,\n metrics: z.array(MetricDefinitionSchema).optional(),\n logs: z\n .object({\n transport: z.literal('console'),\n })\n .strict()\n .optional(),\n })\n .strict(),\n })\n .strict();\n\nexport type TelemetryConfigurationDocument = z.infer<typeof TelemetryConfigurationDocumentSchema>;\n\nexport type SerializedMetricDefinition = z.infer<typeof MetricDefinitionSchema>;\nexport type SerializedSqliteTarget = z.infer<typeof SqliteTargetSchema>;\n","import type { MetricDefinition } from '../core/types/metric.types.js';\nimport type {\n TraceAggregate,\n TraceMeasurement,\n TraceProjection,\n} from './trace_projection.types';\n\n/** Spec 03 §9.1 default ceiling for combined dimension keys per metric version. */\nconst MAX_COMBINED_DIMENSION_KEYS = 10_000;\n\n/**\n * Migration of resolved telemetry.config.yml metric definitions into\n * downstream trace projection definitions (spec 04 §18).\n *\n * The configuration parser has already split selectors into an event glob and\n * groupBy dimensions and resolved per-metric bucket resolutions, so this is a\n * shape mapping. Names and versions carry over so historical intent is\n * preserved; the projection bucket store is new, so no numeric continuity\n * with the legacy sample/rollup tables is implied.\n */\nexport function metricDefinitionToTraceProjection(\n metric: MetricDefinition,\n options: { fallbackResolutions?: readonly number[] } = {},\n): TraceProjection {\n const measurements: TraceMeasurement[] = [];\n for (const measurement of metric.measurements) {\n if (measurement.kind === 'count') {\n // Bucket count is intrinsic to every projection; no field needed.\n continue;\n }\n // Legacy aggregates (sum/min/max/last) are a subset of projection\n // aggregates; count/avg are derivable from bucket count + sum.\n measurements.push({\n field: measurement.field,\n aggregates: measurement.aggregates as readonly TraceAggregate[],\n });\n }\n\n const resolutions = metric.resolutionsMs.length > 0\n ? metric.resolutionsMs\n : options.fallbackResolutions ?? [60_000, 900_000, 3_600_000];\n\n const dimensionPolicies = Object.entries(metric.cardinality);\n const cardinality = dimensionPolicies.length > 0\n ? {\n // Legacy policy is per-dimension per-bucket; the projection policy is\n // per-projection distinct dimension keys. The combined budget is the\n // product of the per-field limits (bounded by the spec's default\n // ceiling): `[routeKey(100), visibility(2)]` allows 200 pairs, not 2.\n // Taking the minimum, as this did until 2026-09-03, folded the third\n // route/visibility pair of frontend_performance_health@2 into `other`.\n maxDimensionKeys: Math.min(\n MAX_COMBINED_DIMENSION_KEYS,\n dimensionPolicies.reduce((product, [, policy]) => product * policy.maxValuesPerBucket, 1),\n ),\n overflow: dimensionPolicies.some(([, policy]) => policy.overflow === 'other')\n ? ('other' as const)\n : ('reject' as const),\n }\n : undefined;\n\n return {\n name: metric.name,\n version: metric.version,\n event: metric.selector,\n ...(metric.groupBy.length > 0 ? { groupBy: metric.groupBy } : {}),\n measurements,\n resolutions,\n missingField: metric.missingField,\n ...(cardinality !== undefined ? { cardinality } : {}),\n };\n}\n\nexport function metricDefinitionsToTraceProjections(\n metrics: readonly MetricDefinition[],\n options: { fallbackResolutions?: readonly number[] } = {},\n): readonly TraceProjection[] {\n return metrics.map((metric) => metricDefinitionToTraceProjection(metric, options));\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,68 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
type MetricAggregate = (typeof METRIC_AGGREGATES)[number];
|
|
5
|
-
declare const METRIC_OVERFLOW_POLICIES: readonly ["other", "drop", "reject"];
|
|
6
|
-
type MetricOverflowPolicy = (typeof METRIC_OVERFLOW_POLICIES)[number];
|
|
7
|
-
type MetricCountMeasurement = Readonly<{
|
|
8
|
-
kind: 'count';
|
|
9
|
-
}>;
|
|
10
|
-
type MetricFieldMeasurement = Readonly<{
|
|
11
|
-
kind: 'field';
|
|
12
|
-
field: string;
|
|
13
|
-
aggregates: readonly MetricAggregate[];
|
|
14
|
-
}>;
|
|
15
|
-
type MetricMeasurement = MetricCountMeasurement | MetricFieldMeasurement;
|
|
16
|
-
type MetricCardinalityRule = Readonly<{
|
|
17
|
-
maxValuesPerBucket: number;
|
|
18
|
-
overflow: MetricOverflowPolicy;
|
|
19
|
-
}>;
|
|
20
|
-
type MetricDefinition = Readonly<{
|
|
21
|
-
name: string;
|
|
22
|
-
version: number;
|
|
23
|
-
selector: string;
|
|
24
|
-
groupBy: readonly string[];
|
|
25
|
-
measurements: readonly MetricMeasurement[];
|
|
26
|
-
cardinality: Readonly<Record<string, MetricCardinalityRule>>;
|
|
27
|
-
targetIds: readonly string[];
|
|
28
|
-
resolutionsMs: readonly number[];
|
|
29
|
-
missingField: 'skip' | 'record-failure';
|
|
30
|
-
}>;
|
|
31
|
-
type ExtractedMetricSample = Readonly<{
|
|
32
|
-
metricName: string;
|
|
33
|
-
definitionVersion: number;
|
|
34
|
-
occurredAtMs: number;
|
|
35
|
-
producerId: string;
|
|
36
|
-
sequence: number;
|
|
37
|
-
dimensions: TelemetryJsonObject;
|
|
38
|
-
dimensionKey: string;
|
|
39
|
-
values: Readonly<Record<string, number>>;
|
|
40
|
-
targetIds: readonly string[];
|
|
41
|
-
}>;
|
|
42
|
-
type MetricExtractionFailure = Readonly<{
|
|
43
|
-
metricName: string;
|
|
44
|
-
definitionVersion: number;
|
|
45
|
-
producerId: string;
|
|
46
|
-
sequence: number;
|
|
47
|
-
reason: string;
|
|
48
|
-
}>;
|
|
49
|
-
type MetricExtraction = Readonly<{
|
|
50
|
-
samples: readonly ExtractedMetricSample[];
|
|
51
|
-
failures: readonly MetricExtractionFailure[];
|
|
52
|
-
}>;
|
|
53
|
-
type MetricRollupValues = Readonly<{
|
|
54
|
-
count: number;
|
|
55
|
-
fields: Readonly<Record<string, Readonly<{
|
|
56
|
-
count: number;
|
|
57
|
-
sum: number;
|
|
58
|
-
min: number;
|
|
59
|
-
max: number;
|
|
60
|
-
last: number;
|
|
61
|
-
lastOccurredAtMs: number;
|
|
62
|
-
lastProducerId: string;
|
|
63
|
-
lastSequence: number;
|
|
64
|
-
}>>>;
|
|
65
|
-
}>;
|
|
1
|
+
import { M as MetricDefinition } from './metric.types-Dg4eZq6u.cjs';
|
|
2
|
+
import { T as TelemetryEnvelope } from './envelope.types-DyrlRG49.cjs';
|
|
3
|
+
import { a as TelemetryJsonValue, T as TelemetryJsonObject } from './json.types-BqS77fcN.cjs';
|
|
66
4
|
|
|
67
5
|
declare const TELEMETRY_ROLES: readonly ["producer", "collector", "combined"];
|
|
68
6
|
type TelemetryRole = (typeof TELEMETRY_ROLES)[number];
|
|
@@ -190,4 +128,4 @@ type TelemetryQueryError = Readonly<{
|
|
|
190
128
|
message: string;
|
|
191
129
|
}>;
|
|
192
130
|
|
|
193
|
-
export type {
|
|
131
|
+
export type { MetricQuery as M, ResolvedTelemetryConfiguration as R, SqliteTargetConfiguration as S, TimelineQuery as T, TimelineQueryResponse as a, TelemetryQueryError as b, MetricQueryResponse as c, MetricBucket as d, MetricQueryGap as e, MetricQuerySegment as f, SqliteMaintenanceConfiguration as g, SqliteRetentionConfiguration as h, SqliteSchemaConfiguration as i, SqliteTableOverrides as j, TelemetryRole as k, TimelineGap as l };
|
|
@@ -1,68 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
type MetricAggregate = (typeof METRIC_AGGREGATES)[number];
|
|
5
|
-
declare const METRIC_OVERFLOW_POLICIES: readonly ["other", "drop", "reject"];
|
|
6
|
-
type MetricOverflowPolicy = (typeof METRIC_OVERFLOW_POLICIES)[number];
|
|
7
|
-
type MetricCountMeasurement = Readonly<{
|
|
8
|
-
kind: 'count';
|
|
9
|
-
}>;
|
|
10
|
-
type MetricFieldMeasurement = Readonly<{
|
|
11
|
-
kind: 'field';
|
|
12
|
-
field: string;
|
|
13
|
-
aggregates: readonly MetricAggregate[];
|
|
14
|
-
}>;
|
|
15
|
-
type MetricMeasurement = MetricCountMeasurement | MetricFieldMeasurement;
|
|
16
|
-
type MetricCardinalityRule = Readonly<{
|
|
17
|
-
maxValuesPerBucket: number;
|
|
18
|
-
overflow: MetricOverflowPolicy;
|
|
19
|
-
}>;
|
|
20
|
-
type MetricDefinition = Readonly<{
|
|
21
|
-
name: string;
|
|
22
|
-
version: number;
|
|
23
|
-
selector: string;
|
|
24
|
-
groupBy: readonly string[];
|
|
25
|
-
measurements: readonly MetricMeasurement[];
|
|
26
|
-
cardinality: Readonly<Record<string, MetricCardinalityRule>>;
|
|
27
|
-
targetIds: readonly string[];
|
|
28
|
-
resolutionsMs: readonly number[];
|
|
29
|
-
missingField: 'skip' | 'record-failure';
|
|
30
|
-
}>;
|
|
31
|
-
type ExtractedMetricSample = Readonly<{
|
|
32
|
-
metricName: string;
|
|
33
|
-
definitionVersion: number;
|
|
34
|
-
occurredAtMs: number;
|
|
35
|
-
producerId: string;
|
|
36
|
-
sequence: number;
|
|
37
|
-
dimensions: TelemetryJsonObject;
|
|
38
|
-
dimensionKey: string;
|
|
39
|
-
values: Readonly<Record<string, number>>;
|
|
40
|
-
targetIds: readonly string[];
|
|
41
|
-
}>;
|
|
42
|
-
type MetricExtractionFailure = Readonly<{
|
|
43
|
-
metricName: string;
|
|
44
|
-
definitionVersion: number;
|
|
45
|
-
producerId: string;
|
|
46
|
-
sequence: number;
|
|
47
|
-
reason: string;
|
|
48
|
-
}>;
|
|
49
|
-
type MetricExtraction = Readonly<{
|
|
50
|
-
samples: readonly ExtractedMetricSample[];
|
|
51
|
-
failures: readonly MetricExtractionFailure[];
|
|
52
|
-
}>;
|
|
53
|
-
type MetricRollupValues = Readonly<{
|
|
54
|
-
count: number;
|
|
55
|
-
fields: Readonly<Record<string, Readonly<{
|
|
56
|
-
count: number;
|
|
57
|
-
sum: number;
|
|
58
|
-
min: number;
|
|
59
|
-
max: number;
|
|
60
|
-
last: number;
|
|
61
|
-
lastOccurredAtMs: number;
|
|
62
|
-
lastProducerId: string;
|
|
63
|
-
lastSequence: number;
|
|
64
|
-
}>>>;
|
|
65
|
-
}>;
|
|
1
|
+
import { M as MetricDefinition } from './metric.types-D8aOAnUm.js';
|
|
2
|
+
import { T as TelemetryEnvelope } from './envelope.types-DIvZD3xH.js';
|
|
3
|
+
import { a as TelemetryJsonValue, T as TelemetryJsonObject } from './json.types-BqS77fcN.js';
|
|
66
4
|
|
|
67
5
|
declare const TELEMETRY_ROLES: readonly ["producer", "collector", "combined"];
|
|
68
6
|
type TelemetryRole = (typeof TELEMETRY_ROLES)[number];
|
|
@@ -190,4 +128,4 @@ type TelemetryQueryError = Readonly<{
|
|
|
190
128
|
message: string;
|
|
191
129
|
}>;
|
|
192
130
|
|
|
193
|
-
export type {
|
|
131
|
+
export type { MetricQuery as M, ResolvedTelemetryConfiguration as R, SqliteTargetConfiguration as S, TimelineQuery as T, TimelineQueryResponse as a, TelemetryQueryError as b, MetricQueryResponse as c, MetricBucket as d, MetricQueryGap as e, MetricQuerySegment as f, SqliteMaintenanceConfiguration as g, SqliteRetentionConfiguration as h, SqliteSchemaConfiguration as i, SqliteTableOverrides as j, TelemetryRole as k, TimelineGap as l };
|
package/dist/sqlite/index.cjs
CHANGED
|
@@ -398,11 +398,15 @@ var MetricDefinitionContract = class {
|
|
|
398
398
|
if (!eventSelector || !bracket) {
|
|
399
399
|
return { ok: false, error: `Invalid metric selector ${selector}` };
|
|
400
400
|
}
|
|
401
|
+
const groupBy = bracket === "*" ? [] : bracket.split(",").map((field) => field.trim());
|
|
402
|
+
if (groupBy.some((field) => field.length === 0)) {
|
|
403
|
+
return { ok: false, error: `Invalid metric selector ${selector}` };
|
|
404
|
+
}
|
|
401
405
|
return {
|
|
402
406
|
ok: true,
|
|
403
407
|
value: {
|
|
404
408
|
selector: eventSelector,
|
|
405
|
-
groupBy
|
|
409
|
+
groupBy,
|
|
406
410
|
wildcardUngrouped: bracket === "*"
|
|
407
411
|
}
|
|
408
412
|
};
|