@saidsef/tracing-node 3.12.2 → 3.13.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 (2) hide show
  1. package/libs/index.mjs +21 -130
  2. package/package.json +1 -1
package/libs/index.mjs CHANGED
@@ -109,61 +109,24 @@ export function setupTracing(options = {}) {
109
109
  return req.url.startsWith('/metrics') || req.url.startsWith('/healthz');
110
110
  };
111
111
 
112
- // Helper function to extract hostname from various request formats
113
- const extractHostname = (request) => {
114
- // Try to get hostname from various possible locations
115
- let hostname = request?.hostname || request?.host || '';
112
+ // Hook to set peer service name for outgoing requests
113
+ const applyCustomAttributesOnSpan = (span, request) => {
114
+ const url = request?.url || request?.uri || '';
115
+ const hostname = request?.hostname || request?.host || '';
116
116
 
117
- // If not found, try to parse from URL
118
- if (!hostname && request?.url) {
119
- try {
120
- const urlObj = new URL(request.url);
121
- hostname = urlObj.hostname;
122
- } catch {
123
- // If URL parsing fails, try to extract from request options
124
- if (request?.options?.hostname) {
125
- hostname = request.options.hostname;
126
- } else if (request?.options?.host) {
127
- hostname = request.options.host;
128
- }
129
- }
130
- }
131
-
132
- return hostname;
133
- };
134
-
135
- // Helper function to determine peer service name from hostname/URL
136
- const getPeerServiceName = (hostname, url = '') => {
137
- const lowerHostname = hostname.toLowerCase();
138
- const lowerUrl = url.toLowerCase();
139
-
140
- // Check for known service patterns
141
- if (lowerHostname.includes('elasticsearch') || lowerUrl.includes('elasticsearch') ||
142
- lowerHostname.includes(':9200') || lowerUrl.includes(':9200')) {
143
- return 'elasticsearch';
144
- }
145
-
146
- if (lowerHostname.includes('redis') || lowerUrl.includes('redis') ||
147
- lowerHostname.includes(':6379') || lowerUrl.includes(':6379')) {
148
- return 'redis';
149
- }
150
-
151
- // Extract service name from hostname patterns like:
152
- // - service-name.namespace.svc.cluster.local
153
- // - service-name.namespace.svc
154
- // - api.service-name.com
155
- if (lowerHostname.includes('.svc')) {
156
- const parts = lowerHostname.split('.');
157
- return parts[0]; // Return the service name part
117
+ // Detect Elasticsearch endpoints
118
+ if (hostname.includes('elasticsearch') || url.includes('elasticsearch') ||
119
+ hostname.includes(':9200') || url.includes(':9200')) {
120
+ span.setAttribute('peer.service', 'elasticsearch');
121
+ span.setAttribute('db.system', 'elasticsearch');
158
122
  }
159
123
 
160
- // For external domains, use the hostname without 'www'
161
- if (lowerHostname.startsWith('www.')) {
162
- return lowerHostname.substring(4);
124
+ // Detect Redis endpoints
125
+ if (hostname.includes('redis') || url.includes('redis') ||
126
+ hostname.includes(':6379') || url.includes(':6379')) {
127
+ span.setAttribute('peer.service', 'redis');
128
+ span.setAttribute('db.system', 'redis');
163
129
  }
164
-
165
- // Return the full hostname as the service name
166
- return hostname || 'unknown';
167
130
  };
168
131
 
169
132
  // Register instrumentations
@@ -171,46 +134,8 @@ export function setupTracing(options = {}) {
171
134
  new HttpInstrumentation({
172
135
  serverName: serviceName,
173
136
  ignoreIncomingRequestHook,
174
- requireParentforOutgoingSpans: false,
175
- requireParentforIncomingSpans: false,
137
+ applyCustomAttributesOnSpan,
176
138
  requestHook: (span, request) => {
177
- const spanKind = span.kind;
178
- const isClientSpan = spanKind === 3; // SpanKind.CLIENT = 3
179
-
180
- // For CLIENT spans (outgoing requests), add peer service attributes
181
- if (isClientSpan) {
182
- const hostname = extractHostname(request);
183
- const url = request?.url || request?.uri || '';
184
-
185
- if (hostname) {
186
- const peerService = getPeerServiceName(hostname, url);
187
-
188
- // Set attributes for service graph - CRITICAL for Tempo
189
- span.setAttribute('peer.service', peerService);
190
- span.setAttribute('net.peer.name', hostname);
191
-
192
- // Add db.system for database clients (elasticsearch, redis, etc.)
193
- if (peerService === 'elasticsearch') {
194
- span.setAttribute('db.system', 'elasticsearch');
195
- } else if (peerService === 'redis') {
196
- span.setAttribute('db.system', 'redis');
197
- }
198
-
199
- // Add port if available
200
- const port = request?.port || request?.options?.port;
201
- if (port) {
202
- span.setAttribute('net.peer.port', parseInt(port, 10));
203
- }
204
-
205
- // Add method for better span naming
206
- const method = request?.method || 'GET';
207
- span.setAttribute('http.method', method.toUpperCase());
208
-
209
- // Update span name for clarity
210
- span.updateName(`${method.toUpperCase()} ${peerService}`);
211
- }
212
- }
213
-
214
139
  // Enrich spans with additional HTTP request attributes
215
140
  if (request.headers) {
216
141
  const userAgent = request.headers['user-agent'];
@@ -341,6 +266,11 @@ export function setupTracing(options = {}) {
341
266
  // Ensure peer.service persists through response
342
267
  span.setAttribute('peer.service', 'redis');
343
268
 
269
+ // Add command details for better observability
270
+ if (cmdName) {
271
+ span.setAttribute('db.operation', cmdName.toUpperCase());
272
+ }
273
+
344
274
  // Log response size if available
345
275
  if (response !== undefined && response !== null) {
346
276
  const responseType = typeof response;
@@ -360,46 +290,7 @@ export function setupTracing(options = {}) {
360
290
  return `${cmdName} ${args.join(' ')}`;
361
291
  },
362
292
  }),
363
- new ElasticsearchInstrumentation({
364
- suppressInternalInstrumentation: true,
365
- requestHook: (span, request) => {
366
- // Set peer.service for service graph visualization - CRITICAL for Tempo
367
- // This ensures Elasticsearch spans are properly identified
368
- span.setAttribute('peer.service', 'elasticsearch');
369
- span.setAttribute('db.system', 'elasticsearch');
370
-
371
- // Add operation details if available
372
- if (request?.method) {
373
- span.setAttribute('db.operation', request.method.toUpperCase());
374
- }
375
- },
376
- responseHook: (span, response) => {
377
- // Ensure peer.service persists through response
378
- span.setAttribute('peer.service', 'elasticsearch');
379
- span.setAttribute('db.system', 'elasticsearch');
380
-
381
- // Add response details for better observability
382
- if (response) {
383
- // Add status code if available
384
- if (response.statusCode) {
385
- span.setAttribute('db.response.status_code', response.statusCode);
386
- }
387
-
388
- // Add response body size if available
389
- if (response.body) {
390
- const bodySize = typeof response.body === 'string'
391
- ? response.body.length
392
- : JSON.stringify(response.body).length;
393
- span.setAttribute('db.response.body_size', bodySize);
394
- }
395
-
396
- // Add took time if available (Elasticsearch response timing)
397
- if (response.body?.took) {
398
- span.setAttribute('db.elasticsearch.took_ms', response.body.took);
399
- }
400
- }
401
- },
402
- }),
293
+ new ElasticsearchInstrumentation(),
403
294
  ];
404
295
 
405
296
  if (enableFsInstrumentation) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saidsef/tracing-node",
3
- "version": "3.12.2",
3
+ "version": "3.13.0",
4
4
  "description": "tracing NodeJS - Wrapper for OpenTelemetry instrumentation packages",
5
5
  "main": "libs/index.mjs",
6
6
  "scripts": {