typescript 如何使用nestjs日志记录服务

aelbi1ox  于 2023-03-04  发布在  TypeScript
关注(0)|答案(7)|浏览(198)

我尝试使用nestjs的内部Logger(在https://docs.nestjs.com/techniques/logger-〉上描述,但没有描述如何使用它)
但是我遇到了问题(试图注入LoggerService等等)
有人能解释一下怎么做吗?

gg58donl

gg58donl1#

最佳实践

比静态访问Logger更好的方法是为类创建一个示例:

@Controller()
export class AppController {
  private readonly logger = new Logger(AppController.name);

  @Get()
  async get() {
    this.logger.log('Getting stuff');
  }
}

为什么这样更好?

1.您可以在构造函数中提供一个上下文,如new Logger(AppController.name),这样类名(或其他任何内容)将成为该类中所有日志消息的一部分。
1.如果你想扩展或替换默认的LoggerService,除了设置新的日志记录器之外,你不需要改变任何应用程序代码。你的新日志记录器将被自动使用。如果你静态访问它,它将继续采用默认的实现。

const app = await NestFactory.create(AppModule, {logger: new MyLogger()});

1.您可以在测试中模拟Logger

module.useLogger(new NoOpLogger());
hc8w905p

hc8w905p2#

您需要首先导入到类中:

import { Logger } from '@nestjs/common';

然后你就可以开始记录了

Logger.log('info')
Logger.warn('warning')
Logger.error('something went wrong! ', error)
brc7rcf0

brc7rcf03#

最佳实践是注入现有记录器。

  • 一月一日 *
import { Logger, Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService, Logger],
})
export class AppModule {}

在 * app. service. ts * 中

import { Injectable, Logger } from '@nestjs/common';

@Injectable()
export class AppService {
  constructor(private readonly logger: Logger) {}

  sayHello() {
    this.logger.log('Hello world!') 
  }
}
yftpprvb

yftpprvb4#

这个答案可能对其他尝试使用CustomLogger实现的人有用。我试图展示一个示例自定义日志记录器实现以及如何将其注入Nestjs框架。
我知道Nestjs本质上使用pino logger,这只是logger服务的一个自定义实现(你可以用bunyan,winston等代替)这是我使用的文件夹结构:

> src /  
>   modules /
>      database /
>        ...
>        database.module.ts
>      api /
>        services /
>        controllers /
>        interceptors /
>        middlewares /
>        models /
>        schemas /
>      shared /
>        services /
>           app.util.service.ts
>           pino.logger.service.ts
>        utils / 
>        interceptors /
>        filters /
>        main.ts    
>        app.controller.ts    
>        app.service.ts
>        server.util.service.ts

这是它的主要要点,因此日志服务的实现如下

import {Injectable, LoggerService, Scope} from "@nestjs/common";
import * as pino from 'pino';
import {AppUtilService} from "./app.util.service";
import * as os from "os";
import {APP_LOG_REDACT, APP_MESSAGE_KEY} from "../utils/app.constants";

    @Injectable({
        scope: Scope.DEFAULT
    })
    export class PinoLoggerService implements LoggerService{
        constructor(private appUtilService: AppUtilService) {

        }

        logService = (fileNameString): pino.Logger => {
            return pino({
                useLevelLabels: true,
                prettyPrint: this.appUtilService.isDevEnv(),
                // tslint:disable-next-line: object-literal-sort-keys
                messageKey: APP_MESSAGE_KEY,
                level: this.appUtilService.getLogLevel(),
                redact: {
                    paths: APP_LOG_REDACT,
                    censor: '**SECRET-INFO**'
                },
                base: {
                    hostName: os.hostname(),
                    platform: os.platform(),
                    processId: process.pid,
                    timestamp: this.appUtilService.getCurrentLocaleTimeZone(),
                    // tslint:disable-next-line: object-literal-sort-keys
                    fileName: this.appUtilService.getFileName(fileNameString),
                },
            });
        }

        debug(message: any, context?: string): any {
        }

        error(message: any, trace?: string, context?: string): any {
        }

        log(message: any, context?: string): any {
        }

        warn(message: any, context?: string): any {
        }

    }

自定义实现是通过pinojs github中的我的特定选项实现的我使用fastify js而不是express(同样是为了满足我的项目需求)。因此我在fastify js服务器选项中添加了日志记录器。如果您使用express,最好如上所述在Nest应用适配器中指定新的自定义实现。
负责实现fastify服务器的实用程序服务

