polemo-logger 分析

polemo-logger 是网易游戏框架 polemo 所用的日志系统接口,对 log4js-node 进行了封装,有其弱化及增强之处。具体描述为:

  • 增强部分

    • 多前缀的支持
    • 行号的支持
    • 前缀、行号颜色的支持
    • 配置项的取值来源支持:环境变量、 命令行参数、可选项
  • 弱化部分(或限制部分)
    • 定时配置文件的加载函数中去掉了 appender 的变化支持,只保留了 level、replaceConsole 的动态加载
    • reloadSecs 从 opts 移动到了配置(config)中
    • 大幅减少模块导出函数

一、多前缀、行号、及其颜色的显示

通常,每行的日志消息格式如下。

[2010-01-17 11:43:37.987] [DEBUG] [default] - Some debug messages
  • DEBUG 为优先级
  • default 为类别,category

而polemo-logger增加的多前缀,形如:

[2014-07-01 14:29:39.193] [INFO] log - [/Users/xxx/pomelo-logger/examples/log.js] [1334] test1

[/Users/pomelo-logger/examples/log.js]、[1334] 即为前缀。前缀格式可以为0个,也可以为1到多个。

支持多前缀的调用方式如:

var logger = require(‘pomelo-logger‘).getLogger(‘log‘, __filename, process.pid);

实现方式:

  1. 在 getLogger 中,获取到 log4js 的 logger 之后,重定义每个日志函数,如 log、error 等
  2. 在其中实现对前缀、行号、前缀及行号的颜色支持

重定义的日志函数的实现:

  1. 如果 catagoryName 为文件名,从中去掉当前的目录前缀
  2. 初始化 prefix 变量为空串
  3. 如果是原始模式(process.env.RAW_MESSAGE 为真,这个环境变量也是 polemo-logger 扩展的),直接调用原始 log4js 对应的日志函数,即跳转到 6
  4. 否则,如果存在前缀参数列表的话,构造参数列表字符串,形如 "[a] [b]",赋值到 prefix
  5. 如果存在参数列表的话,并且需要显示行号(process.env.LOGGER_LINE),则在 prefix 增加 行号,如“4: ”
  6. 调用 log4js 的对应日志函数
  7. 返回

二、行号的支持

行号的正确显示使用了技巧。

  1. 构造一个 Error 类
  2. 将其中的 stack 成员,按照回车拆分字符串,取第四行
  3. 按冒号拆分,取第二个

在 var e = new Error(); 后,打印 Error 的栈,如下:

Error

at getLine (/Users/xxx/pomelo-logger/lib/logger.js:243:10)

at Object.pLogger.(anonymous function) [as info] (/Users/xxx/pomelo-logger/lib/logger.js:39:10)

at Object.<anonymous> (/Users/xxx/pomelo-logger/examples/log.js:4:8)

at Module._compile (module.js:456:26)

at Object.Module._extensions..js (module.js:474:10)

at Module.load (module.js:356:32)

at Function.Module._load (module.js:312:12)

at Function.Module.runMain (module.js:497:10)

at startup (node.js:119:16)

at node.js:906:3

三、颜色的支持

polemo-logger 对前缀、行号使用了与优先级一致的颜色。利用 ASCII 的控制码进行前景颜色的显示。Linux、MacOSX 的控制台支持它。

实现方式是:

  1. 从 log4js 中复制变量 styles,表示当前样式对应的 ASCII 转义
  2. 从 log4js 中复制变量 colours,表示不同优先级对应的样式
  3. 从 log4js 中复制 colorizeStart、colorizeEnd、colorize 函数,它们接收字符串与样式参数,返回处理后的字符串
  4. 由当前的日志优先级,获取到相应的样式,并调用 colorize 来获得带有颜色支持的字符串

四、配置项的取值来源扩展

configure 函数负责进行日志系统的配置(config,文件或对象)及选项(opts)设置。

polemo-logger 在 configure 函数中,对配置项的取值进行了扩展,支持环境变量(process.env)、 命令行参数(process.argv),及可选项(opts)。

当配置项的赋值类型为字符串,并且符合格式 {scope:arg-name} 时,就会触发此扩展。

scope 的有效值:env、args、opts。

arg-name 为其中 key 的名字。

五、ReloadSecs

ReloadSecs 表示自动重新加载配置文件的时间间隔,以秒为单位,为0时不会自动加载。

在 configure 函数中调用了重新加载的初始化函数 initReloadConfiguration,即初始化重新加载功能所需的参数。

并在 initReloadConfiguration 中调用了 setInterval 函数,定期执行重新加载操作 reloadConfiguration。

这个 reloadConfiguration 函数会检查并记录配置文件的最后修改时间,两相比较,不同时才会加载,以确保配置文件每次变化后只被加载一次。

polemo-logger 的 configure 最终还是会调用 log4js 的此函数。

从 configure 函数,直到 reload 相关的各个函数,polemo-logger 对 log4js 所做的修改为:

  • 在 configure 函数中,对配置项的取值来源进行扩展
  • 在 configure 函数中,支持自定义的 lineDebug(行号是否显示)、config.rawMessage(是否不显示前缀及行号)
  • 在 configure 函数中,读取 reloadSecs,并调用 initReloadConfiguration
  • 在 configureOnceOff 函数(reloadConfiguration 所调用的函数,即对具体配置项进行应用和设置的函数)中,去掉了 appenders(如文件 file、控制台 console 等) 的设置

ReloadSecs 从 opts 移动到了 config(配置文件或对象) 中,大概是为了让自动重新加载的时间间隔以配置项的形式存在。

