V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
gratonos
V2EX  ›  分享创造

给!这是不是你想要的 Golang 日志库?

  •  
  •   gratonos · 2019-01-20 17:30:24 +08:00 · 5433 次点击
    这是一个创建于 2169 天前的主题,其中的信息可能已经有所发展或是发生改变。

    一直以来我都没有找到一个称心如意的 Go 日志库,从个人角度看来,有的库功能太过单一,有的库接口使用起来不够顺手,有的库专注的点不在自己需要的点上。(好吧,以上都是自己造轮子的借口。)于是,我结合自己近几年的一些想法和实际需求实现了一个(希望)可以让人眼前一亮的 Go 日志库—— gxlog。gxlog 只依赖于标准库,简洁易用、功能丰富、灵活可扩展是它的设计目标。

    很多人只需要一些常规日志功能,比如:日志分级,日志信息(时间、文件名、行号、消息等)格式化,日志输出到控制台或文件,日志文件按天保存到子目录,日志文件大小到上限时创建新文件等。

    一部分人可能有一些特殊需求,比如:日志格式化为 JSON 等其他格式,日志输出对接 syslog 等后端系统,出错时不仅打印日志还要产生告警事件等。

    gxlog 用比较恰当合理的方式同时满足了上述核心需求和扩展需求:对于核心需求用户,gxlog 使用简单方便;对于扩展需求用户,gxlog 能进行灵活定制和扩展。

    gxlog 采用了插槽式结构,并且对格式化和输出进行了分离。gxlog 内置 8 个槽,每个槽可放置一个 formatter 和一个 writer,也可闲置。另外,gxlog 整体和每个槽都有独立的 level 和 filter。这样,日志格式和输出方式就可以灵活搭配,比如:槽 1 放 text formatter 和 file writer,槽 2 放 json formatter 和 syslog writer,槽 3 放 text formatter 和 file writer,但是 level 设置为 Error,额外单独保存错误日志。

    另外,有需要的用户也可把 event 或 hook 集成进 gxlog,比如:实现一个自定义 formatter,用来发送事件通知,然后把自定义的 formatter 和一个 null writer 放到槽 4,可选地设置槽 4 的 level 或 filter,这样就能在输出日志的同时进行一些额外的操作。

    formatter 方面,gxlog 内置了:

    • text formatter:可进行非常灵活的定制,并提供日志染色功能
    • json formatter:可定制省略字段
    • formatter function wrapper:类似于 http.HandlerFunc

    writer 方面,gxlog 内置了:

    • tcp/unixdomain socket writer:主要目的在于支持使用 netcat 在本机实时查看日志,代替"tail -f",因为日志文件大小超限会创建新文件,用"tail -f"不方便
    • file writer:支持文件分片、按日存放、文件删除检测、压缩、加密
    • syslog writer:支持自定义 level 到 severity 的映射
    • writer function wrapper:类似于 http.HandlerFunc
    • io.Writer wrapper:适配标准库的 Writer 接口
    • async wrapper:适配所有 writer 到异步模式
    • multi-writer wrapper:如果多个 writer 都需要以相同的格式输出,那么可以复合成一个 writer,避免重复格式化

    另外,gxlog 还提供了一些“酷炫”功能:

    • 日志标记:被标记日志以特殊颜色显示,适合调试时加的临时日志,让眼睛更轻松
    • 日志前缀:在不支持转义序列染色的系统上可以用来代替日志标记,只是效果没有那么好
    • 日志上下文:产生一个日志对象,该对象打印的日志都会带上设置的上下文字段
    • 动态上下文:产生一个日志对象,该对象打印的日志都会带上设置的上下文字段的当前值。此功能很适合用于调试,可以经过设置,使得某对象的方法被调用时,所打印的日志都自动带上该对象的所有字段的当前值
    • 日志输出限制:
      • 按数量限制:限制当前文件当前行的日志每 N 条只打印 n 条
      • 按时间限制:限制当前文件当前行的日志每 N 秒最多打印 n 条

    最后,gxlog 还提供了一些方便使用的辅助方法:

    • 计时辅助方法:更方便记录一段代码执行花费的时间
    • 错误辅助方法:出错时打印错误日志的同时返回一个格式化的错误
    • 自动回溯:默认在出现 Fatal 错误时自动打印当前协程堆栈

    项目目前已经有了比较高的完成度,其中有详细的文档和使用示例。_examples 目录下的示例可以"go run"看效果。欢迎大家试用、提建议、做贡献。感觉项目合自己胃口的,请猛击 Star 。 项目地址: https://github.com/gxlog/gxlog

    后面预计会增加一些配套工具,如压缩加密的日志文件的解压解密、为之前未染色的日志增加染色。根据配置文件初始化日志实例的功能目前也在考虑。

    题外话:vim (通过插件)和 emacs (内置命令支持)都是可以解析转义序列表示的颜色的,有需要的不妨也为要写入文件的日志打开染色功能,让眼睛更轻松。

    几张跑示例的截图:

    basic

    auxiliary

    formatters

    5 条回复    2019-01-23 16:19:30 +08:00
    dabaibai
        1
    dabaibai  
       2019-01-21 19:59:47 +08:00
    马克一下
    Comdex
        2
    Comdex  
       2019-01-22 23:16:58 +08:00 via Android
    性能如何?
    gratonos
        3
    gratonos  
    OP
       2019-01-23 10:28:09 +08:00
    gratonos
        4
    gratonos  
    OP
       2019-01-23 10:28:42 +08:00
    简单测试,仅供参考

    硬件:小米 air13
    系统:Win10 上 VirtualBox 虚拟的 Linuxmint18
    Go:go1.11.4
    单条日志:消息负载 120 字节,上下文一对键值,无 mark,无 prefix,无染色,总长度 234 (算上换行)
    写入 /dev/null 性能( go run bench.go 2>/dev/null ):每秒 23-24 万条日志
    写入文件性能( go run bench.go 2> log.txt ):每秒 16-17 万条日志

    不获取运行时(文件、行号等),手动改了实现代码,新版本中会加入 Flag 控制:
    写入 /dev/null 性能:每秒 37-38 万条日志
    写入文件性能:每秒 24-25 万条日志

    参考测试代码:
    package main

    import (
    "fmt"
    "time"

    "github.com/gxlog/gxlog"
    )

    func main() {
    msg := "012345678901234567890123456789012345678901234567890123456789" +
    "012345678901234567890123456789012345678901234567890123456789"
    log := gxlog.Logger().WithContext("k1", "v1")

    now := time.Now()
    for i := 0; i < 200000; i++ {
    log.Trace(msg)
    }
    fmt.Println("costs:", time.Since(now))
    }
    gratonos
        5
    gratonos  
    OP
       2019-01-23 16:19:30 +08:00
    补充一下标准库 log 的性能作为对比

    环境:同上
    Flags:LstdFlags | Llongfile | Lmicroseconds
    单条日志:消息负载 146 字节,总长度 234 (算上换行)
    调用:log.Println
    备注:gxlog 为了支持异步,每条日志都需要分配一个 buf,标准库 log 不支持异步,buf 为 log 对象的一个字段,无需重复分配。
    写入 /dev/null 性能:每秒 36-37 万条日志
    写入文件性能:每秒 24-25 万条日志
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1591 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 16:55 · PVG 00:55 · LAX 08:55 · JFK 11:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.