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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@atrim/instrument-node

v0.5.1

Published

OpenTelemetry instrumentation for Node.js with centralized YAML configuration

Readme

@atrim/instrument-node

One-line OpenTelemetry for Node.js

npm version License: MIT

OpenTelemetry instrumentation for Node.js with centralized YAML configuration. Works with any Node.js framework (Express, Fastify, Koa, Hono) and runtime (Node.js, Bun, Deno).

Quick Start

1. Install

npm install @atrim/instrument-node

2. Initialize (at the top of your app)

Promise API (Traditional)

import { initializeInstrumentation } from '@atrim/instrument-node'

await initializeInstrumentation()

Effect API (Recommended)

import { Effect } from 'effect'
import { initializeInstrumentationEffect } from '@atrim/instrument-node'

await Effect.runPromise(initializeInstrumentationEffect())

3. Done! Your app is now sending traces to OpenTelemetry.

By default, traces go to http://localhost:4318. To send to a remote collector:

await initializeInstrumentation({
  otlp: { endpoint: 'https://otel-collector.company.com:4318' }
})

What just happened?

Auto-detected and configured:

  • ✅ Service name from package.json
  • ✅ OTLP endpoint (local or remote)
  • ✅ Auto-instrumentation for Express, HTTP, Fastify, etc.
  • ✅ Graceful shutdown on SIGTERM/SIGINT

Optional: Control What Gets Traced

Create instrumentation.yaml in your project root:

version: "1.0"
instrumentation:
  enabled: true
  instrument_patterns:
    - pattern: "^app\\."      # ✅ Trace application operations
  ignore_patterns:
    - pattern: "^health\\."   # ❌ Skip health checks

That's it!

Features

  • Zero-config - Works out of the box with sensible defaults
  • Universal - Node.js 20+, Bun 1.0+, Deno 1.40+
  • Framework-agnostic - Express, Fastify, Koa, Hono, vanilla HTTP
  • Effect-TS first - Typed error handling with Effect (optional)
  • Pattern-based filtering - Control which spans are created via YAML
  • HTTP filtering - Prevent noisy health checks and metrics endpoints
  • Centralized config - YAML file, URL, or environment variable
  • Production-ready - Graceful shutdown, error handling, performance optimized

Documentation

Full documentation is available in the main repository:

Core Docs

Specialized Guides

Installation

npm

npm install @atrim/instrument-node

yarn

yarn add @atrim/instrument-node

pnpm

pnpm add @atrim/instrument-node

Bun

bun add @atrim/instrument-node

Usage Examples

Express Application

import express from 'express'
import { initializeInstrumentation } from '@atrim/instrument-node'

// Initialize at startup
await initializeInstrumentation()

const app = express()

app.get('/users', async (req, res) => {
  // Automatically traced!
  const users = await fetchUsers()
  res.json(users)
})

app.listen(3000)

Effect-TS Application

import { Effect, Layer } from 'effect'
import { EffectInstrumentationLive } from '@atrim/instrument-node/effect'

const program = Effect.gen(function* () {
  // Automatically traced with Effect.withSpan()
  yield* myOperation.pipe(Effect.withSpan('app.operation'))
}).pipe(
  Effect.provide(EffectInstrumentationLive)
)

await Effect.runPromise(program)

Effect-TS Span Annotation Helpers

The library provides 9 production-tested annotation helpers for enriching spans with semantic attributes:

import { Effect } from 'effect'
import {
  annotateUser,
  annotateBatch,
  annotateDataSize,
  annotateLLM,
  annotateQuery,
  annotateHttpRequest,
  annotateError,
  annotatePriority,
  annotateCache,
  autoEnrichSpan,
  withAutoEnrichedSpan
} from '@atrim/instrument-node/effect'

// Example: Batch processing with automatic enrichment
const processBatch = Effect.gen(function* () {
  // Auto-enrich with Effect metadata (fiber ID, status, parent span info)
  yield* autoEnrichSpan()

  // Add user context
  yield* annotateUser('user-123', '[email protected]')

  // Add batch metadata
  yield* annotateBatch(100, 10) // 100 items in batches of 10

  // Process items
  const results = yield* processItems(items)

  // Update with results
  yield* annotateBatch(100, 10, results.success, results.failures)

  return results
}).pipe(Effect.withSpan('batch.process'))

// Or use the convenience wrapper
const processWithAutoEnrich = withAutoEnrichedSpan('batch.process')(
  Effect.gen(function* () {
    yield* annotateBatch(100, 10)
    return yield* processItems(items)
  })
)

