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:
1node --version
2python3 --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
1npm 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:
1import { Module } from '@nestjs/common';
2import { MiddlewareApmModule } from '@middleware.io/nestjs-apm';
3
4
5@Module({
6 imports: [
7 MiddlewareApmModule.forRoot({
8 projectName: 'Your application name',
9 serviceName: 'Your service name',
10 // You may also set options via env vars (see table below)
11 }),
12 ],
13})
14export class AppModule {}
main.ts
1import { NestFactory, Reflector } from '@nestjs/core';
2import { AppModule } from './app.module';
3import { MiddlewareApmInterceptor } from '@middleware.io/nestjs-apm';
4
5async function bootstrap() {
6 const app = await NestFactory.create(AppModule);
7 app.useGlobalInterceptors(new MiddlewareApmInterceptor(app.get(Reflector)));
8 await app.listen(3000);
9}
10bootstrap();
4. Basic Usage
Ignore routes you don’t want traced (e.g., health checks):
1import { Controller, Get } from '@nestjs/common';
2import { IgnoreApmTrace } from '@middleware.io/nestjs-apm';
3
4@Controller('users')
5export class UsersController {
6 @IgnoreApmTrace()
7 @Get('health')
8 healthCheck() {
9 return 'OK';
10 }
11}
5. Advanced instrumentation
Custom attributes:
1import { Controller, Post } from '@nestjs/common';
2import { WithAttributes } from '@middleware.io/nestjs-apm';
3
4@Controller('orders')
5export class OrdersController {
6 @WithAttributes({ 'business.type': 'order', 'business.tier': 'premium' })
7 @Post()
8 createOrder() {}
9}
Custom spans:
1import { Injectable } from '@nestjs/common';
2import { CreateSpan } from '@middleware.io/nestjs-apm';
3
4@Injectable()
5export class UserService {
6 @CreateSpan('user.registration', { 'user.type': 'new' })
7 async registerUser() {}
8}
Record method params as span attributes:
1import { Controller, Post } from '@nestjs/common';
2import { RecordParams } from '@middleware.io/nestjs-apm';
3
4@Controller('users')
5export class UsersController {
6 @RecordParams(['userId', 'action'])
7 @Post(':userId/action')
8 performAction(userId: string, action: string) {}
9}
Logging integration (Nest logger is captured automatically):
1import { Logger, Injectable } from '@nestjs/common';
2
3@Injectable()
4export class UserService {
5 private readonly logger = new Logger(UserService.name);
6 async createUser() {
7 try {
8 this.logger.log('Creating new user');
9 } catch (e) {
10 this.logger.error('Failed to create user', e);
11 throw e;
12 }
13 }
14}
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).
1MiddlewareApmModule.forRoot({
2 serviceName: 'Your service',
3 projectName: 'Your app',
4 accessToken: '<MW_API_KEY>',
5 target: 'https://<MW_UID>.middleware.io:443',
6});
(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_SERVICE
as per Docker/K8s examples above. - Local debugging: set
MW_CONSOLE_EXPORTER=true
to echo telemetry to stdout.