@noego/telemetry 0.0.3 → 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.
Files changed (93) hide show
  1. package/README.md +6 -0
  2. package/dist/browser/index.cjs +21 -0
  3. package/dist/browser/index.cjs.map +1 -1
  4. package/dist/browser/index.d.cts +6 -5
  5. package/dist/browser/index.d.ts +6 -5
  6. package/dist/browser/index.js +21 -0
  7. package/dist/browser/index.js.map +1 -1
  8. package/dist/{browser_telemetry_client-BzBPQm4m.d.cts → browser_telemetry_client-ClZl3awO.d.cts} +2 -2
  9. package/dist/{browser_telemetry_client-Ch_VzwEa.d.ts → browser_telemetry_client-t4dPp8Ku.d.ts} +2 -2
  10. package/dist/cli/telemetry_bin.cjs +393 -35
  11. package/dist/cli/telemetry_bin.cjs.map +1 -1
  12. package/dist/cli/telemetry_bin.js +378 -20
  13. package/dist/cli/telemetry_bin.js.map +1 -1
  14. package/dist/cli/telemetry_cli.cjs +393 -35
  15. package/dist/cli/telemetry_cli.cjs.map +1 -1
  16. package/dist/cli/telemetry_cli.d.cts +35 -5
  17. package/dist/cli/telemetry_cli.d.ts +35 -5
  18. package/dist/cli/telemetry_cli.js +378 -20
  19. package/dist/cli/telemetry_cli.js.map +1 -1
  20. package/dist/{client_defaults-B5tC-TgG.d.ts → client_defaults-CZ8PysZX.d.ts} +2 -2
  21. package/dist/{client_defaults-C9LnSX4j.d.cts → client_defaults-lDbWYWWK.d.cts} +2 -2
  22. package/dist/core/index.cjs +26 -1
  23. package/dist/core/index.cjs.map +1 -1
  24. package/dist/core/index.d.cts +15 -12
  25. package/dist/core/index.d.ts +15 -12
  26. package/dist/core/index.js +26 -1
  27. package/dist/core/index.js.map +1 -1
  28. package/dist/electron/index.cjs +21 -0
  29. package/dist/electron/index.cjs.map +1 -1
  30. package/dist/electron/index.d.cts +5 -4
  31. package/dist/electron/index.d.ts +5 -4
  32. package/dist/electron/index.js +21 -0
  33. package/dist/electron/index.js.map +1 -1
  34. package/dist/{envelope.types-rOLpWXRC.d.cts → envelope.types-DIvZD3xH.d.ts} +2 -6
  35. package/dist/{envelope.types-rOLpWXRC.d.ts → envelope.types-DyrlRG49.d.cts} +2 -6
  36. package/dist/{in_memory_batch_transport-DKW9EZnU.d.cts → in_memory_batch_transport-3T6gElXP.d.cts} +1 -1
  37. package/dist/{in_memory_batch_transport-oOwNxXnA.d.ts → in_memory_batch_transport-DpQU6JqM.d.ts} +1 -1
  38. package/dist/index.cjs +26 -1
  39. package/dist/index.cjs.map +1 -1
  40. package/dist/index.d.cts +14 -12
  41. package/dist/index.d.ts +14 -12
  42. package/dist/index.js +26 -1
  43. package/dist/index.js.map +1 -1
  44. package/dist/json.types-BqS77fcN.d.cts +7 -0
  45. package/dist/json.types-BqS77fcN.d.ts +7 -0
  46. package/dist/{maintenance_coordinator.types-C4ULi4A4.d.cts → maintenance_coordinator.types-Crhx9i9k.d.cts} +3 -3
  47. package/dist/{maintenance_coordinator.types-ikUrRXmO.d.ts → maintenance_coordinator.types-DprmgpVn.d.ts} +3 -3
  48. package/dist/metric.types-D8aOAnUm.d.ts +67 -0
  49. package/dist/metric.types-Dg4eZq6u.d.cts +67 -0
  50. package/dist/{metric_definition_contract-BYtnODhu.d.ts → metric_definition_contract-C6MERhJs.d.ts} +1 -1
  51. package/dist/{metric_definition_contract-DfhhmTZ1.d.cts → metric_definition_contract-DoAk7NOw.d.cts} +1 -1
  52. package/dist/node/index.cjs +38 -2
  53. package/dist/node/index.cjs.map +1 -1
  54. package/dist/node/index.d.cts +62 -10
  55. package/dist/node/index.d.ts +62 -10
  56. package/dist/node/index.js +37 -2
  57. package/dist/node/index.js.map +1 -1
  58. package/dist/node/producer/index.cjs +21 -0
  59. package/dist/node/producer/index.cjs.map +1 -1
  60. package/dist/node/producer/index.d.cts +5 -4
  61. package/dist/node/producer/index.d.ts +5 -4
  62. package/dist/node/producer/index.js +21 -0
  63. package/dist/node/producer/index.js.map +1 -1
  64. package/dist/projector/index.cjs +1370 -0
  65. package/dist/projector/index.cjs.map +1 -0
  66. package/dist/projector/index.d.cts +246 -0
  67. package/dist/projector/index.d.ts +246 -0
  68. package/dist/projector/index.js +1328 -0
  69. package/dist/projector/index.js.map +1 -0
  70. package/dist/{query.types-DU5v7vM0.d.ts → query.types-CRqAsGTX.d.cts} +4 -66
  71. package/dist/{query.types-DuYWbFFe.d.cts → query.types-DnOMYXpC.d.ts} +4 -66
  72. package/dist/sqlite/index.cjs +5 -1
  73. package/dist/sqlite/index.cjs.map +1 -1
  74. package/dist/sqlite/index.d.cts +7 -5
  75. package/dist/sqlite/index.d.ts +7 -5
  76. package/dist/sqlite/index.js +5 -1
  77. package/dist/sqlite/index.js.map +1 -1
  78. package/dist/{storage.types-k7oElEB3.d.ts → storage.types-BKWoIOHp.d.ts} +3 -2
  79. package/dist/{storage.types-Bji_pWqr.d.cts → storage.types-DHbAm3j_.d.cts} +3 -2
  80. package/dist/{telemetry_client-BXw8WH_F.d.ts → telemetry_client-Bg5tbj5E.d.cts} +12 -3
  81. package/dist/{telemetry_client-CYaPYfOl.d.cts → telemetry_client-DWKgufmc.d.ts} +12 -3
  82. package/dist/{telemetry_configuration_parser-BZ8Nvnle.d.ts → telemetry_configuration_parser-6BR3_dD_.d.ts} +2 -2
  83. package/dist/{telemetry_configuration_parser-CgSN7R6A.d.cts → telemetry_configuration_parser-ybeweUPE.d.cts} +2 -2
  84. package/dist/testing/index.d.cts +7 -5
  85. package/dist/testing/index.d.ts +7 -5
  86. package/dist/trace-adapter/index.d.cts +4 -3
  87. package/dist/trace-adapter/index.d.ts +4 -3
  88. package/dist/{transport.types-BAl_TRtU.d.cts → transport.types-C2dP-eed.d.cts} +1 -1
  89. package/dist/{transport.types-DDnZoKWi.d.ts → transport.types-SA8KpLiK.d.ts} +1 -1
  90. package/migrations/1786100000000_animation_artifacts.down.sql +5 -0
  91. package/migrations/1786100000000_animation_artifacts.up.sql +41 -0
  92. package/native/noego_telemetry_native.node +0 -0
  93. package/package.json +11 -4
