改进log4go的一些设想
log4go 的 4.0.2 版本(https://github.com/ccpaging/log4go/tree/4.0.2)发布以后,
看了看别的 go 语言日志文件设计。发现了一篇好文:
log4go 和 logrus 的对比与分析
https://www.doraemonext.com/archives/783.html
顺藤摸瓜,找了一窝关于日志的设计。链接如下(含老的链接):
- https://github.com/alecthomas/log4go/
这是log4go项目的“鼻祖” - https://github.com/ngmoco/timber
实现了结构化,写文件缓冲,热配置等。把log4go重构的面目全非 - https://github.com/siddontang/go/tree/master/log
- https://github.com/sirupsen/logrus
- https://github.com/YoungPioneers/blog4go
- https://github.com/YoungPioneers/blog4go-benchmark 各种 go log 的benchmark对比
- https://github.com/cihub/seelog
异步写入日志
log4go 的特点之一是异步写入。格式化日志记录、写入文件、转储日志等,都会消耗 CPU 的时间,并可能因为错误处理而阻塞主线程。
但日志系统仅仅是一个辅助功能,所以,保证主线程的高效运行是首先要达到的设计要求。异步写入是可行的方案之一。
自扩展日志接口
其实,log4go 是支持类似 logrus 的扩展特性的。
正好纠结于 color text term log 的设计如何处理的问题……因为这个功能使用了第三方包。放在log4go里增加了它的依赖性。但这确实又是我特别特别喜欢的一个功能。
不如把 color text term log 做成扩展日志接口。说干就干……
先搞清楚 log4go 中可用的扩展接口:
type LogWriter interface {
LogWrite(rec *LogRecord)
// This should clean up anything lingering about the LogWriter, as it is called before
// the LogWriter is removed. LogWrite should not be called after Close.
Close()
}
type Filter struct {
Level Level
rec chan *LogRecord // write queue
closed bool // true if Socket was closed at API level
LogWriter
}
type Logger map[string]*Filter
func (log Logger) AddFilter(name string, lvl Level, writer LogWriter) Logger {
log[name] = NewFilter(lvl, writer)
return log
}
扩展程序只要做:
NewXXXLogWrite
,初始化扩展要使用的资源。LogWrite(rec *LogRecord)
,输出日志记录- 在
Close()
中关闭或释放资源 - 在应用程序中调用
AddFilter
把新的日志扩展加入到log4go日志结构中
大功告成了。
其中,Add filter name 是 Logger map 的索引关键字,log4go 使用了:
"stdout", "file", "syslog"
如果新加的 Filter 的关键字已存在,log4go(4.0.2以后的版本)将自动关闭原来的,再增加新的。代码如下:
func (log Logger) AddFilter(name string, lvl Level, writer LogWriter) Logger {
if filt, isExist := log[name]; isExist {
filt.Close()
delete(log, name)
}
log[name] = NewFilter(lvl, writer)
return log
}
借助扩展接口,log4go的日志记录可以采用任何你希望的封装格式,例如 xml 和 json,这是已经实现的。
以后还可以扩展csv(使日志文件导入到Excel中)或者json封装的message。
可扩展的日志接口包括:
Send error messages as a mail
Make TCP/UDP server and let client pull the messages
websocket
nanomsg pub/sub
Store log messages in MySQL
自扩展日志配置接口
log4go 4.0.2 支持 xml 和 json 配置。日志文件的配置有三种方式:
- 在应用程序中配置
- 单独的配置文件
- 存于主程序配置文件中
日志系统作为一个辅助功能,常常面临的是第三种情况。而配置文件的格式多种多样。例如:
windows ini, linux config, json, xml ...
郁闷。log4go 不应当去支持所有的配置文件格式,而是提供接口,让用户可以根据自己的主程序的设计需要,自行扩展。
也许应该把 xml 和 json 配置文件支持都以扩展配置文件接口的方式实现,而不是跟 log4go 的主程序捆绑在一起。
文件日志的写缓冲
已经测试了两层缓冲写文件。
第一层是格式化日志记录,一个单独的go routine,另一个写文件,边格式化记录边写文件,消耗降低了40%。
第二层是用bufio。达到一定的缓冲数量如4k、8k,一次写文件。消耗降低了80%。
通过判断Channel中的记录长度来决定系统何时空闲。当长度为0时,后续没有新的日志记录,做一次Flush()。
这种方案简单。
另外加上 rotate 的优化,效率提高了5倍。
BenchmarkFileLog-4 200000 10675 ns/op
BenchmarkFileNotLogged-4 20000000 106 ns/op
BenchmarkFileUtilLog-4 200000 10660 ns/op
BenchmarkFileUtilNotLog-4 5000000 239 ns/op
BenchmarkCacheFileLog-4 1000000 2191 ns/op
BenchmarkCacheFileNotLogged-4 20000000 106 ns/op
BenchmarkCacheFileUtilLog-4 500000 3680 ns/op
BenchmarkCacheFileUtilNotLog-4 5000000 240 ns/op
Rotate 的改进设想
log4go 自带 rotate。
linux 系统本来是有 logrotate 的,用 cron 定时执行。非常棒的设计。
简单说,就是写日志文件归写日志文件,不要去做任何转储的判断。程序员可根据系统的实际运行情况,
自行设置转储的时间间隔。转储时:
加锁。使 log4go 暂时停止写日志,这可能是在 linux 系统中 log4go 没有使用 logrotate 的原因之一。
对当前日志文件进行处理。
解锁。尽快恢复 log4go,继续写日志到当前日志文件。
另开 go routine 对历史日志文件进行处理。
好吧。暂时就想到这么多了。很多有趣的工作正在进行……
再次感谢 doraemonext@gmail.com 童鞋的好文:log4go 和 logrus 的对比与分析
请关注:
https://github.com/ccpaging/log4go
改进log4go的一些设想的更多相关文章
- 团队作业7---Alpha冲刺值事后诸葛
一.设想和目标 1.我们的软件要解决什么问题? 解决教师和助教对实验报告查重的问题,拥有两个用户:1.教师或助教:查看学生实验报告的重复率:4.学生:上传实验报告. 2.是否定义得很清楚?是否对典型用 ...
- [软工顶级理解组] Beta阶段事后分析
目录 设想和目标 计划 资源 变更管理 设计/实现 测试/发布 团队的角色,管理,合作 总结 质量提高 会议截图 设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰 ...
- log4go的一些改进设想
log4go 的 4.0.2 版本(https://github.com/ccpaging/log4go/tree/4.0.2)发布以后, 看了看别的 go 语言日志文件设计.发现了一篇好文: log ...
- log4go的日志滚动处理——适应生产环境的需要
日志处理有三类使用环境,开发环境DE,测试环境TE,生产环境PE. 前两类可以看成是一类,重要的是屏幕显示--termlog.生产环境中主要用的是socklog 和 filelog,即网络传输日志和文 ...
- log4go的日志滚动处理——生产环境的适配
日志处理有三类使用环境,开发环境DE,测试环境TE,生产环境PE. 前两类可以看成是一类,重要的是屏幕显示--termlog.生产环境中主要用的是socklog 和 filelog,即网络传输日志和文 ...
- homework_06 围棋程序改进
1) 把程序编译通过, 跑起来. 读懂程序,在你觉得比较难懂的地方加上一些注释,这样大家就能比较容易地了解这些程序在干什么. 把正确的 playPrev(GoMove) 的方法给实现了. 注释见Git ...
- 企业级应用架构(三)三层架构之数据访问层的改进以及测试DOM的发布
在上一篇我们在宏观概要上对DAL层进行了封装与抽象.我们的目的主要有两个:第一,解除BLL层对DAL层的依赖,这一点我们通过定义接口做到了:第二,使我们的DAL层能够支持一切数据访问技术,如Ado.n ...
- 数据访问层的改进以及测试DOM的发布
数据访问层的改进以及测试DOM的发布 在上一篇我们在宏观概要上对DAL层进行了封装与抽象.我们的目的主要有两个:第一,解除BLL层对DAL层的依赖,这一点我们通过定义接口做到了:第二,使我们的DAL层 ...
- log4go的全局封装Wrapper和标准log库函数的兼容
方便易用的全局函数 大多数时候,只不过是写一个简单的测试程序.例如: package main import ( "log" ) func main(){ log.Fatal(&q ...
随机推荐
- 目前微信 微博 新浪 豆瓣等所有分享的js插件
原理 功能 集成微信.微博.开心.豆瓣.人人.qq微博.搜狐.qq空间等分享 即时分享: 默认加载插件,即启动全部分享 定制分享:通过参数配置.静态数据配置 由你决定何时分享,如何分享 扩展: 通过数 ...
- css3中强大的filter(滤镜)属性
CSS3中强大的filter(滤镜)属性 博主最近在做网站的过程中发现了一个非常强大的CSS3属性,就是filter(滤镜)属性,喜欢p图的朋友看名字都应该知道这是什么神器了吧.当然,这个属性的效果肯 ...
- Ch2. Loop Structure
Ex Input some integers and output their min, max and average values (keep three decimal places). It ...
- HTML中那些不常用标签
先思考一个问题:为什么H5里面又多了那么多看似没用的标签? 我们知道,<div>能干百分之99的标签能干的事,而标签的主要作用是用来包裹内容,只要把基本内容都包含进去不就好了??胡闹!不带 ...
- 关于前后端同构,我的一点思路和心得(vue、nodejs、react、模版、amd)
最近1年多,前后端同构慢慢变成一个流行词,也许很多人还停留在前后端分离的最佳实践道路上,但实际上又有一批人已经从简单的服务端渲染走向探索最佳前后端同构方案的路上了.不过,我只是膜拜后者的过客. 虽然大 ...
- nginx之 nginx + tomcat + redis 负载均衡且session一致性
说明: 本文描述的是 nginx + tomcat + redis 实现应用负载均衡且满足session一致性,从安装到配置的全部过程,供大家学习!nginx 代理服务器ip: 10.219.24.2 ...
- Centos常用命令及解释
ps -ef|grep java ps:将某个进程显示出来-A 显示所有程序. -e 此参数的效果和指定"A"参数相同.-f 显示UID,PPIP,C与STIME栏位. grep命 ...
- C# 计时器写法
刚才一个交流群里有人问计时器怎么写,正好我也不太熟,就写了个demo,和大家分享一下这个是参考师傅的写的! 计时器有好多种写法,这里给大家推荐一个性能比较好的,用dispatchertimer ...
- WCF入门的了解准备工作
了解WCF, 及WCF入门需要掌握哪里基本概念? 1.准备工作 >1.1 . XML >1.2 . Web Service >1.3 . 远程处理 (RPC) >1.4. 消 ...
- Jenkin-持续集成
1.Jenkins安装 本文将会介绍如何在windows 中安装Jenkins,并且使用Jenkins进行项目的构建. 首先我们进入到Jenkins 的官网下载地址:https://jenkins.i ...