Propagate W3C Trace Context in Axios

Distributed tracing enables monitoring and troubleshooting of microservices by tracking HTTP requests across multiple service boundaries. This article explains how to integrate distributed tracing IDs into the Axios HTTP client using the standard W3C Trace Context specification (traceparent and tracestate headers). You will learn how to manually inject trace headers using Axios interceptors as well as how to automate trace propagation using OpenTelemetry instrumentation.

Understanding the W3C Trace Context Standard

The W3C Trace Context specification defines standard HTTP headers to propagate context across system boundaries:


Method 1: Manual Header Injection with Axios Interceptors

If you manage trace IDs manually or use a custom tracing solution, use an Axios request interceptor to append the traceparent header to every outgoing HTTP call.

import axios from 'axios';
import crypto from 'crypto';

// Helper to generate compliant hex IDs
const generateTraceId = () => crypto.randomBytes(16).toString('hex');
const generateSpanId = () => crypto.randomBytes(8).toString('hex');

// Create an Axios instance
const apiClient = axios.create({
  baseURL: 'https://api.example.com',
});

// Attach a request interceptor to inject trace context
apiClient.interceptors.request.use((config) => {
  // Retrieve existing trace ID from context or generate a new one
  const traceId = config.headers['x-trace-id'] || generateTraceId();
  const spanId = generateSpanId();
  const traceFlags = '01'; // 01 indicates sampled

  const traceparent = `00-${traceId}-${spanId}-${traceFlags}`;

  // Set the W3C traceparent header
  config.headers['traceparent'] = traceparent;

  return config;
}, (error) => {
  return Promise.reject(error);
});

export default apiClient;

Method 2: Automatic Propagation with OpenTelemetry

OpenTelemetry provides native instrumentation that automatically extracts the active trace context from the application's runtime context and injects the W3C headers into all Axios requests.

1. Install Required Packages

npm install @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/instrumentation-http @opentelemetry/instrumentation-axios

2. Initialize the OpenTelemetry Tracing SDK

Initialize OpenTelemetry before loading Axios or your application entry point.

// tracing.js
import { NodeSDK } from '@opentelemetry/sdk-node';
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
import { AxiosInstrumentation } from '@opentelemetry/instrumentation-axios';
import { W3CTraceContextPropagator } from '@opentelemetry/core';

const sdk = new NodeSDK({
  textMapPropagator: new W3CTraceContextPropagator(),
  instrumentations: [
    new HttpInstrumentation(),
    new AxiosInstrumentation(),
  ],
});

sdk.start();

3. Executing Requests with Active Context

With instrumentation configured, standard Axios calls will automatically include the active traceparent header without manual configuration.

import axios from 'axios';
import { trace } from '@opentelemetry/api';

const tracer = trace.getTracer('example-service');

async function makeCall() {
  await tracer.startActiveSpan('fetch-data-span', async (span) => {
    try {
      // Axios automatically attaches 'traceparent' matching this active span
      const response = await axios.get('https://api.example.com/items');
      console.log('Response:', response.data);
    } catch (error) {
      span.recordException(error);
      throw error;
    } finally {
      span.end();
    }
  });
}

Best Practices