Skip to main content
This guide will help you get started with tctx for distributed tracing in your application.

Installation

First, install tctx using your preferred package manager:
npm install tctx

Basic Usage

tctx provides two main modules: traceparent for trace identification and tracestate for vendor-specific metadata.
1

Import the modules

Import the traceparent and tracestate modules from tctx:
import * as traceparent from 'tctx/traceparent';
import * as tracestate from 'tctx/tracestate';
2

Create a trace context (Producer)

When initiating a request to another service, create a new trace context:
// Create new trace headers
fetch('/api', {
  headers: {
    traceparent: traceparent.make(),
    tracestate: tracestate.make({ key: 'value' }),
  },
});
The make() function creates a new W3C-compliant traceparent with:
  • A unique trace ID (32 hex characters)
  • A unique parent ID (16 hex characters)
  • Default flags (sampled and random)
3

Parse incoming traces (Consumer)

When receiving a request with trace headers, parse them and create a child span:
// Parse incoming trace headers
const parent = traceparent.parse(request.headers.traceparent);
const state = tracestate.parse(request.headers.tracestate);

// Add your vendor-specific data
state.set('vendor', 'value');

// Propagate to downstream services
fetch('/downstream', {
  headers: {
    traceparent: parent.child(),
    tracestate: state,
  },
});
The child() method creates a new span with the same trace ID but a new parent ID, maintaining the trace lineage.
4

Convert to string

Both traceparent and tracestate objects automatically convert to strings when used in headers:
const parent = traceparent.make();
console.log(String(parent));
// 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01

const state = tracestate.make({ key: 'value' });
console.log(String(state));
// key=value

Complete Example

Here’s a complete example showing both producer and consumer patterns:
// Producer: Initiating a traced request
import * as traceparent from 'tctx/traceparent';
import * as tracestate from 'tctx/tracestate';

fetch('/api', {
  headers: {
    traceparent: traceparent.make(),
    tracestate: tracestate.make({ key: 'value' }),
  },
});

Understanding Traceparent

The traceparent header follows this format:
00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
^  ^                                ^                ^
|  |                                |                flags (2 hex)
|  |                                parent-id (16 hex)
|  trace-id (32 hex)
version (2 hex)
  • version: Always 00 (current W3C spec version)
  • trace-id: 32-character hex string uniquely identifying the trace
  • parent-id: 16-character hex string identifying the current span
  • flags: 2-character hex representing trace flags (sampling, etc.)

Working with Flags

tctx provides utilities for managing trace flags:
import { sample, unsample, is_sampled } from 'tctx/traceparent';

const parent = traceparent.make();

// Check if sampled
console.log(is_sampled(parent)); // true (by default)

// Toggle sampling
unsample(parent);
console.log(is_sampled(parent)); // false

sample(parent);
console.log(is_sampled(parent)); // true
According to the W3C spec, you should call .child() before modifying flags to ensure proper trace propagation.

Working with Tracestate

Tracestate is a ring buffer of up to 32 key-value pairs:
const state = tracestate.make();

// Set values
state.set('vendor1', 'value1');
state.set('vendor2', 'value2');

// Get values
console.log(state.get('vendor1')); // 'value1'

// Update moves key to front
state.set('vendor1', 'updated');
console.log(String(state)); // 'vendor1=updated,vendor2=value2'

// Automatically drops oldest when full (32 entries)
for (let i = 0; i < 35; i++) {
  state.set(`key${i}`, `value${i}`);
}
console.log(state.size); // 32

Error Handling

The parse() function returns null for invalid input:
const parent = traceparent.parse(request.headers.traceparent);

if (!parent) {
  // Invalid or missing traceparent, create new one
  const newParent = traceparent.make();
}
Always validate that parse() returns a non-null value before calling methods like child() to avoid runtime errors.

Next Steps

API Reference

Explore the complete API documentation

Guides

See more real-world usage patterns

W3C Specification

Read the official W3C Trace Context spec

GitHub Repository

View the source code and contribute

Build docs developers (and LLMs) love