Log4js原理解析

基于log4js 0.6.14版本

Log4js总共三篇博客

《Log4js原理解析》http://blog.csdn.net/hfty290/article/details/42844085

《Log4js配置详解》http://blog.csdn.net/hfty290/article/details/42843737

《Log4js多进程陷阱与避免》http://blog.csdn.net/hfty290/article/details/42843303

一、概述

网络上有不少关于Log4j的源码解析文章,但是到目前为止还未见到一个log4js的源码解析,虽然这两者有其共同之处,但是在实现原理是存在显著的差别。作为在node.js世界里最流行的日志模块,了解其内部设计与实现还是挺有意义的。本篇将描述log4js的架构与实现,先简要说明log4js中出现的元素,接着为每个元素做详细说明,最后分析元素的协同工作。

二、设计元素简述

在log4js中出现的设计元素包括:level、layout、appender、logger;请看下面表格:

三、色彩缤纷的Appender

不同的Appender实现不同的日志写入方式,所有的Appender都在源码的 lib/appenders目录下,目前log4js提供了很多种的写入方式,有file、datefile、multiprocess、console、clustered、gelf、hookio、loggly、smtp。本文将依次介绍前五种Appender。每个Appender的js文件都会导出appender和configure两个函数,file与dateFile还会导出shutdown函数。

appender函数返回的是一个闭包函数,该闭包函数实现将内容写入到日志。典型的appender函数实现如下:

function fileAppender (file, layout, logSize, numBackups) {…….var logFile = openTheStream(file, logSize, numBackups);
return function(loggingEvent) {logFile.write(layout(loggingEvent) + eol, "utf8");
};
}

而configure函数根据参数提供配置信息,去调用对应的appender函数,将appender函数的返回值作为自己的返回值,如下:

function configure(config, options) {……return fileAppender(config.filename, layout, config.maxLogSize, config.backups);
}

因此configure返回值是一个闭包函数,通过该函数可以实现将日志写入到文件之中。

下面将依次介绍每个Appender的实现:

1、file:实现将日志写入到文本文件之中,同时支持日志文件按照大小滚动。

2、datefile:实现将日志写入到文本文件之中,日志按照日期进行滚动。

3、console:实现将日志写入到控制台。

4、multiprocess:实现多进程同步方式写日志,具体是在master(自主配置)进程上开启一个监听端口,所有的worker进程将日志通过tcp发送给master,由master将日志写入到文件中。注意:这种模式只支持配置一个appender,不能配置多个。

Master配置参数:

Worker配置参数:

5、clustered:用于node的cluster环境之中,实现方式与multiprocess类似,真正的写日志是在Master中,Worker只是将日志发送给Master。Worker和Master的配置一样,内部根据cluster.isMaster可以自动判断。

配置参数:

四、布局Layout

Layout实现每条日志记录的格式化,log4js提供了多种的格式化样式可供选择,有basicLayout、messagePassThroughLayout、patternLayout、colouredLayout、coloredLayout,默认情况下会使用basicLayout。所有的Layout都在源码的lib/layouts.js中定义。layouts.js文件除了导出上述说到的这些Layout,还导出一个layout函数,定义如下:

layout: function(name, config) {return layoutMakers[name] && layoutMakers[name](config);
}layoutMakers = {"messagePassThrough": function() { return messagePassThroughLayout; }, "basic": function() { return basicLayout; }, "colored": function() { return colouredLayout; }, "coloured": function() { return colouredLayout; }, "pattern": function (config) {return patternLayout(config && config.pattern, config && config.tokens);}
}
实现将一个文本描述的Layout转换成内部定义的Layout函数。使用起来就像这样:
layout = layouts.layout(config.layout.type, config.layout);
其中的config.layout.type字段表示Layout的名称,而config.layout中的其他字段为对应Layout的配置信息。只有创建pattern类型的Layout时才需要其他配置。

下面依次介绍每种Layout的功能。

1、basicLayout:最基础的Layout,一个message通过该basicLayout会变成如下样子:

[startTime] [logLevel] categoryName - message\n

2、 colouredLayout 、c oloredLayout :格式化日志内容,其中包括了颜色信息,颜色是根据每条日志的级别预定义的。每条记录内容与basicLayout一样:

[startTime] [logLevel] categoryName - message\n

3、 messagePassThroughLayout :日志内容只包括消息,没有其他字段:

