CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-opentelemetry--instrumentation

Base class for node which OpenTelemetry instrumentation modules extend

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

semconv-stability.mddocs/

Semantic Convention Stability

Support for OpenTelemetry semantic convention stability migration, allowing instrumentations to emit stable, old, or both versions of semantic conventions based on configuration.

Capabilities

SemconvStability Enum

Enum defining the semantic convention stability options.

/**
 * Semantic convention stability options
 */
enum SemconvStability {
  /** Emit only stable semantic conventions */
  STABLE = 0x1,
  /** Emit only old semantic conventions */
  OLD = 0x2,
  /** Emit both stable and old semantic conventions */
  DUPLICATE = 0x1 | 0x2
}

Usage Example:

import { SemconvStability } from "@opentelemetry/instrumentation";

class HttpInstrumentation extends InstrumentationBase {
  private _semconvStability: SemconvStability;

  constructor(config = {}) {
    super("@opentelemetry/instrumentation-http", "1.0.0", config);
    
    // Configure semconv stability
    this._semconvStability = semconvStabilityFromStr(
      'http',
      process.env.OTEL_SEMCONV_STABILITY_OPT_IN
    );
  }

  private _addAttributes(span: Span, request: IncomingMessage) {
    // Apply semantic conventions based on stability setting
    if (this._semconvStability & SemconvStability.OLD) {
      // Old semantic conventions
      span.setAttributes({
        'http.method': request.method,
        'http.url': request.url,
        'http.scheme': 'http'
      });
    }

    if (this._semconvStability & SemconvStability.STABLE) {
      // Stable semantic conventions
      span.setAttributes({
        'http.request.method': request.method,
        'url.full': request.url,
        'url.scheme': 'http'
      });
    }
  }
}

semconvStabilityFromStr Function

Parse semantic convention stability configuration from string (typically environment variable).

/**
 * Determine appropriate semconv stability for the given namespace
 * @param namespace The semantic convention namespace (e.g., 'http', 'database')
 * @param str Comma-separated configuration string
 * @returns SemconvStability setting for the namespace
 */
function semconvStabilityFromStr(
  namespace: string,
  str: string | undefined
): SemconvStability;

Usage Examples:

import { semconvStabilityFromStr, SemconvStability } from "@opentelemetry/instrumentation";

// Parse from environment variable
const httpStability = semconvStabilityFromStr(
  'http',
  process.env.OTEL_SEMCONV_STABILITY_OPT_IN
);

// Example environment variable values and results:
// OTEL_SEMCONV_STABILITY_OPT_IN="http" -> SemconvStability.STABLE
// OTEL_SEMCONV_STABILITY_OPT_IN="http/dup" -> SemconvStability.DUPLICATE  
// OTEL_SEMCONV_STABILITY_OPT_IN="database" -> SemconvStability.OLD (http not mentioned)
// OTEL_SEMCONV_STABILITY_OPT_IN="http,database/dup" -> SemconvStability.STABLE (for http)

// Parse from configuration option
const databaseStability = semconvStabilityFromStr(
  'database',
  config?.semconvStabilityOptIn || process.env.OTEL_SEMCONV_STABILITY_OPT_IN
);

// Multiple namespace support
const messagingStability = semconvStabilityFromStr('messaging', 'messaging/dup,http');
// Result: SemconvStability.DUPLICATE for messaging

const k8sStability = semconvStabilityFromStr('k8s', 'http,database,k8s');
// Result: SemconvStability.STABLE for k8s

Configuration Patterns

Common patterns for configuring semantic convention stability in instrumentations.

Usage Examples:

// Environment variable based configuration
class EnvironmentBasedInstrumentation extends InstrumentationBase {
  private _semconvStability: SemconvStability;

  constructor(config = {}) {
    super("@example/instrumentation", "1.0.0", config);
    
    this._semconvStability = semconvStabilityFromStr(
      'http', 
      process.env.OTEL_SEMCONV_STABILITY_OPT_IN
    );
  }
}

// Configuration option based (for browser environments)
interface CustomInstrumentationConfig extends InstrumentationConfig {
  semconvStabilityOptIn?: string;
}

class ConfigurableInstrumentation extends InstrumentationBase<CustomInstrumentationConfig> {
  private _semconvStability: SemconvStability;

  constructor(config: CustomInstrumentationConfig = {}) {
    super("@example/instrumentation", "1.0.0", config);
    
    this._semconvStability = semconvStabilityFromStr(
      'database',
      config.semconvStabilityOptIn
    );
  }
}

// Multi-namespace instrumentation
class MultiNamespaceInstrumentation extends InstrumentationBase {
  private _httpStability: SemconvStability;
  private _databaseStability: SemconvStability;

  constructor(config = {}) {
    super("@example/instrumentation", "1.0.0", config);
    
    const stabilityConfig = process.env.OTEL_SEMCONV_STABILITY_OPT_IN;
    this._httpStability = semconvStabilityFromStr('http', stabilityConfig);
    this._databaseStability = semconvStabilityFromStr('database', stabilityConfig);
  }

