GO的日志库log竟然这么简单!
前言
最近在尝试阅读字节开源RPC框架Kitex的源码,看到日志库klog
部分,果不其然在Go原生的log库
的基础上增加了自己的设计,大体包括增加了一些格式化的输出、增加一些常用的日志级别等。
一番了解后,发现有不少开源的日志库也做了类似的事情,以补充原生log库
的不足。因为Go原生的log库
本身也比较简单,这篇文章先分析一下它的实现,为后续阅读Kitex的日志库klog
做一下铺垫。
本次分析基于:GO SDK 1.18.1 /src/log/log.go
的源码。
log库的使用
结果如下:
第三个日志因为第二个日志打印之后,调用panic()
函数,且没有调用recover()
,导致程序终止。如果注释掉第二行日志即可打印出第三个日志的结果如下:
log.xxx能直接打印日志的原因
通过观察源码,log包
的log.go
文件中,提供了9个函数可以直接使用,3个一套,分别针对print型
日志输出、panic型
日志输出(可以recover
)、fatal型
日志输出(直接终止程序)。
并且这9个函数中频繁使用到了一个std实例
,只要我们引入了log包
,std
就会完成初始化,并且作为默认使用的log
实例。
Logger结构
既然std
是默认的Logger实例
,这里先看一下Logger
的结构:
mu
:互斥锁,用于原子写入操作。prefix
:日志前缀/后缀。flag
:控制需要展示的日志内容。out
:描述输出。buf
:缓冲区。
关于flag
的使用,Go定义了如下的常量:
iota
是常量计数器,从0开始自增,可以配合表达式使用,且在一系列常量声明时,可以只指定第一个位置,后续会默认初始化,这里依次初始化为1、2、4...
Ldata
:输出当地日期,如2009/01/23。
Ltime
:输出当地时间,如01:23:23。
Lmicroseconds
:时间精确到微妙,如01:23:23.123123
,兼并Ltime。
Llongfile
:输出文件名全路径 + 调用行号,如/a/b/c/d.go:23。
Lshortfile
:输出最终文件的名称 + 调用行号,如d.go:23
,覆盖Llongfile
。LUTC
:如果设置了Ldata
和Ltime
,则将输出UTC
时间,而不是本地时区。Lmsgprefix
:将prefix信息
从当前日志行首部移动到message
之前。LstdFlags
:std实例
的默认值,表示Ldata | Ltime = 3
。
官方的注释中给出了一些介绍flag用法的例子,这里介绍一个:
如果:std.flag == Ldate | Ltime | Lmicroseconds | Llongfile == 15
,
则日志行输出结果为:2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
,message
为具体的日志内容。
std.Output()
回到上面9个函数打印日志,都通过调用std.Output()
实现日志的输出,是log库
的核心函数,看一下代码:
- 通过
l.mu.Lock()
,确保日志内容的写入是原子的。
- 检查
l.flag
是否包括Lshortfile
或者Llongfile
标志位,如果有则需要获取文件名
和行数
,且这一步先释放了锁,因为Caller方法
的调用比较耗时(expensive),确保锁住的临界区尽可能小。 calldepth
:0表示获取调用runtime.Caller(calldepth)
的文件名和行数,1表示调用std.Output()
的文件名和函数,2表示调用log.Println()
的文件名和行数,3则已经用不到了,Go原生log库获取行信息用的都是2。
- 清空缓冲区
l.buf
,并格式化日志头部信息(日期、文件名、行数),将其append
入`buf。 - 最后将具体的
日志信息s
添加入buf
,会补全末尾换行符,并调用l.out.Write()
,将日志写入事先注册的输出文件。
定制自己的Logger
log库默认使用的std实例是事先初始化好的,那么借助New方法,我们也可以定制自己的logger:
这里指定了日志输出到文件log.txt中,并且定义了一些flag,结果如下:
小结
通过分析,我们发现log是一个很简洁的日志库,它有三种日志输出方式print
、panic
、fatal
,且可以自己定制日志的输出格式。但是熟悉其他语言开发的同学可能会对日志级别有更多的需求,且log
的格式化用起来比较复杂。
因此会衍生出很多基于log
的二次封装的日志库,下一篇文章将讲解字节跳动RPC框架Kitex的日志库klog
的实现。
GO的日志库log竟然这么简单!的更多相关文章
- 字节开源RPC框架Kitex的日志库klog源码解读
前言 这篇文章将着重于分析字节跳动开源的RPC框架Kitex的日志库klog的源码,通过对比Go原生日志库log的实现,探究其作出的改进. 为了平滑学习曲线,我写下了这篇分析Go原生log库的文章,希 ...
- easylog -- Linux 下的简单日志库
之前使用 log4c 或者 log4cpp 的时候, 总需要配置一些文件和链接库之类复杂的配置. 虽然越复杂越说明这个软件支持的功能多.可选择性强, 但是对于一个小的项目,或者要研究他人的代码而加点儿 ...
- C/C++log日志库比较
事实上,在C的世界里面没有特别好的日志函数库(就像Java里面的的log4j,或者C++的log4cxx).C程序员都喜欢用自己的轮子.printf就是个挺好的轮子,但没办法通过配置改变日志的格式或者 ...
- SQLServer某个库log日志过大,无法收缩日志文件 ,因为该文件结尾的逻辑日志文件正在使用
问题描述: 今天看到user库日志备份方面很久,然后查看到user库这个log日志很大 图片是我已经解决了,然后现在可以收缩的大小 解决方法: 1.先备份user库日志,因为很大,所以要等很久,这个只 ...
- C++ 日志库 boost::log 以及 glog 的对比
日志能方便地诊断程序原因.统计程序运行数据,是大型软件系统必不可少的组件之一.本文将从设计上和功能上对比 C++ 语言常见的两款日志库: boost::log 和 google-glog . 设计 b ...
- 爆料喽!!!开源日志库Logger的剖析分析
导读 Logger类提供了多种方法来处理日志活动.上一篇介绍了开源日志库Logger的使用,今天我主要来分析Logger实现的原理. 库的整体架构图 详细剖析 我们从使用的角度来对Logger库抽茧剥 ...
- 爆料喽!!!开源日志库Logger的使用秘籍
日志对于开发来说是非常重要的,不管是调试数据查看.bug问题追踪定位.数据信息收集统计,日常工作运行维护等等,都大量的使用到.今天介绍著名开源日志库Logger的使用,库的地址:https://git ...
- GitHub开源库排名一百的简单介绍,值得收藏!
GitHub Android Libraries Top 100 简介 本项目主要对目前 GitHub 上排名前 100 的 Android 开源库进行简单的介绍, 至于排名完全是根据 GitHub ...
- 开源日志库log4cplus+VS2008使用
一.简介 log4cplus是C++编写的开源的日志系统,功能非常全面.本文介绍如何在Windows+VS2008中使用该日志库. 二.下载 可从网站[url]http://log ...
随机推荐
- C#编写一个控制台应用程序,输入三角形或者长方形边长,计算其周长和面积并输出
编写一个控制台应用程序,输入三角形或者长方形边长,计算其周长和面积并输出. 代码: using System; using System.Collections.Generic; using Syst ...
- java中操作符的用法
5.操作符 public class Test{ public static void main(String[] args){ int i, k; i = 10; /*下面 ...
- 从零搭建react开发环境
早在六年前,前端开发已经实现了模块化.工程化开发,既然是模块化工程化开发那就少不了包管理工具,所以我们的第一步就是先从安装nodejs开始(安装nodejs携带JavaScript的包管理工具npm) ...
- clone github代码库很慢,如何提速
博主,最近在搭建hyperledger fabric的环境,其中有一步就是clone github上的代码,但是在过程中发现clone是真的慢. 为此google了一圈,发一现一个好用的办法: 1.登 ...
- 服务器的cpu 核心、线程
此版本有大范围改动,因为cpu作为一个大脑,所以更细致的进行了,相关的分析和阐述. 1.版本1. 2022.1.242.版本2: 2022.3.2 采集数据: ht2机器为物理机,cpu是4颗cpu, ...
- javap命令反编译
javap命令反编译生成的是程序员可以认识的字节码文件 -help --help -? 输出此用法消息 -version 版本信息,其实是当前javap所在jdk的版本信息,不是class在哪个jdk ...
- Unity中制作血条2.0
##1.血量显示 不必像之前那样添加Slider组件 直接创建Image 在添加Source Image之后,将Image Type 修改为Filled 通过修改Fill Mode就可以显示不同效果 ...
- 2019-2020 10th BSUIR Open Programming Championship. Semifinal
2019-2020 10th BSUIR Open Programming Championship. Semifinal GYM链接https://codeforces.com/gym/103637 ...
- MySQL学习day3随笔
索引在数据量不大的时候体现不出来,数据很多的时候区别明显 1 select * from app_user where `name`='用户9999';-- 0.053 sec 2 select * ...
- 认识 vh 和 vw 单位
1. 页面 html 结构 <header> <h1>欢迎来到米修在线</h1> <p>Lorem ipsum dolor sit amet conse ...