message\n

4、patternLayout:实现日志按照配置进行格式化,该Layout需要两个参数,pattern、tokens;其中的pattern表示格式化字符串,tokens表示自定义函数。

预定义格式化有:

  var replacers = {'c': categoryName,'d': formatAsDate,'h': hostname,'m': formatMessage,'n': endOfLine,'p': logLevel,'r': startTime,'[': startColour,']': endColour,'%': percent,'x': userDefined};

例如,一个patternLayout的配置如下:

"pattern": "%[%r (%x{pid}) %p %c -%] %m%n",

"tokens": {

"pid" : function() { return process.pid; }

}

其中自定义了tokens为pid,通过%x{pid}来引用。注意pattern的的 %[ 与 %] 表示颜色的开始于结束。上述配置打印出来的日志如下:

18:13:39 (19556) INFO app - Test log message

五、Logger对象

Logger对象实现对日志Level的管理,并定义了对外的写日志接口。客户端通过log4js.getLogger()获取的就是该Logger对象。Logger类从events.EventEmitter继承,因此Logger对象具有发生事件的能力。在log4js之中,写日志是通过在log事件上注册对应的appender来实现的。

Logger对象的组成:

六、log4js

log4js源码文件为lib/log4js.js,里面包含了一些函数来实现对appender的加载,日志的管理等操作。所有外面要使用log4js中的对象,都采用export的方式导出,可以直接引用,导出的成员如下:

1、日志管理

log4js中为日志进行类别划分,每个类别下最多可以创建一个Logger。同样每个appender实例也有归属的类别,但是一个appender实例可以同时属于多个类别。如图1:

图1:有两个category分别为cheese与bread;每个category最多对应着一个logger对象。图中有三个appender,cheese.log与cheese1.log类型为file,另外还有一个console。console这个appender同时指向了cheese和bread,也就是这两个日志都会使用到console。另外cheese有三个appender指向它,意味着,如果想cheese分类的日志中写日志,会同时向三个地方写入,cheese.log, cheese1.log, console.

2、log事件

前面已经说明,调用Logger实例的写日志操作,会触发log事件。appender在log事件中被调用,从而实现记录写入到日志文件中。如图1中类型为Cheese的Logger,关联着三个appender实例,fileAppender-cheese.log,fileAppender-cheese1.log,console。那么当调用该logger写日志函数,如logger.info时,触发了log事件,与其关联的三个appender实例被调用,最终这条日志内容被写入到三个地方。

