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

otel-apollo-plugin

v0.0.1

Published

OpenTelemetry integration for Apollo Server - replaces the deprecated `@alphasense/jaeger-apollo-plugin`.

Readme

@alphasense/otel-apollo-plugin

OpenTelemetry integration for Apollo Server - replaces the deprecated @alphasense/jaeger-apollo-plugin.

This package provides a modern, standards-based approach to distributed tracing in Apollo Server using OpenTelemetry (OTEL), replacing the deprecated Jaeger/OpenTracing implementation.

Why Migrate?

  • Deprecated Dependencies: jaeger-client-node is officially deprecated and unmaintained
  • Industry Standard: OpenTelemetry is a CNCF graduated project, the future of observability
  • Better Performance: OTLP protocol is more efficient than Jaeger's HTTP/Thrift
  • Vendor Flexibility: Easy to switch backends (Datadog, Honeycomb, AWS X-Ray, etc.)
  • Active Maintenance: Regular releases and security updates

Installation

bun add @alphasense/otel-apollo-plugin
# or
npm install @alphasense/otel-apollo-plugin
# or
pnpm add @alphasense/otel-apollo-plugin

Usage

1. Initialize OpenTelemetry (Required)

CRITICAL: Initialize OpenTelemetry at the very top of your entry file, before importing Apollo Server or Express!

// index.ts - MUST be the first import!
import { initializeOpenTelemetry } from '@alphasense/otel-apollo-plugin';

// Initialize OTEL first
const sdk = initializeOpenTelemetry({
  serviceName: 'graphql-search',
  serviceVersion: '1.0.0',
});

// Now import Apollo Server and other modules
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';

2. Add Plugin to Apollo Server (Optional)

The plugin enriches traces with additional context like operation names, user IDs, and error information.

import { ApolloServer } from '@apollo/server';
import { OpenTelemetryPlugin, enrichContextWithOtel } from '@alphasense/otel-apollo-plugin';

const server = new ApolloServer({
  typeDefs,
  resolvers,
  plugins: [
    OpenTelemetryPlugin(),
    // ... other plugins
  ],
});

3. Enrich Context with OpenTelemetry Data

import { enrichContextWithOtel } from '@alphasense/otel-apollo-plugin';

const server = new ApolloServer({
  typeDefs,
  resolvers,
  context: async ({ req }) => {
    const baseContext = {
      user: await getUserFromToken(req.headers.authorization),
      // ... other context fields
    };

    // Adds requestId from trace ID
    return enrichContextWithOtel(baseContext);
  },
});

4. Use Utility Functions in Resolvers

import { getActiveSpan, getBaggageItem, BAGGAGE_KEYS, SpanStatusCode } from '@alphasense/otel-apollo-plugin';

const resolvers = {
  Query: {
    user: async (parent, { id }, context) => {
      // Get active span to add custom attributes
      const span = getActiveSpan();
      span?.setAttribute('user.id', id);

      // Get baggage values (e.g., clientId from gateway)
      const clientId = getBaggageItem(BAGGAGE_KEYS.CLIENT_ID);

      try {
        const user = await fetchUser(id);
        span?.setStatus({ code: SpanStatusCode.OK });
        return user;
      } catch (error) {
        span?.setStatus({
          code: SpanStatusCode.ERROR,
          message: error.message,
        });
        span?.recordException(error);
        throw error;
      }
    },
  },
};

5. Create Custom Spans

import { getTracer, SpanStatusCode } from '@alphasense/otel-apollo-plugin';

async function fetchUserData(userId: number) {
  const tracer = getTracer('graphql-search');
  const span = tracer.startSpan('fetch-user-data');

  try {
    const data = await database.query('SELECT * FROM users WHERE id = ?', [userId]);
    span.setAttribute('user.id', userId);
    span.setAttribute('db.rows_returned', data.length);
    span.setStatus({ code: SpanStatusCode.OK });
    return data;
  } catch (error) {
    span.setStatus({
      code: SpanStatusCode.ERROR,
      message: error.message,
    });
    span.recordException(error);
    throw error;
  } finally {
    span.end();
  }
}

