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

newrelic-nestjs-instrumentation

v0.3.0

Published

Comprehensive New Relic instrumentation for NestJS applications - SQS, Kafka, HTTP/2, cron jobs and custom protocols

Readme

New Relic NestJS Instrumentation

A comprehensive New Relic instrumentation library for NestJS applications, designed to provide automatic transaction tracking and monitoring for scenarios not covered by standard New Relic auto-instrumentation.

npm version License: ISC TypeScript

Overview

This library provides robust New Relic instrumentation for NestJS applications, especially targeting use cases where New Relic's automatic instrumentation falls short:

  • SQS and Kafka Consumers - Track message processing with proper transaction boundaries
  • HTTP/2 Applications - Full support for HTTP/2 protocol instrumentation
  • Custom Applications - Cron jobs, background tasks, and microservices
  • Microservice Architectures - Distributed tracing across custom protocols
  • WebSocket Applications - Real-time application monitoring
  • GraphQL APIs - Detailed resolver and subscription tracking

Features

  • 🚀 Automatic Transaction Management - Zero-configuration transaction creation and lifecycle management
  • 🔄 Distributed Tracing - Full support for distributed tracing headers and correlation
  • 📊 Event-Driven Monitoring - Real-time transaction event emissions for custom monitoring
  • 🛡️ HTTP/2 Compatible - Full support for HTTP/2 applications
  • 🔧 Custom Protocol Support - Works with any NestJS controller-based application
  • 📱 Async Context Preservation - Maintains transaction context across async operations
  • 🎯 Type-Safe - Full TypeScript support with comprehensive type definitions
  • 🔍 Debugging Support - Built-in event system for transaction monitoring and debugging

Installation

npm install newrelic-nestjs-instrumentation newrelic
# or
yarn add newrelic-nestjs-instrumentation newrelic
# or
pnpm add newrelic-nestjs-instrumentation newrelic

📋 Setup Checklist:

  1. Install the package
  2. Import newrelic in your main.ts before any other imports
  3. Import NestJsNewrelicInstrumentationModule as the FIRST module in your AppModule
  4. Configure New Relic environment variables

Quick Start

⚠️ Important: Module Import Order

The instrumentation module MUST be imported as the FIRST module in your main application module. This ensures proper initialization before any other application code runs.

1. Basic Setup

import { Module } from '@nestjs/common';
import { NestJsNewrelicInstrumentationModule } from 'newrelic-nestjs-instrumentation';
// Import other modules AFTER the instrumentation module
import { UsersModule } from './users/users.module';
import { OrdersModule } from './orders/orders.module';

@Module({
  imports: [
    // ⚠️ CRITICAL: Must be the FIRST import
    NestJsNewrelicInstrumentationModule,
    // Other modules come after
    UsersModule,
    OrdersModule,
  ],
})
export class AppModule {}

2. New Relic Configuration

Ensure you have New Relic configured in your application:

// main.ts (before importing any other modules)
import 'newrelic';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();

3. Environment Variables

NEW_RELIC_LICENSE_KEY=your_license_key
NEW_RELIC_APP_NAME=your_app_name
NEW_RELIC_LOG_LEVEL=info

Use Cases

SQS Message Processing

@Controller('sqs')
export class SqsController {
  constructor(private readonly sqsService: SqsService) {}

  @Post('process-message')
  async processMessage(@Body() sqsEvent: any) {
    // New Relic transaction automatically created
    // Transaction name: "SqsController.processMessage"

    for (const record of sqsEvent.Records) {
      await this.sqsService.processMessage(record);
    }

    return { processed: sqsEvent.Records.length };
  }
}

Kafka Consumer

@Controller('kafka')
export class KafkaController {
  constructor(
    private readonly kafkaService: KafkaService,
    private readonly events: NewReliNestjsEvent
  ) {
    // Monitor Kafka message processing
    this.events.on('transactionStarted', (transactionId) => {
      console.log(`Processing Kafka message in transaction: ${transactionId}`);
    });
  }

  @Post('handle-message')
  async handleMessage(@Body() kafkaMessage: any) {
    // Automatic transaction tracking for Kafka messages
    const result = await this.kafkaService.process(kafkaMessage);

    // Transaction context preserved throughout processing
    return result;
  }
}

HTTP/2 Application

// Works seamlessly with HTTP/2
@Controller('users')
export class UserController {
  @Get(':id')
  async getUser(@Param('id') id: string) {
    // Full HTTP/2 support with proper transaction tracking
    // Distributed tracing headers automatically handled
    return this.userService.findById(id);
  }
}

Cron Jobs and Background Tasks

@Injectable()
export class CronService {
  constructor(private readonly events: NewReliNestjsEvent) {}

  @Cron('0 */6 * * *') // Every 6 hours
  async processScheduledTask() {
    // For cron jobs, manually trigger the guard and interceptor
    // or create a controller endpoint and call it internally
    return this.performTask();
  }
}

// Better approach for cron jobs:
@Controller('cron')
export class CronController {
  @Post('scheduled-task')
  async scheduledTask() {
    // This will be properly instrumented
    return this.cronService.performTask();
  }
}

API Reference

NestJsNewrelicInstrumentationModule

The main module that sets up New Relic instrumentation.

@Module({
  imports: [NestJsNewrelicInstrumentationModule]
})
export class AppModule {}

