Skip to content

Commit feb63d3

Browse files
committed
Make README example less pseudo-y
1 parent 49fa7d4 commit feb63d3

File tree

1 file changed

+92
-35
lines changed

1 file changed

+92
-35
lines changed

README.md

Lines changed: 92 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -29,35 +29,108 @@ It must be configured before defining routes and other plugins in order to cover
2929
- `onResponse`
3030
- `onError`
3131
- Instruments automatically custom 404 Not Found handler
32+
- TODO: Clarify server shutdown/cleanup around otel metrics/traces
3233

33-
Example:
34+
## Example
3435

3536
```js
36-
// ... in your OTEL setup
37-
const FastifyOtelInstrumentation = require('@fastify/otel');
37+
// otej.js
38+
// This example sets up metrics and traces,
39+
// the http and node runtime insturmentations, as well as host metrics.
40+
const { NodeSDK } = require('@opentelemetry/sdk-node')
41+
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http')
42+
const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus')
43+
const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http')
44+
const { RuntimeNodeInstrumentation } = require('@opentelemetry/instrumentation-runtime-node')
45+
const { HostMetrics } = require('@opentelemetry/host-metrics')
46+
const { FastifyOtelInstrumentation } = require('@fastify/otel')
47+
const { metrics, trace } = require('@opentelemetry/api')
48+
const { resourceFromAttributes } = require('@opentelemetry/resources')
49+
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions')
50+
51+
// OTLP/HTTP trace exporter
52+
const traceExporter = new OTLPTraceExporter({
53+
url: 'http://localhost:4318/v1/traces',
54+
});
3855

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)
56+
// Prometheus pull-based metrics exporter
57+
const prometheusExporter = new PrometheusExporter({ port: 9091 });
58+
59+
export const sdk = new NodeSDK({
60+
resource: resourceFromAttributes({
61+
[SemanticResourceAttributes.SERVICE_NAME]: 'my-service-name',
62+
}),
63+
traceExporter,
64+
metricReader: prometheusExporter,
65+
instrumentations: [
66+
new HttpInstrumentation(),
67+
new RuntimeNodeInstrumentation(),
68+
],
69+
});
4370

44-
module.exports = { fastifyOtelInstrumentation }
71+
await sdk.start();
4572

46-
// ... in your Fastify definition
47-
const { fastifyOtelInstrumentation } = require('./otel.js');
48-
const Fastify = require('fastify');
73+
export const fastifyOtelInstrumentation = new FastifyOtelInstrumentation({
74+
registerOnInitialization: true, // auto-register on fastify() creation
75+
});
76+
fastifyOtelInstrumentation.setTracerProvider(trace.getTracerProvider());
4977

50-
const app = fastify();
78+
new HostMetrics({ meterProvider: metrics.getMeterProvider() }).start();
79+
```
80+
81+
If `registerOnInitialization=true`, use a loader to load your otel.js before everything else.
82+
83+
[Fastify-cli](https://github.com/fastify/fastify-cli):
84+
85+
- `fastify start --import otel.js` for esm
86+
- `fastify start --require otel.js` for cjs
87+
88+
Node.js:
89+
90+
- `node --import ./otel.js ./app.js` for esm
91+
- `node --require ./otel.js ./app.js` for cjs
92+
93+
```js
94+
// app.js
95+
import Fastify from 'fastify';
96+
97+
// create instance *after* OTEL has been bootstrapped so that
98+
// registerOnInitialization can hook into route creation
99+
const app = await Fastify();
100+
101+
app.get('/', async () => 'hello world');
102+
103+
app.get(
104+
'/healthcheck',
105+
{ config: { otel: false } }, // skip tracing/metrics for this route
106+
async () => 'Up!'
107+
);
108+
109+
// example of encapsulated context with its own instrumentation
110+
app.register(async (instance) => {
111+
// will inherit global FastifyOtelInstrumentation because we registered with
112+
// registerOnInitialization
113+
instance.get('/', async () => 'nested hello world');
114+
}, { prefix: '/nested' });
115+
116+
await app.listen({ port: 3000 });
117+
console.log('⚡ Fastify listening on http://localhost:3000');
118+
````
119+
120+
### Manual plugin registration
121+
122+
If `registerOnInitialization=false`, you must register the fastify plugin before defining any routes.
123+
124+
```js
125+
import Fastify from 'fastify';
126+
import { fastifyOtelInstrumentation } from './otel.js';
127+
128+
const app = await Fastify();
51129
// It is necessary to await for its register as it requires to be able
52130
// to intercept all route definitions
53131
await app.register(fastifyOtelInstrumentation.plugin());
54132
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!')
133+
app.get('/', async () => 'hello world');
61134
62135
// you can also scope your instrumentation to only be enabled on a sub context
63136
// of your application
@@ -69,23 +142,7 @@ app.register((instance, opts, done) => {
69142
70143
done()
71144
}, { 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-
```
145+
````
89146
90147
> **Notes**:
91148
>

0 commit comments

Comments
 (0)