Koa.js 中的日志管理

566 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第25天,点击查看活动详情

日志

日志用来记录程序的运行信息。开发服务端程序,必须集成日志管理的功能,一旦系统出现故障可以及时排查问题所在。

日志一般分为:

  • 访问日志:记录系统的访问记录。
  • 运行日志:输出系统运行时的一些信息
  • 错误日志:记录系统出错的状态

一般我们都是通过 nginx 做负载均衡,它具备了记录访问日志的功能。所以访问日志交给 Nginx 去做就好。

在后端程序开发中,我们只需要关注运行日志和错误日志。

Koa-logger

Koa.js 官方的日志插件是 koa-logger,功能比较简单,只能打印一些请求的信息,并不会记录日志,不能满足复杂场景的需求。

const logger = require('koa-logger')
​
app.use(logger())
​
// logger
app.use(async (ctx, next) => {
  const start = new Date()
  await next()
  const ms = new Date() - start
  console.log(`${ctx.method} ${ctx.url} - ${ms}ms`)
})

看似是一个日志中间件,本质只是一个 console.log 打印内容的格式化。只能开发模式下打印的更加美观。

所以通常会使用一些第三方的日志模块,比如 log4jswinston 等。

Log4js

Log4js 是一个优秀的日志插件,常用的功能包括按级别输出不同的日志信息,保存日志为文件等。

使用 log4js

安装依赖:

npm install log4js

配置

新建 log4js 的配置文件, utils/log4js.js:

// log4js.jsconst path = require('path')
const log4js = require('log4js')
​
const { isProd } = require('./index')
​
​
// 日志配置对象
log4js.configure({
  // 日志记录方式
  appenders: {
    // 自定义category为error,记录服务器报错信息
    error: {
      type: 'file',           //日志类型 指定单一文件存储
      filename: path.join('logs/', 'error/error.log'), //日志输出位置,当目录文件或文件夹不存在时自动创建
      maxLogSize: 1024 * 1000 * 100, // 文件最大存储空间,单位是字节 1024k 1m
      backups: 100  //当文件内容超过文件存储空间时,备份文件的数量
    },
​
    // 自定义category为response,记录服务器的响应情况 用户访问服务的情况
    response: {
      type: 'dateFile', // 以日期命名的文件记录日志
      filename: path.join('logs/', 'access/response'),
      pattern: 'yyyy-MM-dd.log', //日志输出模式
      alwaysIncludePattern: true,
​
      // dateFile类型的appender没有这个选项
      maxLogSize: 1024 * 1000 * 100,
      // dateFile类型的appender没有这个选项
      backups: 1
    },
​
    console: {
      type: "console",
      layout: {
        // 开发环境下带颜色输出,生产环境下使用基本输出
        type: isProd ? 'basic' : 'coloured'
      }
    }
  },
​
  // log4js.getLogger(type):就是读取这里的key
  categories: {
    error: { appenders: ['error'], level: 'error' },
    response: { appenders: ['response'], level: 'info' },
    default: { appenders: ['console'], level: 'all' }
  }
​
  replaceConsole: true
})
​
let logger = {}
​
// 自定义输出格式,确定哪些内容输出到日志文件中
const formatError = (ctx, err) => {
  const { method, url } = ctx
  let body = ctx.request.body
  const user = ctx.state.user
​
  // 将请求方法,请求路径,请求体,登录用户,错误信息
  return { method, url, body, user, err }
}
​
const formatRes = (ctx, costTime) => {
  // const { method, url, response: { status, message, body: { success } }, request: { header: { authorization } } } = ctx
  const { ip, method, url, response: { status, message }, request: { header: { authorization } } } = ctx
  let body = ctx.request.body
  const user = ctx.state.user
​
  // 将请求方法,请求路径,请求体,登录用户,请求消耗时间,请求头中的authorization字段即token,响应体中的状态码,消息,以及自定义的响应状态
  return { ip, method, url, body, user, costTime, authorization, response: { status, message } }
}
​
// 生成一个error类型的日志记录器
let errorLogger = log4js.getLogger('error')
​
// 生成一个response类型的日志记录器
let resLogger = log4js.getLogger('response')
​
// 生成一个控制台类型的日志记录器
let console = log4js.getLogger()
​
// 封装错误日志
logger.errLogger = (ctx, error) => {
  if (ctx && error) {
    errorLogger.error(formatError(ctx, error))
  }
}
​
// 封装响应日志
logger.resLogger = (ctx, resTime) => {
  if (ctx) {
    resLogger.info(formatRes(ctx, resTime))
  }
}
​
// 控制台输出
logger.log = consolemodule.exports = logger

在应用中使用 log4js 插件:

const Koa = require('koa')
​
const { isProd } = require('./utils/index')
const { log, errLogger, resLogger } = require('./utils/log4js')
​
​
// 初始化web服务
const app = new Koa()
​
const router = new Router()
​
// 通过log4js记录访问日志
app.use(async (ctx, next) => {
  const start = new Date()
  await next()
  const end = new Date() - start
  // 生产环境下,使用中间件记录日志,使用console.log打印消息
  // 其他环境下,使用log4js的console打印信息
  if (isProd) {
    resLogger(ctx, end)
    console.log((`${ctx.method} ${ctx.url} - ${end}ms`))
  } else {
    log.info(`${ctx.method} ${ctx.url} - ${end}ms`)
  }
})
​
// error-handling
app.on('error', (err, ctx) => {
  if (isProd) {
    errLogger(ctx, err);
    log.error(`${ctx.method} ${ctx.url}`, err)
  } else {
    console.error(`${ctx.method} ${ctx.url}`, err)
  }
})

小结

本文总结了在 Koa.js 项目中使用第三方日志插件 log4js 的方法,首先是定义log4js的配置,它决定了该如何记录日志。然后在应用入口中使用 log4js,让其生效。