Configuration

Environment Variables

# Enable/disable OpenTelemetry (default: true)
OTEL_ENABLED=true

# OTLP endpoint (default: http://grafana-agent-traces.tracing:4317)
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://grafana-agent-traces.tracing:4317

# Service version (optional, default: 1.0.0)
OTEL_SERVICE_VERSION=2.3.0

# Sampling configuration (optional)
OTEL_TRACES_SAMPLER=always_on  # always_on, always_off, traceidratio
OTEL_TRACES_SAMPLER_ARG=1.0    # For traceidratio: 0.0 to 1.0

Programmatic Configuration

initializeOpenTelemetry({
  serviceName: 'graphql-search',
  serviceVersion: '1.0.0',
  otlpEndpoint: 'http://grafana-agent-traces.tracing:4317',
  enabled: true,
  graphqlConfig: {
    ignoreTrivialResolveSpans: true, // Skip trivial resolvers (default: true)
    depth: 10,                        // Maximum span depth (default: 10)
    mergeItems: true,                 // Merge list items (default: true)
  },
});

Migration from jaeger-apollo-plugin

Breaking Changes

1. Context Structure

Before (OpenTracing):

interface BaseContext extends JaegerPluginContext {
  tracer: Tracer;
  rootSpan: Span;
  // ...
}

After (OpenTelemetry):

import { getActiveSpan, getTracer } from '@alphasense/otel-apollo-plugin';

interface BaseContext {
  requestId: string;  // From enrichContextWithOtel()
  // No tracer or rootSpan needed
  // ...
}

// In resolvers:
const span = getActiveSpan();
const tracer = getTracer('my-service');

2. Baggage Access

Before:

const clientId = context.rootSpan?.getBaggageItem('CLIENT_ID');

After:

import { getBaggageItem, BAGGAGE_KEYS } from '@alphasense/otel-apollo-plugin';

const clientId = getBaggageItem(BAGGAGE_KEYS.CLIENT_ID);

3. Span Operations

Before:

span.setTag('http.status_code', 200);
span.log({ event: 'error', message: 'Failed' });
span.finish();

After:

span.setAttribute('http.status_code', 200);
span.addEvent('error', { message: 'Failed' });
span.end();

4. Initialization Order

Critical: OpenTelemetry MUST be initialized before importing Apollo Server:

// ✅ Correct
import { initializeOpenTelemetry } from '@alphasense/otel-apollo-plugin';
const sdk = initializeOpenTelemetry({ serviceName: 'my-service' });
import { ApolloServer } from '@apollo/server';

// ❌ Wrong - traces will be incomplete!
import { ApolloServer } from '@apollo/server';
import { initializeOpenTelemetry } from '@alphasense/otel-apollo-plugin';

API Reference

Initialization

initializeOpenTelemetry(config: OtelConfig)

Initialize the OpenTelemetry SDK with OTLP exporter.

Plugin

OpenTelemetryPlugin<TContext>()

Apollo Server plugin that enriches traces with GraphQL operation data.

enrichContextWithOtel<TContext>(context: TContext)

Adds OpenTelemetry data (requestId) to your Apollo Server context.

Utility Functions

getActiveSpan(): Span | undefined

Get the currently active span from the OpenTelemetry context.

getTracer(name: string, version?: string): Tracer

Get a tracer instance for creating custom spans.

getBaggageItem(key: BaggageKey): string | undefined

Get a baggage value from the current context.

setBaggageItem(key: BaggageKey, value: string): Context

Set a baggage value in the current context.

getAllBaggage(): Record<string, string>

Get all baggage items as an object.

getTraceId(): string | undefined

Get the current trace ID.

getSpanId(): string | undefined

Get the current span ID.

Constants

BAGGAGE_KEYS

Standard baggage keys:

  • BAGGAGE_KEYS.CLIENT_ID - Client ID making the request
  • BAGGAGE_KEYS.OPERATION_NAME - Root operation name

Development

Build

bun run build

Test

bun test

Lint

bun run lint

License

MIT

Contributing

Issues and pull requests are welcome!