nestjs 功能之:🐉日誌 logger

logger 是 nestjs 內置的功能。看看怎麼使用,以及如何自定義 logger。markdown

開啓/關閉 logger 的顯示

  1. 咱們在建立一個 app 的時候,咱們就可在 create 參數添加第二參數,來配置 logger
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> {}
複製代碼
  • NestApplicationOptions 繼承子 NestApplicationContextOptions
export class NestApplicationContextOptions {
  logger?: LoggerService | LogLevel[] | boolean;
}
複製代碼

logger 級別:

  • 'log'
  • 'error'
  • 'warn'
  • 'debug'
  • 'verbose'。
// 層次類型
export type LogLevel = 'log' | 'error' | 'warn' | 'debug' | 'verbose';

// 建立app時使用配置 logger 層次
const app = await NestFactory.create(ApplicationModule, {
  logger: ['error', 'warn'],
});
await app.listen(3000);
複製代碼

LoggerService 接口

咱們要實現自定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) {}
}
複製代碼

擴展示有 logger

擴展 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) {}
}
複製代碼

logger模塊

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屬性傳遞給@Injectable()裝飾器選項對象來指定注入範圍

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

第三方 logger

生產應用程序一般具備特定的日誌記錄要求,包括高級篩選,格式化和集中式日誌記錄。Nest的內置記錄器用於監視Nest系統的行爲,而且在開發過程當中也可用於功能模塊中的基本格式化文本記錄,可是生產應用程序一般會利用Winston等專用記錄模塊。與任何標準Node.js應用程序同樣,您能夠在Nest中充分利用此類模塊。日誌

相關文章
相關標籤/搜索