@comprehend/telemetry-node 0.2.2 → 0.2.4
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/.claude/settings.local.json +2 -2
- package/.idea/telemetry-node.iml +0 -1
- package/README.md +16 -4
- package/dist/ComprehendDevSpanProcessor.js +4 -3
- package/dist/ComprehendDevSpanProcessor.test.js +1 -0
- package/dist/sql-analyzer.js +2 -11
- package/dist/sql-analyzer.test.js +0 -12
- package/dist/wire-protocol.d.ts +1 -0
- package/package.json +1 -1
- package/src/ComprehendDevSpanProcessor.test.ts +1 -0
- package/src/ComprehendDevSpanProcessor.ts +4 -3
- package/src/wire-protocol.ts +1 -0
package/.idea/telemetry-node.iml
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
<component name="NewModuleRootManager">
|
|
4
4
|
<content url="file://$MODULE_DIR$">
|
|
5
5
|
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
|
6
|
-
<excludeFolder url="file://$MODULE_DIR$/dist" />
|
|
7
6
|
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
|
8
7
|
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
|
9
8
|
</content>
|
package/README.md
CHANGED
|
@@ -119,16 +119,30 @@ hostMetrics.start();
|
|
|
119
119
|
|
|
120
120
|
This collects `process.cpu.time`, `process.cpu.utilization`, and `process.memory.usage`. The `metricGroups` option limits collection to process-level metrics only, avoiding the overhead of system-wide CPU, memory, and network data gathering.
|
|
121
121
|
|
|
122
|
+
### Service instance identity
|
|
123
|
+
|
|
124
|
+
Include `serviceInstanceIdDetector` in your `resourceDetectors` to give each running process a unique identity that changes on every restart. This lets comprehend.dev distinguish between different instances of the same service and track restarts over time:
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
import { envDetector, hostDetector, processDetector, serviceInstanceIdDetector } from '@opentelemetry/resources';
|
|
128
|
+
|
|
129
|
+
const sdk = new NodeSDK({
|
|
130
|
+
// ...
|
|
131
|
+
resourceDetectors: [envDetector, processDetector, hostDetector, serviceInstanceIdDetector],
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
`serviceInstanceIdDetector` generates a random UUID (`service.instance.id`) at process startup. Note that specifying `resourceDetectors` explicitly replaces the `NodeSDK` defaults, so include the built-in detectors (`envDetector`, `processDetector`, `hostDetector`) alongside it.
|
|
136
|
+
|
|
122
137
|
### Kubernetes / container resources
|
|
123
138
|
|
|
124
|
-
When running in containers or Kubernetes,
|
|
139
|
+
When running in containers or Kubernetes, add `containerDetector` to your `resourceDetectors`:
|
|
125
140
|
|
|
126
141
|
```bash
|
|
127
142
|
npm install @opentelemetry/resource-detector-container
|
|
128
143
|
```
|
|
129
144
|
|
|
130
145
|
```typescript
|
|
131
|
-
import { NodeSDK } from '@opentelemetry/sdk-node';
|
|
132
146
|
import { envDetector, hostDetector, processDetector, serviceInstanceIdDetector } from '@opentelemetry/resources';
|
|
133
147
|
import { containerDetector } from '@opentelemetry/resource-detector-container';
|
|
134
148
|
|
|
@@ -138,8 +152,6 @@ const sdk = new NodeSDK({
|
|
|
138
152
|
});
|
|
139
153
|
```
|
|
140
154
|
|
|
141
|
-
**`serviceInstanceIdDetector`** generates a random UUID (`service.instance.id`) at process startup. This gives each deployment instance a unique identity that changes on every restart, which is useful for distinguishing runs in environments where `container.id` is not available (see below).
|
|
142
|
-
|
|
143
155
|
**`containerDetector`** reads `container.id` from `/proc/self/cgroup`. This works reliably with Docker-based runtimes but not on modern containerd-based Kubernetes clusters (which is the default since k8s 1.24), where the cgroup format does not expose the container ID in the expected location. Add it anyway — it will populate `container.id` when available and is a no-op otherwise.
|
|
144
156
|
|
|
145
157
|
For k8s identity attributes that cannot be read from the host (pod name, namespace, node), use the Kubernetes Downward API to inject them as `OTEL_RESOURCE_ATTRIBUTES`:
|
|
@@ -174,9 +174,9 @@ class ComprehendDevSpanProcessor {
|
|
|
174
174
|
: {
|
|
175
175
|
scrubbed: '',
|
|
176
176
|
user: undefined,
|
|
177
|
-
host: (attrs['net.peer.name'] ?? attrs['net.peer.ip']),
|
|
178
|
-
port: attrs['net.peer.port']?.toString(),
|
|
179
|
-
name: attrs['db.name'],
|
|
177
|
+
host: (attrs['server.address'] ?? attrs['net.peer.name'] ?? attrs['net.peer.ip']),
|
|
178
|
+
port: (attrs['server.port'] ?? attrs['net.peer.port'])?.toString(),
|
|
179
|
+
name: (attrs['db.namespace'] ?? attrs['db.name']),
|
|
180
180
|
};
|
|
181
181
|
const hash = hashIdString(`database:${system}:${parsed.host ?? ''}:${parsed.port ?? ''}:${parsed.name ?? ''}`);
|
|
182
182
|
let observedDatabase = this.observedDatabases.find(db => db.hash === hash);
|
|
@@ -351,6 +351,7 @@ class ComprehendDevSpanProcessor {
|
|
|
351
351
|
spanId,
|
|
352
352
|
traceId,
|
|
353
353
|
timestamp: span.startTime,
|
|
354
|
+
duration: span.duration,
|
|
354
355
|
attributes: collectedAttrs,
|
|
355
356
|
...(errorMessage ? { errorMessage } : {}),
|
|
356
357
|
...(errorType ? { errorType } : {}),
|
|
@@ -304,6 +304,7 @@ describe('ComprehendDevSpanProcessor', () => {
|
|
|
304
304
|
expect(customObs).toBeDefined();
|
|
305
305
|
expect(customObs.subject).toBe('custom-server-obs');
|
|
306
306
|
expect(customObs.id).toBe('custom-server-obs');
|
|
307
|
+
expect(customObs.duration).toBeDefined();
|
|
307
308
|
expect(customObs.attributes).toBeDefined();
|
|
308
309
|
});
|
|
309
310
|
it('should match spans by attribute-present rule', () => {
|
package/dist/sql-analyzer.js
CHANGED
|
@@ -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
|
-
//
|
|
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,
|
|
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/wire-protocol.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -403,6 +403,7 @@ describe('ComprehendDevSpanProcessor', () => {
|
|
|
403
403
|
expect(customObs).toBeDefined();
|
|
404
404
|
expect(customObs.subject).toBe('custom-server-obs');
|
|
405
405
|
expect(customObs.id).toBe('custom-server-obs');
|
|
406
|
+
expect(customObs.duration).toBeDefined();
|
|
406
407
|
expect(customObs.attributes).toBeDefined();
|
|
407
408
|
});
|
|
408
409
|
|
|
@@ -257,9 +257,9 @@ export class ComprehendDevSpanProcessor implements SpanProcessor {
|
|
|
257
257
|
: {
|
|
258
258
|
scrubbed: '',
|
|
259
259
|
user: undefined,
|
|
260
|
-
host: (attrs['net.peer.name'] ?? attrs['net.peer.ip']) as string | undefined,
|
|
261
|
-
port: (attrs['net.peer.port'] as number | undefined)?.toString(),
|
|
262
|
-
name: attrs['db.name'] as string | undefined,
|
|
260
|
+
host: (attrs['server.address'] ?? attrs['net.peer.name'] ?? attrs['net.peer.ip']) as string | undefined,
|
|
261
|
+
port: (attrs['server.port'] ?? attrs['net.peer.port'] as number | undefined)?.toString(),
|
|
262
|
+
name: (attrs['db.namespace'] ?? attrs['db.name']) as string | undefined,
|
|
263
263
|
};
|
|
264
264
|
|
|
265
265
|
const hash = hashIdString(`database:${system}:${parsed.host ?? ''}:${parsed.port ?? ''}:${parsed.name ?? ''}`);
|
|
@@ -448,6 +448,7 @@ export class ComprehendDevSpanProcessor implements SpanProcessor {
|
|
|
448
448
|
spanId,
|
|
449
449
|
traceId,
|
|
450
450
|
timestamp: span.startTime,
|
|
451
|
+
duration: span.duration,
|
|
451
452
|
attributes: collectedAttrs,
|
|
452
453
|
...(errorMessage ? { errorMessage } : {}),
|
|
453
454
|
...(errorType ? { errorType } : {}),
|
package/src/wire-protocol.ts
CHANGED