What it provides:

  • Global NewrelicContextGuard for transaction management
  • Global NewrelicInterceptor for transaction lifecycle
  • NewReliNestjsEvent service for event monitoring

NewReliNestjsEvent

Event emitter service for monitoring transaction lifecycle.

@Injectable()
export class MyService {
  constructor(private events: NewReliNestjsEvent) {
    this.setupEventListeners();
  }

  private setupEventListeners() {
    // Transaction started successfully
    this.events.on('transactionStarted', (transactionId: string) => {
      console.log(`Transaction ${transactionId} started`);
    });

    // Transaction completed (success or error)
    this.events.on('transactionFinished', (transactionId: string) => {
      console.log(`Transaction ${transactionId} finished`);
    });

    // Transaction creation failed
    this.events.on('transactionStartFailed', (transactionId: string, error: unknown) => {
      console.error(`Transaction ${transactionId} failed to start:`, error);
    });
  }
}

NewrelicContextGuard

Guard that sets up New Relic transaction context (automatically applied globally).

Transaction Naming Convention:

  • Format: ControllerName.methodName
  • Example: UserController.getUser, KafkaController.processMessage

NewrelicInterceptor

Interceptor that manages transaction lifecycle (automatically applied globally).

Advanced Usage

Custom Monitoring Integration

@Injectable()
export class CustomMonitoringService {
  private transactionMetrics = new Map<string, { startTime: number }>();

  constructor(private events: NewReliNestjsEvent) {
    this.setupAdvancedMonitoring();
  }

  private setupAdvancedMonitoring() {
    this.events.on('transactionStarted', (transactionId) => {
      this.transactionMetrics.set(transactionId, {
        startTime: Date.now()
      });

      // Send to external monitoring system
      this.externalMonitoring.trackTransactionStart(transactionId);
    });

    this.events.on('transactionFinished', (transactionId) => {
      const metrics = this.transactionMetrics.get(transactionId);
      if (metrics) {
        const duration = Date.now() - metrics.startTime;
        this.externalMonitoring.trackTransactionEnd(transactionId, duration);
        this.transactionMetrics.delete(transactionId);
      }
    });
  }
}

Error Tracking

@Injectable()
export class ErrorTrackingService {
  constructor(private events: NewReliNestjsEvent) {
    this.events.on('transactionStartFailed', (transactionId, error) => {
      // Log to external error tracking service
      this.errorTracker.captureException(error, {
        transactionId,
        context: 'newrelic-transaction-start'
      });
    });
  }
}

Best Practices

1. Module Import Order

Always import the New Relic module early in your application:

// Correct order
@Module({
  imports: [
    NestJsNewrelicInstrumentationModule, // First
    DatabaseModule,
    AuthModule,
    // Other modules...
  ],
})
export class AppModule {}

2. Environment Configuration

Use environment-specific New Relic configuration:

// config/newrelic.config.ts
export const newRelicConfig = {
  development: {
    enabled: false,
    logging: { level: 'trace' }
  },
  production: {
    enabled: true,
    logging: { level: 'info' }
  }
};

3. Error Handling

Always handle New Relic instrumentation errors gracefully:

@Injectable()
export class SafeInstrumentationService {
  constructor(private events: NewReliNestjsEvent) {
    this.events.on('transactionStartFailed', (transactionId, error) => {
      // Log but don't throw - keep application functional
      this.logger.warn(`New Relic transaction failed: ${transactionId}`, error);
    });
  }
}

4. Performance Monitoring

Monitor the performance impact of instrumentation:

@Injectable()
export class PerformanceMonitoringService {
  constructor(private events: NewReliNestjsEvent) {
    this.events.on('transactionStarted', (transactionId) => {
      // Track instrumentation overhead
      this.performanceMonitor.startTimer(`instrumentation.${transactionId}`);
    });
  }
}

Troubleshooting

Common Issues

  1. Transactions not appearing in New Relic

    • Ensure New Relic agent is properly configured
    • Check that NEW_RELIC_LICENSE_KEY is set
    • Verify the module is imported before other modules
  2. HTTP/2 requests not tracked

    • This library specifically addresses HTTP/2 compatibility
    • Ensure you're using NestJS controllers (not pure HTTP/2 handlers)
  3. SQS/Kafka messages not instrumented

    • Make sure your message handlers are in NestJS controllers
    • Use @Post() or similar decorators for handler methods
  4. Events not firing

    • Verify NewReliNestjsEvent is properly injected
    • Check that the module is correctly imported

Debug Mode

Enable debug logging to troubleshoot issues:

@Injectable()
export class DebugService {
  constructor(private events: NewReliNestjsEvent) {
    // Log all transaction events
    this.events.on('transactionStarted', (id) =>
      console.log(`[DEBUG] Transaction started: ${id}`));
    this.events.on('transactionFinished', (id) =>
      console.log(`[DEBUG] Transaction finished: ${id}`));
    this.events.on('transactionStartFailed', (id, error) =>
      console.error(`[DEBUG] Transaction failed: ${id}`, error));
  }
}

Contributing

We welcome contributions! Please see our Contributing Guide for details on development setup, testing, and submission guidelines.

Development Setup

# Clone the repository
git clone https://github.com/your-org/newrelic-nestjs-instrumentation.git

# Install dependencies
pnpm install

# Run tests
pnpm test

# Run linting
pnpm lint

# Build the project
pnpm build

License

This project is licensed under the ISC License - see the LICENSE file for details.

Support

Related Projects