log4js简介
log4js是nodejs中的一个日志模块,通过设置其优先级别,可以打印出不同级别的日志,便于后续的系统分析。node其他的日志还有bunyan、winston等。
开箱即用,它支持以下功能:
- 彩色控制台记录到标准输出或标准输出
- 文件追加器,具有基于文件大小或日期的可配置日志滚动
- 用于连接/快速服务器的记录器
- 可配置的日志消息布局/模式
- 不同日志类别的不同日志级别(将应用日志的某些部分设为 DEBUG,其他部分仅设为错误等)
站在巨人的肩膀上,只会看的更远,感谢官方文档和民间使用文档
更多信息看官方文档:log4js-node.github.io/log4js-node…
其他的参考文档:juejin.cn/post/684490…(有点老了)
log4js安装
npm install log4js (俺的版本是^6.7.1)
基本使用
var log4js = require("log4js");
var logger = log4js.getLogger();
logger.level = "debug";
logger.debug("Some debug messages");
调用.getLogger() 可以获得 log4js 的 Logger 实例,这个实例的用法与 console 是一致的,可以调用.debug(也有.info、.error 等方法)来输出日志。将logger对象的level设置为debug(默认为OFF不会输出任何日志)。
运行node test.js,终端输出如下:
由 - 分割开来的说明符区与内容区
说明符:[2023-01-05T10:23:02.337] [DEBUG] default
内容:Some debug messages
等级Level(也叫分级)
Level其实就是日志的分级,log4js 才能更好地为我们展示日志(不同级别的日志在控制台中采用不同的颜色,比如 error 通常是红色的)
log4js 的日志分为九个等级,各个级别的名字和权重如下:
{
ALL: new Level(Number.MIN_VALUE, "ALL"),
TRACE: new Level(5000, "TRACE"),
DEBUG: new Level(10000, "DEBUG"),
INFO: new Level(20000, "INFO"),
WARN: new Level(30000, "WARN"),
ERROR: new Level(40000, "ERROR"),
FATAL: new Level(50000, "FATAL"),
MARK: new Level(9007199254740992, "MARK"), // 2^53
OFF: new Level(Number.MAX_VALUE, "OFF")
}
log4js 的输出级别: trace,debug,info,warn,error,fatal,设置为info后,则只会打印info及其后面类型的日志。
类别(也叫分类)
log4js 还有一个概念就是 category(类别),你可以设置一个 Logger 实例的类型,按照另外一个维度来区分日志:
const log4js = require("log4js");
let loggerOne = log4js.getLogger();
let loggerTwo = log4js.getLogger('main.js');//!!!
loggerOne.level = "debug";
loggerTwo.level = "debug";
loggerOne.debug("Some debug messages");
loggerTwo.debug("Some debug messages");
说明符的default变成了main.js
类别为日志了提供了第二个区分的维度,可以针对不同的 node package 使用不同的category,这样可以区分日志来源于哪个模块(人话就是方便看来自哪个js文件的日志)。
log4js中的配置
先上基础完整代码在逐各分析
const log4js = require("log4js");
// log4js的配置
log4js.configure({
// 追加器
appenders: {
out: {
type: "stdout",
layout: {
type: 'colored'
}
},
app: {
type: "file",
filename: "application.log"
},
},
//类别
categories: {
default: {
appenders: ["out", "app"],
level: "debug"
},
cheese:{
appenders: ["out"],
level: "debug"
}
},
});
const loggerOne = log4js.getLogger() //使用默认类别(default)
const loggerTwo = log4js.getLogger('cheese') //使用cheese类别
loggerOne.debug("loggerOne")
loggerOne.info("loggerOne")
loggerOne.warn("loggerOne")
loggerOne.error("loggerOne")
loggerOne.fatal("loggerOne")
loggerOne.mark("loggerOne")
loggerTwo.info('loggerTwo')
一些注意点:
- 没有对 log4js 进行任何配置的时候,默认是将日志都输出到了控制台。
- log4js 2.0 版本以上 stdout 作为默认 appender, 推荐使用 stdout 而不是 console 打印控制台日志 appender-console 在大量日志输出时会占用 v8 大量内存,拖慢系统性能,不推荐使用 !
appenders(追加器)
关于日志的保存问题(即日志输出到哪里)是由 Appender 来解决。
appenders: {
out: {
type: "stdout",//输出在终端中
layout: {
type: 'colored'
}
},
app: {
type: "file",
//存在当前文件的目录下的 application.log文件中
filename: "application.log"
},
},
out与app是两个不同类型的追加器(人话就是你想怎么输出,咋样输出),每个追加器可以对应单个或多个类别,比如app对应了categories中的default(默认类别)和cheese。
type输出样式(列举几个常用其余可以看官方文档)
- stdout:日志事件写入标准输出流。它是 log4js 的默认追加器(人话输出在终端看得见)。
- file:日志事件写入到文件中。完整的扩展配置后面say。
- dateFile:日志事件写入到根据当天日期创建文件中。完整扩展后面say
- 其他见官方文档
Layout(列举一些常用的,具体用到见官方文档)
大多数追加器配置将采用一个名为布局的字段,这是一个对象 - 通常具有单个字段类型,该字段类型是下面定义的布局的名称。(人话就是每个追加器都可能有一个layout对象并且只有一个type的属性)
type可能有的值:
- colored:时间戳、级别和类别将根据日志事件的级别着色(也是log4js默认就选择的)
1. TRACE - ‘blue’
2. DEBUG - ‘cyan’
3. INFO - ‘green’
4. WARN - ‘yellow’
5. ERROR - ‘red’
6. FATAL - ‘magenta’
- basic:基本布局将输出时间戳、级别、类别,后跟格式化的日志事件数据。colored就是在此基础上上色了而已。
- messagePassThrough:此布局仅只输出日志事件数据的格式,不输出时间戳、级别或类别。
categories(类别)的配置
categories: {
default: {
appenders: ["out", "app"],
level: "debug"
},
cheese:{
appenders: ["out"],
level: "debug"
}
},
default与cheese两个不同的类别,两个设置的level都为debug级别,使用的追加器(输出方式)不同(default默认多一个日志事件保存文件)
- appenders:选择appenders中设置好的追加器(可以有多个,也就是输出的方式可以有多个,即可输出在终端的同时又输出到log文件中)
- level:设置等级(设置能输出日志的等级)
具体使用
file文件类型输出使用
const log4js = require('log4js');
log4js.configure({
appenders: {
everything: {
type: "file",
filename: "all-the-logs.log",
//当大小达到 10Mb 时,它将被重命名并压缩为 all-the-logs.log.1(2,3依次递增)并打开一个名为 all-the-logs.log 的新文件。
//如果未指定 maxLogSize 或 0,则不会发生日志滚动。后缀K、M、G(dddd)
maxLogSize: "10M",
//日志滚动期间要保留的旧日志文件数(不包括热文件all-the-logs.log)(结合下图看更明白)
backups: 6,
// 是否压缩,会压缩成在all-the-logs.log.1基础上压缩成all-the-logs.log.1.gz文件
compress: true,
},
},
categories: {
default: { appenders: ["everything"], level: "debug" },
},
});
const logger = log4js.getLogger();
// 自行for循环试试看
logger.debug("loggerOne")
logger.info("loggerOne")
logger.warn("loggerOne")
dateFile文件类型使用
const log4js = require('log4js');
log4js.configure({
appenders: {
cheese: {
type: 'dateFile',
filename: 'logs/cheese.log',
pattern: "yyyy-MM-dd",
compress: true,
numBackups: 5,
}
},
categories: {
default: {
appenders: ['cheese'],
level: 'info'
}
}
});
const logger = log4js.getLogger();
logger.debug("loggerOne")
logger.info("loggerOne")
logger.warn("loggerOne")
这个我就逐个分析:
{
// 只有这两个属性的时候,默认就是一天滚动一次日志
// 初始文件将是 cheese.log,每日备份是 cheese.log.2023-01-6 等
type: 'dateFile',
// 指定输出地址(当前文件下的)
filename: 'logs/cheese.log',
}
- pattern属性:用于确定何时滚动日志的模式。例如:"yyyy-MM-dd-hh",则是每小时滚动一次日志。(不写默认是隔天滚动)
- numBackups:日志滚动期间保留旧日志文件数(不包括热文件cheese.log)
- compress:开启压缩
- 开压缩的情况下就不需要
alwaysIncludePattern:true至于为什么大家可以拿我代码去试试看。(压缩和不压缩都是一种选择把,不压缩的话就开启alwaysIncludePattern这样文件命名信息就比较清楚些)
log4js在Node中的应用
我实践的代码(写的可能不是很规范)
官方参考:log4js-node.github.io/log4js-node…
const log4js = require("log4js");
const express = require("express");
log4js.configure({
appenders: {
console: { type: "console" },
file: { type: "file", filename: "cheese.log" },
},
categories: {
cheese: { appenders: ["file"], level: "info" },
default: { appenders: ["console"], level: "info" },
},
});
const logger = log4js.getLogger("cheese");
const app = express();
app.use(express.json())
app.use(log4js.connectLogger(logger, {
level: log4js.levels.INFO,
// format: ":method :url",
// 这种方法可以拿请求的数据放进日志中比如id等
/* format: (req, res, format) =>
format(
`:remote-addr - ${req.id} - ":method :url HTTP/:http-version" :status :content-length ":referrer" ":user-agent"`
), */
// 这个则是将post请求的携带的json文件保存进日志中
format: (req, res, format) =>
format(`:remote-addr :method :url :status ${JSON.stringify(req.body)}`),
statusRules: [
{ codes: [303, 304], level: "info" },
{ codes: [404], level: "warn" },
],
// nolog: (req, res) => res.statusCode < 400,
}));
app.get("/", function (req, res) {
res.send("hello world");
});
app.listen(5002);
-
log4js.connectLogger中间件用来收集访问的信息(自己试试就明白了)。 -
log4js.connectLogger配置:- level:值可以是
"debug"、"info"字符串或log4js.levels[.DEBUG]、[.INFO],设置日志等级。 - format:设置格式。
:method请求方式:url请求地址HTTP/:http-versionhtpp版本号:status状态码:content-length内容长度:user-agent用户代理
-
statusRules:状态规则。
{ codes: [404], level: "warn" }如果状态码为404,则等级为warn。 -
nolog:哪些信息不用输出在log文件上。例子:
nolog: (req, res) => res.statusCode < 400状态码小于400的访问信息则不会出现在log文件中。也支持字符串、正则表达式、数组省略日志消息,比如:nolog: "\.gif|\.jpg$",访问example.com/hoge.gif 则会省略日志消息。
- level:值可以是
express、koa、egg用法大差不差都是中间件使用。log4js.configure中的配置可以放置在json文件中读取使用,log4js.connectLogger中间件方法也可以分离出来,测试就不写那么正式了。