首页 > 其他分享 >Koa.js 中的日志管理

Koa.js 中的日志管理

时间:2023-12-20 11:32:28浏览次数:29  
标签:const Koa ctx js error console 日志 log4js

日志

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

日志一般分为:

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

一般我们都是通过 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.js

const 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 = console

module.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,让其生效。

标签:const,Koa,ctx,js,error,console,日志,log4js
From: https://blog.51cto.com/u_12382805/8904776

相关文章

  • Newtonsoft.Json.JsonReaderException:“Bad JSON escape sequence: \*. Path '****'
    测试Json字符串msg:{"field1":"\\\9527\","field2":"\\\\\data\\","field3":"\r\n\\\G\\\d\\\","field4":"TESTTEST\\1TEST\\\GTEST\\\\GTEST2\\\\\TEST3\\......
  • js实现el-select选中的文本,一键复制
    <divclass="invite-buttom">请选择要复制的网站:<el-selectv-model="webValue"placeholder="请选择要复制的网站"><el-optionv-for="iteminformUrl.webInviteUrl"......
  • npmjs.com 网站
    npmjs.com提供了许多对日常开发非常有用的功能:包管理:你可以使用npm来安装、升级、卸载包。这些包可以是全局安装的,也可以是本地安装的。依赖控制:npm可以帮助你管理项目的依赖,使得代码部署变得更加容易。发布和维护包:如果你是一个开发者,npm也提供了命令行工具,让你......
  • 在Mapbox-gl-js中添加自定义图层
    在Mapbox-gl-js中添加自定义图层前言一、制作geojson地图二、使用Tippecanoe将geojson转换成vectortile(.pbf)文件三、使用mapbox-gl-js显示三、Mapbox-gl-js中根据矢量数据的属性过滤显示前言本文说明如何制作自定义的地图数据,并使用mapbox-gl-js进行显示一、制作geoj......
  • JsonNode、ObjectNode和ArrayNode
    我个人不喜欢fastjson,但是项目中很多地方用到json字符串转换对象但又不想创建pojo所以使用jackson的JsonNode、ObjectNode和ArrayNode就非常好用,万能对象,这三个对象是非常全面的,感兴趣的可以看下源码JsonNode只读,通常由ObjectMapper解析json字符串得到ObjectNode可修改,继承......
  • 【力扣】-9. 回文数|刷题打卡-JS
    给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。示例1:输入:x=121输出:true示例 2:输入:x=-121输出:false解释:从左向右读,为-121。从右向左读,为121-。......
  • Parallax.js:实现自适应智能设备方向的视差效果
    哈喽!大家好!我是程序视点的小二哥。今天给大家分享一款功能非常强大的javascript视觉差特效引擎插件:Parallax.js。Parallax.js简介Parallax.js是一个简单的,轻量级的视差引擎。你可以将它作为作为jQuery或Zepto插件来使用,也可以以纯JS的方式来使用。最-最-最厉害的是它可以对智......
  • 前端json转excel 到zip下载
    问题描述:后端返回数据原先返回是多个json文件的压缩包二进制文件流,前端直接下载二进制文件流。但是客户要求下载excel类型文件。解决方案:前端拿到表格的json数据转换成对应table的html字符串,使用插件js-xlsx。给个链接,import*asXLSXfrom'xlsx'//JSONData为导出的json数......
  • json模块
    json模块(一)序列化和反序列化(1)什么是序列化将原本的字典、列表等内容转换成一个字符串的过程就叫做序列化。(2)为什么要序列化给另外一段程序使用,那我们怎么给?现在我们能想到的方法就是存在文件里然后另一个python程序再从文件里读出来。但是我们都知道对于文件......
  • leaflet在vue2中标点 加载geoJSON
    lealfet版本1.9.4vue版本2.6引入:importLfrom'leaflet'  import'leaflet/dist/leaflet.css'  //记得引入样式不然加载瓦片图后地图会错乱1.初始化this.map=L.map(this.mapId,mapInitOptionNew)//this.mapId是容器的idletcenter=[32.666,129.547]const......