简体   繁体   English

如何使用nestjs日志服务

[英]How to use nestjs Logging service

I tried to use the internal Logger of nestjs (described on https://docs.nestjs.com/techniques/logger -> but with no description of how to use it)我尝试使用nestjs的内部Logger (在https://docs.nestjs.com/techniques/logger -> 上进行了描述,但没有描述如何使用它)

But I had problems (tried to inject LoggerService and so on)但是我遇到了问题(试图注入LoggerService等等)

Can anybody explain how to do this?任何人都可以解释如何做到这一点?

Best practice最佳实践

Better than accessing the Logger statically is to create an instance for your class:比静态访问Logger更好的是为您的类创建一个实例:

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

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

Why is this better?为什么这样更好?

  1. You can provide a context in the constructor like new Logger(AppController.name) so that the class name (or anything else) will be part of all log messages in this class.您可以在构造函数中提供上下文,例如new Logger(AppController.name)以便类名(或其他任何名称)将成为此类中所有日志消息的一部分。

  2. If you at some point want to extend or replace the default LoggerService , you do not need to change any of your application code besides setting the new logger.如果您在某个时候想要扩展或替换默认的LoggerService ,除了设置新的记录器之外,您不需要更改任何应用程序代码。 Your new logger will automatically be used.您的新记录器将自动使用。 If you access it statically it will continue to take the default implementation.如果您静态访问它,它将继续采用默认实现。

const app = await NestFactory.create(AppModule, {logger: new MyLogger()});
  1. You can mock the Logger in your tests:您可以在测试中模拟Logger
module.useLogger(new NoOpLogger());

You need to import first into your class:您需要先导入到您的班级中:

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

and then you can begin with logging:然后你可以开始记录:

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

The answer is simple.答案很简单。 There are static methods on the Logger class. Logger 类有静态方法。

eg例如

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

Usage:用法:

Logger.log('Only a test');

Best practice is to inject the existing logger.最佳实践是注入现有的记录器。

app.module.ts

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 {}

And in the app.service.tsapp.service.ts

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

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

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

This answer might be useful for others who are trying with CustomLogger Implementation.此答案可能对尝试使用 CustomLogger 实现的其他人有用。 I am trying to show a sample custom logger implementation and how it can be injected to the Nestjs framework.我正在尝试展示一个示例自定义记录器实现以及如何将其注入 Nestjs 框架。

I understand that Nestjs inherently uses pino logger.我知道 Nestjs 固有地使用 pino 记录器。 This is just a custom implementation of logger service (which you can replace with bunyan, winston, etc..) This is the folder structure I use:这只是记录器服务的自定义实现(您可以用 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 

This is the main gist of it.这是它的主要要点。 So the logger service is implemented as follows所以logger服务实现如下

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 {
        }

    }

The custom implementation is implemented with the my specific options in pinojs github I am using fastifyjs instead of express (again to match my prject needs).自定义实现是使用我在 pinojs github 中的特定选项实现的,我使用的是 fastifyjs 而不是 express(再次匹配我的项目需求)。 So I've added the logger in fastify js server options.所以我在 fastify js 服务器选项中添加了记录器。 If you are using express, its better to specify the new custom implementation in the Nest application Adapter as stated above.如果您使用 express,最好在 Nest 应用程序适配器中指定新的自定义实现,如上所述。

My util service that takes care of implementing the fastify server我的 util 服务负责实现 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();

And in my main.ts在我的 main.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');

}

Simply you can use logger for your requirement(for error, for warn).This is the sample code for it.只需您可以根据您的要求使用记录器(用于错误,用于警告)。这是它的示例代码。

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
 }
}

then output:然后 output: 在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM