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

nodejs-observability

v1.0.5

Published

tracing and logging using aws distro for opentelemetry

Downloads

11

Readme

nodejs-observability

A comprehensive AWS X-Ray telemetry package for Node.js applications using AWS Distro for OpenTelemetry (ADOT). This package provides automatic instrumentation, distributed tracing, and correlated logging with minimal configuration.

Features

  • 🔍 Automatic Instrumentation - HTTP, Database, Express and other services
  • 📊 Distributed Tracing - Full request tracing with AWS X-Ray
  • 📝 Correlated Logging - TraceId injection for log-trace correlation
  • 🎯 Method-level Tracing - Decorator-based span creation
  • 🛠️ Built-in Logger - Structured logging with severity levels
  • 🏃 Local Development - Jaeger support for local testing

Installation

npm install nodejs-observability

Quick Start

1. Initialize Telemetry

Import adotInit() at the very top of your server.ts file, before any other imports:

import { adotInit } from "nodejs-observability";

adotInit(
  "my-service-name",           // Service name for traces
  "/health",                    // Health check endpoint to exclude
  {                            // Local development config (optional)
    enable: true,
    endpoint: "http://localhost:4317"
  }
);

// Other imports follow...
import { logger } from "nodejs-observability";

2. Add Method Tracing

Use the @traceDecorator to automatically create spans for your methods:

import { traceDecorator } from "nodejs-observability";

class UserService {
  @traceDecorator
  public async getUser(id: string) {
    // This method is now automatically traced
    const user = await db.findUser(id);
    return user;
  }
  
  @traceDecorator
  public async updateUser(id: string, data: any) {
    // Nested traces are automatically linked
    await this.validateUser(id);
    return await db.updateUser(id, data);
  }
  
  @traceDecorator
  private async validateUser(id: string) {
    // Creates a child span under updateUser
    // Errors are automatically captured
  }
}

3. Use the Logger

The built-in logger automatically includes TraceId for correlation:

import { logger } from "nodejs-observability";

@traceDecorator
public async processOrder(orderId: string) {
  logger.info(
    "Processing order",
    "OrderService.processOrder",
    { orderId, status: "started" }
  );
  
  try {
    const result = await this.executeOrder(orderId);
    
    logger.info(
      "Order processed successfully",
      "OrderService.processOrder",
      { orderId, result }
    );
    
    return result;
  } catch (error) {
    logger.error(
      "Order processing failed",
      "OrderService.processOrder",
      { orderId, error: error.message }
    );
    throw error;
  }
}

4. Add Context Information

Enrich your logs with request and user context:

import { contextData, userContext } from "nodejs-observability";

// Middleware to add request context
app.use((req, res, next) => {
  contextData({
    url: req.url,
    method: req.method,
    requestId: req.headers['x-request-id']
  });
  next();
});

// Add user context after authentication
app.use(authMiddleware, (req, res, next) => {
  if (req.user) {
    userContext({
      userId: req.user.id,
      role: req.user.role
    });
  }
  next();
});

API Reference

adotInit(serviceName, healthCheckUrl, localhostConfig?)

Initializes the telemetry system.

| Parameter | Type | Description | |-----------|------|-------------| | serviceName | string | Name of your service in traces | | healthCheckUrl | string | Endpoint to exclude from tracing | | localhostConfig | object | Optional local development configuration | | localhostConfig.enable | boolean | Enable local tracing | | localhostConfig.endpoint | string | Local collector endpoint |

@traceDecorator

Method decorator that automatically creates spans.

@traceDecorator
async myMethod() {
  // Automatically traced
}

Logger Methods

All logger methods follow the pattern: logger.level(message, source, data?)

logger.info(message: string, source: string, data?: Record<string, unknown>)
logger.warning(message: string, source: string, data?: Record<string, unknown>)
logger.error(message: string, source: string, data?: Record<string, unknown>)
logger.debug(message: string, source: string, data?: Record<string, unknown>)

Context Methods

contextData(ctx: Record<string, unknown>)  // Set request context
userContext(usrCtx: Record<string, unknown>)  // Set user context

Local Development

For local development and testing, you can use Jaeger to visualize traces:

1. Start Jaeger

docker run -d --name jaeger \
  -e COLLECTOR_OTLP_ENABLED=true \
  -p 16686:16686 \
  -p 4317:4317 \
  -p 4318:4318 \
  jaegertracing/all-in-one:latest