@@ -0,0 +1,246 @@
1
+ import { Database } from 'better-sqlite3';
2
+ import { TraceSource, TraceSourceDescription } from '@noego/trace/sqlite';
3
+ import { M as MetricDefinition } from '../metric.types-D8aOAnUm.js';
4
+ import '../json.types-BqS77fcN.js';
5
+
6
+ /**
7
+ * Declarative trace projection definitions (spec 04 §6).
8
+ *
9
+ * A projection describes how raw trace events become historical time-series
10
+ * observations. Definitions are immutable by (name, version) once historical
11
+ * data exists: changing meaning requires a version bump.
12
+ */
13
+ type TraceAggregate = 'count' | 'sum' | 'min' | 'max' | 'avg' | 'last';
14
+ type TraceMeasurement = {
15
+ /** Numeric field read from the trace event's context. */
16
+ field: string;
17
+ aggregates: readonly TraceAggregate[];
18
+ };
19
+ type TraceCardinalityPolicy = {
20
+ /** Bound on distinct dimension-value combinations per projection. */
21
+ maxDimensionKeys?: number;
22
+ /** At the bound: 'reject' records a projection failure; 'other' folds into an __other__ bucket. */
23
+ overflow?: 'reject' | 'other';
24
+ };
25
+ type TraceProjection = {
26
+ name: string;
27
+ version: number;
28
+ /**
29
+ * Trace event name selector (TraceEvent.event). Exact match, or a glob:
30
+ * `*` matches one dot-separated segment, `**` matches any remainder
31
+ * (e.g. 'render-cycle.**' matches 'render-cycle.turns-changed').
32
+ */
33
+ event: string;
34
+ /** Optional source filter (TraceEvent.source). */
35
+ source?: string;
36
+ /** Context fields promoted to bounded historical dimensions. */
37
+ groupBy?: readonly string[];
38
+ measurements: readonly TraceMeasurement[];
39
+ /** Bucket resolutions in milliseconds (e.g. 60_000, 3_600_000). */
40
+ resolutions: readonly number[];
41
+ /**
42
+ * Behavior when a measurement field is absent/non-numeric on a matching
43
+ * event: 'record-failure' (default) records a bounded projection failure and
44
+ * skips the event; 'skip' omits the field but still counts the event.
45
+ */
46
+ missingField?: 'skip' | 'record-failure';
47
+ cardinality?: TraceCardinalityPolicy;
48
+ };
49
+ /** Validates a projection definition, throwing on structural errors. */
50
+ declare function validateTraceProjection(projection: TraceProjection): void;
51
+
52
+ type TraceProjectorOptions = {
53
+ /** Bounded reader over the raw trace store (owned by @noego/trace). */
54
+ source: TraceSource;
55
+ /** Historical SQL destination. Owned by telemetry; separate from raw traces. */
56
+ destination: Database;
57
+ projections: readonly TraceProjection[];
58
+ /** Raw events read per page; default 500. */
59
+ pageSize?: number;
60
+ now?: () => number;
61
+ };
62
+ /**
63
+ * Why a pass produced no bucket updates (spec 05 §5.4). A pass with buckets
64
+ * reports `buckets-updated`; every other value names the reason so "cursor
65
+ * advancing, zero buckets" can never be mistaken for health.
66
+ */
67
+ type TraceProjectorProgress = 'buckets-updated' | 'caught-up-no-new-source' | 'new-source-no-selector-match' | 'matching-source-no-bucket';
68
+ /** Why the durable cursor was discarded before this pass. */
69
+ type TraceSourceReset = 'store-epoch-changed' | 'cursor-beyond-source';
70
+ type TraceProjectorRunResult = {
71
+ pages: number;
72
+ eventsRead: number;
73
+ /** Events that matched at least one projection selector. */
74
+ selectorMatches: number;
75
+ bucketsUpdated: number;
76
+ failures: number;
77
+ progress: TraceProjectorProgress;
78
+ /** Cursor after the pass (rowid in the source store); null when nothing was ever projected. */
79
+ cursorRowId: number | null;
80
+ /** Newest source rowid at the start of the pass; null when the source cannot describe itself. */
81
+ sourceHighRowId: number | null;
82
+ sourceEpoch: string | null;
83
+ sourceReset: TraceSourceReset | null;
84
+ };
85
+ /** Backfill reprojects a range; it never touches the forward cursor, so it reports only volume. */
86
+ type TraceBackfillResult = Pick<TraceProjectorRunResult, 'pages' | 'eventsRead' | 'bucketsUpdated' | 'failures'>;
87
+ type TraceBucketQuery = {
88
+ projection: string;
89
+ version: number;
90
+ resolutionMs: number;
91
+ fromMs?: number;
92
+ toMs?: number;
93
+ /** Exact-match dimension filter. */
94
+ dimensions?: Record<string, string>;
95
+ };
96
+ type TraceBucketRow = {
97
+ projection: string;
98
+ version: number;
99
+ resolutionMs: number;
100
+ bucketStartMs: number;
101
+ dimensions: Record<string, string>;
102
+ count: number;
103
+ values: Record<string, MeasurementState>;
104
+ /** Computed views: avg per field where sum+count exist. */
105
+ averages: Record<string, number>;
106
+ };
107
+ type MeasurementState = {
108
+ count: number;
109
+ sum: number;
110
+ min: number;
111
+ max: number;
112
+ /** Last observed value in projector processing order. */
113
+ last: number;
114
+ };
115
+ /**
116
+ * Downstream trace projector (spec 04): reads retained raw traces through the
117
+ * TraceSource contract and materializes idempotent historical buckets in SQL.
118
+ *
119
+ * The projector is never part of trace ingestion. Buckets are keyed by
120
+ * (projection, version, resolution, bucket start, dimensions) and bucketed by
121
+ * the event's producer-assigned occurrence time — never by projector run time
122
+ * or insert time. Each page commits bucket updates, failures, and the scan
123
+ * cursor in one destination transaction, so a crash resumes exactly at the
124
+ * durable cursor with no double counting. The insertion-ordered source cursor
125
+ * means a late-delivered event is still observed and folded into its
126
+ * historical occurrence-time bucket.
127
+ */
128
+ declare class TraceProjector {
129
+ private readonly source;
130
+ private readonly db;
131
+ private readonly projections;
132
+ private readonly pageSize;
133
+ private readonly now;
134
+ constructor(options: TraceProjectorOptions);
135
+ /**
136
+ * Drains all unprojected raw traces, page by page, committing progress per
137
+ * page.
138
+ *
139
+ * The durable cursor is a source rowid, so it is only meaningful against
140
+ * the store file it was taken from. When the source describes itself, a
141
+ * cursor whose epoch differs from the store's — or that lies beyond the
142
+ * store's newest row — belongs to a store that has since been recreated
143
+ * (boot reset, manual deletion) and is discarded, restarting the scan at
144
+ * row 0. 2026-09-03: the live projector sat at rowid 22.6M over a rebuilt
145
+ * store holding rows 1–440k, reported "caught up" every minute, and wrote
146
+ * no buckets for ten hours.
147
+ */
148
+ runOnce(): TraceProjectorRunResult;
149
+ /** Newest completed bucket start per projection at the given resolution — the freshness signal. */
150
+ newestBucketStartMs(resolutionMs: number): number | null;
151
+ /**
152
+ * Rebuilds one projection's derived buckets for an occurrence-time range
153
+ * from retained raw traces (spec 04 §14–15): clears coverage for the range,
154
+ * then reprojects every retained matching event. Uses the same extraction
155
+ * code as forward projection; does not touch the forward scan cursor.
156
+ */
157
+ backfill(options: {
158
+ projection: string;
159
+ version: number;
160
+ fromOccurredAtMs: number;
161
+ toOccurredAtMs: number;
162
+ }): TraceBackfillResult;
163
+ /** Historical bucket query with explicit projection/version/resolution. */
164
+ query(query: TraceBucketQuery): readonly TraceBucketRow[];
165
+ /** Bounded projection failures, newest first. */
166
+ failures(limit?: number): readonly {
167
+ projection: string;
168
+ version: number;
169
+ traceId: string;
170
+ reason: string;
171
+ }[];
172
+ private matches;
173
+ private applyEvent;
174
+ private admitDimensions;
175
+ private updateBucket;
176
+ private recordFailure;
177
+ private loadProgress;
178
+ private saveProgress;
179
+ private registerDefinitions;
180
+ private initializeSchema;
181
+ }
182
+ /**
183
+ * Matches a projection event selector against an event name. Exact match, or
184
+ * glob where `*` matches exactly one dot-separated segment and a trailing
185
+ * `**` matches any remainder (including empty).
186
+ */
187
+ declare function eventSelectorMatches(selector: string, eventName: string): boolean;
188
+ /** Durable scan progress: the source rowid plus the epoch of the store it was read from. */
189
+ type ScanProgress = {
190
+ rowId: number;
191
+ /** Null for progress written before epochs existed; such a cursor is validated by extent only. */
192
+ storeEpoch: string | null;
193
+ };
194
+ /**
195
+ * Decide whether the persisted cursor still refers to the store in front of
196
+ * us. Epoch mismatch is definitive. Without an epoch (legacy progress, or a
197
+ * source that cannot describe itself) fall back to extent: a rowid beyond the
198
+ * newest row cannot have been read from this store.
199
+ */
200
+ declare function detectSourceReset(progress: ScanProgress | null, description: TraceSourceDescription | null): TraceSourceReset | null;
201
+
202
+ type TraceProjectorProcessOptions = {
203
+ /** Path to the raw trace SQLite written by @noego/trace (traces.db). */
204
+ tracesDbPath: string;
205
+ /** Path to the historical projection SQLite destination. */
206
+ destinationDbPath: string;
207
+ /** Projection definitions; or use configurationPath to migrate legacy metrics. */
208
+ projections?: readonly TraceProjection[];
209
+ /** telemetry.config.yml whose metric definitions become projections. */
210
+ configurationPath?: string;
211
+ /** Raw events per page; default 500. */
212
+ pageSize?: number;
213
+ };
214
+ type TraceProjectorProcess = {
215
+ runOnce(): TraceProjectorRunResult;
216
+ projector: TraceProjector;
217
+ close(): void;
218
+ };
219
+ /**
220
+ * Builds a runnable projector process over file-based stores (spec 04 §5).
221
+ *
222
+ * This is the separate-process execution mode: it opens the raw trace store
223
+ * read-side and its own historical destination, resumes from the durable
224
+ * cursor, and can be run continuously, on a schedule, or as an explicit
225
+ * maintenance command. Its lifecycle never gates raw trace collection.
226
+ */
227
+ declare function createTraceProjectorProcess(options: TraceProjectorProcessOptions): TraceProjectorProcess;
228
+
229
+ /**
230
+ * Migration of resolved telemetry.config.yml metric definitions into
231
+ * downstream trace projection definitions (spec 04 §18).
232
+ *
233
+ * The configuration parser has already split selectors into an event glob and
234
+ * groupBy dimensions and resolved per-metric bucket resolutions, so this is a
235
+ * shape mapping. Names and versions carry over so historical intent is
236
+ * preserved; the projection bucket store is new, so no numeric continuity
237
+ * with the legacy sample/rollup tables is implied.
238
+ */
239
+ declare function metricDefinitionToTraceProjection(metric: MetricDefinition, options?: {
240
+ fallbackResolutions?: readonly number[];
241
+ }): TraceProjection;
242
+ declare function metricDefinitionsToTraceProjections(metrics: readonly MetricDefinition[], options?: {
243
+ fallbackResolutions?: readonly number[];
244
+ }): readonly TraceProjection[];
245
+
246
+ export { type TraceAggregate, type TraceBackfillResult, type TraceBucketQuery, type TraceBucketRow, type TraceCardinalityPolicy, type TraceMeasurement, type TraceProjection, TraceProjector, type TraceProjectorOptions, type TraceProjectorProcess, type TraceProjectorProcessOptions, type TraceProjectorProgress, type TraceProjectorRunResult, type TraceSourceReset, createTraceProjectorProcess, detectSourceReset, eventSelectorMatches, metricDefinitionToTraceProjection, metricDefinitionsToTraceProjections, validateTraceProjection };