而在重新加载函数中去除了对 appenders 的应用和设置,意图不清楚,或者具体意义有多大也不清楚,代价就是从 log4js 中引入(复制)了6个函数。

六、模块导出 (module.exports)

因为 polemo-logger 是 log4js 的封装,那么它的导出也就是对使用方所期望使用的功能限定。从下表看, polemo-logger 是 log4js 的子集,并进行了小功能改进及限制。

分类 名称 实现位置
Logger getLogger polemo-logger
  getDefaultLogger log4js
配置 configure polemo-logger
Appender addAppender log4js
  loadAppender log4js
  clearAppenders log4js
  appenders log4js
控制台 replaceConsole log4js
  restoreConsole log4js
优先级 levels log4js
  setGlobalLogLevel log4js
布局 layouts log4js

七、综述

我的感觉是,增强部分意义较大,弱化部分中 appender 的去除意义较小,除非 log4js 的相关代码存在着 BUG。

八、参考:

https://github.com/NetEase/pomelo-logger/

https://github.com/nomiddlename/log4js-node/

polemo-logger 分析

时间: 2024-10-14 21:36:45

polemo-logger 分析的相关文章

Wakatime 测试工作时间

Wakatime – 现在几点了,你在做什么呢 前面提到了一个用来QS自己的工具Clarify.这次介绍一个专门给程序员用的工具.大家都知道一万小时定律,但我究竟写java写了多久了呢?WakaTime知道.估计很多人都知道RescueTime,我也是用RescueTime来记录我的工作时间.但它无法记录更具体的行为(也许实际也做了),比如我写了多久javascript,多久objective-C.Waka就可以啦,因为它提供了几个主要的IDE的插件,只需要安装对应的插件,Waka就能自动记录你

大数据技术之_18_大数据离线平台_02_Nginx+Mysql+数据收集+Web 工程 JS/JAVA SDK 讲解+Flume 故障后-如何手动上传 Nginx 日志文件至 HDFS 上

十一.Nginx11.1.介绍11.2.常见其他 Web 服务器11.3.版本11.4.Nginx 安装11.5.目录结构11.6.操作命令十二.Mysql12.1.介绍12.2.关系型数据库(SQL)种类12.3.特征12.4.术语12.4.与非关系型数据库比较(Not Only SQL)12.4.1.种类12.4.2.特征12.4.3.总结十三.数据收集13.1.收集方式13.2.数据的事件类型13.2.1.Launch 事件13.2.2.PageView 事件13.3.Nginx 日志收集

Android日志系统驱动程序Logger源代码分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6595744 我们知道,在Android系统中,提供了一个轻量级的日志系统,这个日志系统是以驱动程序的形式实现在内核空间的,而在用户空间分别提供了Java接口和C/C++接口来使用这个日志系统,取决于你编写的是Android应用程序还是系统组件.在前面的文章浅谈Android系统开发中LOG的使用中,已经简要地介绍了在Android应用程序开发中

log4j.xml 异常: &quot;log4j:configuration&quot; must match &quot;(renderer*,appender*,(category|logger)*......问题分析及解决

使用log4j.xml进行log4j的配置,在项目中报如下异常: log4j:ERROR The content of element type "log4j:configuration" must match "(renderer*,appender*,(category|logger)*,root?,categoryFactory?)". 异常分析: log4j.xml中相关元素的位置不正确 配置文件定位及解决: 经对比,发现项目log4j.xml中"

Logger.getLogger(*.class)源码分析

//补偿:http://blog.csdn.net/anlina_1984/article/details/5313023//方法 protected static Logger logger = Logger.getLogger(PropertiesConfigLocalLoader.class); //进去这个 package org.apache.log4j; public class Logger extends Category { //只列出这个静态方法 static public

Openfire分析之二:主干程序分析

引言 宇宙大爆炸,于是开始了万物生衍,从一个连人渣都还没有的时代,一步步进化到如今的花花世界. 然而沧海桑田,一百多亿年过去了-. 好复杂,但程序就简单多了,main()函数运行,敲个回车,一行Hello World就出来了,所以没事多敲敲回车,可以练手感-. 一.程序入口 Java的程序入口是main方法,Openfire也不例外.可以全局检索一下"void main",可以看到,Openfire的main函数有两个: (1)org.jivesoftware.openfire.lau

c#:ThreadPool实现并行分析,并实现线程同步结束

背景: 一般情况下,经常会遇到一个单线程程序时执行对CPU,MEMORY,IO利用率上不来,且速度慢下问题:那么,怎么解决这些问题呢? 据我个人经验来说有以下两种方式: 1.并行.多线程(Parallel.Task.ThreadPool) 2.多进程MutilpleProcess 恰好工作中又一次遇到单线程程序性能低的问题,本次我主要想尝试使用ThreadPool来实现多线程,并且在实现多线程任务同步结束. 测试代码: 1 static void Main(string[] args) 2 {

kafka producer实例及原理分析

1.前言 首先,描述下应用场景: 假设,公司有一款游戏,需要做行为统计分析,数据的源头来自日志,由于用户行为非常多,导致日志量非常大.将日志数据插入数据库然后再进行分析,已经满足不了.最好的办法是存日志,然后通过对日志的分析,计算出有用的数据.我们采用kafka这种分布式日志系统来实现这一过程. 步骤如下: 搭建KAFKA系统运行环境 如果你还没有搭建起来,可以参考我的博客: http://zhangfengzhe.blog.51cto.com/8855103/1556650 设计数据存储格式

【Spring】DispatcherServlet源码分析

使用过HttpServlet的都应该用过其doGet和doPost方法,接下来看看DispatcherServlet对这两个方法的实现(源码在DispatcherServlet的父类FrameworkServlet中): @Override protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { proce