Nestjs项目实战 日志记录与监控系统集成
在Nestjs项目中集成日志记录与监控系统时,如何选择合适的日志库(如Winston、Pino)并实现多层级(DEBUG/INFO/ERROR)分类输出?
如何将日志自动按日期或大小切割存储,同时避免日志文件过大影响性能?
监控系统(如Prometheus+Grafana)对接Nestjs的最佳实践是什么?需要重点关注哪些性能指标(请求延迟、内存使用等)?
在生产环境中,如何通过中间件或拦截器统一处理请求日志,并确保敏感信息(如用户密码)不被记录?
分布式部署时怎样将多实例日志集中管理(ELK方案或其他推荐工具)?是否需考虑日志的异步写入机制?
在Nestjs项目中集成日志记录与监控系统,可以使用@nestjs/common
自带的Logger模块,并结合第三方工具如winston
或pino
实现更强大的日志功能。
首先安装winston
:
npm install winston
创建一个自定义Logger服务:
import { Injectable } from '@nestjs/common';
import * as winston from 'winston';
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'logs/error.log', level: 'error' }),
new winston.transports.File({ filename: 'logs/combined.log' }),
],
});
@Injectable()
export class CustomLogger {
log(message: any) {
logger.info(message);
}
error(message: any, trace: string) {
logger.error(message, { trace });
}
warn(message: any) {
logger.warn(message);
}
}
在模块中注入该服务并使用。对于监控,可以集成Prometheus和Grafana。安装@promster/metrics
:
npm install @promster/metrics
创建Prometheus服务:
import { Injectable } from '@nestjs/common';
import { MetricsService } from '@promster/metrics';
@Injectable()
export class PrometheusService {
constructor(private readonly metrics: MetricsService) {}
registerMetrics() {
this.metrics.setCounter('http_requests_total', 'Total number of HTTP requests');
// 其他指标...
}
}
在应用启动时注册这些指标即可。
在NestJS项目中实现日志记录与监控系统集成,可以按以下步骤进行:
-
引入日志库:推荐使用
pino
或winston
。例如,通过npm安装pino:npm install pino
然后在
main.ts
中配置日志:import * as pino from 'pino'; const logger = pino(); app.useLogger(logger);
-
监控系统集成:可以集成Prometheus+Grafana。首先安装
[@nestjs](/user/nestjs)/microservices
和[@promster](/user/promster)/nestjs
:npm install [@nestjs](/user/nestjs)/microservices [@promster](/user/promster)/nestjs
配置
app.module.ts
启用监控:import { PrometheusModule } from '[@promster](/user/promster)/nestjs';
@Module({ imports: [ PrometheusModule.register({ endpoint: ‘/metrics’, }), ], }) export class AppModule {}
3. **自定义日志格式**:在`logger.service.ts`中定义日志格式,支持上下文信息:
```typescript
export class LoggerService {
log(message: string, context?: string) {
this.logger.info(`[${context}] ${message}`);
}
}
- 错误处理与监控:通过中间件捕获异常并上报至监控系统:
app.useGlobalFilters(new AllExceptionsFilter());
这样,你的NestJS应用就能实现高效的日志记录与监控功能了。
在NestJS项目中集成日志记录和监控系统的最佳实践如下:
- 日志记录方案: 推荐使用NestJS内置的Logger结合Winston:
// logger.service.ts
import { Injectable, LoggerService } from '@nestjs/common';
import * as winston from 'winston';
@Injectable()
export class AppLogger implements LoggerService {
private logger: winston.Logger;
constructor() {
this.logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' }),
],
});
}
log(message: string) {
this.logger.info(message);
}
error(message: string, trace: string) {
this.logger.error(message, { trace });
}
warn(message: string) {
this.logger.warn(message);
}
}
- 监控系统集成: 推荐使用Prometheus + Grafana组合:
// prometheus.module.ts
import { Module } from '@nestjs/common';
import { PrometheusModule } from '@willsoto/nestjs-prometheus';
@Module({
imports: [PrometheusModule.register()],
})
export class AppPrometheusModule {}
- 性能监控:
使用
@nestjs/platform-express
的拦截器:
// logging.interceptor.ts
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const now = Date.now();
return next
.handle()
.pipe(
tap(() => console.log(`Execution time: ${Date.now() - now}ms`)),
);
}
}
- 健康检查:
使用
@nestjs/terminus
:
npm install @nestjs/terminus
// health.controller.ts
import { Controller, Get } from '@nestjs/common';
import { HealthCheckService, HealthCheck } from '@nestjs/terminus';
@Controller('health')
export class HealthController {
constructor(private health: HealthCheckService) {}
@Get()
@HealthCheck()
check() {
return this.health.check([]);
}
}
部署建议:
- 生产环境应将日志发送到ELK或类似系统
- 设置日志轮转防止磁盘爆满
- 敏感信息需过滤后再记录
- 监控指标应包含API响应时间、错误率、请求量等关键指标