使用Express-Winston记录日志:错误的日志顺序

时间:2020-05-03 19:07:39

标签: express winston

我正在使用如下代码:

  constructor(
      private readonly _http: HttpClient) {
    this.getPosts().subscribe(res => {
      this.posts = res;
    });
  }

  getPosts(): Observable<any[]> {
    console.log('getPosts');
    return this._http.get('https://jsonplaceholder.typicode.com/todos').pipe(
        map<any, any[]>(response => {
            console.log(response);
            return response;
          })
      );
  }

,当我尝试调用const app = require('express')(); const winston = require('winston'); const expressWinston = require('express-winston'); app.use(expressWinston.logger({ transports: [ new winston.transports.Console(), ], format: winston.format.combine( winston.format.printf(info => `Date from winston: ${Date.now()} ${info.message}`), ), expressFormat: true, })); app.get('/check', (req, res) => { console.log(`Date from route: ${Date.now()}`); res.end('OK'); }); app.listen(3000, () => console.log('Listening...')); 路由时,会在控制台中收到此消息:

/check

如您所见,中间件的时间晚于路由处理程序的时间。

为什么?我该如何解决?我需要正确确定传递中间件的顺序。

1 个答案:

答案 0 :(得分:0)

更新

根据issue,此功能在Express-Winston中尚不存在。

一种解决方法是,您在路由拦截所有请求之前添加一个中间件来表示,然后通过自定义记录器记录所需的信息,或者创建custom transport in winston for that。一个简单的例子就是

function logRequest(req, res, next) {
  console.log('Request', req.path, Date.now());

  next();
}

app.use(logRequest);
// routes...

上一个答案

问题1:

如您所见,中间件的时间晚于路由的时间 处理程序。为什么?

答案:

这是因为控制台传输new winston.transports.Console()将HTTP请求记录到控制台而不是console.log(<some-text>)。这来自express-winston

的文档

使用expressWinston.logger(options)创建一个中间件来记录您的 HTTP请求

为演示这一点,让我们看一下代码并查看结果:

// Your above code here...

app.get('/check', (req, res) => {
    console.log(`Date from route: ${Date.now()}`);
    let i = 1;

    const handle = setInterval(() => {
      console.log('i:', i);
      i++;
    }, 1000);

    setTimeout(() => {
      console.log('i before response:', i);
      clearInterval(handle);
      res.end('OK');
    }, 3000);
});

app.listen(3000, () => console.log('Listening...'));

结果

Listening...
Date from route: 1588616514869
i: 1
i: 2
i before response: 3
Date from winston: 1588616517889 GET /check 200 3005ms

从结果中我们看到,您仅在调用Date from winston: 1588616065807之后而不是在调用res.end('OK')时才从winston收到自定义消息console.log('Date from route: ${Date.now()}');

问题2:

我该如何解决?

答案:

您无需使用默认的console.log,而是创建自己的记录器,在其中记录消息的格式,然后输出标准输出。像这样:

const app = require('express')();
const winston = require('winston');

const { combine, timestamp, printf } = winston.format;
const myFormat = printf(({ message, timestamp }) => {
  const customMessage = `Date from winston: ${timestamp}`;
  return `${customMessage}\n${message}`;
});

const logger = winston.createLogger({
  transports: [
    new winston.transports.Console(),
  ],
  format: combine(timestamp(), myFormat)
});

app.get('/check', (req, res) => {
  logger.info(`Date from route: ${Date.now()}`);
  let i = 1;

  const handle = setInterval(() => {
    console.log('i:', i);
    i++;
  }, 1000);

  setTimeout(() => {
    console.log('i before response:', i);
    clearInterval(handle);
    res.end('OK');
  }, 3000);
});

app.listen(3000, () => console.log('Listening...'));

结果

Listening...
Date from winston: 2020-05-04T18:26:26.508Z
Date from route: 1588616786506
i: 1
i: 2
i before response: 3

在这种情况下,您看到的是格式化的消息,当您致电logger.info而不是致电res.end('OK')时。

总而言之,请使用自定义记录器使日志看起来像您想要的样子。