npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@validatedid/opentelemetry-wrapper

v0.0.1

Published

A TypeScript wrapper for OpenTelemetry SDK with singleton pattern support

Readme

OpenTelemetry Wrapper

A TypeScript wrapper for OpenTelemetry SDK with singleton pattern support.

Installation

npm install @your-scope/opentelemetry-wrapper

Note: Replace @your-scope/opentelemetry-wrapper with the actual package name when published.

Local Development

For testing this package locally before publishing, see LOCAL_TESTING.md.

Usage

Initialize OpenTelemetry

import { OpenTelemetryInitializer } from './src/OpenTelemetryInitializer';

// Initialize once at application startup
// build() returns the OpenTelemetry singleton instance directly
const otel = OpenTelemetryInitializer
    .initialize({
        baseUrl: 'http://localhost:4318',
        resourceAttributes: {
            serviceName: 'my-service',
            version: '1.0.0',
            product: 'my-product',
            environment: 'production',
            role: 'api',
            entry: 'http',
            costCenter: 'CC001',
        }
    })
    .withTraceExporter()
    .withLogExporter()
    .withMetricsExporter()
    .build();

Adding Custom Instrumentations

If you need to add instrumentations that are not automatically detected, use the withInstrumentation() method:

import { OpenTelemetryInitializer } from './src/OpenTelemetryInitializer';
import { GraphQLInstrumentation } from '@opentelemetry/instrumentation-graphql';
import { MongoDBInstrumentation } from '@opentelemetry/instrumentation-mongodb';

const otel = OpenTelemetryInitializer
    .initialize({
        baseUrl: 'http://localhost:4318',
        resourceAttributes: {
            serviceName: 'my-service',
            version: '1.0.0',
            product: 'my-product',
            environment: 'production',
            role: 'api',
            entry: 'http',
            costCenter: 'CC001',
        }
    })
    .withInstrumentation(new GraphQLInstrumentation())
    .withInstrumentation(new MongoDBInstrumentation())
    .withTraceExporter()
    .withLogExporter()
    .withMetricsExporter()
    .build();

Note: You can call withInstrumentation() multiple times to add multiple custom instrumentations. These will be added alongside the auto-detected instrumentations.

Configuration Validation

All configuration values are validated during initialization. Missing or empty values will throw descriptive errors:

// ❌ This will throw an error
OpenTelemetryInitializer.initialize({
    baseUrl: '',  // Error: "baseUrl is required in OpenTelemetry configuration"
    resourceAttributes: {
        serviceName: '',  // Error: "resourceAttributes.serviceName is required..."
        // ...
    }
});

Required configuration fields:

  • baseUrl - The OpenTelemetry collector endpoint
  • resourceAttributes.serviceName - Name of your service
  • resourceAttributes.version - Version of your service
  • resourceAttributes.product - Product name
  • resourceAttributes.environment - Environment (e.g., production, staging)
  • resourceAttributes.role - Service role (e.g., api, worker)
  • resourceAttributes.entry - Entry point type (e.g., http, grpc)
  • resourceAttributes.costCenter - Cost center identifier

Get Logger with Parameter

import { LogLevel } from '@vididentity/opentelemetry-wrapper';

// Get logger for a specific controller/component
const logger = otel.getLogger('user-controller');
logger.emit({
    severityNumber: LogLevel.INFO,
    severityText: 'INFO',
    body: 'User login successful',
    attributes: { userId: '123' }
});

// Get logger for another component
const orderLogger = otel.getLogger('order-service');
orderLogger.emit({
    severityNumber: LogLevel.ERROR,
    severityText: 'ERROR',
    body: 'Order processing failed',
    attributes: { orderId: '456' }
});

Available Log Levels

The LogLevel enum provides standard log severity levels without exposing OpenTelemetry internals:

LogLevel.TRACE      // Most verbose - fine-grained debugging
LogLevel.DEBUG      // Detailed debugging information
LogLevel.INFO       // Informational messages
LogLevel.WARN       // Warning messages
LogLevel.ERROR      // Error messages
LogLevel.FATAL      // Critical errors

// Each level also has variants (e.g., TRACE2, TRACE3, TRACE4, DEBUG2, etc.)
// for more granular control

Example usage:

import { OpenTelemetry, LogLevel } from '@vididentity/opentelemetry-wrapper';

const otel = OpenTelemetry.getInstance();
const logger = otel.getLogger('payment-service');

