@comprehend/telemetry-node 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/.claude/settings.local.json +2 -2
  2. package/.idea/telemetry-node.iml +0 -1
  3. package/README.md +73 -27
  4. package/dist/ComprehendDevSpanProcessor.d.ts +9 -6
  5. package/dist/ComprehendDevSpanProcessor.js +145 -87
  6. package/dist/ComprehendDevSpanProcessor.test.js +270 -449
  7. package/dist/ComprehendMetricsExporter.d.ts +18 -0
  8. package/dist/ComprehendMetricsExporter.js +178 -0
  9. package/dist/ComprehendMetricsExporter.test.d.ts +1 -0
  10. package/dist/ComprehendMetricsExporter.test.js +266 -0
  11. package/dist/ComprehendSDK.d.ts +18 -0
  12. package/dist/ComprehendSDK.js +56 -0
  13. package/dist/ComprehendSDK.test.d.ts +1 -0
  14. package/dist/ComprehendSDK.test.js +126 -0
  15. package/dist/WebSocketConnection.d.ts +23 -3
  16. package/dist/WebSocketConnection.js +106 -12
  17. package/dist/WebSocketConnection.test.js +236 -169
  18. package/dist/index.d.ts +3 -1
  19. package/dist/index.js +5 -1
  20. package/dist/sql-analyzer.js +2 -11
  21. package/dist/sql-analyzer.test.js +0 -12
  22. package/dist/util.d.ts +2 -0
  23. package/dist/util.js +7 -0
  24. package/dist/wire-protocol.d.ts +168 -28
  25. package/package.json +3 -1
  26. package/src/ComprehendDevSpanProcessor.test.ts +311 -507
  27. package/src/ComprehendDevSpanProcessor.ts +169 -105
  28. package/src/ComprehendMetricsExporter.test.ts +334 -0
  29. package/src/ComprehendMetricsExporter.ts +225 -0
  30. package/src/ComprehendSDK.test.ts +160 -0
  31. package/src/ComprehendSDK.ts +63 -0
  32. package/src/WebSocketConnection.test.ts +286 -205
  33. package/src/WebSocketConnection.ts +135 -13
  34. package/src/index.ts +3 -2
  35. package/src/util.ts +6 -0
  36. package/src/wire-protocol.ts +204 -29
  37. package/src/sql-analyzer.test.ts +0 -599
  38. package/src/sql-analyzer.ts +0 -439
