@saidsef/tracing-node 4.0.0 → 4.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 +1 -0
- package/libs/index.mjs +25 -12
- package/libs/index.test.mjs +14 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@ Effortlessly supercharge your applications with world-class distributed tracing!
|
|
|
15
15
|
| Feature | Description |
|
|
16
16
|
|---------|-------------|
|
|
17
17
|
| HTTP/HTTPS instrumentation | Automatic service detection |
|
|
18
|
+
| fetch/undici instrumentation | Outgoing `globalThis.fetch` calls |
|
|
18
19
|
| Express.js support | Framework instrumentation |
|
|
19
20
|
| Elasticsearch client | Database instrumentation |
|
|
20
21
|
| IORedis client | Cache instrumentation |
|
package/libs/index.mjs
CHANGED
|
@@ -25,6 +25,7 @@ import {ExpressInstrumentation} from '@opentelemetry/instrumentation-express';
|
|
|
25
25
|
import {NodeTracerProvider} from '@opentelemetry/sdk-trace-node';
|
|
26
26
|
import {OTLPTraceExporter} from '@opentelemetry/exporter-trace-otlp-grpc';
|
|
27
27
|
import {PinoInstrumentation} from '@opentelemetry/instrumentation-pino';
|
|
28
|
+
import {UndiciInstrumentation} from '@opentelemetry/instrumentation-undici';
|
|
28
29
|
import {IORedisInstrumentation} from '@opentelemetry/instrumentation-ioredis';
|
|
29
30
|
import {registerInstrumentations} from '@opentelemetry/instrumentation';
|
|
30
31
|
import {FsInstrumentation} from '@opentelemetry/instrumentation-fs';
|
|
@@ -50,6 +51,21 @@ const truncateArg = (value, limit) => {
|
|
|
50
51
|
return str.length > limit ? `${str.substring(0, limit)}...` : str;
|
|
51
52
|
};
|
|
52
53
|
|
|
54
|
+
// Tempo names a service-graph node from peer.service, which no instrumentation
|
|
55
|
+
// emits, so both the http and undici hooks below derive it from the remote host.
|
|
56
|
+
const PEER_SERVICES = ['elasticsearch', 'redis'];
|
|
57
|
+
|
|
58
|
+
const setPeerService = (span, host) => {
|
|
59
|
+
if (!host) return;
|
|
60
|
+
for (const service of PEER_SERVICES) {
|
|
61
|
+
if (host.includes(service)) {
|
|
62
|
+
span.setAttribute('peer.service', service);
|
|
63
|
+
span.setAttribute('db.system.name', service);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
53
69
|
let tracerProvider = null; // Declare provider in module scope for access in stopTracing
|
|
54
70
|
|
|
55
71
|
/**
|
|
@@ -134,18 +150,7 @@ export function setupTracing(options = {}) {
|
|
|
134
150
|
|
|
135
151
|
// Only an outgoing ClientRequest carries .host, so bailing without it keeps
|
|
136
152
|
// server spans out: peer.service must name the remote service being called.
|
|
137
|
-
const applyCustomAttributesOnSpan = (span, request) =>
|
|
138
|
-
const host = request?.host;
|
|
139
|
-
if (!host) return;
|
|
140
|
-
|
|
141
|
-
for (const service of ['elasticsearch', 'redis']) {
|
|
142
|
-
if (host.includes(service)) {
|
|
143
|
-
span.setAttribute('peer.service', service);
|
|
144
|
-
span.setAttribute('db.system.name', service);
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
};
|
|
153
|
+
const applyCustomAttributesOnSpan = (span, request) => setPeerService(span, request?.host);
|
|
149
154
|
|
|
150
155
|
const instrumentations = [
|
|
151
156
|
new HttpInstrumentation({
|
|
@@ -178,6 +183,14 @@ export function setupTracing(options = {}) {
|
|
|
178
183
|
if (requestId) span.setAttribute('http.request_id', requestId);
|
|
179
184
|
},
|
|
180
185
|
}),
|
|
186
|
+
// globalThis.fetch runs on undici, which never touches the http/https
|
|
187
|
+
// modules HttpInstrumentation patches. Without this, fetch calls produce no
|
|
188
|
+
// client span and inject no traceparent, so the callee starts a new trace
|
|
189
|
+
// and the two services can never be paired into a service-graph edge.
|
|
190
|
+
new UndiciInstrumentation({
|
|
191
|
+
// UndiciRequest exposes origin, not the .host the http hook reads.
|
|
192
|
+
requestHook: (span, request) => setPeerService(span, request?.origin),
|
|
193
|
+
}),
|
|
181
194
|
new ExpressInstrumentation({
|
|
182
195
|
requestHook: (span, info) => {
|
|
183
196
|
// info is ExpressRequestInfo: { request, route, layerType }
|
package/libs/index.test.mjs
CHANGED
|
@@ -49,6 +49,20 @@ describe('setupTracing', () => {
|
|
|
49
49
|
assert.ok(tracer, 'tracer should be defined');
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
+
// globalThis.fetch runs on undici, so it is invisible to HttpInstrumentation.
|
|
53
|
+
// Registering it must not disturb setup, and the patch has to land on the
|
|
54
|
+
// global fetch itself - otherwise outgoing calls carry no traceparent.
|
|
55
|
+
it('should instrument global fetch', () => {
|
|
56
|
+
const before = globalThis.fetch;
|
|
57
|
+
const tracer = setupTracing({
|
|
58
|
+
serviceName: 'test-service',
|
|
59
|
+
url: 'http://localhost:4317',
|
|
60
|
+
});
|
|
61
|
+
assert.ok(tracer, 'tracer should be defined');
|
|
62
|
+
assert.strictEqual(typeof globalThis.fetch, 'function', 'global fetch should still be callable');
|
|
63
|
+
assert.ok(before, 'global fetch should exist on a supported runtime');
|
|
64
|
+
});
|
|
65
|
+
|
|
52
66
|
it('should accept optional instrumentations', () => {
|
|
53
67
|
const tracer = setupTracing({
|
|
54
68
|
serviceName: 'test-service',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saidsef/tracing-node",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "tracing NodeJS - Wrapper for OpenTelemetry instrumentation packages",
|
|
5
5
|
"main": "libs/index.mjs",
|
|
6
6
|
"scripts": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"author": "Said Sef <saidsef@gmail.com>",
|
|
24
24
|
"license": "Apache-2.0",
|
|
25
25
|
"engines": {
|
|
26
|
-
"node": ">= 20"
|
|
26
|
+
"node": ">= 20.6.0"
|
|
27
27
|
},
|
|
28
28
|
"bugs": {
|
|
29
29
|
"url": "https://github.com/saidsef/tracing-node/issues"
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"@opentelemetry/instrumentation-http": "^0.221.0",
|
|
42
42
|
"@opentelemetry/instrumentation-ioredis": "^0.69.0",
|
|
43
43
|
"@opentelemetry/instrumentation-pino": "^0.67.0",
|
|
44
|
+
"@opentelemetry/instrumentation-undici": "^0.31.0",
|
|
44
45
|
"@opentelemetry/resources": "^2.10.0",
|
|
45
46
|
"@opentelemetry/sdk-trace-base": "^2.10.0",
|
|
46
47
|
"@opentelemetry/sdk-trace-node": "^2.10.0",
|