logger 是 nestjs 內置的功能。看看怎麼使用,以及如何自定義 logger。markdown
const app = await NestFactory.create(ApplicationModule, {
logger: false,
});
await app.listen(3000);
複製代碼
源碼:app
public async create<T extends INestApplication = INestApplication>(
module: any,
serverOrOptions?: AbstractHttpAdapter | NestApplicationOptions,
options?: NestApplicationOptions,
): Promise<T> {}
複製代碼
export class NestApplicationContextOptions {
logger?: LoggerService | LogLevel[] | boolean;
}
複製代碼
// 層次類型
export type LogLevel = 'log' | 'error' | 'warn' | 'debug' | 'verbose';
// 建立app時使用配置 logger 層次
const app = await NestFactory.create(ApplicationModule, {
logger: ['error', 'warn'],
});
await app.listen(3000);
複製代碼
咱們要實現自定Logger必須實現 LoggerServiceasync
export interface LoggerService {
log(message: any, context?: string);
error(message: any, trace?: string, context?: string);
warn(message: any, context?: string);
debug?(message: any, context?: string);
verbose?(message: any, context?: string);
}
import { LoggerService } from '@nestjs/common';
export class MyLogger implements LoggerService {
log(message: string) {}
error(message: string, trace: string) {}
warn(message: string) {}
debug(message: string) {}
verbose(message: string) {}
}
複製代碼
擴展 nestjs 的 logger 須要繼承 nestjs 的 Logger 接口,而 Logger 是繼承上面的 LoggerService 接口ide
import { Logger } from '@nestjs/common';
export class MyLogger extends Logger {
error(message: string, trace: string) {
super.error(message, trace);
}
}
複製代碼
源碼函數
@Injectable()
export class Logger implements LoggerService {
private static logLevels: LogLevel[] = [
'log',
'error',
'warn',
'debug',
'verbose',
];
private static lastTimestamp?: number;
private static instance?: typeof Logger | LoggerService = Logger;
constructor( @Optional() protected context?: string, @Optional() private readonly isTimestampEnabled = false, ) {}
error(message: any, trace = '', context?: string) {}
log(message: any, context?: string) {}
warn(message: any, context?: string) {}
debug(message: any, context?: string) {}
verbose(message: any, context?: string) {}
setContext(context: string) {}
static overrideLogger(logger: LoggerService | LogLevel[] | boolean) {}
static log(message: any, context = '', isTimeDiffEnabled = true) {}
static error( message: any, trace = '', context = '', isTimeDiffEnabled = true, ) {}
static warn(message: any, context = '', isTimeDiffEnabled = true) {}
static debug(message: any, context = '', isTimeDiffEnabled = true) {}
static verbose(message: any, context = '', isTimeDiffEnabled = true) {}
private callFunction( name: 'log' | 'warn' | 'debug' | 'verbose', message: any, context?: string, ) {}
private getInstance(): typeof Logger | LoggerService {}
private isLogLevelEnabled(level: LogLevel): boolean {}
private static printMessage( message: any, color: (message: string) => string, context = '', isTimeDiffEnabled?: boolean, ) {}
private static updateAndGetTimestampDiff(
isTimeDiffEnabled?: boolean,
): string {}
private static printStackTrace(trace: string) {}
}
複製代碼
import { Module } from '@nestjs/common';
import { MyLogger } from './my-logger.service';
@Module({
providers: [MyLogger],
exports: [MyLogger],
})
export class LoggerModule {}
複製代碼
同歸依賴注入將 LoggerModule 注入都 AppModule 中,經過 app 的 get 方法來獲取 MyLogger 的實例。app 也提供了 useLogger 來使用 Logger。ui
const app = await NestFactory.create(ApplicationModule, {
// 關閉系統日誌
logger: false,
});
app.useLogger(app.get(MyLogger))
await app.listen(3000);
複製代碼
這看起來彷佛有點麻煩,其實咱們能夠直接創新一個實例,不使用 Module 的方式來注入。this
const app = await NestFactory.create(ApplicationModule, {
// 關閉系統日誌
logger: false,
});
// 使用自定義日誌
app.useLogger(new MyLogger());
await app.listen(3000);
複製代碼
Scope 是枚舉類型spa
export enum Scope {
/** * 提供程序能夠在多個類之間共享。提供者生命週期 *與應用程序生命週期嚴格相關。一旦應用程序具備 *自舉,全部提供程序都已實例化。 */
DEFAULT,
/** * 每次使用都會實例化提供者的新私有實例。 */
TRANSIENT,
/** * 爲每一個請求處理管道實例化一個新實例 */
REQUEST,
}
複製代碼
// scope選項做爲Logger類的配置元數據,並指定一個臨時範圍,
// 以確保Logger在每一個功能模塊中都有一個惟一的實例
import { Injectable, Scope, Logger } from '@nestjs/common';
@Injectable({ scope: Scope.TRANSIENT })
export class MyLogger extends Logger {}
import { Module } from '@nestjs/common';
import { MyLogger } from './my-logger.service';
@Module({
providers: [MyLogger],
exports: [MyLogger],
})
export class LoggerModule {}
import { Injectable } from '@nestjs/common';
import { MyLogger } from './my-logger.service';
@Injectable()
export class CatsService {
private readonly cats: Cat[] = [];
constructor(private myLogger: MyLogger) {
this.myLogger.setContext('CatsService');
}
findAll(): Cat[] {
this.myLogger.warn('About to return cats!');
return this.cats;
}
}
const app = await NestFactory.create(ApplicationModule, {
logger: false,
});
app.useLogger(new MyLogger());
await app.listen(3000);
複製代碼
使用做用域注入,能夠每一個模塊中都包含一個 logger 實例,咱們經過須要定義個單獨的 Module 模塊。在使用的的時候,咱們在服務中使用 MyLogger。最後咱們還須要在 app 須要調用 useLogger 來實例化 MyLogger 函數。debug
生產應用程序一般具備特定的日誌記錄要求,包括高級篩選,格式化和集中式日誌記錄。Nest的內置記錄器用於監視Nest系統的行爲,而且在開發過程當中也可用於功能模塊中的基本格式化文本記錄,可是生產應用程序一般會利用Winston等專用記錄模塊。與任何標準Node.js應用程序同樣,您能夠在Nest中充分利用此類模塊。日誌