import * as fastify from "fastify";
import {Http2Server, Http2ServerRequest, Http2ServerResponse} from "http2";
import {DocumentBuilder, SwaggerModule} from "@nestjs/swagger";
import * as fs from "fs";
import * as path from "path";
import * as uuid from "uuid";
import * as qs from "query-string";
import {PinoLoggerService} from "./modules/shared/services/pino.logger.service";
import {AppUtilService} from "./modules/shared/services/app.util.service";
import {AppConstantsService} from "./modules/shared/services/app.constants.service";
import {AppModel} from "./modules/shared/model/app.model";
import {Reflector} from "@nestjs/core";
export class ServerUtilService {
    private logService;
    private appConstantsService;
    private appUtilServiceInstance: AppUtilService;
    private fastifyInstance: fastify.FastifyInstance<Http2Server, Http2ServerRequest, Http2ServerResponse>;
    constructor() {
        this.appUtilServiceInstance = new AppUtilService();
        this.logService = new PinoLoggerService(this.appUtilServiceInstance);
        this.appConstantsService = new AppConstantsService(this.appUtilServiceInstance);
    }

    retrieveAppConstants(): AppModel {
        return this.appConstantsService.getServerConstants();
    }

    retrieveAppUtilService(): AppUtilService {
        return this.appConstantsService;
    }
    createFastifyServerInstance = (): fastify.FastifyInstance<Http2Server, Http2ServerRequest, Http2ServerResponse> => {
        const serverConstants = this.appConstantsService.getServerConstants();
        const httpsOptions = {
            cert: fs.readFileSync(path.join(process.cwd() + '/https-keys/cert.pem')),
            key: fs.readFileSync(path.join(process.cwd() + '/https-keys/key.pem')),

            allowHTTP1: true,
            rejectUnauthorized: true,
        };
        this.fastifyInstance = fastify({

            http2: true,
            https: httpsOptions,
            bodyLimit: 26214400,
            pluginTimeout: 20000,
            genReqId: () => {
                return uuid.v4().toString();
            },
            requestIdHeader: serverConstants.requestIdHeader,
            modifyCoreObjects: true,
            trustProxy: serverConstants.trustProxy,
            ignoreTrailingSlash: true,
            logger: this.logService,
            querystringParser: (str) => {
                return qs.parse(str);
            },
        });
        this.addContentTypeParser();
        return this.fastifyInstance;
    };

    private addContentTypeParser() {
        this.fastifyInstance.addContentTypeParser('*', (req, done) => {
            let data = '';
            req.on('data', chunk => {
                console.log('inside data listener event');
                return data += chunk; });
            req.on('end', () => {
                done(null,data);
            })
        });
    }

}
export const ServerUtilServiceInstance = new ServerUtilService();

在我的主要。ts

async function bootstrap() {
  const fastifyServerInstance = 
  ServerUtilServiceInstance.createFastifyServerInstance();
  const serverConstants = ServerUtilServiceInstance.retrieveAppConstants();
  const app: NestFastifyApplication = await NestFactory.create<NestFastifyApplication>(
      AppModule,
      new FastifyAdapter(fastifyServerInstance)
  );
    ....
    ... // global filters, interceptors, pipes
    ....
    await app.listen(serverConstants.port, '0.0.0.0');

}
zkure5ic

zkure5ic5#

答案很简单,Logger类上有静态方法。
例如:

static log(message: string, context = '', isTimeDiffEnabled = true)

用法:

Logger.log('Only a test');
4zcjmb1e

4zcjmb1e6#

简单地说,你可以使用logger来满足你的需求(错误,警告)。这是它的示例代码。

import {Logger, Injectable} from '@nestjs/common';

@Injectable()
export class EmployersService {
 private readonly logger = new Logger(EmployersService.name);

 findAll() {
  this.logger.log('info message'); //for info
  this.logger.warn('warn message'); //for warn
  this.logger.error('error message'); //for error
 }
}

则输出:

x33g5p2x

x33g5p2x7#

我的方法是通过NestJS DI使用AppLogger服务,它 Package 了NestJS日志记录器。

  • 我们可以在单元测试中轻松地更改/模拟AppLogger的实现(这是private readonly logger = new Logger(AppController.name);方法的一个难题)
  • 我们的代码依赖于我们自己的类/接口,而不是NestJS的,在六角体系结构的精神。

它看起来像:

@Injectable()
export class MyService {
  constructor(private readonly logger: AppLogger) {}

  doSomething() {
    this.logger.log('Did something.', MyService.name);
  }
}
@Global()
@Module({
  imports: [],
  controllers: [],
  providers: [
    AppLogger,
    Logger,
  ],
  exports: [AppLogger],
})
export class ConfigModule {}
import { Injectable, Logger } from '@nestjs/common';

@Injectable()
export class AppLogger {
  constructor(private readonly logger: Logger) {}

  error(message: any, context: string) {
    this.logger.error(message, context);
  }

  warn(message: any, context: string) {
    this.logger.warn(message, context);
  }

  log(message: any, context: string) {
    this.logger.log(message, context);
  }

  debug(message: any, context: string) {
    this.logger.debug(message, context);
  }

  verbose(message: any, context: string) {
    this.logger.verbose(message, context);
  }
}

相关问题