图2:Logger的事件监听机制;用户在调用logger.info(‘hello'); 触发了Logger实例的log事件,所有类别为Cheese的Appender实例(有三个),都会监听到该事件,实现将日志记录写入到三个位置。另外还有一种为all的分类,如果指定一个appender的类型为all,那么将收到所有logger的log事件,log4js默认加载的console就是类型为all的appender。

3、替换console

在开发的过程中,为了方便可能直接将日志直接以console.log方式打印出来,使用log4js可以将console的日志重定向到日志文件中。log4js导出了两个函数:

4、日志配置定期检查更新

log4js提供了自动重新加载日志配置,更新所有的appender与日志级别的信息,是一项非常使用的功能。log4js导出的configure函数中,第二个参数如果设置了reloadSecs,则会在指定的间隔秒数之后,重载配置。如下:

log4js.configure('file.json', { reloadSecs: 300 });

5、其他导出函数说明

Log4js总共三篇博客

《Log4js原理解析》http://blog.csdn.net/hfty290/article/details/42844085

《Log4js配置详解》http://blog.csdn.net/hfty290/article/details/42843737

《Log4js多进程陷阱与避免》http://blog.csdn.net/hfty290/article/details/42843303

Log4js原理解析相关推荐

  1. Spark Shuffle原理解析

    Spark Shuffle原理解析 一:到底什么是Shuffle? Shuffle中文翻译为"洗牌",需要Shuffle的关键性原因是某种具有共同特征的数据需要最终汇聚到一个计算节 ...

  2. 秋色园QBlog技术原理解析:性能优化篇:用户和文章计数器方案(十七)

    2019独角兽企业重金招聘Python工程师标准>>> 上节概要: 上节 秋色园QBlog技术原理解析:性能优化篇:access的并发极限及分库分散并发方案(十六)  中, 介绍了 ...

  3. Tomcat 架构原理解析到架构设计借鉴

    ‍ 点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 Tomcat 架构原理解析到架构设计借鉴 Tomcat 发展这 ...

  4. 秋色园QBlog技术原理解析:性能优化篇:数据库文章表分表及分库减压方案(十五)...

    文章回顾: 1: 秋色园QBlog技术原理解析:开篇:整体认识(一) --介绍整体文件夹和文件的作用 2: 秋色园QBlog技术原理解析:认识整站处理流程(二) --介绍秋色园业务处理流程 3: 秋色 ...

  5. CSS实现元素居中原理解析

    原文:CSS实现元素居中原理解析 在 CSS 中要设置元素水平垂直居中是一个非常常见的需求了.但就是这样一个从理论上来看似乎实现起来极其简单的,在实践中,它往往难住了很多人. 让元素水平居中相对比较简 ...

  6. 秋色园QBlog技术原理解析:Web之页面处理-内容填充(八)

    文章回顾: 1: 秋色园QBlog技术原理解析:开篇:整体认识(一) --介绍整体文件夹和文件的作用 2: 秋色园QBlog技术原理解析:认识整站处理流程(二) --介绍秋色园业务处理流程 3: 秋色 ...

  7. 秋色园QBlog技术原理解析:UrlRewrite之无后缀URL原理(三)

    文章回顾: 1: 秋色园QBlog技术原理解析:开篇:整体认识(一) --介绍整体文件夹和文件的作用 2: 秋色园QBlog技术原理解析:认识整站处理流程(二) --介绍秋色园业务处理流程 本节,将从 ...

  8. Android之Butterknife原理解析

    转载请标明出处:[顾林海的博客] 个人开发的微信小程序,目前功能是书籍推荐,后续会完善一些新功能,希望大家多多支持! ##前言 Butterknife是一个专注于Android系统的View注入框架, ...

  9. 【深度学习】谷歌大脑EfficientNet的工作原理解析

    [深度学习]谷歌大脑EfficientNet的工作原理解析 文章目录 1 知识点准备1.1 卷积后通道数目是怎么变多的1.2 EfficientNet 2 结构2.1 方式2.2 MBConv卷积块2 ...

最新文章

  1. linux我ll查不到usr,Linux学习-文件查寻
  2. LOJ#2132. 「NOI2015」荷马史诗
  3. HDLBits答案(3)_Verilog模块的例化与调用
  4. linux的ftp下载假死,记一次commons-net FTP上传下载卡死
  5. 缺少linux内核,Linux内核缺页
  6. 19年8月 字母哥 第二章 RESTFul接口实现与测试 看到这里了
  7. 【Python】cv2.error: ... (-215:Assertion failed) ssize.empty() in function ‘cv::resize’ 的解决方法
  8. 设计素材|剪纸风新年春节烫金PSD分层模板,牛气!
  9. poj 3335 Rotating Scoreboard - 半平面交
  10. php checkbox表单提交,HTML表单Checkbox的值如何正确提交到PHP后台?,需要技巧
  11. Inondb中的checkpoint
  12. 微信 Android design 代码,微信代码有哪些_微信隐藏代码介绍_3DM手游
  13. python循环结构高一信息技术_高一信息技术For循环语句公开课【2019原创资源大赛】...
  14. 如何科学进行用户分析?六大方法论了解一下!
  15. VR,AR,MR的区别与联系
  16. Alpine镜像中时区的设置
  17. The song from the Chef
  18. 给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1
  19. 数据挖掘冰山立方体构建算法:BUC及实现
  20. 数据可视化----ECharts---柱状图(三)

热门文章

  1. Zotero下载安装!浏览器以及翻译插件分享!
  2. 我与女朋友的不平等条约
  3. 时间的玫瑰-让自己慢下来(24)
  4. python爬虫好友聊天记录_利用Python网络爬虫抓取微信好友的签名及其可视化展示...
  5. QQ浏览器HD iOS 动态化/热修复方案QBDF解释器-语法制导翻译与递归子程序设计(编译原理)(5)简书被冻结-搬运】
  6. 老男孩培训视频听课笔记七(在51cto上听的)--5.8 64bit 基础优化
  7. 数据库系统概论期末复习二、关系数据库
  8. 易语言学习第3天。登录窗口。
  9. 数据库系统原理与实践题库及答案(完整版)
  10. 照片修复软件有哪些?这几款照片修复软件快收好