在Go语言中记录log:seelog包

前两周调bug调的吐血,虽然解决了但是还是挺浪费时间的。跟同事聊了聊,觉得我们现在项目中的日志记录太少了,导致出了问题不知道怎么下手,还得自己改代码记录日志,然后排查问题。这样如果将来还有bug的话还得这么调,很麻烦,让我深入看一下go语言中如何记录日志(好吧我最近就跟日志耗上了)。

根据python的经验和目前项目中的要求,我对日志的要求有两个:

一是定义日志级别,可以记录debug/warning/error之类的不同级别的日志,这样的话,在通常正常运行的时候,就只需要记录一下运行状态,而报错需要调试的时候,可以显示的日志多一些;

二是定义日志格式,想要记录什么内容,比如时间、级别、位置、日志信息等等。于是,简单的看了一下Go自带的log模块,就知道根本达不到我的要求。

在网上查了一下现在比较流行的日志记录方法,看到有人推荐seelog,于是尝试一下。中了几个小坑,不过还算顺利,写起来也比较流畅。记录一下。

seelog官网:https://github.com/cihub/seelog

安装seelog

在命令行下

go get -u github.com/cihub/seelog

这里我踩了第一个坑——因为对go语言还不太熟,没有装git。去百度一下,装个git,回来发现还是不行,因为windows下git不会自动配置环境变量。需要在path中添加bin路径和git-core路径。如果是默认安装,一般就是添加

;C:\Program Files\Git\bin;C:\Program Files\Git\mingw64\libexec\git-core

需要注意一下windows是32位还是64位的(linux下就没这么多事了,直接apt-get install git完事)

之后敲个命令git试试,有这个命令了就是环境变量配置好了。再次go get安装seelog十分顺利就装好了。

使用seelog

安装好了之后就可以试试看了。跟python和java的logging不同的是,seelog是需要一个xml配置文件的,里面设置log输出的路径,等级,格式等。一个典型的配置文件是长成酱婶的:

<seelog type="asynctimer" asyncinterval="5000000" minlevel="debug" maxlevel="error">
    <exceptions>
        <exception funcpattern="*main.test*Something*" minlevel="info"/>
        <exception filepattern="*main.go" minlevel="error"/>
    </exceptions>
    <outputs formatid="main">
        <console/>

        <splitter formatid="format1">
            <file path="log.log"/>
            <file path="log2.log"/>
        </splitter>
        <splitter formatid="format2">
            <file path="log3.log"/>
            <file path="log4.log"/>
        </splitter>

        <rollingfile formatid="someformat" type="size" filename="./log/roll.log" maxsize="100" maxrolls="5" />

        <buffered formatid="testlevels" size="10000" flushperiod="1000">
            <file path="./log/bufFileFlush.log"/>
        </buffered>

        <filter levels="error">
            <file path="./log/error.log"/>
            <smtp senderaddress="[email protected]"
                  sendername="Automatic notification service"
                  hostname="mail.none.org"
                  hostport="587"
                  username="nns"
                  password="123">
                <recipient address="[email protected]"/>
                <recipient address="[email protected]"/>
            </smtp>
            <conn net="tcp4" addr="server.address:5514" tls="true" insecureskipverify="true" />
        </filter>

    </outputs>
    <formats>
        <format id="main" format="%Date(2006 Jan 02/3:04:05.000000000 PM MST) [%Level] %Msg%n"/>
        <format id="someformat" format="%Ns [%Level] %Msg%n"/>
        <format id="testlevels" format="%Level %Lev %LEVEL %LEV %l %Msg%n"/>
        <format id="usetags" format="&lt;msg&gt;%Msg&lt;/time&gt;"/>
        <format id="format1" format="%Date/%Time [%LEV] %Msg%n"/>
        <format id="format2" format="%File %FullPath %RelFile %Msg%n"/>
    </formats>
</seelog>

此xml见:https://github.com/cihub/seelog/wiki/Example-config

别问我这虾米,我也只能看懂一部分。目前我只知道最简单的几个节点的用法,满足我的需求的。对于我来说,下面这样一个xml就基本够用了:

(这里我用-->这符号假装注释,xml本身没有注释)

<seelog>
    <outputs formatid="main">   -->去找id为main的格式
        <filter levels="info,debug,critical,error">    -->定义记录格式
            <console />    -->向屏幕输出
        </filter>
        <filter levels="debug">
            <file path="debug.txt" />    -->向文件输出。可以多个共存。
        </filter>
    </outputs>
    <formats>
        <format id="main" format="%Date/%Time [%LEV] %Msg%n"/>    -->format内容,可以多个共存,只要id不相同。然后上面可以用不同的id来输出不同格式的日志。
    </formats>
</seelog>

OK。写好xml之后可以码代码了。写个简单的例子:

// TestSeelog.go
package main

import (
    seelog "github.com/cihub/seelog"
)

func main() {
    logger, err := seelog.LoggerFromConfigAsFile("seelog.xml")

    if err != nil {
        seelog.Critical("err parsing config log file", err)
        return
    }
    seelog.ReplaceLogger(logger)

    seelog.Error("seelog error")
    seelog.Info("seelog info")
    seelog.Debug("seelog debug")
}

