微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

javascript – 使用winston,morgan和winston-daily-rotate-file实现记录器

我正在尝试在节点js中实现一个记录器,它将在日志的自定义格式上每天创建一个新的日志文件

为此,我使用了三个包

> winston
> morgan
> winston-daily-rotate-file

所以每天应该在日志文件夹中创建一个新的日志文件的最终输出,它应该将所有http(摩根日志)和键入的日志(winston日志)记录到以下格式的单个文件

日期||文件名|| statusCode || logMessage || uuid(用于追踪)

例如:Fri Jan 18 2019 13:48:18 GMT 0530(IST)|| [index.js] || 200 ||调用新路径|| 287dccb0-1afa-11e9-88a0-dfb1c665be9d

所以为此,我写了三个文件index.js(nodejs的根文件)logger.js(logger实现和配置)和logger.test.js(使用jest的logger测试用例)

额外的包

> cors
> uuid
> http-context
> app-root-path
> express-http-context
> jest

我遇到的问题

>如果我在app.listen上的index.js中放入一个logger.error({message:{statusCode:200,logMsg:“服务器将在端口3000中启动”}}},之后再转到console.log()uuid一片空白
>我写的测试用例是错误的,我是开玩笑的新手,我只想知道如何检查所有这些情况.
>为什么当我测试套装uuid为null时,我怎么能通过uuid测试用例呢
>我如何检查是否将创建新文件夹,如果已经登录文件夹,那么新文件就会被创建一种测试用例.
>我如何添加其他级别,信息,debuge,警告基于环境.如何改进此代码以实现记录器功能

// index.js

const app = require('express')();
const cors = require('cors')
const morgan = require('morgan') // HTTP request logger middleware 
const logger = require('./config/logger')(module) //Logger
const uuid = require('uuid')
const httpContext = require('express-http-context')

// Use any third party middleware that does not need access to the context here
// app.use(some3rdParty.middleware);

app.use(httpContext.middleware);
// all code from here on has access to the same context for each request

// Run the context for each request.
// Assigning a unique identifier to each request
app.use((req,res,next) => {
  httpContext.set('reqId',uuid.v1());
  next()
})


// using morgan with winston(logger)
app.use(morgan('combined',{
  stream: {
    write: (message) => logger.error(message)
  }
}))


app.use(cors());

app.use("/new",(req,res) => {
  logger.error({
    message: {
      statusCode: 400,logMsg: "hitting new route"
    }
  })
  nextLayer(res)
})

const nextLayer = (res) => {
  logger.error({
    message: {
      statusCode: 400,logMsg: "hitting in nextLayer function"
    }
  })
  res.send("OK")
}

app.listen(4000,() => {
  console.log('Server running on port 4000');
})





// Logger.js

const appRoot = require('app-root-path')
const {
  createLogger,format,transports
} = require('winston')
const {
  combine,timestamp,label,printf
} = format
const path = require('path')
require('winston-daily-rotate-file');
const httpContext = require('express-http-context')

/**
 * @method checkMessageProp
 * @param {message} can be object if developer defined,else it will be string
 *                  if its a network request
 * @returns a fixed format how the status code and message should show
 */
const checkMessageProp = (message) => {
  switch (typeof message) {
    case "object":
      const {
        statusCode,logMsg
      } = message
      return `${statusCode ? statusCode : "Not Defined"} || ${logMsg ? logMsg : "Not Defined"}`;
    case "string":
      let messageSplit = message.split(`"`)
      var message = messageSplit ? `${messageSplit[2].trim().split(" ")[0]} || ${messageSplit[1]}` : null
      return message
    default:
      return message
  }
}

/**
 * @method customFormat
 * @param {log} the log passed by the developer or based on network requests
 * @returns a customFormat how it should be logged to the log files
 */
