@platformatic/telemetry 0.46.1 → 0.46.2

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
@@ -31,8 +31,9 @@ const { name: moduleName, version: moduleVersion } = require('../package.json')
31
31
  const extractPath = (request) => {
32
32
  // We must user RouterPath, because otherwise `/test/123` will be considered as
33
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
34
+ const { routeOptions, url } = request
35
35
  let path
36
+ const routerPath = routeOptions && routeOptions.url
36
37
  if (routerPath) {
37
38
  path = formatParamUrl(routerPath)
38
39
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/telemetry",
3
- "version": "0.46.1",
3
+ "version": "0.46.2",
4
4
  "description": "OpenTelemetry integration for Platformatic",
5
5
  "main": "index.js",
6
6
  "author": "Marco Piraccini <marco.piraccini@gmail.com>",
@@ -1,283 +0,0 @@
1
- 'use strict'
2
-
3
- const { test } = require('tap')
4
- const fastify = require('fastify')
5
- const { SpanStatusCode, SpanKind } = require('@opentelemetry/api')
6
- const telemetryPlugin = require('../lib/telemetry')
7
- const { PlatformaticContext } = require('../lib/platformatic-context')
8
- const { fastifyTextMapGetter } = require('../lib/fastify-text-map')
9
-
10
- async function setupApp (pluginOpts, routeHandler, teardown) {
11
- const app = fastify()
12
- await app.register(telemetryPlugin, pluginOpts)
13
- app.get('/test', routeHandler)
14
- app.ready()
15
- teardown(async () => {
16
- await app.close()
17
- const { exporters } = app.openTelemetry
18
- exporters.forEach(exporter => {
19
- if (exporter.constructor.name === 'InMemorySpanExporter') {
20
- exporter.reset()
21
- }
22
- })
23
- })
24
- return app
25
- }
26
-
27
- test('should add the propagation headers correctly, new propagation started', async ({ equal, same, teardown }) => {
28
- const handler = async (request, reply) => {
29
- return { foo: 'bar' }
30
- }
31
-
32
- const app = await setupApp({
33
- serviceName: 'test-service',
34
- exporter: {
35
- type: 'memory'
36
- }
37
- }, handler, teardown)
38
-
39
- const { startSpanClient } = app.openTelemetry
40
-
41
- const url = 'http://localhost:3000/test'
42
- const { span, telemetryHeaders } = startSpanClient(url, 'GET')
43
-
44
- const spanId = span._spanContext.spanId
45
- const traceId = span._spanContext.traceId
46
- same(telemetryHeaders, {
47
- traceparent: `00-${traceId}-${spanId}-01`
48
- })
49
- })
50
-
51
- test('should add the propagation headers correctly, with propagation already started', async ({ equal, same, teardown }) => {
52
- const traceId = '5e994e8fb53b27c91dcd2fec22771d15'
53
- const spanId = '166f3ab30f21800b'
54
- const traceparent = `00-${traceId}-${spanId}-01`
55
-
56
- const handler = async (request, reply) => {
57
- return { foo: 'bar' }
58
- }
59
-
60
- const app = await setupApp({
61
- serviceName: 'test-service',
62
- version: '1.0.0',
63
- exporter: {
64
- type: 'memory'
65
- }
66
- }, handler, teardown)
67
-
68
- const { startSpanClient } = app.openTelemetry
69
-
70
- const url = 'http://localhost:3000/test'
71
- const incomingHeaders = {
72
- host: 'test',
73
- traceparent
74
- }
75
- const { propagator } = app.openTelemetry
76
- const context = propagator.extract(new PlatformaticContext(), { headers: incomingHeaders }, fastifyTextMapGetter)
77
-
78
- const { span, telemetryHeaders } = startSpanClient(url, 'GET', context)
79
-
80
- const spanId2 = span._spanContext.spanId
81
- const traceId2 = span._spanContext.traceId
82
-
83
- // We preserved the tracedId
84
- same(traceId, traceId2)
85
- same(telemetryHeaders, {
86
- traceparent: `00-${traceId}-${spanId2}-01`
87
- })
88
- })
89
-
90
- test('should trace a client request', async ({ equal, same, teardown }) => {
91
- let receivedHeaders = null
92
- const handler = async (request, reply) => {
93
- receivedHeaders = request.headers
94
- return { foo: 'bar' }
95
- }
96
-
97
- const app = await setupApp({
98
- serviceName: 'test-service',
99
- version: '1.0.0',
100
- exporter: {
101
- type: 'memory'
102
- }
103
- }, handler, teardown)
104
-
105
- const { startSpanClient, endSpanClient } = app.openTelemetry
106
-
107
- const url = 'http://localhost:3000/test'
108
-
109
- const { propagator } = app.openTelemetry
110
- const context = propagator.extract(new PlatformaticContext(), { headers: {} }, fastifyTextMapGetter)
111
-
112
- const { span, telemetryHeaders } = startSpanClient(url, 'GET', context)
113
- const args = {
114
- method: 'GET',
115
- url: '/test',
116
- headers: {
117
- ...telemetryHeaders
118
- }
119
- }
120
-
121
- const response = await app.inject(args)
122
- endSpanClient(span, response)
123
-
124
- const { exporters } = app.openTelemetry
125
- const exporter = exporters[0]
126
- const finishedSpans = exporter.getFinishedSpans()
127
- equal(finishedSpans.length, 2)
128
- // We have two one for the client and one for the server
129
- const spanServer = finishedSpans[0]
130
- equal(spanServer.name, 'GET /test')
131
- equal(spanServer.kind, SpanKind.SERVER)
132
- equal(spanServer.status.code, SpanStatusCode.OK)
133
- equal(spanServer.attributes['http.request.method'], 'GET')
134
- equal(spanServer.attributes['url.path'], '/test')
135
- equal(spanServer.attributes['http.response.status_code'], 200)
136
-
137
- const spanClient = finishedSpans[1]
138
- equal(spanClient.name, 'GET http://localhost:3000/test')
139
- equal(spanClient.kind, SpanKind.CLIENT)
140
- equal(spanClient.status.code, SpanStatusCode.OK)
141
- equal(spanClient.attributes['url.full'], 'http://localhost:3000/test')
142
- equal(spanClient.attributes['http.response.status_code'], 200)
143
- equal(spanClient.attributes['server.port'], 3000)
144
- equal(spanClient.attributes['server.address'], 'localhost')
145
- equal(spanClient.attributes['url.path'], '/test')
146
-
147
- // The traceparent header is added to the request and propagated to the server
148
- equal(receivedHeaders.traceparent, telemetryHeaders.traceparent)
149
- })
150
-
151
- test('should trace a client request failing', async ({ equal, same, teardown }) => {
152
- const handler = async (request, reply) => {
153
- return { foo: 'bar' }
154
- }
155
-
156
- const app = await setupApp({
157
- serviceName: 'test-service',
158
- version: '1.0.0',
159
- exporter: {
160
- type: 'memory'
161
- }
162
- }, handler, teardown)
163
-
164
- const { startSpanClient, endSpanClient } = app.openTelemetry
165
-
166
- const { propagator } = app.openTelemetry
167
- const context = propagator.extract(new PlatformaticContext(), { headers: {} }, fastifyTextMapGetter)
168
-
169
- const url = 'http://localhost:3000/test'
170
- const { span, telemetryHeaders } = startSpanClient(url, 'GET', context)
171
- const args = {
172
- method: 'GET',
173
- url: '/wrong',
174
- headers: telemetryHeaders
175
- }
176
- const response = await app.inject(args)
177
- endSpanClient(span, response)
178
-
179
- const { exporters } = app.openTelemetry
180
- const exporter = exporters[0]
181
-
182
- const finishedSpans = exporter.getFinishedSpans()
183
- equal(finishedSpans.length, 2)
184
- // We have two one for the client and one for the server
185
- const spanServer = finishedSpans[0]
186
- equal(spanServer.name, 'GET /wrong')
187
- equal(spanServer.kind, SpanKind.SERVER)
188
- equal(spanServer.status.code, SpanStatusCode.ERROR)
189
- equal(spanServer.attributes['http.request.method'], 'GET')
190
- equal(spanServer.attributes['url.path'], '/wrong')
191
- equal(spanServer.attributes['http.response.status_code'], 404)
192
-
193
- const spanClient = finishedSpans[1]
194
- equal(spanClient.name, 'GET http://localhost:3000/test')
195
- equal(spanClient.kind, SpanKind.CLIENT)
196
- equal(spanClient.status.code, SpanStatusCode.ERROR)
197
- equal(spanClient.attributes['url.full'], 'http://localhost:3000/test')
198
- equal(spanClient.attributes['http.response.status_code'], 404)
199
- })
200
-
201
- test('should trace a client request failing (no HTTP error)', async ({ equal, same, teardown }) => {
202
- const handler = async (request, reply) => {
203
- return { foo: 'bar' }
204
- }
205
-
206
- const app = await setupApp({
207
- serviceName: 'test-service',
208
- version: '1.0.0',
209
- exporter: {
210
- type: 'memory'
211
- }
212
- }, handler, teardown)
213
-
214
- const { startSpanClient, endSpanClient, setErrorInSpanClient } = app.openTelemetry
215
-
216
- const url = 'http://localhost:3000/test'
217
- const { span } = startSpanClient(url, 'GET')
218
- try {
219
- throw new Error('KABOOM!!!')
220
- } catch (err) {
221
- setErrorInSpanClient(span, err)
222
- } finally {
223
- endSpanClient(span)
224
- }
225
-
226
- const { exporters } = app.openTelemetry
227
- const exporter = exporters[0]
228
- const finishedSpans = exporter.getFinishedSpans()
229
- equal(finishedSpans.length, 1)
230
-
231
- const spanClient = finishedSpans[0]
232
- equal(spanClient.name, 'GET http://localhost:3000/test')
233
- equal(spanClient.status.code, SpanStatusCode.ERROR)
234
- equal(spanClient.attributes['url.full'], 'http://localhost:3000/test')
235
- equal(spanClient.attributes['error.name'], 'Error')
236
- equal(spanClient.attributes['error.message'], 'KABOOM!!!')
237
- equal(spanClient.attributes['error.stack'].includes('Error: KABOOM!!!'), true)
238
- })
239
-
240
- test('should not add the query in span name', async ({ equal, same, teardown }) => {
241
- const handler = async (request, reply) => {
242
- return { foo: 'bar' }
243
- }
244
-
245
- const app = await setupApp({
246
- serviceName: 'test-service',
247
- exporter: {
248
- type: 'memory'
249
- }
250
- }, handler, teardown)
251
-
252
- const { startSpanClient } = app.openTelemetry
253
-
254
- const url = 'http://localhost:3000/test?foo=bar'
255
- const { span } = startSpanClient(url, 'GET')
256
- same(span.name, 'GET http://localhost:3000/test')
257
- })
258
-
259
- test('should ignore the skipped operations', async ({ equal, same, ok, teardown }) => {
260
- const handler = async (request, reply) => {
261
- return { foo: 'bar' }
262
- }
263
-
264
- const app = await setupApp({
265
- serviceName: 'test-service',
266
- skip: [
267
- {
268
- path: '/skipme',
269
- method: 'POST'
270
- }
271
- ],
272
- exporter: {
273
- type: 'memory'
274
- }
275
- }, handler, teardown)
276
-
277
- const { startSpanClient } = app.openTelemetry
278
-
279
- const url = 'http://localhost:3000/skipme'
280
- const ret = startSpanClient(url, 'POST')
281
- // no spam should be created
282
- ok(!ret)
283
- })
@@ -1,81 +0,0 @@
1
- 'use strict'
2
-
3
- const { test } = require('tap')
4
- const { MultiSpanProcessor } = require('../lib/multispan-processor')
5
-
6
- test('should add multiple processors', async ({ equal, same, teardown }) => {
7
- const mockSpanProcessor = {
8
- onStart: () => {},
9
- onEnd: () => {},
10
- shutdown: async () => {},
11
- forceFlush: async () => {}
12
- }
13
- const processor = new MultiSpanProcessor()
14
- equal(processor._spanProcessors.length, 0)
15
-
16
- {
17
- const processor = new MultiSpanProcessor([mockSpanProcessor, mockSpanProcessor])
18
- equal(processor._spanProcessors.length, 2)
19
- }
20
- })
21
-
22
- test('should call onStart on every processor', async ({ equal, same, teardown }) => {
23
- let called1 = false
24
- let called2 = false
25
- const mockSpanProcessor1 = {
26
- onStart: () => { called1 = true }
27
- }
28
- const mockSpanProcessor2 = {
29
- called: false,
30
- onStart: () => { called2 = true }
31
- }
32
- const processor = new MultiSpanProcessor([mockSpanProcessor1, mockSpanProcessor2])
33
- processor.onStart()
34
- equal(called1, true)
35
- equal(called2, true)
36
- })
37
-
38
- test('should call onEnd on every processor', async ({ equal, same, teardown }) => {
39
- let called1 = false
40
- let called2 = false
41
- const mockSpanProcessor1 = {
42
- onEnd: () => { called1 = true }
43
- }
44
- const mockSpanProcessor2 = {
45
- onEnd: () => { called2 = true }
46
- }
47
- const processor = new MultiSpanProcessor([mockSpanProcessor1, mockSpanProcessor2])
48
- processor.onEnd()
49
- equal(called1, true)
50
- equal(called2, true)
51
- })
52
-
53
- test('should call shutdown on every processor', async ({ equal, same, teardown }) => {
54
- let called1 = false
55
- let called2 = false
56
- const mockSpanProcessor1 = {
57
- shutdown: async () => { called1 = true }
58
- }
59
- const mockSpanProcessor2 = {
60
- shutdown: async () => { called2 = true }
61
- }
62
- const processor = new MultiSpanProcessor([mockSpanProcessor1, mockSpanProcessor2])
63
- await processor.shutdown()
64
- equal(called1, true)
65
- equal(called2, true)
66
- })
67
-
68
- test('should call forceFlush on every processor', async ({ equal, same, teardown }) => {
69
- let called1 = false
70
- let called2 = false
71
- const mockSpanProcessor1 = {
72
- forceFlush: async () => { called1 = true }
73
- }
74
- const mockSpanProcessor2 = {
75
- forceFlush: async () => { called2 = true }
76
- }
77
- const processor = new MultiSpanProcessor([mockSpanProcessor1, mockSpanProcessor2])
78
- await processor.forceFlush()
79
- equal(called1, true)
80
- equal(called2, true)
81
- })
@@ -1,46 +0,0 @@
1
- 'use strict'
2
-
3
- const { test } = require('tap')
4
- const { PlatformaticTracerProvider } = require('../lib/platformatic-trace-provider')
5
-
6
- test('should propagate forceFlush to all registered processors ', async ({ equal, same, teardown }) => {
7
- let called1 = false
8
- let called2 = false
9
- const mockSpanProcessor1 = {
10
- forceFlush: async () => { called1 = true }
11
- }
12
- const mockSpanProcessor2 = {
13
- forceFlush: async () => { called2 = true }
14
- }
15
- const provider = new PlatformaticTracerProvider()
16
- equal(provider._registeredSpanProcessors.length, 0)
17
-
18
- provider.addSpanProcessor(mockSpanProcessor1)
19
- provider.addSpanProcessor(mockSpanProcessor2)
20
-
21
- equal(provider._registeredSpanProcessors.length, 2)
22
- await provider.forceFlush()
23
- equal(called1, true)
24
- equal(called2, true)
25
- })
26
-
27
- test('should propagate shutdown to the active span processor, which should propagate to all the processors ', async ({ equal, same, teardown }) => {
28
- let called1 = false
29
- let called2 = false
30
- const mockSpanProcessor1 = {
31
- shutdown: async () => { called1 = true }
32
- }
33
- const mockSpanProcessor2 = {
34
- shutdown: async () => { called2 = true }
35
- }
36
- const provider = new PlatformaticTracerProvider()
37
- equal(provider._registeredSpanProcessors.length, 0)
38
-
39
- provider.addSpanProcessor(mockSpanProcessor1)
40
- provider.addSpanProcessor(mockSpanProcessor2)
41
-
42
- equal(provider._registeredSpanProcessors.length, 2)
43
- await provider.shutdown()
44
- equal(called1, true)
45
- equal(called2, true)
46
- })
@@ -1,383 +0,0 @@
1
- 'use strict'
2
-
3
- const { test } = require('tap')
4
- const fastify = require('fastify')
5
- const { SpanStatusCode, SpanKind } = require('@opentelemetry/api')
6
- const telemetryPlugin = require('../lib/telemetry')
7
-
8
- async function setupApp (pluginOpts, routeHandler, teardown) {
9
- const app = fastify()
10
- await app.register(telemetryPlugin, pluginOpts)
11
- app.get('/test', routeHandler)
12
- app.get('/test/:id', routeHandler)
13
- app.ready()
14
- teardown(async () => {
15
- await app.close()
16
- const { exporters } = app.openTelemetry
17
- exporters.forEach(exporter => {
18
- if (exporter.constructor.name === 'InMemorySpanExporter') {
19
- exporter.reset()
20
- }
21
- })
22
- })
23
- return app
24
- }
25
-
26
- const injectArgs = {
27
- method: 'GET',
28
- url: '/test',
29
- headers: {
30
- host: 'test'
31
- }
32
- }
33
-
34
- test('should trace a request not failing', async ({ equal, same, teardown }) => {
35
- const handler = async (request, reply) => {
36
- return { foo: 'bar' }
37
- }
38
-
39
- const app = await setupApp({
40
- serviceName: 'test-service',
41
- version: '1.0.0',
42
- exporter: {
43
- type: 'memory'
44
- }
45
- }, handler, teardown)
46
-
47
- await app.inject(injectArgs)
48
- const { exporters } = app.openTelemetry
49
- const exporter = exporters[0]
50
- const finishedSpans = exporter.getFinishedSpans()
51
- equal(finishedSpans.length, 1)
52
- const span = finishedSpans[0]
53
- equal(span.kind, SpanKind.SERVER)
54
- equal(span.name, 'GET /test')
55
- equal(span.status.code, SpanStatusCode.OK)
56
- equal(span.attributes['http.request.method'], 'GET')
57
- equal(span.attributes['url.path'], '/test')
58
- equal(span.attributes['http.response.status_code'], 200)
59
- equal(span.attributes['url.scheme'], 'http')
60
- equal(span.attributes['server.address'], 'test')
61
- const resource = span.resource
62
- same(resource.attributes['service.name'], 'test-service')
63
- same(resource.attributes['service.version'], '1.0.0')
64
- })
65
-
66
- test('should not put query in `url.path', async ({ equal, same, teardown }) => {
67
- const handler = async (request, reply) => {
68
- return { foo: 'bar' }
69
- }
70
-
71
- const injectArgs = {
72
- method: 'GET',
73
- url: '/test?foo=bar',
74
- headers: {
75
- host: 'test'
76
- }
77
- }
78
-
79
- const app = await setupApp({
80
- serviceName: 'test-service',
81
- version: '1.0.0',
82
- exporter: {
83
- type: 'memory'
84
- }
85
- }, handler, teardown)
86
-
87
- await app.inject(injectArgs)
88
- const { exporters } = app.openTelemetry
89
- const exporter = exporters[0]
90
- const finishedSpans = exporter.getFinishedSpans()
91
- equal(finishedSpans.length, 1)
92
- const span = finishedSpans[0]
93
- equal(span.kind, SpanKind.SERVER)
94
- equal(span.name, 'GET /test')
95
- equal(span.status.code, SpanStatusCode.OK)
96
- equal(span.attributes['http.request.method'], 'GET')
97
- equal(span.attributes['url.path'], '/test')
98
- equal(span.attributes['http.response.status_code'], 200)
99
- equal(span.attributes['url.scheme'], 'http')
100
- equal(span.attributes['server.address'], 'test')
101
- const resource = span.resource
102
- same(resource.attributes['service.name'], 'test-service')
103
- same(resource.attributes['service.version'], '1.0.0')
104
- })
105
-
106
- test('request should add attribute to a span', async ({ equal, same, teardown }) => {
107
- const handler = async (request, reply) => {
108
- request.span.setAttribute('foo', 'bar')
109
- return { foo: 'bar' }
110
- }
111
-
112
- const app = await setupApp({
113
- serviceName: 'test-service',
114
- version: '1.0.0',
115
- exporter: {
116
- type: 'memory'
117
- }
118
- }, handler, teardown)
119
-
120
- await app.inject(injectArgs)
121
- const { exporters } = app.openTelemetry
122
- const exporter = exporters[0]
123
- const finishedSpans = exporter.getFinishedSpans()
124
- equal(finishedSpans.length, 1)
125
- const span = finishedSpans[0]
126
- equal(span.name, 'GET /test')
127
- equal(span.status.code, SpanStatusCode.OK)
128
- equal(span.attributes['http.request.method'], 'GET')
129
- equal(span.attributes['url.path'], '/test')
130
- equal(span.attributes['http.response.status_code'], 200)
131
- // This is the attribute we added
132
- equal(span.attributes.foo, 'bar')
133
- const resource = span.resource
134
- same(resource.attributes['service.name'], 'test-service')
135
- same(resource.attributes['service.version'], '1.0.0')
136
- })
137
-
138
- test('should be able to set the W3C trace context', async ({ equal, same, teardown, ok }) => {
139
- const handler = async (request, reply) => {
140
- const context = request.openTelemetry().span.context
141
- const newContext = context.setValue('foo', 'bar')
142
- request.openTelemetry().span.context = newContext
143
- return { foo: 'bar' }
144
- }
145
-
146
- const app = await setupApp({
147
- serviceName: 'test-service',
148
- version: '1.0.0',
149
- exporter: {
150
- type: 'memory'
151
- }
152
- }, handler, teardown)
153
-
154
- const response = await app.inject(injectArgs)
155
- // see: https://www.w3.org/TR/trace-context/#design-overview
156
- ok(response.headers.traceparent)
157
- })
158
-
159
- test('should trace a request that fails', async ({ equal, same, teardown }) => {
160
- const handler = async (request, reply) => {
161
- throw new Error('booooom!!!')
162
- }
163
- const app = await setupApp({
164
- serviceName: 'test-service',
165
- version: '1.0.0',
166
- exporter: {
167
- type: 'memory'
168
- }
169
- }, handler, teardown)
170
-
171
- await app.inject(injectArgs)
172
- const { exporters } = app.openTelemetry
173
- const exporter = exporters[0]
174
- const finishedSpans = exporter.getFinishedSpans()
175
- equal(finishedSpans.length, 1)
176
- const span = finishedSpans[0]
177
- equal(span.name, 'GET /test')
178
- equal(span.status.code, SpanStatusCode.ERROR)
179
- equal(span.attributes['http.request.method'], 'GET')
180
- equal(span.attributes['url.path'], '/test')
181
- equal(span.attributes['http.response.status_code'], 500)
182
- equal(span.attributes['error.message'], 'booooom!!!')
183
- const resource = span.resource
184
- same(resource.attributes['service.name'], 'test-service')
185
- same(resource.attributes['service.version'], '1.0.0')
186
- })
187
-
188
- test('if no exporter is configured, should default to console', async ({ equal, same, teardown }) => {
189
- const handler = async (request, reply) => {
190
- return {}
191
- }
192
- const app = await setupApp({
193
- serviceName: 'test-service',
194
- version: '1.0.0'
195
- }, handler, teardown)
196
-
197
- await app.inject(injectArgs)
198
- const { exporters } = app.openTelemetry
199
- const exporter = exporters[0]
200
- same(exporter.constructor.name, 'ConsoleSpanExporter')
201
- })
202
-
203
- test('should configure OTLP correctly', async ({ equal, same, teardown }) => {
204
- const handler = async (request, reply) => {
205
- return {}
206
- }
207
- const app = await setupApp({
208
- serviceName: 'test-service',
209
- version: '1.0.0',
210
- exporter: {
211
- type: 'otlp',
212
- options: {
213
- url: 'http://localhost:4317'
214
- }
215
- }
216
- }, handler, teardown)
217
-
218
- const { exporters } = app.openTelemetry
219
- const exporter = exporters[0]
220
- same(exporter.constructor.name, 'OTLPTraceExporter')
221
- same(exporter.url, 'http://localhost:4317')
222
- })
223
-
224
- test('should configure Zipkin correctly', async ({ equal, same, teardown }) => {
225
- const handler = async (request, reply) => {
226
- return {}
227
- }
228
- const app = await setupApp({
229
- serviceName: 'test-service',
230
- version: '1.0.0',
231
- exporter: {
232
- type: 'zipkin',
233
- options: {
234
- url: 'http://localhost:9876'
235
- }
236
- }
237
- }, handler, teardown)
238
-
239
- const { exporters } = app.openTelemetry
240
- const exporter = exporters[0]
241
- same(exporter.constructor.name, 'ZipkinExporter')
242
- same(exporter._urlStr, 'http://localhost:9876')
243
- })
244
-
245
- test('wrong exporter is configured, should default to console', async ({ equal, same, teardown }) => {
246
- const handler = async (request, reply) => {
247
- return {}
248
- }
249
- const app = await setupApp({
250
- serviceName: 'test-service',
251
- version: '1.0.0',
252
- exporter: {
253
- type: 'wrong-exporter'
254
- }
255
- }, handler, teardown)
256
-
257
- await app.inject(injectArgs)
258
- const { exporters } = app.openTelemetry
259
- const exporter = exporters[0]
260
- same(exporter.constructor.name, 'ConsoleSpanExporter')
261
- })
262
-
263
- test('should not trace if the operation is skipped', async ({ equal, same, teardown }) => {
264
- const handler = async (request, reply) => {
265
- return { foo: 'bar' }
266
- }
267
-
268
- const app = await setupApp({
269
- serviceName: 'test-service',
270
- version: '1.0.0',
271
- skip: [{
272
- path: '/documentation/json',
273
- method: 'GET'
274
- }],
275
- exporter: {
276
- type: 'memory'
277
- }
278
- }, handler, teardown)
279
-
280
- const injectArgs = {
281
- method: 'GET',
282
- url: '/documentation/json',
283
- headers: {
284
- host: 'test'
285
- }
286
- }
287
-
288
- await app.inject(injectArgs)
289
- const { exporters } = app.openTelemetry
290
- const exporter = exporters[0]
291
- const finishedSpans = exporter.getFinishedSpans()
292
- equal(finishedSpans.length, 0)
293
- })
294
-
295
- test('should not put the URL param in path', async ({ equal, same, teardown }) => {
296
- const handler = async (request, reply) => {
297
- return { foo: 'bar' }
298
- }
299
-
300
- const injectArgs = {
301
- method: 'GET',
302
- url: '/test/123',
303
- headers: {
304
- host: 'test'
305
- }
306
- }
307
-
308
- const app = await setupApp({
309
- serviceName: 'test-service',
310
- version: '1.0.0',
311
- exporter: {
312
- type: 'memory'
313
- }
314
- }, handler, teardown)
315
-
316
- await app.inject(injectArgs)
317
- const { exporters } = app.openTelemetry
318
- const exporter = exporters[0]
319
- const finishedSpans = exporter.getFinishedSpans()
320
- equal(finishedSpans.length, 1)
321
- const span = finishedSpans[0]
322
- equal(span.kind, SpanKind.SERVER)
323
- equal(span.name, 'GET /test/{id}')
324
- equal(span.status.code, SpanStatusCode.OK)
325
- equal(span.attributes['http.request.method'], 'GET')
326
- equal(span.attributes['url.path'], '/test/{id}')
327
- equal(span.attributes['http.response.status_code'], 200)
328
- equal(span.attributes['url.scheme'], 'http')
329
- equal(span.attributes['server.address'], 'test')
330
- const resource = span.resource
331
- same(resource.attributes['service.name'], 'test-service')
332
- same(resource.attributes['service.version'], '1.0.0')
333
- })
334
-
335
- test('should configure an exporter as an array', async ({ equal, same, teardown }) => {
336
- const handler = async (request, reply) => {
337
- return {}
338
- }
339
- const app = await setupApp({
340
- serviceName: 'test-service',
341
- version: '1.0.0',
342
- exporter: [{
343
- type: 'otlp',
344
- options: {
345
- url: 'http://localhost:4317'
346
- }
347
- }]
348
- }, handler, teardown)
349
- const { exporters } = app.openTelemetry
350
- const exporter = exporters[0]
351
- same(exporter.constructor.name, 'OTLPTraceExporter')
352
- same(exporter.url, 'http://localhost:4317')
353
- })
354
-
355
- test('should use multiple exporters and sent traces to all the exporters', async ({ equal, same, teardown }) => {
356
- const handler = async (request, reply) => {
357
- return {}
358
- }
359
- const app = await setupApp({
360
- serviceName: 'test-service',
361
- version: '1.0.0',
362
- exporter: [{
363
- type: 'memory'
364
- }, {
365
- type: 'memory'
366
- }]
367
- }, handler, teardown)
368
- const { exporters } = app.openTelemetry
369
-
370
- await app.inject(injectArgs)
371
-
372
- const finishedSpans0 = exporters[0].getFinishedSpans()
373
- equal(finishedSpans0.length, 1)
374
- const span0 = finishedSpans0[0]
375
- equal(span0.name, 'GET /test')
376
- equal(span0.status.code, SpanStatusCode.OK)
377
-
378
- const finishedSpans1 = exporters[1].getFinishedSpans()
379
- equal(finishedSpans1.length, 1)
380
- const span1 = finishedSpans1[0]
381
- equal(span1.name, 'GET /test')
382
- equal(span1.status.code, SpanStatusCode.OK)
383
- })