Nest.JS

TracesMetricsApp LogsCustom LogsProfiling

1. Prerequisites

Node.js 18.17.1+ and Python 3.8+ (for builds like node-gyp). Check with:

node --version
python3 --version
  • Middleware Host Agent on the same machine/cluster (Host mode). In containers, set MW_AGENT_SERVICE so your app can reach the agent:
    • Docker: MW_AGENT_SERVICE=172.17.0.1
    • Kubernetes: MW_AGENT_SERVICE=mw-service.mw-agent-ns.svc.cluster.local (Use this only when the app isn’t on the host network namespace.)

2. Install Nest.js APM package

npm install @middleware.io/nestjs-apm

3. Initialise the module (and add the interceptor)

Add the module in app.module.ts. Use serviceName (and optionally projectName). Then add the global interceptor in main.ts so requests/spans are captured.

app.module.ts:

import { Module } from '@nestjs/common';
import { MiddlewareApmModule } from '@middleware.io/nestjs-apm';


@Module({
  imports: [
    MiddlewareApmModule.forRoot({
      projectName: 'Your application name',
      serviceName: 'Your service name',
      // You may also set options via env vars (see table below)
    }),
  ],
})
export class AppModule {}

main.ts

import { NestFactory, Reflector } from '@nestjs/core';
import { AppModule } from './app.module';
import { MiddlewareApmInterceptor } from '@middleware.io/nestjs-apm';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalInterceptors(new MiddlewareApmInterceptor(app.get(Reflector)));
  await app.listen(3000);
}
bootstrap();

4. Basic Usage

Ignore routes you don’t want traced (e.g., health checks):

import { Controller, Get } from '@nestjs/common';
import { IgnoreApmTrace } from '@middleware.io/nestjs-apm';

@Controller('users')
export class UsersController {
  @IgnoreApmTrace()
  @Get('health')
  healthCheck() {
    return 'OK';
  }
}

5. Advanced instrumentation

Custom attributes:

import { Controller, Post } from '@nestjs/common';
import { WithAttributes } from '@middleware.io/nestjs-apm';

@Controller('orders')
export class OrdersController {
  @WithAttributes({ 'business.type': 'order', 'business.tier': 'premium' })
  @Post()
  createOrder() {}
}

Custom spans:

import { Injectable } from '@nestjs/common';
import { CreateSpan } from '@middleware.io/nestjs-apm';

@Injectable()
export class UserService {
  @CreateSpan('user.registration', { 'user.type': 'new' })
  async registerUser() {}
}

Record method params as span attributes:

import { Controller, Post } from '@nestjs/common';
import { RecordParams } from '@middleware.io/nestjs-apm';

@Controller('users')
export class UsersController {
  @RecordParams(['userId', 'action'])
  @Post(':userId/action')
  performAction(userId: string, action: string) {}
}

Logging integration (Nest logger is captured automatically):

import { Logger, Injectable } from '@nestjs/common';

@Injectable()
export class UserService {
  private readonly logger = new Logger(UserService.name);
  async createUser() {
    try {
      this.logger.log('Creating new user');
    } catch (e) {
      this.logger.error('Failed to create user', e);
      throw e;
    }
  }
}

6. Serverless (no Host Agent)

Send directly to Middleware by supplying your tenant target and API key. Put options in forRoot (or via env vars).

MiddlewareApmModule.forRoot({
  serviceName: 'Your service',
  projectName: 'Your app',
  accessToken: '<MW_API_KEY>',
  target: 'https://<MW_UID>.middleware.io:443',
});

(Use secrets manager for keys in production.)

7. View your data

Give it 3–5 minutes after starting, then open APM → Traces, Logs, and APM → Continuous Profiling in your Middleware account.

8. Environment variables — quick reference

These map 1:1 to MiddlewareApmModule.forRoot options (env usually wins). Values shown are typical; defaults noted where the package defines them.

VariableMaps to (forRoot)Purpose / DefaultExample
MW_API_KEYaccessTokenAuth token used to export data. No default.xxxxxxxx…
MW_TARGETtargetOTLP endpoint (serverless/remote). Default: http://localhost:9319https://<MW_UID>.middleware.io:443
MW_SERVICE_NAMEserviceNameAPM service identifier.payments-svc
MW_PROJECT_NAMEprojectNameLogical project/app name.ShopApp
MW_CONSOLE_EXPORTERconsoleExporterLog spans/metrics to console (dev). Default: falsetrue
MW_APM_TRACES_ENABLEDpauseTracesEnable/disable traces. Default: truetrue
MW_APM_METRICS_ENABLEDpauseMetricsEnable/disable metrics. Default: truetrue
MW_SELF_INSTRUMENTATIONenableSelfInstrumentationTrace the APM itself. Default: falsefalse
MW_FS_INSTRUMENTATIONenableFsInstrumentationFilesystem tracing (⚠️ perf cost). Default: falsefalse
MW_NODE_DISABLED_INSTRUMENTATIONSdisabledInstrumentationsComma-separated list of instrumentations to disable.dns, net
MW_AGENT_SERVICE(Host-agent helper)Host/Service for agent in containers (Docker/K8s).172.17.0.1 / mw-service.mw-agent-ns.svc.cluster.local

(Env → option mappings and defaults come from the package README; MW_AGENT_SERVICE comes from the Node APM guidance for container networking.)

9. Troubleshooting quick checks

  • No traces/logs? Ensure the global interceptor is added (see step 3).
  • Container cannot reach Host Agent? Set MW_AGENT_SERVICE as per Docker/K8s examples above.
  • Local debugging: set MW_CONSOLE_EXPORTER=true to echo telemetry to stdout.