Nest.JS
| Traces | Metrics | App Logs | Custom Logs | Profiling |
|---|---|---|---|---|
| ✅ | ✅ | ✅ | ✅ | ✅ |
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.)
- Docker:
2. Install Nest.js APM package
npm install @middleware.io/nestjs-apm3. 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.
| Variable | Maps to (forRoot) | Purpose / Default | Example |
|---|---|---|---|
MW_API_KEY | accessToken | Auth token used to export data. No default. | xxxxxxxx… |
MW_TARGET | target | OTLP endpoint (serverless/remote). Default: http://localhost:9319 | https://<MW_UID>.middleware.io:443 |
MW_SERVICE_NAME | serviceName | APM service identifier. | payments-svc |
MW_PROJECT_NAME | projectName | Logical project/app name. | ShopApp |
MW_CONSOLE_EXPORTER | consoleExporter | Log spans/metrics to console (dev). Default: false | true |
MW_APM_TRACES_ENABLED | pauseTraces | Enable/disable traces. Default: true | true |
MW_APM_METRICS_ENABLED | pauseMetrics | Enable/disable metrics. Default: true | true |
MW_SELF_INSTRUMENTATION | enableSelfInstrumentation | Trace the APM itself. Default: false | false |
MW_FS_INSTRUMENTATION | enableFsInstrumentation | Filesystem tracing (⚠️ perf cost). Default: false | false |
MW_NODE_DISABLED_INSTRUMENTATIONS | disabledInstrumentations | Comma-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_SERVICEas per Docker/K8s examples above. - Local debugging: set
MW_CONSOLE_EXPORTER=trueto echo telemetry to stdout.