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

@nestlib/apm

v4.0.1

Published

Nestlib – Nest APM – helpers for APM (Application Performance Monitoring) in NestJS projects

Readme

📊 @nestlib/apm – APM Module for NestJS

LSK.js NPM version NPM downloads Package size Package size Ask us in Telegram

📊 Elastic APM integration: Full-featured APM agent integration for NestJS
🎯 Transaction tracking: Automatic and manual transaction management
🔍 Span tracking: Detailed performance monitoring with spans
🎨 Decorators: @ApmTrack and @ApmSpan for easy integration
🗄️ Specialized tracking: Elasticsearch, MongoDB, LLM, RabbitMQ
💉 DI Support: Dependency injection with @InjectApmService decorator

🚀 Quick Start

# pnpm
pnpm add @nestlib/apm elastic-apm-node

# yarn
yarn add @nestlib/apm elastic-apm-node

# npm
npm i @nestlib/apm elastic-apm-node
import { Module } from '@nestjs/common';
import { ApmModule } from '@nestlib/apm';

@Module({
  imports: [
    ApmModule.forRoot({
      active: true,
      config: {
        serviceName: 'my-service',
        serverUrl: 'http://apm-server:8200',
      },
    }),
  ],
})
export class AppModule {}

The module will automatically load APM configuration from .env file, environment variables, or provided options.

✨ Features

  • 📊 Elastic APM integration for NestJS applications
  • 🎯 Automatic transaction tracking with decorators
  • 🔍 Span tracking for detailed performance monitoring
  • 🗄️ Specialized tracking for Elasticsearch, MongoDB, LLM, and RabbitMQ
  • 🎨 Decorator-based API for easy integration
  • 🔌 Interceptor support for automatic HTTP request tracking
  • ⚙️ Flexible configuration via module options, config files, or environment variables
  • 🛡️ Graceful degradation when APM is disabled
  • 📝 Full TypeScript support with type definitions
  • 🔀 Async module registration with forRootAsync

📖 Usage

Using ApmService

Inject and Access APM Service

import { Injectable } from '@nestjs/common';
import { ApmService, InjectApmService } from '@nestlib/apm';

@Injectable()
export class MyService {
  constructor(
    @InjectApmService() private readonly apm: ApmService,
  ) {}

  async getUser(id: string) {
    return this.apm.runTransaction('getUser', 'request', async () => {
      // Your logic here
      return { id, name: 'John Doe' };
    });
  }
}

Transaction with Labels and Context

async createOrder(userId: string, items: any[]) {
  return this.apm.runTransaction(
    'createOrder',
    'request',
    async () => {
      // Your order creation logic
      return { orderId: '12345' };
    },
    {
      labels: { userId, itemCount: items.length },
      context: { order: { items } },
    },
  );
}

Span Tracking

async performDatabaseQuery() {
  return this.apm.runSpan(
    'database-query',
    'db',
    async () => {
      // Database query logic
    },
    {
      subtype: 'postgresql',
      labels: { 'db.name': 'mydb' },
    },
  );
}

Using Decorators

@ApmTrack Decorator

Automatically track methods as transactions:

import { Injectable } from '@nestjs/common';
import { ApmTrack } from '@nestlib/apm';

@Injectable()
export class DataService {
  @ApmTrack('fetchData', 'request')
  async fetchData() {
    // Your logic here
  }

  @ApmTrack() // Uses method name automatically
  async processData() {
    // Your logic here
  }
}

@ApmSpan Decorator

Track methods as spans within transactions:

import { Injectable } from '@nestjs/common';
import { ApmSpan } from '@nestlib/apm';

@Injectable()
export class DatabaseService {
  @ApmSpan('database-query', 'db', 'postgresql')
  async queryDatabase() {
    // Database query logic
  }

  @ApmSpan() // Uses method name automatically
  async cacheLookup() {
    // Cache lookup logic
  }
}

Specialized Tracking Methods

Elasticsearch

async searchUsers(query: string) {
  return this.apm.trackElasticsearchQuery(
    'users-index',
    'search',
    async () => {
      return await elasticsearchClient.search({ ... });
    },
    { query },
  );
}

MongoDB

async findUsers(filter: any) {
  return this.apm.trackMongoQuery(
    'users',
    'find',
    async () => {
      return await mongoCollection.find(filter).toArray();
    },
    filter,
  );
}

LLM Requests

async generateText(prompt: string) {
  return this.apm.trackLlmRequest(
    'gpt-4',
    'completion',
    async () => {
      return await llmClient.complete(prompt);
    },
    { text: prompt, tokenCount: 100 },
  );
}

