11

在 TypeScript 中创建将记录快速 Morgan 中间件日志记录的 winston 记录器的正确方法是什么?我找到了一些 JavaScript 示例,但在将它们转换为 TypeScript 时遇到了麻烦,因为我收到了一个错误Type '{ write: (message: string, encoding: any) => {}; logger: any; }' is not assignable to type '(options?: any) => ReadableStream'. Object literal may only specify known properties, and 'write' does not exist in type '(options?: any) => ReadableStream'.

这是我的代码:

import { Logger, transports } from 'winston';

// http://tostring.it/2014/06/23/advanced-logging-with-nodejs/
// https://www.loggly.com/ultimate-guide/node-logging-basics/

const logger = new Logger({
    transports: [
        new (transports.Console)({
            level: process.env.NODE_ENV === 'production' ? 'error' : 'debug',
            handleExceptions: true,
            json: false,
            colorize: true
        }),
        new (transports.File)({
            filename: 'debug.log', level: 'info',
            handleExceptions: true,
            json: true,
            colorize: false
        })
    ],
    exitOnError: false,
});



if (process.env.NODE_ENV !== 'production') {
    logger.debug('Logging initialized at debug level');
}



// [ts]
// Type '{ write: (message: string, encoding: any) => {}; logger: any; }' is not assignable to type '(options?: any) => ReadableStream'.
//   Object literal may only specify known properties, and 'write' does not exist in type '(options?: any) => ReadableStream'.
logger.stream = {
    write: function (message: string, encoding: any) {
        logger.info(message);
    };
}


export default logger;

我已经能够通过调整要使用的代码来解决此问题,const winston = require('winston');但想知道您应该如何维护类型?

4

4 回答 4

8

最终,我最终将其作为解决方案。我用一种叫做 write 的方法创建了一个类

export class LoggerStream {
    write(message: string) {
        logger.info(message.substring(0, message.lastIndexOf('\n')));
    }
}

然后在添加到表达时,我创建了一个类的实例:

 app.use(morgan('combined', { stream: new LoggerStream() }));

这很适合我的情况

于 2018-08-19T14:49:18.517 回答
5

stream预计将是返回流的工厂函数,而不是流本身。

流应该是真正可读的流,而不是模仿它的对象。

由于它也应该是可写的,因此它应该是双工的:

logger.stream = (options?: any) => new stream.Duplex({
    write: function (message: string, encoding: any) {
        logger.info(message);
    }
});

这是 Winston TS types 建议的解决方案。我无法确认它是否正常工作。

于 2018-04-26T18:30:39.770 回答
3

感谢@estus 让我超越了我被挂断的地方。这是我最终使用的解决方案:

import { Logger, transports } from 'winston';
import stream from 'stream';
import split from 'split';

// http://tostring.it/2014/06/23/advanced-logging-with-nodejs/
// https://www.loggly.com/ultimate-guide/node-logging-basics/

const logger = new Logger({
    transports: [
        new (transports.Console)({
            level: process.env.NODE_ENV === 'production' ? 'error' : 'debug',
            handleExceptions: true,
            json: false,
            colorize: true
        }),
        new (transports.File)({
            filename: 'debug.log', level: 'info',
            handleExceptions: true,
            json: true,
            colorize: false
        })
    ],
    exitOnError: false,
});

if (process.env.NODE_ENV !== 'production') {
    logger.debug('Logging initialized at debug level');
}

logger.stream = split().on('data', function (message: string) {
    logger.info(message);
});

export default logger;

最终这个问题让我找到了最终的解决方案 - https://github.com/expressjs/morgan/issues/70

于 2018-04-26T21:26:43.510 回答
1

如果您将 TypeScript 类用于记录器,则可以声明一个 stream() 函数,该函数从 morgan 返回 StreamOptions 类型:

import { StreamOptions } from 'morgan';

//...rest of the class code

public stream(): StreamOptions {
return {
  write: (message: string): void => {
    this.info(message.trim());
  }
};

然后你可以在 express 中间件中使用这个流函数:

app.use('combined', { stream: this.logger.stream()})
于 2021-02-16T08:44:15.703 回答