@platformatic/telemetry 0.34.0 → 0.34.1
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 +25 -7
- package/package.json +2 -1
- package/test/client.test.js +19 -13
- package/test/telemetry.test.js +13 -10
package/lib/telemetry.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const fp = require('fastify-plugin')
|
|
4
|
-
const { SpanStatusCode } = require('@opentelemetry/api')
|
|
4
|
+
const { SpanStatusCode, SpanKind } = require('@opentelemetry/api')
|
|
5
5
|
const { ConsoleSpanExporter, BatchSpanProcessor, SimpleSpanProcessor, InMemorySpanExporter } = require('@opentelemetry/sdk-trace-base')
|
|
6
6
|
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions')
|
|
7
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 fastUri = require('fast-uri')
|
|
11
12
|
|
|
12
13
|
// Platformatic telemetry plugin.
|
|
13
14
|
// Supported Exporters:
|
|
@@ -34,14 +35,19 @@ function formatSpanName (request) {
|
|
|
34
35
|
|
|
35
36
|
const defaultFormatSpanAttributes = {
|
|
36
37
|
request (request) {
|
|
38
|
+
const { hostname, method, url, protocol } = request
|
|
39
|
+
const urlData = fastUri.parse(`${protocol}://${hostname})`)
|
|
37
40
|
return {
|
|
38
|
-
'
|
|
39
|
-
'
|
|
41
|
+
'server.address': hostname,
|
|
42
|
+
'server.port': urlData.port,
|
|
43
|
+
'http.request.method': method,
|
|
44
|
+
'url.path': url,
|
|
45
|
+
'url.scheme': protocol
|
|
40
46
|
}
|
|
41
47
|
},
|
|
42
48
|
reply (reply) {
|
|
43
49
|
return {
|
|
44
|
-
'
|
|
50
|
+
'http.response.status_code': reply.statusCode
|
|
45
51
|
}
|
|
46
52
|
},
|
|
47
53
|
error (error) {
|
|
@@ -60,7 +66,7 @@ const setupProvider = (app, opts) => {
|
|
|
60
66
|
app.log.warn('No exporter configured, defaulting to console.')
|
|
61
67
|
exporter = { type: 'console' }
|
|
62
68
|
}
|
|
63
|
-
app.log.info(`Setting up telemetry for service: ${serviceName} version:
|
|
69
|
+
app.log.info(`Setting up telemetry for service: ${serviceName}${version ? ' version: ' + version : ''} with exporter of type ${exporter.type}`)
|
|
64
70
|
const provider = new PlatformaticTracerProvider({
|
|
65
71
|
resource: new Resource({
|
|
66
72
|
[SemanticResourceAttributes.SERVICE_NAME]: serviceName,
|
|
@@ -119,6 +125,7 @@ async function setupTelemetry (app, opts) {
|
|
|
119
125
|
{},
|
|
120
126
|
context
|
|
121
127
|
)
|
|
128
|
+
span.kind = SpanKind.SERVER
|
|
122
129
|
// Next 2 lines are needed by W3CTraceContextPropagator
|
|
123
130
|
context = context.setSpan(span)
|
|
124
131
|
span.setAttributes(formatSpanAttributes.request(request))
|
|
@@ -177,8 +184,19 @@ async function setupTelemetry (app, opts) {
|
|
|
177
184
|
/* istanbul ignore next */
|
|
178
185
|
method = method || ''
|
|
179
186
|
const span = tracer.startSpan(`${method} ${url}`, {}, context)
|
|
187
|
+
span.kind = SpanKind.CLIENT
|
|
188
|
+
|
|
189
|
+
const urlObj = fastUri.parse(url)
|
|
180
190
|
/* istanbul ignore next */
|
|
181
|
-
const attributes = url
|
|
191
|
+
const attributes = url
|
|
192
|
+
? {
|
|
193
|
+
'server.address': urlObj.host,
|
|
194
|
+
'server.port': urlObj.port,
|
|
195
|
+
'http.request.method': method,
|
|
196
|
+
'url.full': url,
|
|
197
|
+
'url.path': urlObj.path
|
|
198
|
+
}
|
|
199
|
+
: {}
|
|
182
200
|
span.setAttributes(attributes)
|
|
183
201
|
|
|
184
202
|
// Next 2 lines are needed by W3CTraceContextPropagator
|
|
@@ -200,7 +218,7 @@ async function setupTelemetry (app, opts) {
|
|
|
200
218
|
spanStatus.code = SpanStatusCode.ERROR
|
|
201
219
|
}
|
|
202
220
|
span.setAttributes({
|
|
203
|
-
'response.
|
|
221
|
+
'http.response.status_code': response.statusCode
|
|
204
222
|
})
|
|
205
223
|
span.setStatus(spanStatus)
|
|
206
224
|
} else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/telemetry",
|
|
3
|
-
"version": "0.34.
|
|
3
|
+
"version": "0.34.1",
|
|
4
4
|
"description": "OpenTelemetry integration for Platformatic",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"author": "Marco Piraccini <marco.piraccini@gmail.com>",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"@opentelemetry/resources": "^1.15.0",
|
|
24
24
|
"@opentelemetry/sdk-trace-base": "^1.15.0",
|
|
25
25
|
"@opentelemetry/semantic-conventions": "^1.15.0",
|
|
26
|
+
"fast-uri": "^2.2.0",
|
|
26
27
|
"fastify-plugin": "^4.5.0"
|
|
27
28
|
},
|
|
28
29
|
"scripts": {
|
package/test/client.test.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { test } = require('tap')
|
|
4
4
|
const fastify = require('fastify')
|
|
5
|
-
const { SpanStatusCode } = require('@opentelemetry/api')
|
|
5
|
+
const { SpanStatusCode, SpanKind } = require('@opentelemetry/api')
|
|
6
6
|
const telemetryPlugin = require('../lib/telemetry')
|
|
7
7
|
const { PlatformaticContext } = require('../lib/platformatic-context')
|
|
8
8
|
const { fastifyTextMapGetter } = require('../lib/fastify-text-map')
|
|
@@ -29,7 +29,6 @@ test('should add the propagation headers correctly, new propagation started', as
|
|
|
29
29
|
|
|
30
30
|
const app = await setupApp({
|
|
31
31
|
serviceName: 'test-service',
|
|
32
|
-
version: '1.0.0',
|
|
33
32
|
exporter: {
|
|
34
33
|
type: 'memory'
|
|
35
34
|
}
|
|
@@ -126,16 +125,21 @@ test('should trace a client request', async ({ equal, same, teardown }) => {
|
|
|
126
125
|
// We have two one for the client and one for the server
|
|
127
126
|
const spanServer = finishedSpans[0]
|
|
128
127
|
equal(spanServer.name, 'GET /test')
|
|
128
|
+
equal(spanServer.kind, SpanKind.SERVER)
|
|
129
129
|
equal(spanServer.status.code, SpanStatusCode.OK)
|
|
130
|
-
equal(spanServer.attributes['
|
|
131
|
-
equal(spanServer.attributes['
|
|
132
|
-
equal(spanServer.attributes['
|
|
130
|
+
equal(spanServer.attributes['http.request.method'], 'GET')
|
|
131
|
+
equal(spanServer.attributes['url.path'], '/test')
|
|
132
|
+
equal(spanServer.attributes['http.response.status_code'], 200)
|
|
133
133
|
|
|
134
134
|
const spanClient = finishedSpans[1]
|
|
135
135
|
equal(spanClient.name, 'GET http://localhost:3000/test')
|
|
136
|
+
equal(spanClient.kind, SpanKind.CLIENT)
|
|
136
137
|
equal(spanClient.status.code, SpanStatusCode.OK)
|
|
137
|
-
equal(spanClient.attributes['
|
|
138
|
-
equal(spanClient.attributes['response.
|
|
138
|
+
equal(spanClient.attributes['url.full'], 'http://localhost:3000/test')
|
|
139
|
+
equal(spanClient.attributes['http.response.status_code'], 200)
|
|
140
|
+
equal(spanClient.attributes['server.port'], 3000)
|
|
141
|
+
equal(spanClient.attributes['server.address'], 'localhost')
|
|
142
|
+
equal(spanClient.attributes['url.path'], '/test')
|
|
139
143
|
|
|
140
144
|
// The traceparent header is added to the request and propagated to the server
|
|
141
145
|
equal(receivedHeaders.traceparent, telemetryHeaders.traceparent)
|
|
@@ -175,16 +179,18 @@ test('should trace a client request failing', async ({ equal, same, teardown })
|
|
|
175
179
|
// We have two one for the client and one for the server
|
|
176
180
|
const spanServer = finishedSpans[0]
|
|
177
181
|
equal(spanServer.name, 'GET')
|
|
182
|
+
equal(spanServer.kind, SpanKind.SERVER)
|
|
178
183
|
equal(spanServer.status.code, SpanStatusCode.ERROR)
|
|
179
|
-
equal(spanServer.attributes['
|
|
180
|
-
equal(spanServer.attributes['
|
|
181
|
-
equal(spanServer.attributes['
|
|
184
|
+
equal(spanServer.attributes['http.request.method'], 'GET')
|
|
185
|
+
equal(spanServer.attributes['url.path'], '/wrong')
|
|
186
|
+
equal(spanServer.attributes['http.response.status_code'], 404)
|
|
182
187
|
|
|
183
188
|
const spanClient = finishedSpans[1]
|
|
184
189
|
equal(spanClient.name, 'GET http://localhost:3000/test')
|
|
190
|
+
equal(spanClient.kind, SpanKind.CLIENT)
|
|
185
191
|
equal(spanClient.status.code, SpanStatusCode.ERROR)
|
|
186
|
-
equal(spanClient.attributes['
|
|
187
|
-
equal(spanClient.attributes['response.
|
|
192
|
+
equal(spanClient.attributes['url.full'], 'http://localhost:3000/test')
|
|
193
|
+
equal(spanClient.attributes['http.response.status_code'], 404)
|
|
188
194
|
})
|
|
189
195
|
|
|
190
196
|
test('should trace a client request failing (no HTTP error)', async ({ equal, same, teardown }) => {
|
|
@@ -219,7 +225,7 @@ test('should trace a client request failing (no HTTP error)', async ({ equal, sa
|
|
|
219
225
|
const spanClient = finishedSpans[0]
|
|
220
226
|
equal(spanClient.name, 'GET http://localhost:3000/test')
|
|
221
227
|
equal(spanClient.status.code, SpanStatusCode.ERROR)
|
|
222
|
-
equal(spanClient.attributes['
|
|
228
|
+
equal(spanClient.attributes['url.full'], 'http://localhost:3000/test')
|
|
223
229
|
equal(spanClient.attributes['error.name'], 'Error')
|
|
224
230
|
equal(spanClient.attributes['error.message'], 'KABOOM!!!')
|
|
225
231
|
equal(spanClient.attributes['error.stack'].includes('Error: KABOOM!!!'), true)
|
package/test/telemetry.test.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { test } = require('tap')
|
|
4
4
|
const fastify = require('fastify')
|
|
5
|
-
const { SpanStatusCode } = require('@opentelemetry/api')
|
|
5
|
+
const { SpanStatusCode, SpanKind } = require('@opentelemetry/api')
|
|
6
6
|
const telemetryPlugin = require('../lib/telemetry')
|
|
7
7
|
|
|
8
8
|
async function setupApp (pluginOpts, routeHandler, teardown) {
|
|
@@ -46,11 +46,14 @@ test('should trace a request not failing', async ({ equal, same, teardown }) =>
|
|
|
46
46
|
const finishedSpans = exporter.getFinishedSpans()
|
|
47
47
|
equal(finishedSpans.length, 1)
|
|
48
48
|
const span = finishedSpans[0]
|
|
49
|
+
equal(span.kind, SpanKind.SERVER)
|
|
49
50
|
equal(span.name, 'GET /test')
|
|
50
51
|
equal(span.status.code, SpanStatusCode.OK)
|
|
51
|
-
equal(span.attributes['
|
|
52
|
-
equal(span.attributes['
|
|
53
|
-
equal(span.attributes['
|
|
52
|
+
equal(span.attributes['http.request.method'], 'GET')
|
|
53
|
+
equal(span.attributes['url.path'], '/test')
|
|
54
|
+
equal(span.attributes['http.response.status_code'], 200)
|
|
55
|
+
equal(span.attributes['url.scheme'], 'http')
|
|
56
|
+
equal(span.attributes['server.address'], 'test')
|
|
54
57
|
const resource = span.resource
|
|
55
58
|
same(resource.attributes['service.name'], 'test-service')
|
|
56
59
|
same(resource.attributes['service.version'], '1.0.0')
|
|
@@ -77,9 +80,9 @@ test('request should add attribute to a span', async ({ equal, same, teardown })
|
|
|
77
80
|
const span = finishedSpans[0]
|
|
78
81
|
equal(span.name, 'GET /test')
|
|
79
82
|
equal(span.status.code, SpanStatusCode.OK)
|
|
80
|
-
equal(span.attributes['
|
|
81
|
-
equal(span.attributes['
|
|
82
|
-
equal(span.attributes['
|
|
83
|
+
equal(span.attributes['http.request.method'], 'GET')
|
|
84
|
+
equal(span.attributes['url.path'], '/test')
|
|
85
|
+
equal(span.attributes['http.response.status_code'], 200)
|
|
83
86
|
// This is the attribute we added
|
|
84
87
|
equal(span.attributes.foo, 'bar')
|
|
85
88
|
const resource = span.resource
|
|
@@ -127,9 +130,9 @@ test('should trace a request that fails', async ({ equal, same, teardown }) => {
|
|
|
127
130
|
const span = finishedSpans[0]
|
|
128
131
|
equal(span.name, 'GET /test')
|
|
129
132
|
equal(span.status.code, SpanStatusCode.ERROR)
|
|
130
|
-
equal(span.attributes['
|
|
131
|
-
equal(span.attributes['
|
|
132
|
-
equal(span.attributes['
|
|
133
|
+
equal(span.attributes['http.request.method'], 'GET')
|
|
134
|
+
equal(span.attributes['url.path'], '/test')
|
|
135
|
+
equal(span.attributes['http.response.status_code'], 500)
|
|
133
136
|
equal(span.attributes['error.message'], 'booooom!!!')
|
|
134
137
|
const resource = span.resource
|
|
135
138
|
same(resource.attributes['service.name'], 'test-service')
|