CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-opentelemetry--instrumentation-http

OpenTelemetry instrumentation for Node.js HTTP and HTTPS modules enabling automatic telemetry collection for client and server operations

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

configuration.mddocs/

Configuration

The HttpInstrumentationConfig interface provides extensive options for customizing HTTP instrumentation behavior, including request filtering, custom attributes, header capture, and telemetry control.

Capabilities

HttpInstrumentationConfig Interface

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[];
}

Configuration Options

Request Filtering Options

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');
  }
});

Custom Attribute Options

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');
  }
});

Header Capture Options

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'
      ]
    }
  }
});

Parent Span Requirements

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
});

Server Configuration

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'
});

Experimental Features

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'
  ]
});

Complete Configuration Example

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

docs

configuration.md

hook-functions.md

http-instrumentation.md

index.md

tile.json