2. Configure Local Tracing

adotInit("my-service", "/health", {
  enable: true,
  endpoint: "http://localhost:4317"
});

3. View Traces

Open Jaeger UI at http://localhost:16686 to view your traces.

Best Practices

1. Trace Key Operations

Apply @traceDecorator to:

  • API route handlers
  • Database operations
  • External API calls
  • Business logic methods
  • Error-prone operations

2. Use Structured Logging

// Good
logger.info("User created", "UserService.create", {
  userId: user.id,
  email: user.email,
  timestamp: Date.now()
});

// Avoid
logger.info(`User ${user.id} created`);

3. Handle Errors Properly

@traceDecorator
async riskyOperation() {
  try {
    return await externalApi.call();
  } catch (error) {
    logger.error("External API failed", "Service.riskyOperation", {
      error: error.message,
      code: error.code
    });
    throw error;  // Re-throw to maintain trace error status
  }
}

4. Create Trace Hierarchies

@traceDecorator
async parentOperation() {
  await this.childOperation1();  // Apply decorator to create child span
  await this.childOperation2();  // Apply decorator to create child span
}

Examples

Express Application

import { adotInit, traceDecorator, logger } from "nodejs-observability";

// Initialize at the very top
adotInit("express-api", "/health", {
  enable: process.env.NODE_ENV === 'development',
  endpoint: "http://localhost:4317"
});

import express from 'express';
const app = express();

class UserController {
  @traceDecorator
  async getUsers(req, res) {
    logger.info("Fetching users", "UserController.getUsers");
    const users = await userService.getAllUsers();
    res.json(users);
  }
}

app.get('/users', (req, res) => controller.getUsers(req, res));

Error Tracking

@traceDecorator
async processPayment(paymentData) {
  logger.info("Payment initiated", "PaymentService.process", {
    amount: paymentData.amount,
    currency: paymentData.currency
  });
  
  try {
    const result = await paymentGateway.charge(paymentData);
    logger.info("Payment successful", "PaymentService.process", {
      transactionId: result.id
    });
    return result;
  } catch (error) {
    // Error automatically linked to trace
    logger.error("Payment failed", "PaymentService.process", {
      error: error.message,
      paymentData
    });
    throw error;
  }
}

Open Source & Contributing

This package is completely free and open source! Feel free to:

  • 🍴 Fork it for your own use and modifications
  • 🔧 Customize it to fit your specific needs
  • 🚀 Use it in your commercial or personal projects
  • 💡 Contribute back if you've built something useful

Want to Contribute?

We'd love your help making this package better! Here's how:

# 1. Fork the repo to your account
# 2. Clone your fork
git clone https://github.com/manas-aggrawal/nodejs-observability.git
cd nodejs-observability
npm install

# 3. Create a feature branch
git checkout -b your-awesome-feature

# 4. Make your changes and test
npm test
npm run lint

# 5. Push to your fork
git push origin your-awesome-feature

# 6. Open a Pull Request to our main repo

All contributions are welcome:

  • 🐛 Bug fixes
  • ✨ New features
  • 📚 Documentation improvements
  • 🎨 Code refactoring
  • 💭 Ideas and suggestions

See CONTRIBUTING.md for detailed guidelines.

Using in Your Project?

No need to ask permission! This is MIT licensed - just fork it and make it your own. If you build something cool with it, we'd love to hear about it!

Troubleshooting

Traces not appearing in AWS X-Ray

  • Ensure AWS credentials are configured
  • Check IAM permissions for X-Ray
  • Verify service name doesn't contain invalid characters

Local traces not showing in Jaeger

  • Confirm Jaeger is running: docker ps
  • Check endpoint configuration matches Jaeger port
  • Verify localhostConfig.enable is true

Decorator not creating spans

  • Ensure @traceDecorator is applied to methods (not arrow functions)
  • Verify adotInit() is called before decorator usage
  • Check that decorated methods are actually being called

Requirements

  • Node.js >= 14.x
  • TypeScript >= 4.x (for decorator support)
  • AWS credentials configured (for X-Ray)

License

MIT

Support

For issues and questions:

Roadmap

  • [ ] Support for additional databases (MongoDB)
  • [ ] Custom span attributes
  • [ ] Sampling strategies configuration
  • [ ] Metrics collection
  • [ ] Support for other telemetry backends
  • [ ] NestJS integration

Made with ❤️ for the Node.js community