Available annotation helpers:

  • annotateUser(userId, email?, username?) - User context
  • annotateDataSize(bytes, items, compressionRatio?) - Data size metrics
  • annotateBatch(totalItems, batchSize, successCount?, failureCount?) - Batch operations
  • annotateLLM(model, provider, tokens?) - LLM operations (GPT, Claude, etc.)
  • annotateQuery(query, duration?, rowCount?, database?) - Database queries
  • annotateHttpRequest(method, url, statusCode?, contentLength?) - HTTP requests
  • annotateError(error, recoverable, errorType?) - Error context
  • annotatePriority(priority, reason?) - Operation priority
  • annotateCache(hit, key, ttl?) - Cache operations

Auto-enrichment utilities:

  • autoEnrichSpan() - Automatically add Effect metadata (fiber ID, status, parent span info)
  • withAutoEnrichedSpan(name, options?) - Wrapper combining Effect.withSpan() + auto-enrichment

All helpers return Effect.Effect<void> and use Effect.annotateCurrentSpan() under the hood.

Bun Runtime

import { initializeInstrumentation } from '@atrim/instrument-node'

// Works exactly the same as Node.js
await initializeInstrumentation()

Bun.serve({
  port: 3000,
  fetch(req) {
    return new Response('Hello from Bun!')
  }
})

Remote Configuration

import { initializeInstrumentation } from '@atrim/instrument-node'

await initializeInstrumentation({
  configUrl: 'https://config.company.com/instrumentation.yaml',
  cacheTimeout: 300_000 // 5 minutes
})

Configuration

Priority Order (Highest to Lowest)

  1. Explicit Config Object - Passed programmatically
  2. Environment Variable - ATRIM_INSTRUMENTATION_CONFIG
  3. Project Root File - ./instrumentation.yaml
  4. Default Config - Built-in defaults

instrumentation.yaml Example

version: "1.0"

instrumentation:
  enabled: true
  logging: "on"

  # Pattern-based span filtering
  instrument_patterns:
    - pattern: "^app\\."
      enabled: true
      description: "Application operations"
    - pattern: "^storage\\."
      enabled: true
      description: "Storage layer"

  ignore_patterns:
    - pattern: "^health\\."
      description: "Health checks"
    - pattern: "^metrics\\."
      description: "Metrics endpoints"

# Effect-TS specific (optional)
effect:
  auto_extract_metadata: true

See Configuration Guide for complete reference.

HTTP Request Filtering

IMPORTANT: HTTP filtering requires explicit configuration to prevent noisy traces.

Add HTTP Filtering Patterns

# instrumentation.yaml
instrumentation:
  http_filtering:
    enabled: true
    ignore_routes:
      - pattern: "^/health$"
      - pattern: "^/metrics$"
      - pattern: "^/api/internal/"
      - pattern: "http://.*:4318/v1/traces"  # Prevent OTLP trace loops!

See HTTP Filtering Guide for details.

API Reference

Standard API (Promise-based)

// Main initialization
initializeInstrumentation(options?: SdkInitializationOptions): Promise<NodeSDK | null>

// Pattern matching only (skip SDK)
initializePatternMatchingOnly(options?: ConfigLoaderOptions): Promise<void>

// Configuration
loadConfig(options?: ConfigLoaderOptions): Promise<InstrumentationConfig>

// Service detection
detectServiceInfo(): Promise<ServiceInfo>
getServiceName(): Promise<string>
getServiceVersion(): Promise<string>

Effect API

// Main initialization (Effect)
initializeInstrumentationEffect(options?: SdkInitializationOptions): Effect.Effect<NodeSDK | null, InitializationError | ConfigError>

// Effect-TS Layer
EffectInstrumentationLive: Layer.Layer<Tracer.Tracer, ConfigError, never>

// Service detection (Effect)
detectServiceInfoEffect: Effect.Effect<ServiceInfo, ServiceDetectionError>
getServiceNameEffect: Effect.Effect<string, ServiceDetectionError>
getServiceVersionEffect: Effect.Effect<string, never>

See API Reference for complete documentation.

Runtimes Supported

  • Node.js 20.0.0+
  • Bun 1.0.0+
  • Deno 1.40.0+ (via npm compatibility)

Frameworks Supported

  • Express - Auto-instrumentation included
  • Fastify - Auto-instrumentation included
  • Koa - Auto-instrumentation included
  • Hono - Works with manual spans
  • Vanilla HTTP - Works with any Node.js HTTP server
  • Effect-TS - First-class integration with Effect.withSpan()

Examples

See the examples directory for complete working examples:

Troubleshooting

See Troubleshooting Guide for common issues and solutions.

Quick Fixes

No traces appearing?

  • Check collector is running: docker run -p 4318:4318 otel/opentelemetry-collector
  • Check endpoint: OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318

Too many traces?

Effect-TS spans not appearing?

  • Make sure you're using Effect.withSpan()
  • Provide EffectInstrumentationLive layer

Contributing

Contributions welcome! See main repository for guidelines.

License

MIT © Atrim AI

Related Packages

Links