我正在使用如下代码:
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
如您所见,中间件的时间晚于路由处理程序的时间。
为什么?我该如何解决?我需要正确确定传递中间件的顺序。
答案 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')
时。
总而言之,请使用自定义记录器使日志看起来像您想要的样子。