const customFormat = printf(log => {
  const Now = new Date();
  const reqId = httpContext.get('reqId');
  return `${log.timestamp ? new Date(log.timestamp) : Now} || [${log.label}] || ${checkMessageProp(log.message)} || ${reqId ? reqId : null}`
});

/**
 * @method getFileName
 * @param {moduleObj} the module realted object passed from the require of logger file 
 * @returns the file name where the logger was invoked
 */
const getFileName = moduleObj => {
  if (Object.keys(moduleObj).length > 0) {
    let parts = moduleObj.filename.split(path.sep)
    return parts.pop()
  } else {
    return "Module not passed while requiring the logger"
  }
}

// Custom settings for each transport 
const options = moduleObj => {
  return {
    dailyRotateFile: {
      filename: `${appRoot}/logs/TPS-UI-%DATE%.log`,datePattern: 'YYYY-MM-DD',prepend: true,level: "error",timestamp: new Date(),localTime: true
    }
  }
}

// Instantiate a Winston Logger with the settings
let logger = moduleObj => {
  return createLogger({
    format: combine(
      label({
        label: getFileName(moduleObj)
      }),customFormat
    ),transports: [
      new transports.DailyRotateFile(options(moduleObj).dailyRotateFile)
    ],exitOnError: false // do not exit on handled exceptions
  })
}



module.exports = logger








// logger.test.js

const logger = require('./logger')

beforeEach(() => {
  mockLoggerMessageObject = {
    message: {
      statusCode: 400,logMsg: "Calling in test suite"
    }
  }
  mockLoggerMessageString = `::ffff:127.0.0.1 - - [18/Jan/2019:04:50:57 +0000] 
                               "GET /new HTTP/1.1" 200 2 "http://localhost/" "Mozilla/5.0 
                               (linux) AppleWebKit/537.36 (KHTML,like Gecko) jsdom/11.12.0"`
  mockLoggerMessageNumberFormat = 123
  mockLoggerMessageArrayFormat = ["data","test",123]
})

describe(`Logger test cases`,() => {
  test('should invoke the logger function with the mock Logger message object',() => {
    expect(logger(module).error(mockLoggerMessageObject)).tobedefined()
  })
  test(`should invoke the logger function with empty object`,() => {
    expect(logger(module).error({})).tobedefined()
  })
  test(`should invoke the logger function without any module object`,() => {
    expect(logger({}).error(mockLoggerMessageObject)).tobedefined()
  })
  test(`should invoke the logger function without any module and message object`,() => {
    expect(logger({}).error({})).tobedefined()
  })
  test(`should invoke the logger function with the http request`,() => {
    expect(logger(module).error(mockLoggerMessageString)).tobedefined()
  })
  test(`should invoke the logger function with the number format`,() => {
    expect(logger(module).error(mockLoggerMessageNumberFormat)).tobedefined()
  })
  test(`should invoke the logger function with the array format`,() => {
    expect(logger(module).error(mockLoggerMessageArrayFormat)).tobedefined()
  })

})
最佳答案
对于winston我正在使用timestamp(),这样它会自动将timestamp()属性添加到对象

const {transports,createLogger,format} = require('winston');
const logger = createLogger({
        format: format.combine(
            format.timestamp(),format.json()
        ),

另外要检查它是否创建文件你可以模拟日期,说2019-01-01并检查它是否创建文件2019-01-01.log
比将日期移至2019-01-02并记录其他内容.
Winston将创建新的文件夹和gzip存档,您可以检查文件是否存在,并且可以解压缩并包含信息

尝试阅读winston的文档.
基本上我会说你可能需要使用

format.timestamp()
format.json()
colorize()

dailyRotate with zippedArchive:true

如果摩根不适合您的需求,您可以尝试直接登录

app.use((req,next) => { 
    logger.silly({ message:'start',req,res}); 

    return next().then(r=>logger.silly({ message:'end',res}; return r;);
}

原文地址:https://www.jb51.cc/js/429294.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