@jaymanyoo/microservices-tracing
v1.1.0
Published
A simple OpenTelemetry tracing setup for Node.js microservices
Maintainers
Readme
Microservice Tracing
A simple, configurable OpenTelemetry tracing package for Node.js microservices with Jaeger integration.
Features
- 🚀 Zero-config setup - Works out of the box with sensible defaults
- 🔧 Highly configurable - Customize instrumentations, endpoints, and behavior
- 🏗️ Framework agnostic - Works with Express, Fastify, and other Node.js frameworks
- 📊 Auto-instrumentation - Automatically traces HTTP, databases, message queues, and more
- 🐳 Container-friendly - Designed for containerized microservices
- ⚡ Minimal overhead - Optimized for production use
Quick Start
Installation
npm install microservice-tracingBasic Usage
// Import at the very top of your main file, before any other imports
import { initializeTracing } from 'microservice-tracing';
// Initialize tracing
initializeTracing({
serviceName: 'my-service'
});
// Now import and start your application
import express from 'express';
// ... rest of your applicationAdvanced Configuration
import { initializeTracing } from 'microservice-tracing';
initializeTracing({
serviceName: 'my-service',
serviceVersion: '1.2.3',
environment: 'production',
jaegerEndpoint: 'http://jaeger-collector:14268/api/traces',
ignoreUrls: ['/health', '/metrics', '/custom-ignore'],
instrumentations: {
http: true,
express: true,
mysql: true,
redis: true,
amqp: true,
socketio: false, // Disable if not using Socket.IO
fs: false, // Disabled by default (noisy)
dns: false // Disabled by default (noisy)
}
});Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| serviceName | string | Required | Name of your service as it appears in Jaeger |
| serviceVersion | string | process.env.SERVICE_VERSION \|\| '1.0.0' | Version of your service |
| environment | string | process.env.NODE_ENV \|\| 'development' | Deployment environment |
| jaegerEndpoint | string | process.env.JAEGER_ENDPOINT \|\| 'http://jaeger:14268/api/traces' | Jaeger collector endpoint |
| disabled | boolean | process.env.OTEL_DISABLED === 'true' | Disable tracing entirely |
| ignoreUrls | string[] | ['/health', '/ping', '/favicon', '/metrics'] | URLs to ignore in HTTP tracing |
| instrumentations | object | See below | Enable/disable specific instrumentations |
Instrumentation Options
instrumentations: {
http: boolean; // HTTP client/server (default: true)
express: boolean; // Express.js framework (default: true)
mysql: boolean; // MySQL/MySQL2 database (default: true)
redis: boolean; // Redis client (default: true)
amqp: boolean; // RabbitMQ/AMQP (default: true)
socketio: boolean; // Socket.IO (default: false)
fs: boolean; // File system operations (default: false)
dns: boolean; // DNS lookups (default: false)
}Environment Variables
You can configure the package using environment variables:
# Disable tracing entirely
OTEL_DISABLED=true
# Set Jaeger endpoint
JAEGER_ENDPOINT=http://jaeger-collector:14268/api/traces
# Set service version
SERVICE_VERSION=1.2.3
# Set environment
NODE_ENV=productionUsage Patterns
Express.js Application
// src/index.ts
import { initializeTracing } from 'microservice-tracing';
// Initialize tracing first
initializeTracing({
serviceName: 'user-service',
instrumentations: {
express: true,
mysql: true,
redis: true
}
});
// Then import your application
import express from 'express';
import { createUserRoutes } from './routes/users';
const app = express();
app.use('/users', createUserRoutes());
app.listen(3000, () => {
console.log('Server running on port 3000');
});With Database and Redis
import { initializeTracing } from 'microservice-tracing';
initializeTracing({
serviceName: 'data-service',
instrumentations: {
mysql: true, // Traces MySQL queries
redis: true, // Traces Redis operations
amqp: true // Traces RabbitMQ messages
}
});
// Your database and Redis operations will be automatically traced
import mysql from 'mysql2/promise';
import redis from 'redis';Chat Service with Socket.IO
import { initializeTracing } from 'microservice-tracing';
initializeTracing({
serviceName: 'chat-service',
instrumentations: {
socketio: true, // Enable Socket.IO tracing
mysql: true,
redis: true
}
});
import { Server } from 'socket.io';
// Socket.IO events will be automatically tracedMicroservice with Message Queues
import { initializeTracing } from 'microservice-tracing';
initializeTracing({
serviceName: 'notification-service',
instrumentations: {
amqp: true, // Traces RabbitMQ publish/consume
http: true // Traces outgoing HTTP calls
}
});
// RabbitMQ operations will be automatically traced
import amqp from 'amqplib';Manual Instrumentation
For custom spans and metrics:
import { trace } from 'microservice-tracing';
const tracer = trace.getTracer('my-service');
async function processOrder(orderId: string) {
const span = tracer.startSpan('process-order');
try {
span.setAttributes({
'order.id': orderId,
'operation.type': 'business-logic'
});
// Your business logic here
const result = await performOrderProcessing(orderId);
span.setStatus({ code: 1 }); // OK
return result;
} catch (error) {
span.recordException(error);
span.setStatus({ code: 2, message: error.message }); // ERROR
throw error;
} finally {
span.end();
}
}Production Considerations
Performance
The package is optimized for production use with minimal overhead (~1-3%). Key optimizations:
- File system and DNS instrumentations are disabled by default
- Health check endpoints are ignored
- Efficient batch export to Jaeger
Sampling
For high-traffic services, you may want to implement sampling:
// Set sampling rate via environment variable
process.env.OTEL_TRACES_SAMPLER = 'traceidratio';
process.env.OTEL_TRACES_SAMPLER_ARG = '0.1'; // Sample 10% of traces
initializeTracing({
serviceName: 'high-traffic-service'
});Security
- The package doesn't expose any sensitive information
- All configuration is done via environment variables or explicit config
- No sensitive data is automatically captured in spans
Container Deployment
# Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
# Set tracing environment variables
ENV JAEGER_ENDPOINT=http://jaeger-collector:14268/api/traces
ENV SERVICE_VERSION=1.0.0
CMD ["node", "dist/index.js"]# docker-compose.yml or Kubernetes deployment
environment:
- JAEGER_ENDPOINT=http://jaeger-collector:14268/api/traces
- SERVICE_VERSION=1.0.0
- NODE_ENV=productionTroubleshooting
Common Issues
No traces appearing in Jaeger
- Check that Jaeger is running and accessible
- Verify the
JAEGER_ENDPOINTis correct - Look for initialization logs in your service
High memory usage
- Disable file system instrumentation (default)
- Implement sampling for high-traffic services
- Check for memory leaks in your application code
Missing spans
- Ensure tracing is initialized before importing other modules
- Check that the relevant instrumentation is enabled
- Verify the operation is supported by auto-instrumentation
Debug Mode
Enable debug logging:
DEBUG=@opentelemetry/* node your-app.jsHealth Checks
The package automatically ignores common health check endpoints. To verify tracing is working:
# This will be traced
curl http://your-service/api/users
# This will be ignored
curl http://your-service/healthAPI Reference
initializeTracing(config: TracingConfig): MicroserviceTracing
Convenience function that creates, initializes, and sets up graceful shutdown for tracing.
class MicroserviceTracing
constructor(config: TracingConfig)
Creates a new tracing instance.
initialize(): void
Initializes OpenTelemetry tracing.
shutdown(): Promise<void>
Gracefully shuts down tracing.
setupGracefulShutdown(): void
Sets up process signal handlers for graceful shutdown.
License
MIT
