CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-opentelemetry--sdk-trace-base

Foundational tracing SDK components for OpenTelemetry JavaScript providing manual instrumentation capabilities

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

samplers.mddocs/

Samplers

Samplers control which traces are collected and recorded by making sampling decisions for each span. OpenTelemetry SDK Trace Base provides several built-in sampling strategies including always-on, always-off, ratio-based, and parent-aware samplers.

Capabilities

Core Sampler Interface

All samplers implement the base Sampler interface for consistent sampling decisions.

/**
 * Interface representing a sampler for controlling trace collection
 */
interface Sampler {
  /**
   * Checks whether span needs to be created and tracked
   * @param context - Parent Context which may contain a span
   * @param traceId - Trace ID of the span to be created
   * @param spanName - Name of the span to be created
   * @param spanKind - Kind of the span to be created
   * @param attributes - Initial set of attributes for the span
   * @param links - Collection of links associated with the span
   * @returns SamplingResult with decision and optional attributes
   */
  shouldSample(
    context: Context,
    traceId: string,
    spanName: string,
    spanKind: SpanKind,
    attributes: Attributes,
    links: Link[]
  ): SamplingResult;
  
  /**
   * Returns the sampler name or short description with configuration
   */
  toString(): string;
}

/**
 * Sampling result containing decision and additional attributes
 */
interface SamplingResult {
  /** Sampling decision determining how the span will be handled */
  decision: SamplingDecision;
  /** Immutable list of attributes to add to the span */
  attributes?: Readonly<Attributes>;
  /** TraceState to associate with the span through SpanContext */
  traceState?: TraceState;
}

/**
 * Sampling decision that determines how a span will be recorded and collected
 */
enum SamplingDecision {
  /** Span.isRecording() === false, span will not be recorded */
  NOT_RECORD,
  /** Span.isRecording() === true, but Sampled flag not set */
  RECORD,
  /** Span.isRecording() === true AND Sampled flag set */
  RECORD_AND_SAMPLED
}

AlwaysOnSampler

Sampler that always samples all traces, useful for development and debugging.

/**
 * Sampler that samples all traces
 */
class AlwaysOnSampler implements Sampler {
  /**
   * Always returns RECORD_AND_SAMPLED decision
   */
  shouldSample(
    context: Context,
    traceId: string,
    spanName: string,
    spanKind: SpanKind,
    attributes: Attributes,
    links: Link[]
  ): SamplingResult;
  
  /**
   * Returns "AlwaysOnSampler"
   */
  toString(): string;
}

Usage Examples:

import { BasicTracerProvider, AlwaysOnSampler } from '@opentelemetry/sdk-trace-base';

// Enable sampling for all traces
const provider = new BasicTracerProvider({
  sampler: new AlwaysOnSampler()
});

// Useful for development environments
const devProvider = new BasicTracerProvider({
  sampler: new AlwaysOnSampler(),
  resource: new Resource({
    'service.name': 'dev-service',
    'deployment.environment': 'development'
  })
});

AlwaysOffSampler

Sampler that never samples traces, useful for disabling tracing or testing scenarios.

/**
 * Sampler that samples no traces
 */
class AlwaysOffSampler implements Sampler {
  /**
   * Always returns NOT_RECORD decision
   */
  shouldSample(
    context: Context,
    traceId: string,
    spanName: string,
    spanKind: SpanKind,
    attributes: Attributes,
    links: Link[]
  ): SamplingResult;
  
  /**
   * Returns "AlwaysOffSampler"
   */
  toString(): string;
}

Usage Examples:

import { BasicTracerProvider, AlwaysOffSampler } from '@opentelemetry/sdk-trace-base';

// Disable all tracing
const provider = new BasicTracerProvider({
  sampler: new AlwaysOffSampler()
});

// Conditional sampling based on environment
const sampler = process.env.NODE_ENV === 'test' 
  ? new AlwaysOffSampler() 
  : new AlwaysOnSampler();