(呃。。博客园没有Golang的代码颜色,就这样吧,反正不耽误看)

写完运行。一个好消息和一个坏消息。好消息是没有问题正常运行结束了。坏消息是特么的没有出来日志。屏幕和日志文件都没有。卧槽我日志呢?你给我藏哪去了?

来来回回检查了十来遍没找到原因,于是去QQ群里问了一下,感谢 吴迎松 和 溺水的鱼 两位同学的解答:没有来得及运行就结束了,并且没有flush。于是在seelog记录日志内容之前加了一句

defer seelog.Flush()

之后就可以出结果了。

2015-12-17/16:28:23 [ERR] seelog error
2015-12-17/16:28:23 [INF] seelog info
2015-12-17/16:28:23 [DBG] seelog debug

至此。seelog第一步算是踏出来了。看看seelog里面还有很多的函数,还有配置文件里那堆我不明白的属性,还有github上的文档,我觉得,这个库还有更多值得深入挖掘的地方。以后有空再看。

时间: 2024-08-28 20:38:49

在Go语言中记录log:seelog包的相关文章

Android JNI中记录log

Android JNI中是有提供相关的接口来记录log的,这样的话,和java写的代码一样,可以直接在logcat中查看.如果代码里都是android提供的log api,一旦遇到新的需求,改起来会很麻烦,每个地方都需要修改,所以说封装android提供的log api是很有必要的. android提供的常用api __android_log_write(ANDROID_LOG_INFO, "tag here", "message here"); __android

Python的logging,记录log的包

最近在做自动化测试时,想给他加上日志,所以用到logging的模块,以下是python增加log的几种方式 一.python代码配置方式(当然还有一种是可以多模块通用的一个python代码设置,这个网上有很多例子,就不在这里赘述了) import loggingimport logging.handlers #LOG_FILE 是要输出的日志的文件地址 LOG_FILE=r"C:\Users\min.sun\Desktop\自动化测试\log.txt" handler = loggin

在Java语言中调用存储过程、存储函数、包头、包体

需要拷贝连接Oracle的jar包,路径如下图所示: 连接Oracle数据库的代码: package demo.utils; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class JDBCUtils { private static Stri

R中常用数据挖掘算法包

数据挖掘主要分为4类,即预测.分类.聚类和关联,根据不同的挖掘目的选择相应的算法.下面对R语言中常用的数据挖掘包做一个汇总: 连续因变量的预测: stats包 lm函数,实现多元线性回归 stats包 glm函数,实现广义线性回归 stats包 nls函数,实现非线性最小二乘回归 rpart包 rpart函数,基于CART算法的分类回归树模型 RWeka包 M5P函数,模型树算法,集线性回归和CART算法的优点 adabag包 bagging函数,基于rpart算法的集成算法 adabag包 b

Lua语言基础汇总(11) -- Lua中的模块与包

前言 从Lua5.1版本开始,就对模块和包添加了新的支持,可是使用require和module来定义和使用模块和包.require用于使用模块,module用于创建模块.简单的说,一个模块就是一个程序库,可以通过require来加载.然后便得到了一个全局变量,表示一个table.这个table就像是一个命名空间,其内容就是模块中导出的所有东西,比如函数和常量,一个符合规范的模块还应使require返回这个table.现在就来具体的总结一下require和module这两个函数. require函

sqlite学习笔记11:C语言中使用sqlite之删除记录

最后一节,这里记录下如何删除数据. 前面所有的代码都继承在这里了,在Ubuntu14.04和Mac10.9上亲测通过. #include <stdio.h> #include <stdlib.h> #include "sqlite/sqlite3.h" #define DB_NANE "sqlite/test.db" sqlite3 *db = NULL; char* sql = NULL; char *zErrMsg = NULL; con

C语言中从大到小的顺序排列《学习记录》

一.前言 终于走到了指针,走到了翘首期盼的指针.指针是c语言中一个重要的概念,也是c语言最精彩的部分.正确而灵活的运用它,可以是程序简洁.紧凑.高效,每一个学习c语言的小伙伴都应该深入的学习和掌握指针. 本节目标 指针是什么 指针变量 通过指针引用数组 通过指针引用字符串 二.指针是什么 为了了解指针的概念,我们先来看一个小故事. 话说福尔摩斯派华生到威尔爵士居住的城堡去取回一个重要的数据.白天,在书房里,威尔爵士当着福尔摩斯和华生的面亲自将数据锁在了书柜中编号为3010的抽屉,用手电筒一照,只

在nginx日志的access log中记录post请求的参数值

背景:有时程序偶出现参数少了或没有提交到下一个链接Url里后出现问题,如何查呢,最好的办法是在nginx上的加post参数,以定位到问题才有可能对某个UIR的代码出现的问题进行排查. og_format access '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent $request_body "$http_referer" "$http_user_

Golang中使用log(二):Golang 标准库log的实现

前一篇文章我们看到了Golang标准库中log模块的使用,那么它是如何实现的呢?下面我从log.Logger开始逐步分析其实现. 其源码可以参考官方地址 1.Logger结构 首先来看下类型Logger的定义: type Logger struct { mu sync.Mutex // ensures atomic writes; protects the following fields prefix string // prefix to write at beginning of each