@@ -29,35 +29,110 @@ It must be configured before defining routes and other plugins in order to cover
29
29
- ` onResponse `
30
30
- ` onError `
31
31
- Instruments automatically custom 404 Not Found handler
32
+ - TODO: Clarify server shutdown/cleanup around otel metrics/traces
32
33
33
- Example:
34
+ ## Example
34
35
35
36
``` js
36
- // ... in your OTEL setup
37
- const FastifyOtelInstrumentation = require (' @fastify/otel' );
37
+ // otel.js
38
+ // Sets up metrics, tracing, HTTP & Node runtime instrumentation, and host metrics.
39
+ // Uses ConsoleSpanExporter for local debugging of spans.
40
+ const { NodeSDK } = require (' @opentelemetry/sdk-node' )
41
+ const { ConsoleSpanExporter } = require (' @opentelemetry/sdk-trace-node' )
42
+ const { SimpleSpanProcessor } = require (' @opentelemetry/sdk-trace-base' )
43
+ const { PrometheusExporter } = require (' @opentelemetry/exporter-prometheus' )
44
+ const { HttpInstrumentation } = require (' @opentelemetry/instrumentation-http' )
45
+ const { RuntimeNodeInstrumentation } = require (' @opentelemetry/instrumentation-runtime-node' )
46
+ const { HostMetrics } = require (' @opentelemetry/host-metrics' )
47
+ const { FastifyOtelInstrumentation } = require (' @fastify/otel' )
48
+ const { metrics , trace } = require (' @opentelemetry/api' )
49
+ const { resourceFromAttributes } = require (' @opentelemetry/resources' )
50
+ const { SemanticResourceAttributes } = require (' @opentelemetry/semantic-conventions' )
51
+
52
+ // Console exporter for development-time span inspection
53
+ // We could use '@opentelemetry/exporter-trace-otlp-http' instead
54
+ const traceExporter = new ConsoleSpanExporter ()
55
+ const spanProcessor = new SimpleSpanProcessor (traceExporter)
56
+
57
+ const prometheusExporter = new PrometheusExporter ({ port: 9091 })
58
+
59
+ const sdk = new NodeSDK ({
60
+ resource: resourceFromAttributes ({
61
+ [SemanticResourceAttributes .SERVICE_NAME ]: ' my-service-name' ,
62
+ }),
63
+ spanProcessor,
64
+ metricReader: prometheusExporter,
65
+ instrumentations: [
66
+ new HttpInstrumentation (),
67
+ new RuntimeNodeInstrumentation (),
68
+ ],
69
+ })
70
+
71
+ await sdk .start ()
38
72
39
- // If serverName is not provided, it will fallback to OTEL_SERVICE_NAME
40
- // as per https://opentelemetry.io/docs/languages/sdk-configuration/general/.
41
- const fastifyOtelInstrumentation = new FastifyOtelInstrumentation ({ servername : ' <yourCustomApplicationName> ' });
42
- fastifyOtelInstrumentation .setTracerProvider (provider )
73
+ const fastifyOtelInstrumentation = new FastifyOtelInstrumentation ({
74
+ registerOnInitialization : true ,
75
+ })
76
+ fastifyOtelInstrumentation .setTracerProvider (trace . getTracerProvider () )
43
77
44
- module . exports = { fastifyOtelInstrumentation }
78
+ new HostMetrics ({ meterProvider : metrics . getMeterProvider () }). start ()
45
79
46
- // ... in your Fastify definition
47
- const { fastifyOtelInstrumentation } = require (' ./otel.js' );
48
- const Fastify = require (' fastify' );
80
+ module .exports = { sdk, fastifyOtelInstrumentation }
81
+ ```
49
82
50
- const app = fastify ();
83
+ If ` registerOnInitialization=true ` , use a loader to load your otel.js before everything else.
84
+
85
+ [ Fastify-cli] ( https://github.com/fastify/fastify-cli ) :
86
+
87
+ - ` fastify start --import otel.js ` for esm
88
+ - ` fastify start --require otel.js ` for cjs
89
+
90
+ Node.js:
91
+
92
+ - ` node --import ./otel.js ./app.js ` for esm
93
+ - ` node --require ./otel.js ./app.js ` for cjs
94
+
95
+ ``` js
96
+ // app.js
97
+ import Fastify from ' fastify' ;
98
+
99
+ // Because we used a loader flag and registerOnInitialization=true
100
+ // All routes will automatically be insturmented
101
+ const app = await Fastify ();
102
+
103
+ app .get (' /' , async () => ' hello world' );
104
+
105
+ app .get (
106
+ ' /healthcheck' ,
107
+ { config: { otel: false } }, // skip tracing/metrics for this route
108
+ async () => ' Up!'
109
+ );
110
+
111
+ // example of encapsulated context with its own instrumentation
112
+ app .register (async (instance ) => {
113
+ // will inherit global FastifyOtelInstrumentation because we registered with
114
+ // registerOnInitialization
115
+ instance .get (' /' , async () => ' nested hello world' );
116
+ }, { prefix: ' /nested' });
117
+
118
+ await app .listen ({ port: 3000 });
119
+ console .log (' ⚡ Fastify listening on http://localhost:3000' );
120
+ ````
121
+
122
+ ### Manual plugin registration
123
+
124
+ If ` registerOnInitialization=false` , you must register the fastify plugin before defining any routes.
125
+
126
+ ` ` ` js
127
+ import Fastify from 'fastify';
128
+ import { fastifyOtelInstrumentation } from './otel.js';
129
+
130
+ const app = await Fastify();
51
131
// It is necessary to await for its register as it requires to be able
52
132
// to intercept all route definitions
53
133
await app.register(fastifyOtelInstrumentation.plugin());
54
134
55
- // automatically all your routes will be instrumented
56
- app .get (' /' , () => ' hello world' )
57
- // as well as your instance level hooks.
58
- app .addHook (' onError' , () => /* do something */ )
59
- // Manually skip telemetry for a specific route
60
- app .get (' /healthcheck' , { config: { otel: false } }, () => ' Up!' )
135
+ app.get('/', async () => 'hello world');
61
136
62
137
// you can also scope your instrumentation to only be enabled on a sub context
63
138
// of your application
@@ -69,23 +144,7 @@ app.register((instance, opts, done) => {
69
144
70
145
done()
71
146
}, { prefix: '/nested' })
72
- ```
73
-
74
- ### Automatic plugin registration
75
-
76
- The plugin can be automatically registered with ` registerOnInitialization ` option set to ` true ` .
77
- In this case, it is necessary to await fastify instance.
78
-
79
- ``` js
80
- // ... in your OTEL setup
81
- const fastifyOtelInstrumentation = new FastifyOtelInstrumentation ({
82
- registerOnInitialization: true ,
83
- });
84
-
85
- // ... in your Fastify definition
86
- const Fastify = require (' fastify' );
87
- const app = await fastify ();
88
- ```
147
+ ` ` ` `
89
148
90
149
> **Notes**:
91
150
>
0 commit comments