@platformatic/telemetry 0.35.5 → 0.37.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/lib/telemetry.js CHANGED
@@ -8,6 +8,7 @@ const { Resource } = require('@opentelemetry/resources')
8
8
  const { PlatformaticTracerProvider } = require('./platformatic-trace-provider')
9
9
  const { PlatformaticContext } = require('./platformatic-context')
10
10
  const { fastifyTextMapGetter, fastifyTextMapSetter } = require('./fastify-text-map')
11
+ const { formatParamUrl } = require('@fastify/swagger')
11
12
  const fastUri = require('fast-uri')
12
13
 
13
14
  // Platformatic telemetry plugin.
@@ -27,14 +28,27 @@ const fastUri = require('fast-uri')
27
28
 
28
29
  const { name: moduleName, version: moduleVersion } = require('../package.json')
29
30
 
30
- function formatSpanName (request) {
31
- const { method, routerPath } = request
31
+ const extractPath = (request) => {
32
+ // We must user RouterPath, because otherwise `/test/123` will be considered as
33
+ // a different operation than `/test/321`. In case is not set (this should actually happen only for HTTP/404) we fallback to the path.
34
+ const { routerPath, url } = request
35
+ let path
36
+ if (routerPath) {
37
+ path = formatParamUrl(routerPath)
38
+ } else {
39
+ path = url
40
+ }
41
+ return path
42
+ }
43
+
44
+ function formatSpanName (request, path) {
45
+ const { method } = request
32
46
  /* istanbul ignore next */
33
- return routerPath ? `${method} ${routerPath}` : method
47
+ return path ? `${method} ${path}` : method
34
48
  }
35
49
 
36
50
  const formatSpanAttributes = {
37
- request (request) {
51
+ request (request, path) {
38
52
  const { hostname, method, url, protocol } = request
39
53
  // Inspired by: https://github.com/fastify/fastify-url-data/blob/master/plugin.js#L11
40
54
  const urlData = fastUri.parse(`${protocol}://${hostname}${url}`)
@@ -42,7 +56,7 @@ const formatSpanAttributes = {
42
56
  'server.address': hostname,
43
57
  'server.port': urlData.port,
44
58
  'http.request.method': method,
45
- 'url.path': urlData.path,
59
+ 'url.path': path,
46
60
  'url.scheme': protocol
47
61
  }
48
62
  },
@@ -122,15 +136,16 @@ async function setupTelemetry (app, opts) {
122
136
  // We populate the context with the incoming request headers
123
137
  let context = propagator.extract(new PlatformaticContext(), request, fastifyTextMapGetter)
124
138
 
139
+ const path = extractPath(request)
125
140
  const span = tracer.startSpan(
126
- formatSpanName(request),
141
+ formatSpanName(request, path),
127
142
  {},
128
143
  context
129
144
  )
130
145
  span.kind = SpanKind.SERVER
131
146
  // Next 2 lines are needed by W3CTraceContextPropagator
132
147
  context = context.setSpan(span)
133
- span.setAttributes(formatSpanAttributes.request(request))
148
+ span.setAttributes(formatSpanAttributes.request(request, path))
134
149
  span.context = context
135
150
  request.span = span
136
151
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/telemetry",
3
- "version": "0.35.5",
3
+ "version": "0.37.0",
4
4
  "description": "OpenTelemetry integration for Platformatic",
5
5
  "main": "index.js",
6
6
  "author": "Marco Piraccini <marco.piraccini@gmail.com>",
@@ -16,6 +16,7 @@
16
16
  "tap": "^16.3.6"
17
17
  },
18
18
  "dependencies": {
19
+ "@fastify/swagger": "^8.9.0",
19
20
  "@opentelemetry/api": "^1.4.1",
20
21
  "@opentelemetry/core": "^1.15.0",
21
22
  "@opentelemetry/exporter-trace-otlp-proto": "^0.41.0",
@@ -178,7 +178,7 @@ test('should trace a client request failing', async ({ equal, same, teardown })
178
178
  equal(finishedSpans.length, 2)
179
179
  // We have two one for the client and one for the server
180
180
  const spanServer = finishedSpans[0]
181
- equal(spanServer.name, 'GET')
181
+ equal(spanServer.name, 'GET /wrong')
182
182
  equal(spanServer.kind, SpanKind.SERVER)
183
183
  equal(spanServer.status.code, SpanStatusCode.ERROR)
184
184
  equal(spanServer.attributes['http.request.method'], 'GET')
@@ -9,6 +9,7 @@ async function setupApp (pluginOpts, routeHandler, teardown) {
9
9
  const app = fastify()
10
10
  await app.register(telemetryPlugin, pluginOpts)
11
11
  app.get('/test', routeHandler)
12
+ app.get('/test/:id', routeHandler)
12
13
  app.ready()
13
14
  teardown(async () => {
14
15
  await app.close()
@@ -278,3 +279,42 @@ test('should not trace if the operation is skipped', async ({ equal, same, teard
278
279
  const finishedSpans = exporter.getFinishedSpans()
279
280
  equal(finishedSpans.length, 0)
280
281
  })
282
+
283
+ test('should not put the URL param in path', async ({ equal, same, teardown }) => {
284
+ const handler = async (request, reply) => {
285
+ return { foo: 'bar' }
286
+ }
287
+
288
+ const injectArgs = {
289
+ method: 'GET',
290
+ url: '/test/123',
291
+ headers: {
292
+ host: 'test'
293
+ }
294
+ }
295
+
296
+ const app = await setupApp({
297
+ serviceName: 'test-service',
298
+ version: '1.0.0',
299
+ exporter: {
300
+ type: 'memory'
301
+ }
302
+ }, handler, teardown)
303
+
304
+ await app.inject(injectArgs)
305
+ const { exporter } = app.openTelemetry
306
+ const finishedSpans = exporter.getFinishedSpans()
307
+ equal(finishedSpans.length, 1)
308
+ const span = finishedSpans[0]
309
+ equal(span.kind, SpanKind.SERVER)
310
+ equal(span.name, 'GET /test/{id}')
311
+ equal(span.status.code, SpanStatusCode.OK)
312
+ equal(span.attributes['http.request.method'], 'GET')
313
+ equal(span.attributes['url.path'], '/test/{id}')
314
+ equal(span.attributes['http.response.status_code'], 200)
315
+ equal(span.attributes['url.scheme'], 'http')
316
+ equal(span.attributes['server.address'], 'test')
317
+ const resource = span.resource
318
+ same(resource.attributes['service.name'], 'test-service')
319
+ same(resource.attributes['service.version'], '1.0.0')
320
+ })