Zipkin Hapi Instrumentation
raw JSON → 0.22.0 verified Thu Apr 23 auth: no javascript
zipkin-instrumentation-hapi provides middleware for integrating Hapi.js applications with Zipkin for distributed tracing. It enables automatic span creation for incoming requests and outgoing responses, propagating trace context across service boundaries. The current stable version is 0.22.0, released as part of the broader zipkin-js monorepo. Releases appear to be somewhat frequent, often including bug fixes, new transport support (like AWS SQS in v0.21.0), and improvements to instrumentation across various libraries. Key differentiators include its adherence to the OpenZipkin specification and its tight integration within the zipkin-js ecosystem, offering consistent tracing across different frameworks and transport layers.
Common errors
error Error: Must be valid TraceId instance ↓
cause This error often relates to issues during transpilation or incorrect handling of trace identifiers.
fix
Ensure your build process correctly transpiles the
zipkin-js library. This was notably fixed in v0.18.6. error TypeError: Cannot read properties of undefined (reading 'register') ↓
cause This typically occurs if `hapiInstrumentation` is not properly imported or if the `server.register` call is malformed.
fix
Verify that
hapiInstrumentation is correctly imported and that the server.register call adheres to Hapi's plugin registration syntax, including wrapping the plugin in an object { plugin: hapiInstrumentation, options: {...} }. Warnings
breaking Node.js 8 support was dropped in version 0.21.0 due to its End-of-Life (EOL). Users on Node.js 8 will not receive updates or fixes. ↓
fix Upgrade Node.js to a supported version (e.g., Node.js 10 or higher).
breaking Node.js 6 support was dropped in version 0.17.1. Applications running on Node.js 6 will fail or encounter issues. ↓
fix Upgrade Node.js to a supported version (e.g., Node.js 8 or higher, preferably 10+).
gotcha When upgrading `zipkin-js` packages, ensure all related `zipkin-instrumentation-*` packages are also updated to compatible versions, as breaking changes in core components can affect instrumentations. ↓
fix Use a consistent version range for all `zipkin-js` related packages, e.g., using `^` or `~` in `package.json`, or explicitly updating all to the latest major release.
gotcha The Hapi instrumentation requires a properly configured `Tracer` instance, which includes a `Recorder` and a `serviceName`. Incorrect configuration can lead to spans not being reported or trace context not propagating. ↓
fix Always initialize `Tracer` with a `recorder` (e.g., `BatchRecorder` or `ConsoleRecorder`) and a descriptive `serviceName`.
breaking Prior to v0.17.1, Hapi 17 support was added. Older versions of the instrumentation may not be fully compatible with Hapi 17+ ↓
fix Upgrade `zipkin-instrumentation-hapi` to version 0.17.1 or newer for robust Hapi 17+ compatibility.
Install
npm install zipkin-instrumentation-hapi yarn add zipkin-instrumentation-hapi pnpm add zipkin-instrumentation-hapi Imports
- hapiInstrumentation wrong
const hapiInstrumentation = require('zipkin-instrumentation-hapi');correctimport { hapiInstrumentation } from 'zipkin-instrumentation-hapi'; - BatchRecorder wrong
import { BatchRecorder } from 'zipkin-instrumentation-hapi';correctimport { BatchRecorder } from 'zipkin'; - ConsoleRecorder wrong
import { ConsoleRecorder } from 'zipkin-instrumentation-hapi';correctimport { ConsoleRecorder } from 'zipkin';
Quickstart
import * as Hapi from '@hapi/hapi';
import { Tracer, BatchRecorder, ConsoleRecorder } from 'zipkin';
import { HttpLogger } from 'zipkin-transport-http';
import { hapiInstrumentation } from 'zipkin-instrumentation-hapi';
const ZIPKIN_URL = process.env.ZIPKIN_URL ?? 'http://localhost:9411';
const recorder = process.env.NODE_ENV === 'production'
? new BatchRecorder({
logger: new HttpLogger({
endpoint: `${ZIPKIN_URL}/api/v2/spans`,
headers: { 'Content-Type': 'application/json' }
})
})
: new ConsoleRecorder();
const tracer = new Tracer({
recorder,
serviceName: 'my-hapi-service'
});
const init = async () => {
const server = Hapi.server({
port: 3000,
host: 'localhost'
});
await server.register({
plugin: hapiInstrumentation,
options: { tracer, serviceName: 'my-hapi-service' }
});
server.route({
method: 'GET',
path: '/hello',
handler: (request, h) => {
// Example of custom span creation
const childSpan = tracer.startSpan('greet-user');
tracer.scoped(() => {
tracer.recordServiceName('my-hapi-service');
tracer.recordRpc('GET');
tracer.recordAnnotation(new tracer.Annotation.ServerRecv());
// ... do some work ...
tracer.recordAnnotation(new tracer.Annotation.ServerSend());
}, childSpan);
return 'Hello, Zipkin!';
}
});
await server.start();
console.log(`Server running on ${server.info.uri}`);
};
process.on('unhandledRejection', (err) => {
console.log(err);
process.exit(1);
});
init();