  private _addHttpAttributes(span: Span, request: any) {
    if (this._httpStability & SemconvStability.OLD) {
      span.setAttributes({ 'http.method': request.method });
    }
    if (this._httpStability & SemconvStability.STABLE) {
      span.setAttributes({ 'http.request.method': request.method });
    }
  }

  private _addDatabaseAttributes(span: Span, query: any) {
    if (this._databaseStability & SemconvStability.OLD) {
      span.setAttributes({ 'db.statement': query.sql });
    }
    if (this._databaseStability & SemconvStability.STABLE) {
      span.setAttributes({ 'db.query.text': query.sql });
    }
  }
}

Migration Helpers

Utility functions to help with semantic convention migration.

Usage Example:

import { SemconvStability, semconvStabilityFromStr } from "@opentelemetry/instrumentation";

class MigrationAwareInstrumentation extends InstrumentationBase {
  private _semconvStability: SemconvStability;

  constructor(config = {}) {
    super("@example/instrumentation", "1.0.0", config);
    this._semconvStability = semconvStabilityFromStr(
      'http',
      process.env.OTEL_SEMCONV_STABILITY_OPT_IN
    );
  }

  // Helper to conditionally set attributes based on stability
  private _setConditionalAttributes(span: Span, attributes: {
    old?: Record<string, any>;
    stable?: Record<string, any>;
  }) {
    if (attributes.old && (this._semconvStability & SemconvStability.OLD)) {
      span.setAttributes(attributes.old);
    }
    
    if (attributes.stable && (this._semconvStability & SemconvStability.STABLE)) {
      span.setAttributes(attributes.stable);
    }
  }

  // Helper to determine if a specific stability mode is enabled
  private _isStabilityEnabled(mode: SemconvStability): boolean {
    return (this._semconvStability & mode) !== 0;
  }

  private _instrumentHttpRequest(span: Span, request: IncomingMessage) {
    // Using helper method
    this._setConditionalAttributes(span, {
      old: {
        'http.method': request.method,
        'http.target': request.url,
        'http.scheme': 'http'
      },
      stable: {
        'http.request.method': request.method,
        'url.path': request.url,
        'url.scheme': 'http'
      }
    });

    // Direct checking
    if (this._isStabilityEnabled(SemconvStability.OLD)) {
      span.setAttributes({
        'http.user_agent': request.headers['user-agent']
      });
    }

    if (this._isStabilityEnabled(SemconvStability.STABLE)) {
      span.setAttributes({
        'user_agent.original': request.headers['user-agent']
      });
    }

    // Duplicate mode handling
    if (this._semconvStability === SemconvStability.DUPLICATE) {
      this._diag.debug('Emitting both old and stable semantic conventions');
    }
  }

  // Configuration validation helper
  private _validateSemconvConfig(): void {
    const config = process.env.OTEL_SEMCONV_STABILITY_OPT_IN;
    if (config) {
      this._diag.debug(`Semconv stability configuration: ${config}`);
      this._diag.debug(`Parsed stability for http: ${this._semconvStability}`);
      
      if (this._semconvStability === SemconvStability.OLD) {
        this._diag.warn('Using deprecated semantic conventions. Consider migrating to stable conventions.');
      }
    }
  }
}

Namespace Support

Examples of supported namespaces and their semantic convention domains.

Usage Examples:

// HTTP semantic conventions
const httpStability = semconvStabilityFromStr('http', stabilityConfig);
// Covers: http.method -> http.request.method, http.status_code -> http.response.status_code

// Database semantic conventions  
const dbStability = semconvStabilityFromStr('database', stabilityConfig);
// Covers: db.statement -> db.query.text, db.type -> db.system

// Messaging semantic conventions
const messagingStability = semconvStabilityFromStr('messaging', stabilityConfig);
// Covers: messaging.system -> messaging.destination.name

// Kubernetes semantic conventions
const k8sStability = semconvStabilityFromStr('k8s', stabilityConfig);
// Covers: k8s.pod.name -> k8s.pod.uid, k8s.namespace.name

// Custom namespace support
const customStability = semconvStabilityFromStr('custom-domain', stabilityConfig);
// Supports any namespace string for custom semantic conventions

// Multiple namespaces in one configuration
// OTEL_SEMCONV_STABILITY_OPT_IN="http/dup,database,messaging/dup,k8s"
const multiConfig = "http/dup,database,messaging/dup,k8s";
const httpResult = semconvStabilityFromStr('http', multiConfig);        // DUPLICATE
const dbResult = semconvStabilityFromStr('database', multiConfig);      // STABLE  
const messagingResult = semconvStabilityFromStr('messaging', multiConfig); // DUPLICATE
const k8sResult = semconvStabilityFromStr('k8s', multiConfig);          // STABLE
const otherResult = semconvStabilityFromStr('other', multiConfig);      // OLD (default)

Install with Tessl CLI

npx tessl i tessl/npm-opentelemetry--instrumentation

docs

auto-registration.md

base-instrumentation.md

index.md

module-definitions.md

semconv-stability.md

utilities.md

tile.json