【问题标题】:How to use nestjs Logging service如何使用nestjs日志服务
【发布时间】:2019-03-10 02:12:52
【问题描述】:

我尝试使用nestjs的内部Logger(描述于https://docs.nestjs.com/techniques/logger->但没有描述如何使用它)

但是我遇到了问题(尝试注入LoggerService等等)

谁能解释一下怎么做?

【问题讨论】:

  • 你想在所有服务中自动使用记录器吗?!

标签: javascript node.js typescript logging nestjs


【解决方案1】:

答案很简单。 Logger 类有静态方法。

例如

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

用法:

Logger.log('Only a test');

【讨论】:

    【解决方案2】:

    最佳实践

    比静态访问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),以便类名(或其他任何内容)将成为此类中所有日志消息的一部分。

    2. 如果您在某个时候想要扩展或替换默认的LoggerService,除了设置新的记录器之外,您不需要更改任何应用程序代码。您的新记录器将自动使用。如果您静态访问它,它将继续采用默认实现。

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

    【讨论】:

    • @KimKern 在代码中有new Logger 会使代码不可测试,对吧?
    • @RezaRahmati 在这种情况下不会,因为您可以使用 module.useLogger(new NoOpLogger()); 的模拟或测试实现覆盖 Logger
    • new Logger 如何选择新的记录器实现?它不是显式调用的默认实现吗?这 Loggergte 是否从应用程序的引擎盖下注入了记录器?
    • @Gherman new Logger 创建的实例持有一个 Logger 实例作为成员变量。所有方法内部调用instance的方法。当您覆盖 Logger 时,它只会设置 instance 字段。看一下源码:github.com/nestjs/nest/blob/master/packages/common/services/…
    • @KimKern 我明白了。我不希望 Logger 成为 Singleton,但它确实是。我想知道他们为什么不把它变成一种可注射的服务。那会更常见。
    【解决方案3】:

    你需要先导入你的类:

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

    然后你就可以开始记录了:

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

    【讨论】:

    • 有效,但 Kim 的回答更好,因为您在输出中还有类的名称
    • 我试过了,如果不使用new,它不会调用自定义实现。
    【解决方案4】:

    此答案可能对尝试使用 CustomLogger 实现的其他人有用。 我正在尝试展示一个示例自定义记录器实现以及如何将其注入到 Nestjs 框架中。

    我了解 Nestjs 天生就使用 pino 记录器。这只是记录器服务的自定义实现(您可以将其替换为 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 
    

    这是它的主要要点。所以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 {
            }
    
        }
    

    自定义实现是使用我在 pinojs github 中的特定选项实现的 我使用的是 fastifyjs 而不是 express(再次符合我的项目需求)。所以我在 fastify js 服务器选项中添加了记录器。如果您使用的是 express,最好如上所述在 Nest 应用程序适配器中指定新的自定义实现。

    我的 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();
    

    在我的 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');
    
    }
    

    【讨论】:

    • 能分享一下 express 和 winston 的例子吗?
    • 对不起。我没有尝试过winston,因为我是皮诺的粉丝。但应该很相似
    猜你喜欢
    • 2022-09-30
    • 2019-06-14
    • 1970-01-01
    • 2020-09-05
    • 1970-01-01
    • 2021-11-07
    • 1970-01-01
    • 2020-12-19
    • 1970-01-01
    相关资源
    最近更新 更多