const provider = new BasicTracerProvider({ sampler });

TraceIdRatioBasedSampler

Sampler that samples a deterministic fraction of traces based on trace ID, ensuring consistent sampling decisions across services.

/**
 * Sampler that samples a deterministic fraction of traces based on trace ID
 */
class TraceIdRatioBasedSampler implements Sampler {
  /**
   * @param ratio - Sampling ratio between 0.0 and 1.0 (default: 0)
   */
  constructor(ratio?: number);
  
  /**
   * Makes sampling decision based on trace ID hash
   * Same trace ID always produces the same decision
   */
  shouldSample(
    context: Context,
    traceId: string,
    spanName: string,
    spanKind: SpanKind,
    attributes: Attributes,
    links: Link[]
  ): SamplingResult;
  
  /**
   * Returns "TraceIdRatioBased{ratio}"
   */
  toString(): string;
}

Behavior Details:

  • Ratio is normalized to be between 0.0 and 1.0
  • Uses deterministic hash of trace ID for consistent decisions
  • Same trace ID will always produce the same sampling decision across all services
  • Ratio of 0.0 = never sample, 1.0 = always sample

Usage Examples:

import { BasicTracerProvider, TraceIdRatioBasedSampler } from '@opentelemetry/sdk-trace-base';

// Sample 10% of traces
const provider = new BasicTracerProvider({
  sampler: new TraceIdRatioBasedSampler(0.1)
});

// Sample 50% of traces
const provider = new BasicTracerProvider({
  sampler: new TraceIdRatioBasedSampler(0.5)
});

// Environment-based sampling rate
const samplingRate = parseFloat(process.env.TRACE_SAMPLING_RATE || '0.1');
const provider = new BasicTracerProvider({
  sampler: new TraceIdRatioBasedSampler(samplingRate)
});

// No sampling (equivalent to AlwaysOffSampler)
const noSampleProvider = new BasicTracerProvider({
  sampler: new TraceIdRatioBasedSampler(0.0)
});

ParentBasedSampler

Composite sampler that respects parent span's sampling decision when available, otherwise delegates to a root sampler. This ensures sampling consistency across distributed traces.

/**
 * Sampler that respects parent span sampling decisions with fallback samplers
 */
class ParentBasedSampler implements Sampler {
  constructor(config: ParentBasedSamplerConfig);
  
  /**
   * Makes sampling decision based on parent context or delegates to appropriate sampler
   */
  shouldSample(
    context: Context,
    traceId: string,
    spanName: string,
    spanKind: SpanKind,
    attributes: Attributes,
    links: Link[]
  ): SamplingResult;
  
  /**
   * Returns string representation with root sampler info
   */
  toString(): string;
}

/**
 * Configuration for ParentBasedSampler with different samplers for different scenarios
 */
interface ParentBasedSamplerConfig {
  /** Required: Sampler to use when there is no parent span */
  root: Sampler;
  
  /** Sampler for remote parent that was sampled (default: AlwaysOnSampler) */
  remoteParentSampled?: Sampler;
  
  /** Sampler for remote parent that was not sampled (default: AlwaysOffSampler) */
  remoteParentNotSampled?: Sampler;
  
  /** Sampler for local parent that was sampled (default: AlwaysOnSampler) */
  localParentSampled?: Sampler;
  
  /** Sampler for local parent that was not sampled (default: AlwaysOffSampler) */
  localParentNotSampled?: Sampler;
}

Sampling Logic:

  1. If parent span exists and was sampled → delegate to appropriate sampled sampler
  2. If parent span exists and was not sampled → delegate to appropriate not-sampled sampler
  3. If no parent span exists → delegate to root sampler
  4. Local vs remote parent determined by trace flags

Usage Examples:

import { 
  BasicTracerProvider, 
  ParentBasedSampler, 
  TraceIdRatioBasedSampler,
  AlwaysOnSampler,
  AlwaysOffSampler 
} from '@opentelemetry/sdk-trace-base';

// Basic parent-based sampling with ratio-based root
const provider = new BasicTracerProvider({
  sampler: new ParentBasedSampler({
    root: new TraceIdRatioBasedSampler(0.1) // 10% of new traces
  })
});

// Advanced parent-based configuration
const provider = new BasicTracerProvider({
  sampler: new ParentBasedSampler({
    root: new TraceIdRatioBasedSampler(0.05), // 5% of new traces
    remoteParentSampled: new AlwaysOnSampler(), // Always continue sampled remote traces
    remoteParentNotSampled: new AlwaysOffSampler(), // Never sample unsampled remote traces
    localParentSampled: new AlwaysOnSampler(), // Always continue sampled local traces
    localParentNotSampled: new TraceIdRatioBasedSampler(0.01) // 1% chance to sample unsampled local
  })
});

// Production-ready configuration
const provider = new BasicTracerProvider({
  sampler: new ParentBasedSampler({
    root: new TraceIdRatioBasedSampler(0.1), // Sample 10% of root traces
    // Use defaults for parent-based decisions (respects parent sampling)
  })
});

Environment Configuration

Samplers can be configured through environment variables for runtime control.

Environment Variables:

  • OTEL_TRACES_SAMPLER - Sampler type
  • OTEL_TRACES_SAMPLER_ARG - Sampler argument (ratio for ratio-based samplers)

Supported Sampler Values:

  • always_offAlwaysOffSampler
  • always_onAlwaysOnSampler
  • traceidratioTraceIdRatioBasedSampler (requires OTEL_TRACES_SAMPLER_ARG)
  • parentbased_always_offParentBasedSampler with AlwaysOffSampler root
  • parentbased_always_onParentBasedSampler with AlwaysOnSampler root
  • parentbased_traceidratioParentBasedSampler with TraceIdRatioBasedSampler root

Usage Examples:

# Set environment variables
export OTEL_TRACES_SAMPLER=traceidratio
export OTEL_TRACES_SAMPLER_ARG=0.1

# Or parent-based with ratio
export OTEL_TRACES_SAMPLER=parentbased_traceidratio  
export OTEL_TRACES_SAMPLER_ARG=0.05
// Configuration will be loaded from environment variables
const provider = new BasicTracerProvider({
  // Sampler will be built from OTEL_TRACES_SAMPLER env var
  // Other configuration can override env vars
  resource: new Resource({
    'service.name': 'my-service'
  })
});

Custom Sampler Implementation

You can implement custom samplers by implementing the Sampler interface.

Usage Examples:

import { Sampler, SamplingResult, SamplingDecision } from '@opentelemetry/sdk-trace-base';

// Custom sampler that samples based on operation name
class OperationBasedSampler implements Sampler {
  constructor(private sampledOperations: Set<string>) {}
  
  shouldSample(
    context: Context,
    traceId: string,
    spanName: string,
    spanKind: SpanKind,
    attributes: Attributes,
    links: Link[]
  ): SamplingResult {
    const decision = this.sampledOperations.has(spanName)
      ? SamplingDecision.RECORD_AND_SAMPLED
      : SamplingDecision.NOT_RECORD;
      
    return { decision };
  }
  
  toString(): string {
    return `OperationBasedSampler{${Array.from(this.sampledOperations).join(',')}}`;
  }
}

// Use custom sampler
const provider = new BasicTracerProvider({
  sampler: new OperationBasedSampler(new Set([
    'user-login',
    'payment-process',
    'critical-operation'
  ]))
});

Install with Tessl CLI

npx tessl i tessl/npm-opentelemetry--sdk-trace-base

docs

index.md

platform.md

samplers.md

span-exporters.md

span-processors.md

tracer-provider.md

tile.json