gremo / nest-winston

A Nest module wrapper form winston logger

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

this.logger.warn and this.logger.verbose is not a function

alko89 opened this issue · comments

I'm trying to add papertrail logging to nest. I am using nest-winston module to inject the logger in bootstrap:

// logging.ts
import { hostname } from 'os';
import { format, config, transports } from 'winston';
import { utilities, WinstonModule } from 'nest-winston';
import { Syslog } from 'winston-syslog';
import { papertrailHost, papertrailPort } from './env';

const papertrail = new Syslog({
  host: papertrailHost,
  port: papertrailPort,
  protocol: 'tls4',
  localhost: hostname(),
  app_name: process.env.npm_package_name,
  eol: '\n',
});

const console = new transports.Console();

export const Logger = WinstonModule.createLogger({
  format: format.combine(
    format.timestamp(),
    format.ms(),
    utilities.format.nestLike(process.env.npm_package_name, {
      prettyPrint: true,
    }),
  ),
  levels: config.syslog.levels,
  transports: [console, papertrail],
});

// main.ts
async function bootstrap() {
  const app = await NestFactory.create(AppModule, {
    logger: Logger,
  });
  await app.listen(apiPort);
}

Doing so seems to work for Error, Info (with missing context) and Debug but throw for Warn and Verbose.

I have created an endpoint to test logging:

import { Injectable, Logger } from '@nestjs/common';
import { LogDto } from './dto/log.dto';

@Injectable()
export class AppService {
  private readonly logger = new Logger('App');

  createLog(logDto: LogDto) {
    switch (logDto.level) {
      case 'log':
        return this.logger.log(logDto.message, logDto.params);
      case 'error':
        return this.logger.error(logDto.message, logDto.params);
      case 'warn':
        return this.logger.warn(logDto.message, logDto.params);
      case 'debug':
        return this.logger.debug(logDto.message, logDto.params);
      case 'verbose':
        return this.logger.verbose(logDto.message, logDto.params);
    }
  }
}

Example console output:

[moralis-admin-api] Info        11/10/2021, 2:26:17 PM [NestApplication] Nest application successfully started - {} +1ms
[moralis-admin-api] Error       11/10/2021, 2:26:37 PM [App] test - { stack: [ null ] } +20s
[moralis-admin-api] Error       11/10/2021, 2:26:46 PM [ExceptionsHandler] this.logger.warn is not a function - {
  stack: [
    'TypeError: this.logger.warn is not a function\n' +
      '    at WinstonLogger.warn (/home/alko/Development/IvanOnTech/Moralis/moralis-admin-api/node_modules/nest-winston/dist/winston.classes.js:48:28)\n' +
      '    at Logger.warn (/home/alko/Development/IvanOnTech/Moralis/moralis-admin-api/node_modules/@nestjs/common/services/logger.service.js:48:75)\n' +
      '    at Logger.descriptor.value (/home/alko/Development/IvanOnTech/Moralis/moralis-admin-api/node_modules/@nestjs/common/services/logger.service.js:163:27)\n' +
      '    at AppService.createLog (/home/alko/Development/IvanOnTech/Moralis/moralis-admin-api/src/resources/app/app.service.ts:15:28)\n' +
      '    at AppController.createLog (/home/alko/Development/IvanOnTech/Moralis/moralis-admin-api/src/resources/app/app.controller.ts:11:21)\n' +
      '    at /home/alko/Development/IvanOnTech/Moralis/moralis-admin-api/node_modules/@nestjs/core/router/router-execution-context.js:38:29\n' +
      '    at processTicksAndRejections (node:internal/process/task_queues:96:5)\n' +
      '    at /home/alko/Development/IvanOnTech/Moralis/moralis-admin-api/node_modules/@nestjs/core/router/router-execution-context.js:46:28\n' +
      '    at /home/alko/Development/IvanOnTech/Moralis/moralis-admin-api/node_modules/@nestjs/core/router/router-proxy.js:9:17'
  ]
} +9s
[moralis-admin-api] Error       11/10/2021, 2:26:52 PM [ExceptionsHandler] this.logger.verbose is not a function - {
  stack: [
    'TypeError: this.logger.verbose is not a function\n' +
      '    at WinstonLogger.verbose (/home/alko/Development/IvanOnTech/Moralis/moralis-admin-api/node_modules/nest-winston/dist/winston.classes.js:64:28)\n' +
      '    at Logger.verbose (/home/alko/Development/IvanOnTech/Moralis/moralis-admin-api/node_modules/@nestjs/common/services/logger.service.js:62:130)\n' +
      '    at Logger.descriptor.value (/home/alko/Development/IvanOnTech/Moralis/moralis-admin-api/node_modules/@nestjs/common/services/logger.service.js:163:27)\n' +
      '    at AppService.createLog (/home/alko/Development/IvanOnTech/Moralis/moralis-admin-api/src/resources/app/app.service.ts:19:28)\n' +
      '    at AppController.createLog (/home/alko/Development/IvanOnTech/Moralis/moralis-admin-api/src/resources/app/app.controller.ts:11:21)\n' +
      '    at /home/alko/Development/IvanOnTech/Moralis/moralis-admin-api/node_modules/@nestjs/core/router/router-execution-context.js:38:29\n' +
      '    at processTicksAndRejections (node:internal/process/task_queues:96:5)\n' +
      '    at /home/alko/Development/IvanOnTech/Moralis/moralis-admin-api/node_modules/@nestjs/core/router/router-execution-context.js:46:28\n' +
      '    at /home/alko/Development/IvanOnTech/Moralis/moralis-admin-api/node_modules/@nestjs/core/router/router-proxy.js:9:17'
  ]
} +5s
[moralis-admin-api] Error       11/10/2021, 2:26:58 PM [App] test - { stack: [ null ] } +6s
[moralis-admin-api] Info        11/10/2021, 2:27:02 PM test - {} +5s

