{"id":22511005,"url":"https://github.com/fastify/otel","last_synced_at":"2025-08-03T14:32:12.145Z","repository":{"id":266792504,"uuid":"895001824","full_name":"fastify/otel","owner":"fastify","description":"OpenTelemetry instrumentation library ","archived":false,"fork":false,"pushed_at":"2024-11-27T11:41:39.000Z","size":0,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":5,"default_branch":"main","last_synced_at":"2024-12-06T06:54:12.521Z","etag":null,"topics":["fastify-library","opentelemetry","opentelemetry-javascript","otel"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fastify.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"fastify","open_collective":"fastify"}},"created_at":"2024-11-27T11:38:30.000Z","updated_at":"2024-11-29T22:15:13.000Z","dependencies_parsed_at":"2024-12-06T06:54:13.855Z","dependency_job_id":"46641ed2-cdc1-467d-b41a-71eb657724f8","html_url":"https://github.com/fastify/otel","commit_stats":null,"previous_names":["fastify/otel"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Fotel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Fotel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Fotel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Fotel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fastify","download_url":"https://codeload.github.com/fastify/otel/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228548594,"owners_count":17935225,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fastify-library","opentelemetry","opentelemetry-javascript","otel"],"created_at":"2024-12-07T02:07:49.040Z","updated_at":"2025-08-03T14:32:11.893Z","avatar_url":"https://github.com/fastify.png","language":null,"readme":"# @fastify/otel\n\n[![CI](https://github.com/fastify/otel/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/fastify/otel/actions/workflows/ci.yml)\n[![NPM version](https://img.shields.io/npm/v/@fastify/otel.svg?style=flat)](https://www.npmjs.com/package/@fastify/otel)\n[![neostandard javascript style](https://img.shields.io/badge/code_style-neostandard-brightgreen?style=flat)](https://github.com/neostandard/neostandard)\n\nOpenTelemetry auto-instrumentation library.\n\n## Install\n\n```sh\nnpm i @fastify/otel\n```\n\n## Usage\n\n`@fastify/otel` works as a metric creator as well as application performance monitor for your Fastify application.\n\nIt must be configured before defining routes and other plugins in order to cover the most of your Fastify server.\n\n- It automatically wraps the main request handler\n- Instruments all route hooks (defined at instance and route definition level)\n  - `onRequest`\n  - `preParsing`\n  - `preValidation`\n  - `preHandler`\n  - `preSerialization`\n  - `onSend`\n  - `onResponse`\n  - `onError`\n- Instruments automatically custom 404 Not Found handler\n\nExample:\n\n```js\n// ... in your OTEL setup\nconst FastifyOtelInstrumentation = require('@fastify/otel');\n\n// If serverName is not provided, it will fallback to OTEL_SERVICE_NAME\n// as per https://opentelemetry.io/docs/languages/sdk-configuration/general/.\nconst fastifyOtelInstrumentation = new FastifyOtelInstrumentation({ servername: '\u003cyourCustomApplicationName\u003e' });\nfastifyOtelInstrumentation.setTracerProvider(provider)\n\nmodule.exports = { fastifyOtelInstrumentation }\n\n// ... in your Fastify definition\nconst { fastifyOtelInstrumentation } = require('./otel.js');\nconst Fastify = require('fastify');\n\nconst app = fastify();\n// It is necessary to await for its register as it requires to be able\n// to intercept all route definitions\nawait app.register(fastifyOtelInstrumentation.plugin());\n\n// automatically all your routes will be instrumented\napp.get('/', () =\u003e 'hello world')\n// as well as your instance level hooks.\napp.addHook('onError', () =\u003e /* do something */)\n// Manually skip telemetry for a specific route\napp.get('/healthcheck', { config: { otel: false } }, () =\u003e 'Up!')\n\n// you can also scope your instrumentation to only be enabled on a sub context\n// of your application\napp.register((instance, opts, done) =\u003e {\n    instance.register(fastifyOtelInstrumentation.plugin());\n    // If only enabled in your encapsulated context\n    // the parent context won't be instrumented\n    app.get('/', () =\u003e 'hello world')\n\n    done()\n}, { prefix: '/nested' })\n```\n\n### Automatic plugin registration\n\nThe plugin can be automatically registered with `registerOnInitialization` option set to `true`.\nIn this case, it is necessary to await fastify instance.\n\n```js\n// ... in your OTEL setup\nconst fastifyOtelInstrumentation = new FastifyOtelInstrumentation({\n  registerOnInitialization: true,\n});\n\n// ... in your Fastify definition\nconst Fastify = require('fastify');\nconst app = await fastify();\n```\n\n\u003e **Notes**:\n\u003e\n\u003e - This instrumentation requires `@opentelemetry/instrumentation-http` to be able to propagate the traces all the way back to upstream\n\u003e   - The HTTP instrumentation might cover all your routes although `@fastify/otel` just covers a subset of your application\n\nFor more information about OpenTelemetry, please refer to the [OpenTelemetry JavaScript](https://opentelemetry.io/docs/languages/js/) documentation.\n\n## APIs\n\n### `FastifyOtelRequestContext`\n\nThe `FastifyOtelRequestContext` is a wrapper around the OpenTelemetry `Context` and `Tracer` APIs. It also provides a way to manage the context of a request and its associated spans as well as some utilities to extract and inject further traces from and to the trace carrier.\n\n#### `FastifyOtelRequestContext#context: Context`\nThe OpenTelemetry context object.\n\n#### `FastifyOtelRequestContext#tracer: Tracer`\nThe OpenTelemetry tracer object.\n\n#### `FastifyOtelRequestContext#span: Span`\nThe OpenTelemetry span object.\nThe span is created for each request and is automatically ended when the request is completed.\n\n#### `FastifyOtelRequestContext#inject: function`\nThe OpenTelemetry inject function. It is used to inject the current context into a carrier object.\n\nThe carrier object can be any object that can hold key-value pairs, such as an HTTP request or response headers.\n\n#### `FastifyOtelRequestContext#extract: function`\nThe OpenTelemetry extract function. It is used to extract a parent context from a carrier object.\n\nThe carrier object can be any object that can hold key-value pairs, such as an HTTP request or response headers.\n\nThe extracted context can be used as a parent span for a new span.\n\n```js\nconst { fastifyOtelInstrumentation } = require('./otel.js');\nconst Fastify = require('fastify');\n\nconst app = fastify();\nawait app.register(fastifyOtelInstrumentation.plugin());\n\napp.get('/', (req, reply) =\u003e {\n  const { context, tracer, span, inject, extract } = req.opentelemetry();\n\n  // Extract a parent span from the request headers\n  const parentCxt = extract(req.headers);\n\n  // Create a new span\n  const newSpan = tracer.startSpan('my-new-span', {\n    parent: parentCxt,\n  });\n  // Do some work\n  newSpan.end();\n\n  // Inject the new span into the response headers\n  const carrier = {};\n  inject(carrier);\n\n  reply.headers(carrier);\n\n  return 'hello world';\n});\n```\n\n## Interfaces\n\n### `FastifyOtelInstrumentationOptions`\n\nThe options for the `FastifyOtelInstrumentation` class.\n\n#### `FastifyOtelInstrumentationOptions#serverName: string`\n\nThe name of the server. If not provided, it will fallback to `OTEL_SERVICE_NAME` as per [OpenTelemetry SDK Configuration](https://opentelemetry.io/docs/languages/sdk-configuration/general/).\n\n#### `FastifyOtelInstrumentationOptions#registerOnInitialization: boolean`\n\nWhether to register the plugin on initialization. If set to `true`, the plugin will be registered automatically when the Fastify instance is created.\n\nThis is useful for applications that want to ensure that all routes are instrumented without having to manually register the plugin.\n\n#### `FastifyOtelInstrumentationOptions#ignorePaths: string | function`\n\nString or function to ignore paths from being instrumented.\n\nIf a string is provided, it will be used as a glob match pattern.\n\nIf a function is provided, it will be called with the request options and should return true if the path should be ignored.\n\n#### `FastifyOtelInstrumentationOptions#requestHook: function`\nA **synchronous** callback that runs immediately after the root request span is created.\n* **span** – the newly-created `Span`\n* **info.request** – the current `FastifyRequest`\n\nUse it to add custom attributes, events, or rename the span.  \nIf the function throws, the error is caught and logged so the request flow is never interrupted.\n\n\n#### Examples\n\n```ts\nimport { FastifyOtelInstrumentation } from '@fastify/otel';\n\nconst fastifyOtelInstrumentation = new FastifyOtelInstrumentation({\n  serverName: 'my-server',\n  registerOnInitialization: true,\n  ignorePaths: (opts) =\u003e {\n    // Ignore all paths that start with /ignore\n    return opts.url.startsWith('/ignore');\n  },\n});\n```\n\n```js\nconst otel = new FastifyOtelInstrumentation({\n  servername: 'my-app',\n  requestHook: (span, request) =\u003e {\n    // attach user info\n    span.setAttribute('user.id', request.headers['x-user-id'] ?? 'anonymous')\n\n    // optional: give the span a cleaner name\n    span.updateName(`${request.method} ${request.routerPath}`)\n  }\n})\n```\n\n## License\n\nLicensed under [MIT](./LICENSE).\n","funding_links":["https://github.com/sponsors/fastify","https://opencollective.com/fastify"],"categories":["Uncategorized"],"sub_categories":["Uncategorized"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffastify%2Fotel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffastify%2Fotel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffastify%2Fotel/lists"}