@@ -23,7 +23,6 @@ function analyzeSQL(sql) {
23
23
  let skippingValues = false;
24
24
  let lookingForCommaOrEnd = false;
25
25
  let valuesDepth = 0;
26
- let skippedWhitespace = [];
27
26
  for (let token of tokenizeSQL(sql)) {
28
27
  switch (token.type) {
29
28
  case "whitespace":
@@ -137,31 +136,23 @@ function analyzeSQL(sql) {
137
136
  switch (token.type) {
138
137
  case "comment":
139
138
  case "whitespace":
140
- // Collect whitespace/comments while looking for comma or end
141
- skippedWhitespace.push(token);
139
+ // Skip whitespace/comments while looking for comma or end
142
140
  break;
143
141
  case "punct":
144
142
  if (token.value === ",") {
145
- // More tuples coming, clear skipped whitespace and continue skipping
146
- skippedWhitespace = [];
143
+ // More tuples coming, continue skipping
147
144
  lookingForCommaOrEnd = false;
148
145
  skippingValues = true;
149
146
  }
150
147
  else {
151
148
  // Not a comma, so VALUES clause is done
152
- // Add back the skipped whitespace, then the current token
153
- presentableTokens.push(...skippedWhitespace);
154
149
  presentableTokens.push(token);
155
- skippedWhitespace = [];
156
150
  lookingForCommaOrEnd = false;
157
151
  }
158
152
  break;
159
153
  default:
160
154
  // VALUES clause is done, resume normal processing
161
- // Add back the skipped whitespace, then the current token
162
- presentableTokens.push(...skippedWhitespace);
163
155
  presentableTokens.push(token);
164
- skippedWhitespace = [];
165
156
  lookingForCommaOrEnd = false;
166
157
  break;
167
158
  }
@@ -482,16 +482,4 @@ describe('SQL Analyzer - bulk INSERT VALUES cardinality reduction', () => {
482
482
  expect(result.presentableQuery).toEqual(`INSERT INTO comments (text, author) VALUES
483
483
  (...)`);
484
484
  });
485
- it('preserves whitespace before ON CONFLICT after VALUES clause', () => {
486
- const sql = `INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com') ON CONFLICT (email) DO NOTHING`;
487
- const result = (0, sql_analyzer_1.analyzeSQL)(sql);
488
- expect(result.tableOperations).toEqual({ users: ['INSERT'] });
489
- expect(result.presentableQuery).toEqual(`INSERT INTO users (name, email) VALUES (...) ON CONFLICT (email) DO NOTHING`);
490
- });
491
- it('preserves whitespace before ON CONFLICT with multiple VALUES tuples', () => {
492
- const sql = `INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com'), ('Bob', 'bob@example.com') ON CONFLICT (email) DO UPDATE SET name = EXCLUDED.name`;
493
- const result = (0, sql_analyzer_1.analyzeSQL)(sql);
494
- expect(result.tableOperations).toEqual({ users: ['INSERT'] });
495
- expect(result.presentableQuery).toEqual(`INSERT INTO users (name, email) VALUES (...) ON CONFLICT (email) DO UPDATE SET name = EXCLUDED.name`);
496
- });
497
485
  });
package/dist/util.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import { HrTime } from './wire-protocol';
2
+ export declare function hrTimeNow(): HrTime;
package/dist/util.js ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hrTimeNow = hrTimeNow;
4
+ function hrTimeNow() {
5
+ const now = Date.now();
6
+ return [Math.floor(now / 1000), (now % 1000) * 1000000];
7
+ }
@@ -1,15 +1,40 @@
1
- import { HrTime } from "@opentelemetry/api";
2
- export type ObservationInputMessage = InitMessage | NewObservedEntityMessage | NewObservedInteractionMessage | ObservationMessage;
3
- export type ObservationOutputMessage = InitAck | ObservedAck | ObservationsAck;
1
+ export type HrTime = [number, number];
2
+ export type ObservationInputMessage = InitMessage | StartProcessContextMessage | EndContextMessage | NewObservedEntityMessage | NewObservedInteractionMessage | ObservationMessage | TimeSeriesMetricsMessage | CumulativeMetricsMessage | TraceSpansMessage | DatabaseQueryMessage;
3
+ export type ObservationOutputMessage = InitAck | ContextAck | CustomMetricChange | ObservedAck | ObservationsAck | TimeSeriesMetricsAck | CumulativeMetricsAck | TraceSpansAck | DatabaseQueryAck;
4
4
  export interface InitMessage {
5
5
  event: "init";
6
- protocolVersion: 1;
6
+ protocolVersion: 2;
7
7
  token: string;
8
8
  }
9
+ export interface InitAck {
10
+ type: "ack-authorized";
11
+ customMetrics: CustomMetricSpecification[];
12
+ }
13
+ export interface StartProcessContextMessage {
14
+ event: "context-start";
15
+ seq: number;
16
+ timestamp: HrTime;
17
+ ingestionId: string;
18
+ type: "process";
19
+ serviceEntityHash: string;
20
+ resources: {
21
+ [key: string]: AttributeType;
22
+ };
23
+ }
24
+ export interface EndContextMessage {
25
+ event: "context-end";
26
+ seq: number;
27
+ timestamp: HrTime;
28
+ ingestionId: string;
29
+ }
30
+ export interface ContextAck {
31
+ type: "ack-context";
32
+ seq: number;
33
+ }
9
34
  export interface NewObservedEntityMessage {
10
35
  event: "new-entity";
11
- type: string;
12
36
  hash: string;
37
+ type: string;
13
38
  }
14
39
  export interface NewObservedServiceMessage extends NewObservedEntityMessage {
15
40
  type: "service";
@@ -36,12 +61,16 @@ export interface NewObservedHttpServiceMessage extends NewObservedEntityMessage
36
61
  host: string;
37
62
  port: number;
38
63
  }
64
+ export interface ObservedAck {
65
+ type: "ack-observed";
66
+ hash: string;
67
+ }
39
68
  export interface NewObservedInteractionMessage {
40
69
  event: "new-interaction";
41
- type: string;
42
70
  hash: string;
43
71
  from: string;
44
72
  to: string;
73
+ type: string;
45
74
  }
46
75
  export interface NewObservedHttpRequestMessage extends NewObservedInteractionMessage {
47
76
  type: "http-request";
@@ -51,28 +80,23 @@ export interface NewObservedDatabaseConnectionMessage extends NewObservedInterac
51
80
  connection?: string;
52
81
  user?: string;
53
82
  }
54
- export interface NewObservedDatabaseQueryMessage extends NewObservedInteractionMessage {
55
- type: "db-query";
56
- query: string;
57
- selects?: string[];
58
- inserts?: string[];
59
- updates?: string[];
60
- deletes?: string[];
61
- }
62
83
  export interface ObservationMessage {
63
84
  event: "observations";
64
85
  seq: number;
65
86
  observations: Array<Observation>;
66
87
  }
67
- export interface Observation {
68
- type: string;
88
+ export type Observation = HttpClientObservation | HttpServerObservation | CustomObservation;
89
+ interface BaseObservation {
69
90
  subject: string;
91
+ spanId: string;
92
+ traceId: string;
70
93
  timestamp: HrTime;
71
94
  errorMessage?: string;
72
95
  errorType?: string;
73
96
  stack?: string;
97
+ type: string;
74
98
  }
75
- export interface HttpClientObservation extends Observation {
99
+ export interface HttpClientObservation extends BaseObservation {
76
100
  type: "http-client";
77
101
  path: string;
78
102
  method: string;
@@ -82,7 +106,7 @@ export interface HttpClientObservation extends Observation {
82
106
  requestBytes?: number;
83
107
  responseBytes?: number;
84
108
  }
85
- export interface HttpServerObservation extends Observation {
109
+ export interface HttpServerObservation extends BaseObservation {
86
110
  type: "http-server";
87
111
  path: string;
88
112
  status: number;
@@ -92,19 +116,135 @@ export interface HttpServerObservation extends Observation {
92
116
  responseBytes?: number;
93
117
  userAgent?: string;
94
118
  }
95
- export interface DatabaseQueryObservation extends Observation {
96
- type: "db-query";
119
+ export type AttributeType = string | number | boolean;
120
+ export interface CustomObservation extends BaseObservation {
121
+ type: "custom";
122
+ id: string;
123
+ attributes: {
124
+ [key: string]: AttributeType;
125
+ };
126
+ }
127
+ export interface ObservationsAck {
128
+ type: "ack-observations";
129
+ seq: number;
130
+ }
131
+ export interface TimeSeriesMetricsMessage {
132
+ event: "timeseries";
133
+ seq: number;
134
+ data: TimeSeriesDataPoint[];
135
+ }
136
+ export interface TimeSeriesDataPoint {
137
+ subject: string;
138
+ type: string;
139
+ timestamp: HrTime;
140
+ value: number;
141
+ unit: string;
142
+ attributes: {
143
+ [key: string]: AttributeType;
144
+ };
145
+ }
146
+ export interface TimeSeriesMetricsAck {
147
+ type: "ack-timeseries";
148
+ seq: number;
149
+ }
150
+ export interface CumulativeMetricsMessage {
151
+ event: "cumulative";
152
+ seq: number;
153
+ data: CumulativeDataPoint[];
154
+ }
155
+ export interface CumulativeDataPoint {
156
+ subject: string;
157
+ type: string;
158
+ timestamp: HrTime;
159
+ value: number;
160
+ unit: string;
161
+ attributes: {
162
+ [key: string]: AttributeType;
163
+ };
164
+ }
165
+ export interface CumulativeMetricsAck {
166
+ type: "ack-cumulative";
167
+ seq: number;
168
+ }
169
+ export interface TraceSpansMessage {
170
+ event: "tracespans";
171
+ seq: number;
172
+ data: TraceSpan[];
173
+ }
174
+ export interface TraceSpan {
175
+ trace: string;
176
+ span: string;
177
+ parent: string;
178
+ name: string;
179
+ timestamp: HrTime;
180
+ }
181
+ export interface TraceSpansAck {
182
+ type: "ack-tracespans";
183
+ seq: number;
184
+ }
185
+ export interface DatabaseQueryMessage {
186
+ event: "db-query";
187
+ seq: number;
188
+ query: string;
189
+ from: string;
190
+ to: string;
191
+ timestamp: HrTime;
97
192
  duration: HrTime;
193
+ traceId?: string;
194
+ spanId?: string;
195
+ errorMessage?: string;
196
+ errorType?: string;
197
+ stack?: string;
98
198
  returnedRows?: number;
99
199
  }
100
- export interface InitAck {
101
- type: "ack-authorized";
200
+ export interface DatabaseQueryAck {
201
+ type: "ack-db-query";
202
+ seq: number;
102
203
  }
103
- export interface ObservedAck {
104
- type: "ack-observed";
105
- hash: string;
204
+ export interface CustomMetricChange {
205
+ type: "custom-metric-change";
206
+ customMetrics: CustomMetricSpecification[];
106
207
  }
107
- export interface ObservationsAck {
108
- type: "ack-observations";
109
- seq: number;
208
+ export type CustomMetricSpecification = CustomCumulativeMetricSpecification | CustomTimeSeriesMetricSpecification | CustomSpanObservationSpecification;
209
+ export interface CustomCumulativeMetricSpecification {
210
+ type: "cumulative";
211
+ id: string;
212
+ attributes: string[];
213
+ subject: string;
214
+ }
215
+ export interface CustomTimeSeriesMetricSpecification {
216
+ type: "timeseries";
217
+ id: string;
218
+ attributes: string[];
219
+ subject: string;
220
+ }
221
+ export interface CustomSpanObservationSpecification {
222
+ type: "span";
223
+ rule: SpanMatcherRule;
224
+ subject: string;
110
225
  }
226
+ export type SpanMatcherRule = {
227
+ kind: "type";
228
+ value: "client" | "server" | "internal";
229
+ } | {
230
+ kind: "attribute-present";
231
+ key: string;
232
+ } | {
233
+ kind: "attribute-absent";
234
+ key: string;
235
+ } | {
236
+ kind: "attribute-equals";
237
+ key: string;
238
+ value: string;
239
+ } | {
240
+ kind: "attribute-not-equals";
241
+ key: string;
242
+ value: string;
243
+ } | {
244
+ kind: "all";
245
+ rules: SpanMatcherRule[];
246
+ } | {
247
+ kind: "any";
248
+ rules: SpanMatcherRule[];
249
+ };
250
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@comprehend/telemetry-node",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "description": "Integration of comprehend.dev with OpenTelemetry in Node.js and similar environemnts.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -19,10 +19,12 @@
19
19
  },
20
20
  "peerDependencies": {
21
21
  "@opentelemetry/api": "^1.9.0",
22
+ "@opentelemetry/sdk-metrics": "^2.0.0",
22
23
  "@opentelemetry/sdk-trace-base": "^2.0.1"
23
24
  },
24
25
  "devDependencies": {
25
26
  "@opentelemetry/api": "^1.9.0",
27
+ "@opentelemetry/sdk-metrics": "^2.5.1",
26
28
  "@opentelemetry/sdk-trace-base": "^2.0.1",
27
29
  "@types/jest": "^29.5.14",
28
30
  "@types/node": "^22.14.1",