OpenTelemetry instrumentation for Node.js HTTP and HTTPS modules enabling automatic telemetry collection for client and server operations
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
The HttpInstrumentationConfig interface provides extensive options for customizing HTTP instrumentation behavior, including request filtering, custom attributes, header capture, and telemetry control.
Main configuration interface for HTTP instrumentation with comprehensive options for customizing telemetry collection behavior.
/**
* Configuration options for HTTP instrumentation
* Extends the base InstrumentationConfig with HTTP-specific options
*/
interface HttpInstrumentationConfig extends InstrumentationConfig {
/** Function to filter incoming requests from instrumentation */
ignoreIncomingRequestHook?: IgnoreIncomingRequestFunction;
/** Function to filter outgoing requests from instrumentation */
ignoreOutgoingRequestHook?: IgnoreOutgoingRequestFunction;
/** Completely disable incoming request instrumentation */
disableIncomingRequestInstrumentation?: boolean;
/** Completely disable outgoing request instrumentation */
disableOutgoingRequestInstrumentation?: boolean;
/** Function for adding custom attributes after response is handled */
applyCustomAttributesOnSpan?: HttpCustomAttributeFunction;
/** Function for adding custom attributes before request is handled */
requestHook?: HttpRequestCustomAttributeFunction;
/** Function for adding custom attributes before response is handled */
responseHook?: HttpResponseCustomAttributeFunction;
/** Function for adding custom attributes before incoming span is started */
startIncomingSpanHook?: StartIncomingSpanCustomAttributeFunction;
/** Function for adding custom attributes before outgoing span is started */
startOutgoingSpanHook?: StartOutgoingSpanCustomAttributeFunction;
/** Primary server name for virtual host matching */
serverName?: string;
/** Require parent span to create spans for outgoing requests */
requireParentforOutgoingSpans?: boolean;
/** Require parent span to create spans for incoming requests */
requireParentforIncomingSpans?: boolean;
/** Map HTTP headers to span attributes */
headersToSpanAttributes?: {
client?: { requestHeaders?: string[]; responseHeaders?: string[] };
server?: { requestHeaders?: string[]; responseHeaders?: string[] };
};
/** Enable automatic population of synthetic source type (experimental) */
enableSyntheticSourceDetection?: boolean;
/** Additional query parameters to redact (experimental) */
redactedQueryParams?: string[];
}Control which requests are instrumented:
/** Completely disable incoming request instrumentation */
disableIncomingRequestInstrumentation?: boolean;
/** Completely disable outgoing request instrumentation */
disableOutgoingRequestInstrumentation?: boolean;
/** Function to filter incoming requests from instrumentation */
ignoreIncomingRequestHook?: IgnoreIncomingRequestFunction;
/** Function to filter outgoing requests from instrumentation */
ignoreOutgoingRequestHook?: IgnoreOutgoingRequestFunction;Usage Examples:
import { HttpInstrumentation } from "@opentelemetry/instrumentation-http";
const instrumentation = new HttpInstrumentation({
// Don't instrument any incoming requests (useful for client-only apps)
disableIncomingRequestInstrumentation: true,
// Filter outgoing requests to ignore internal services
ignoreOutgoingRequestHook: (req) => {
const hostname = req.hostname || req.host;
return hostname?.includes('internal.company.com') === true;
},
// Filter incoming requests to ignore health checks and static assets
ignoreIncomingRequestHook: (req) => {
const url = req.url || '';
return url.startsWith('/health') ||
url.startsWith('/static/') ||
url.endsWith('.ico');
}
});Add custom attributes to spans at different lifecycle points:
/** Function for adding custom attributes after response is handled */
applyCustomAttributesOnSpan?: HttpCustomAttributeFunction;
/** Function for adding custom attributes before request is handled */
requestHook?: HttpRequestCustomAttributeFunction;
/** Function for adding custom attributes before response is handled */
responseHook?: HttpResponseCustomAttributeFunction;
/** Function for adding custom attributes before incoming span is started */
startIncomingSpanHook?: StartIncomingSpanCustomAttributeFunction;
/** Function for adding custom attributes before outgoing span is started */
startOutgoingSpanHook?: StartOutgoingSpanCustomAttributeFunction;Usage Examples:
const instrumentation = new HttpInstrumentation({
// Add attributes at span start for incoming requests
startIncomingSpanHook: (request) => {
return {
'custom.request_id': request.headers['x-request-id'],
'custom.tenant_id': request.headers['x-tenant-id'],
'custom.api_version': request.headers['api-version'] || 'v1'
};
},
// Add attributes during request processing
requestHook: (span, request) => {
const userAgent = request.headers['user-agent'];
if (userAgent) {
span.setAttribute('custom.user_agent', userAgent);
span.setAttribute('custom.is_mobile', userAgent.includes('Mobile'));
}
},
// Add attributes during response processing
responseHook: (span, response) => {
span.setAttribute('custom.response_size',
response.headers['content-length'] || '0');
span.setAttribute('custom.cache_hit',
response.headers['x-cache'] === 'HIT');
},
// Add comprehensive attributes after request completion
applyCustomAttributesOnSpan: (span, request, response) => {
// Calculate and add request duration in a custom format
const duration = Date.now() - span.startTime[0] * 1000;
span.setAttribute('custom.duration_category',
duration < 100 ? 'fast' : duration < 500 ? 'medium' : 'slow');
}
});Configure which HTTP headers to capture as span attributes:
/** Map HTTP headers to span attributes */
headersToSpanAttributes?: {
client?: { requestHeaders?: string[]; responseHeaders?: string[] };
server?: { requestHeaders?: string[]; responseHeaders?: string[] };
};Usage Examples:
const instrumentation = new HttpInstrumentation({
headersToSpanAttributes: {
// For client requests (outgoing)
client: {
requestHeaders: [
'authorization', // Capture auth headers (be careful with sensitive data)
'content-type',
'accept',
'x-api-key'
],
responseHeaders: [
'content-type',
'server',
'x-response-time',
'x-rate-limit-remaining'
]
},
// For server requests (incoming)
server: {
requestHeaders: [
'user-agent',
'referer',
'accept-language',
'x-forwarded-for'
],
responseHeaders: [
'content-type',
'cache-control',
'x-custom-header'
]
}
}
});Control whether spans require parent spans to be created:
/** Require parent span to create spans for outgoing requests */
requireParentforOutgoingSpans?: boolean;
/** Require parent span to create spans for incoming requests */
requireParentforIncomingSpans?: boolean;Usage Examples:
const instrumentation = new HttpInstrumentation({
// Only create outgoing request spans when there's already an active span
// Useful to avoid creating orphaned spans for background tasks
requireParentforOutgoingSpans: true,
// Only create incoming request spans when there's distributed tracing context
// Useful in microservice environments to avoid root spans
requireParentforIncomingSpans: true
});Set server identification for span attributes:
/** Primary server name for virtual host matching */
serverName?: string;Usage Examples:
const instrumentation = new HttpInstrumentation({
// Set the server name for span attributes
serverName: 'api.mycompany.com'
});Configure experimental features (subject to change):
/** Enable automatic population of synthetic source type (experimental) */
enableSyntheticSourceDetection?: boolean;
/** Additional query parameters to redact (experimental) */
redactedQueryParams?: string[];Usage Examples:
const instrumentation = new HttpInstrumentation({
// Enable synthetic traffic detection (bots, test tools)
enableSyntheticSourceDetection: true,
// Redact sensitive query parameters
redactedQueryParams: [
'api_key',
'secret',
'password',
'token',
'auth',
'signature'
]
});import { HttpInstrumentation } from "@opentelemetry/instrumentation-http";
const comprehensiveConfig = new HttpInstrumentation({
// Basic filtering
ignoreIncomingRequestHook: (req) => {
return req.url?.includes('/health') === true;
},
ignoreOutgoingRequestHook: (req) => {
return req.hostname?.includes('localhost') === true;
},
// Custom attributes
requestHook: (span, request) => {
span.setAttribute('service.component', 'http-client');
},
// Header capture
headersToSpanAttributes: {
client: {
requestHeaders: ['content-type'],
responseHeaders: ['server']
},
server: {
requestHeaders: ['user-agent'],
responseHeaders: ['content-type']
}
},
// Span requirements
requireParentforOutgoingSpans: true,
// Server identification
serverName: 'my-service',
// Experimental features
enableSyntheticSourceDetection: true,
redactedQueryParams: ['api_key', 'token']
});Install with Tessl CLI
npx tessl i tessl/npm-opentelemetry--instrumentation-http