Enhanced nestjs-pino with OpenTelemetry integration, file rotation, Loki support, and enterprise features for production-ready logging.
📖 Full Documentation | 🐛 Issues | 💬 Discussions
npm install @nestjs-labs/nestjs-pino-extra
# or
yarn add @nestjs-labs/nestjs-pino-extra
# or
pnpm add @nestjs-labs/nestjs-pino-extra
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import {
LoggerModule,
getLoggerModuleOptions,
} from '@nestjs-labs/nestjs-pino-extra';
@Module({
imports: [
ConfigModule.forRoot(),
LoggerModule.forRootAsync({
imports: [ConfigModule],
useFactory: (configService: ConfigService) =>
getLoggerModuleOptions(configService),
inject: [ConfigService],
}),
],
})
export class AppModule {}
# Required
OTLP_SERVICE_NAME=my-app
# Optional
LOG_LEVEL=info
LOG_FILE=/var/log/app.log
LOG_LOKI=http://localhost:3100
Variable | Default | Description |
---|---|---|
OTLP_SERVICE_NAME |
app |
Application name for log labels |
LOG_LEVEL |
info |
Log level (error, warn, info, debug, trace) |
LOG_FILE |
- | File path for log rotation (optional) |
LOG_LOKI |
- | Loki server URL (optional) |
OTEL_SPAN_ID_KEY |
spanId |
Key for OpenTelemetry span ID in logs |
OTEL_TRACE_ID_KEY |
traceId |
Key for OpenTelemetry trace ID in logs |
Automatically injects trace and span IDs into logs when using OpenTelemetry:
import { trace, context } from '@opentelemetry/api';
// Your logs will automatically include:
// {
// "level": "info",
// "message": "Request processed",
// "spanId": "abc123",
// "traceId": "def456",
// }
Configure log file rotation with automatic compression:
LOG_FILE=/var/log/app.log
This creates:
app.log.1.gz
, app.log.2.gz
, etc.Send logs directly to Grafana Loki:
LOG_LOKI=http://localhost:3100
Automatic request ID generation and header injection:
// Request headers will include:
// X-Request-Id: 550e8400-e29b-41d4-a716-446655440000
Automatic log level based on HTTP status codes:
4xx
responses → warn
level5xx
responses → error
level3xx
responses → silent
(no logging)2xx
responses → info
levelAutomatic redaction of sensitive fields:
// These fields are automatically redacted:
// - password
// - reqBody.password
// - user.password
// - reqBody.user.password
import { Module } from '@nestjs/common';
import { LoggerModule } from '@nestjs-labs/nestjs-pino-extra';
@Module({
imports: [
LoggerModule.forRoot({
pinoHttp: [
{
level: 'info',
customLogLevel: (req, res, err) => {
if (res.statusCode >= 400) return 'warn';
if (res.statusCode >= 500) return 'error';
return 'info';
},
redact: {
paths: ['password', 'token', 'secret'],
},
},
// Your custom stream configuration
],
exclude: [
{ method: RequestMethod.GET, path: '/health' },
{ method: RequestMethod.GET, path: '/metrics' },
],
}),
],
})
export class AppModule {}
import { Injectable, Logger } from '@nestjs/common';
@Injectable()
export class UserService {
private readonly logger = new Logger(UserService.name);
async createUser(userData: any) {
this.logger.log('Creating new user', { userId: userData.id });
try {
// Your logic here
this.logger.log('User created successfully');
} catch (error) {
this.logger.error('Failed to create user', error.stack);
throw error;
}
}
}
npm run build
npm run lint
npm run lint:fix
@nestjs/config
- Configuration management@opentelemetry/api
- OpenTelemetry integrationpino
- Fast Node.js loggerpino-http
- HTTP request loggingpino-loki
- Loki transportpino-pretty
- Pretty printingrotating-file-stream
- File rotationMIT
git checkout -b feature/amazing-feature
)git commit -m 'Add some amazing feature'
)git push origin feature/amazing-feature
)