Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@fastify/otel

Package Overview
Dependencies
Maintainers
16
Versions
27
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@fastify/otel - npm Package Compare versions

Comparing version
0.17.1
to
0.18.0
+12
-0
CHANGELOG.md

@@ -5,2 +5,14 @@ # Changelog

## [0.18.0](https://github.com/fastify/otel/compare/v0.17.1...v0.18.0) (2026-03-26)
### Features
* remove setStatus(OK) calls to comply with OTel spec ([#135](https://github.com/fastify/otel/issues/135)) ([9ff035c](https://github.com/fastify/otel/commit/9ff035c60aa5ec72bee8cbad0837dbbc80ec4e2f))
### Bug Fixes
* support fastify/websocket handlers (fastify/otel[#136](https://github.com/fastify/otel/issues/136)) ([#137](https://github.com/fastify/otel/issues/137)) ([cc9c6b5](https://github.com/fastify/otel/commit/cc9c6b5ad8ae5c88da03e6537f8b494d3d506b8d))
### [0.17.1](https://github.com/fastify/otel/compare/v0.17.0...v0.17.1) (2026-03-03)

@@ -7,0 +19,0 @@

+21
-11

@@ -323,8 +323,4 @@ 'use strict'

if (span != null) {
span.setStatus({
code: SpanStatusCode.OK,
message: 'OK'
})
span.setAttributes({
[ATTR_HTTP_RESPONSE_STATUS_CODE]: 404
[ATTR_HTTP_RESPONSE_STATUS_CODE]: reply.statusCode
})

@@ -349,7 +345,4 @@ span.end()

if (span != null) {
if (reply.statusCode < 500) {
span.setStatus({
code: SpanStatusCode.OK,
message: 'OK'
})
if (reply.statusCode >= 500) {
span.setStatus({ code: SpanStatusCode.ERROR })
}

@@ -453,2 +446,12 @@

// regular handlers are (request, reply), @fastify/websocket handlers are (socket, request)
function getRequestFromArgs (args) {
for (const arg of args) {
if (arg?.routeOptions && arg.url && arg.method) {
return arg
}
}
return null
}
function handlerWrapper (handler, hookName, spanAttributes = {}) {

@@ -458,4 +461,11 @@ return function handlerWrapped (...args) {

const instrumentation = this[kInstrumentation]
const [request] = args
const request = getRequestFromArgs(args)
if (request === null) {
instrumentation.logger.debug(
`Ignoring route instrumentation because ${hookName} was called without a Fastify request argument`
)
return handler.call(this, ...args)
}
if (instrumentation.isEnabled() === false || request.routeOptions.config?.otel === false) {

@@ -462,0 +472,0 @@ instrumentation.logger.debug(

{
"name": "@fastify/otel",
"version": "0.17.1",
"version": "0.18.0",
"description": "Official Fastify OpenTelemetry Instrumentation",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -74,2 +74,7 @@ # @fastify/otel

If the main request handler is not of the form `(request, reply)` (for example, `@fastify/websocket`
handlers take the form `(socket, request)`), the plugin attempts to find the Fastify request object
in any of the handler's arguments. If no request object can be found, instrumentation is skipped and
a debug level message is logged.
### Registration using OpenTelemetry Node SDK

@@ -76,0 +81,0 @@

@@ -339,2 +339,4 @@ 'use strict'

assert.equal(start.status.code, SpanStatusCode.UNSET)
assert.equal(end.name, 'handler - fastify -> @fastify/otel')

@@ -761,2 +763,3 @@ assert.deepStrictEqual(end.attributes, {

assert.equal(preHandler.status.code, SpanStatusCode.ERROR)
assert.equal(start.status.code, SpanStatusCode.ERROR)
assert.equal(preHandler.parentSpanContext.spanId, start.spanContext().spanId)

@@ -799,2 +802,3 @@ assert.equal(response.status, 500)

})
assert.equal(start.status.code, SpanStatusCode.UNSET)
})

@@ -1061,2 +1065,99 @@

test('should create span when wrapped handler is invoked as (socket, request)', async t => {
const app = Fastify()
const plugin = instrumentation.plugin()
await app.register(plugin)
app.addHook('onRoute', (routeOptions) => {
const { handler } = routeOptions
routeOptions.handler = function websocketLikeHandler (request, _reply) {
const socket = { readyState: 1 }
return handler.call(this, socket, request)
}
})
app.get('/', async function wsHandler (_socket, request) {
assert.equal(request.method, 'GET')
return 'hello world'
})
await app.listen()
after(() => app.close())
const response = await fetch(
`http://localhost:${app.server.address().port}/`
)
const spans = memoryExporter
.getFinishedSpans()
.filter(span => span.instrumentationScope.name === '@fastify/otel')
const [end, start] = spans
assert.equal(spans.length, 2)
assert.deepStrictEqual(start.attributes, {
'fastify.root': '@fastify/otel',
'http.route': '/',
'url.path': '/',
'http.request.method': 'GET',
'http.response.status_code': 200
})
assert.deepStrictEqual(end.attributes, {
'hook.name': 'fastify -> @fastify/otel - route-handler',
'fastify.type': 'request-handler',
'http.route': '/',
'hook.callback.name': 'wsHandler'
})
assert.equal(end.parentSpanContext.spanId, start.spanContext().spanId)
assert.equal(response.status, 200)
assert.equal(await response.text(), 'hello world')
})
test('should fallback when wrapped handler is invoked without request argument', async t => {
const app = Fastify()
const plugin = instrumentation.plugin()
await app.register(plugin)
app.addHook('onRoute', (routeOptions) => {
const { handler } = routeOptions
routeOptions.handler = function callWithoutRequest (_request, _reply) {
return handler.call(this)
}
})
app.get('/', async function wsHandlerWithoutRequest () {
return 'hello world'
})
await app.listen()
after(() => app.close())
const response = await fetch(
`http://localhost:${app.server.address().port}/`
)
const spans = memoryExporter
.getFinishedSpans()
.filter(span => span.instrumentationScope.name === '@fastify/otel')
const [start] = spans
assert.equal(spans.length, 1)
assert.deepStrictEqual(start.attributes, {
'fastify.root': '@fastify/otel',
'http.route': '/',
'url.path': '/',
'http.request.method': 'GET',
'http.response.status_code': 200
})
assert.equal(response.status, 200)
assert.equal(await response.text(), 'hello world')
})
test('should end spans upon error', async t => {

@@ -1108,2 +1209,3 @@ const app = Fastify()

})
assert.equal(start.status.code, SpanStatusCode.ERROR)
assert.equal(end.parentSpanContext.spanId, start.spanContext().spanId)

@@ -1110,0 +1212,0 @@ assert.equal(response.status, 500)