RabbitMQ Messages

async handleMessage(queue: string, routingKey: string, data: any) {
  return this.apm.trackRabbitMqMessage(
    queue,
    routingKey,
    async (transaction) => {
      if (transaction) {
        transaction.addLabels({ messageId: data.id });
      }
      // Process message
    },
    data,
  );
}

Async Configuration

Use forRootAsync when you need to load configuration dynamically:

import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { ApmModule } from '@nestlib/apm';

@Module({
  imports: [
    ApmModule.forRootAsync({
      imports: [ConfigModule],
      useFactory: (config: ConfigService) => ({
        active: config.get('APM_ACTIVE') === 'true',
        config: {
          serviceName: config.get('SERVICE_NAME'),
          environment: config.get('NODE_ENV'),
          serverUrl: config.get('APM_SERVER_URL'),
        },
      }),
      inject: [ConfigService],
    }),
  ],
})
export class AppModule {}

Using Interceptors

ElasticsearchApmInterceptor

import { Controller, Get, UseInterceptors } from '@nestjs/common';
import { ElasticsearchApmInterceptor } from '@nestlib/apm';

@Controller('search')
@UseInterceptors(ElasticsearchApmInterceptor)
export class SearchController {
  @Get()
  async search() {
    // Elasticsearch query
  }
}

Environment Variables

# Enable/disable APM
ELASTIC_APM_ACTIVE=true

# Service identification
ELASTIC_APM_SERVICE_NAME=my-service
ELASTIC_APM_ENVIRONMENT=production

# APM Server connection
ELASTIC_APM_SERVER_URL=http://apm-server:8200
ELASTIC_APM_SECRET_TOKEN=your-secret-token

📚 API Reference

ApmModule

ApmModule.forRoot(options?: ApmModuleOptions)

Initialize the APM module synchronously.

Options:

interface ApmModuleOptions {
  config?: AgentConfigOptions; // Elastic APM configuration
  active?: boolean;            // Whether APM is active
  serviceName?: string;        // Service name
  environment?: string;        // Environment name
}

ApmModule.forRootAsync(options?: ApmModuleAsyncOptions)

Initialize the APM module asynchronously.

interface ApmModuleAsyncOptions {
  imports?: any[];             // Modules to import
  inject?: InjectionToken[];   // Dependencies to inject into useFactory
  useFactory?: (...args: any[]) => Promise<ApmModuleOptions> | ApmModuleOptions;
}

ApmService

Service for programmatic APM tracking.

// Run a transaction
await apmService.runTransaction('name', 'type', fn, options?);

// Run a span within current transaction
await apmService.runSpan('name', 'type', fn, options?);

// Specialized tracking
await apmService.trackElasticsearchQuery(index, operation, fn, queryBody?);
await apmService.trackMongoQuery(collection, operation, fn, query?);
await apmService.trackLlmRequest(model, operation, fn, options?);
await apmService.trackRabbitMqMessage(queue, routingKey, fn, messageData?);

// Labels and context
apmService.addLabels({ key: 'value' });
apmService.setCustomContext({ custom: 'data' });

// Error tracking
apmService.captureError(error, context?);

// Check if APM is running
apmService.isStarted();

InjectApmService

Decorator for injecting ApmService.

// Inject default APM service
constructor(@InjectApmService() private apm: ApmService) {}

// Inject namespaced APM service
constructor(@InjectApmService('custom') private apm: ApmService) {}

Decorators

@ApmTrack(name?, type?)

Decorator for automatic transaction tracking.

  • name - Transaction name (optional, defaults to ClassName.methodName)
  • type - Transaction type (default: 'custom')

@ApmSpan(name?, type?, subtype?)

Decorator for span tracking.

  • name - Span name (optional, defaults to ClassName.methodName)
  • type - Span type (default: 'custom')
  • subtype - Span subtype (optional)

🔧 Configuration

Configuration Priority

  1. Module options (highest priority)
  2. Config file (.env via @lsk4/config)
  3. Environment variables (lowest priority)

File Type Detection

The module automatically loads configuration from .env files:

# .env
APM_ACTIVE=true
APM_SERVICE_NAME=my-service
APM_ENVIRONMENT=production
APM_SERVER_URL=http://apm-server:8200

Graceful Degradation

If APM is not started or disabled, all methods work without tracking. Your application continues to function even if APM is unavailable.

📝 License

MIT © Igor Suvorov

🔗 Links


@nestlib/apmElastic APM integration for NestJS 📊

Docs

Read full docs here.