There are three issues I see with my approach:

  • info has no context
  • warn and verbose functions throw
  • wrong response time - the log shows response times as if they took over a second to complete.

I had this same issue

Can you please try to inject the logger as in this app.controller.ts?

In particular, @alko89 , why doing the following?

private readonly logger = new Logger('App');

I have the same issue with the syslog transport :

const winstonOptions: winston.LoggerOptions = {
  levels: winston.config.syslog.levels,
  transports: [
    new winston.transports.Console({
      format: winston.format.combine(
        winston.format.colorize(),
        customFormat,
        winston.format.errors({ stack: true }),
        winston.format.timestamp(),
      ),
    }),
    new winston.transports.File({
      level: 'warn',
      format: winston.format.combine(
        winston.format.errors({ stack: true }),
        winston.format.timestamp(),
        winston.format.json(),
      ),
      filename: '../logs/api.log',
    }),
    new Syslog(syslogOptions),
  ],
};

Here is the initialisation :

  const app = await NestFactory.create(AppModule, {
    logger: WinstonModule.createLogger(winstonOptions),
  });

I think it comes from the levels: winston.config.syslog.levels because when I set it to another thing (winston.config.npm.levels for example)

@gremo I updated my code with what you recommended by injecting the logger, now there is no context in any of the logs and there is still issue with time measurements. Warning seems to be working now though.

Its possible to add context to logs manually by passing name to the function (this.logger.log(logDto.message, AppService.name);). Ideally I would like to have this on by default.

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

  createLog(logDto: LogDto) {
    switch (logDto.level) {
      case 'log':
        return this.logger.log(logDto.message, logDto.params);
      case 'error':
        return this.logger.error(logDto.message, logDto.params);
      case 'warn':
        return this.logger.warn(logDto.message, logDto.params);
      case 'debug':
        return this.logger.debug(logDto.message, logDto.params);
      case 'verbose':
        return this.logger.verbose(logDto.message, logDto.params);
    }
  }
}
[moralis-admin-api] Info        11/29/2021, 3:26:06 PM [NestApplication] Nest application successfully started - {} +1ms
[moralis-admin-api] Info        11/29/2021, 3:26:21 PM test - {} +15s
[moralis-admin-api] Error       11/29/2021, 3:26:29 PM test - { stack: [ null ] } +8s
[moralis-admin-api] Warn        11/29/2021, 3:26:33 PM test - {} +4s

I'm sorry for the very late response, I'm quite busy recently with my personal and working life. I'll try to follow more this library that, honestly, went so far and has been used by many. Didn't expected that 😄

@alko89 is this still relevant? Maybe you can try the setContext method of the logger?

hey @gremo! No worries. Unfortunately we abandoned the library in favor of using syslog driver in Docker instead. We needed winston for logging prod deployment in papertrail. This alternative solution is working great so far.

https://docs.docker.com/config/containers/logging/syslog/