Skip to content

Commit

Permalink
feat(#14): If possible, set serverName as per General SDK Configurati…
Browse files Browse the repository at this point in the history
…on, use process.env.OTEL_SERVICE_NAME; (#17)

Co-authored-by: James Sumners <[email protected]>
  • Loading branch information
tskorupka and jsumners authored Feb 4, 2025
1 parent 49d4df6 commit 7b6d482
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 8 deletions.
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,23 @@ Example:

```js
// ... in your OTEL setup
const FastifyInstrumentation = require('@fastify/otel');
const FastifyOtelInstrumentation = require('@fastify/otel');

const fastifyInstrumentation = new FastifyInstrumentation();
fastifyInstrumentation.setTraceProvider(provider)
// If serverName is not provided, it will fallback to OTEL_SERVICE_NAME
// as per https://opentelemetry.io/docs/languages/sdk-configuration/general/.
const fastifyOtelInstrumentation = new FastifyOtelInstrumentation({ serverName: '<yourCustomApplicationName>' });
fastifyOtelInstrumentation.setTraceProvider(provider)

module.exports = { fastifyInstrumentation }
module.exports = { fastifyOtelInstrumentation }

// ... in your Fastify definition
const { fastifyInstrumentation } = require('./otel.js');
const { fastifyOtelInstrumentation } = require('./otel.js');
const Fastify = require('fastify');

const app = fastify();
// It is necessary to await for its register as it requires to be able
// to intercept all route definitions
await app.register(fastifyInstrumentation.plugin());
await app.register(fastifyOtelInstrumentation.plugin());

// automatically all your routes will be instrumented
app.get('/', () => 'hello world')
Expand All @@ -58,7 +60,7 @@ app.addHook('onError', () => /* do something */)
// you can also scope your instrumentation to only be enabled on a sub context
// of your application
app.register((instance, opts, done) => {
instance.register(fastifyInstrumentation.plugin());
instance.register(fastifyOtelInstrumentation.plugin());
// If only enabled in your encapsulated context
// the parent context won't be instrumented
app.get('/', () => 'hello world')
Expand Down
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class FastifyOtelInstrumentation extends InstrumentationBase {

constructor (config) {
super(PACKAGE_NAME, PACKAGE_VERSION, config)
this.servername = config?.servername ?? 'fastify'
this.servername = config?.servername ?? process.env.OTEL_SERVICE_NAME ?? 'fastify'
}

// We do not do patching in this instrumentation
Expand Down
16 changes: 16 additions & 0 deletions test/env-vars.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { expectAssignable } from 'tsd'
import { InstrumentationBase, InstrumentationConfig } from '@opentelemetry/instrumentation'
import { fastify as Fastify } from 'fastify'

import { FastifyOtelInstrumentation, FastifyOtelInstrumentationOpts } from '..'

expectAssignable<InstrumentationBase>(new FastifyOtelInstrumentation())
expectAssignable<InstrumentationConfig>({ servername: 'server', enabled: true } as FastifyOtelInstrumentationOpts)
expectAssignable<InstrumentationConfig>({} as FastifyOtelInstrumentationOpts)

const app = Fastify()
app.register(new FastifyOtelInstrumentation().plugin())
app.register((nested, _opts, done) => {
nested.register(new FastifyOtelInstrumentation().plugin())
done()
})
100 changes: 100 additions & 0 deletions test/env-vars.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
'use strict'

const {
test,
describe,
after,
afterEach,
beforeEach
} = require('node:test')
const assert = require('node:assert')
const Fastify = require(process.env.FASTIFY_VERSION || 'fastify')

const {
AsyncHooksContextManager
} = require('@opentelemetry/context-async-hooks')
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node')
const {
InMemorySpanExporter,
SimpleSpanProcessor
} = require('@opentelemetry/sdk-trace-base')
const { context } = require('@opentelemetry/api')

const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http')

const FastifyInstrumentation = require('..')

// OTEL_SERVICE_NAME
// https://opentelemetry.io/docs/languages/sdk-configuration/general/
describe('Environment variable aware FastifyInstrumentation', () => {
process.env.OTEL_SERVICE_NAME = 'my_app'

const httpInstrumentation = new HttpInstrumentation()
const instrumentation = new FastifyInstrumentation()
const contextManager = new AsyncHooksContextManager()
const memoryExporter = new InMemorySpanExporter()
const provider = new NodeTracerProvider()
const spanProcessor = new SimpleSpanProcessor(memoryExporter)

provider.addSpanProcessor(spanProcessor)
context.setGlobalContextManager(contextManager)
httpInstrumentation.setTracerProvider(provider)
instrumentation.setTracerProvider(provider)

describe('Instrumentation#enabled', () => {
beforeEach(() => {
instrumentation.enable()
httpInstrumentation.enable()
contextManager.enable()
})

afterEach(() => {
contextManager.disable()
instrumentation.disable()
httpInstrumentation.disable()
spanProcessor.forceFlush()
memoryExporter.reset()
})

test('should create span with service.name equal to general sdk configuration', async t => {
const app = Fastify()
const plugin = instrumentation.plugin()

await app.register(plugin)

app.get('/', async (request, reply) => '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.instrumentationLibrary.name === '@fastify/otel')

const [end, start] = spans

assert.equal(spans.length, 2)
assert.deepStrictEqual(start.attributes, {
'fastify.root': '@fastify/otel',
'http.route': '/',
'service.name': 'my_app',
'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': '/',
'service.name': 'my_app',
'hook.callback.name': 'anonymous'
})
assert.equal(response.status, 200)
assert.equal(await response.text(), 'hello world')
})
})
})

0 comments on commit 7b6d482

Please sign in to comment.