// Log at different levels
logger.emit({
    severityNumber: LogLevel.DEBUG,
    severityText: 'DEBUG',
    body: 'Payment validation started',
    attributes: { transactionId: 'tx-123' }
});

logger.emit({
    severityNumber: LogLevel.WARN,
    severityText: 'WARN',
    body: 'Payment processing slow',
    attributes: { duration: 5000 }
});

logger.emit({
    severityNumber: LogLevel.ERROR,
    severityText: 'ERROR',
    body: 'Payment failed',
    attributes: { error: 'Insufficient funds' }
});

Get Tracer

// Get tracer for a specific service
const tracer = otel.getTracer('my-service', '1.0.0');

// Create spans
const span = tracer.startSpan('process-order');
try {
    // Your code here
    span.setStatus({ code: 0 }); // OK
} finally {
    span.end();
}

Get Meter

// Get meter for metrics
const meter = otel.getMeter('my-service', '1.0.0');

// Create metrics
const counter = meter.createCounter('requests.count');
counter.add(1, { endpoint: '/api/users' });

Singleton Pattern

The OpenTelemetry class is a singleton, so you can get the instance anywhere in your application:

import { OpenTelemetry } from './src/OpenTelemetry';

// Get the singleton instance (must be initialized first)
const otel = OpenTelemetry.getInstance();

// Use it with different logger names for different parts of your application
const apiLogger = otel.getLogger('api-layer');
const dbLogger = otel.getLogger('database-layer');
const cacheLogger = otel.getLogger('cache-layer');

Shutdown

// Gracefully shutdown OpenTelemetry when your application exits
await otel.shutdown();

Architecture

  • OpenTelemetry - Singleton class that provides access to logger, tracer, and meter

    • getInstance() - Get the singleton instance
    • getLogger(name: string) - Get a logger with a specific name
    • getTracer(name: string, version?: string) - Get a tracer
    • getMeter(name: string, version?: string) - Get a meter
    • shutdown() - Shutdown the SDK gracefully
  • OpenTelemetryInitializer - Builder pattern for configuring and initializing OpenTelemetry

    • initialize(config) - Create initializer with configuration and validate all required fields
    • withTraceExporter() - Enable trace export to OTLP endpoint
    • withLogExporter() - Enable log export to OTLP endpoint
    • withMetricsExporter() - Enable metrics export to OTLP endpoint
    • withInstrumentation(instrumentation) - Add custom instrumentation not auto-detected (can be called multiple times)
    • build() - Build, start the SDK, and return the OpenTelemetry singleton instance
  • LogLevel - Enum for log severity levels without exposing OpenTelemetry internals

    • TRACE, DEBUG, INFO, WARN, ERROR, FATAL - Standard log levels
    • Each level includes variants (e.g., TRACE2, DEBUG3, etc.) for granular control
  • OpenTelemetryConfig - Configuration interface

    • baseUrl - OTLP collector endpoint
    • resourceAttributes - Service resource attributes (name, version, environment, etc.)

Design Patterns

Builder Pattern

The initializer uses the builder pattern for fluent configuration:

const otel = OpenTelemetryInitializer
    .initialize(config)
    .withInstrumentation(customInstrumentation) // Optional - add custom instrumentations
    .withTraceExporter()    // Optional
    .withLogExporter()       // Optional
    .withMetricsExporter()   // Optional
    .build();                // Returns OpenTelemetry instance

Singleton Pattern

The OpenTelemetry class ensures only one instance exists throughout the application:

// After initialization, you can get the instance anywhere
const otel = OpenTelemetry.getInstance();

No Temporal Coupling

The design eliminates temporal coupling - the OpenTelemetry singleton is properly initialized before being returned, so there's no risk of using it before it's ready.

Key Features

Singleton Pattern with Factory Methods

The library uses the singleton pattern with factory methods to provide a clean API:

  1. OpenTelemetry is a singleton - Only one instance exists throughout the application
  2. Factory methods - getLogger(name), getTracer(name), getMeter(name) create instrumentation with different identifiers
  3. Component-specific instrumentation - Each part of your application can get its own logger/tracer/meter with a unique name

Benefits:

  • Initialize OpenTelemetry once with all resource attributes (service name, environment, etc.)
  • Different parts of your application call getLogger('component-name') with their specific component identifier
  • All loggers share the same underlying configuration but are identified by different names
  • No temporal coupling - the SDK is fully initialized before being used
  • Type-safe configuration with runtime validation