最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【记录】go语言中通过log4go实现同时输出log信息到log文件和console

GO crifan 6889浏览 0评论

【背景】

折腾:

【已解决】go语言中实现log信息同时输出到文件和控制台(命令行)

期间,已经通过io的MultiWriter搞定了同时输出信息到文件和console,但是不支持level。

所以,再去试试这个log4go。

http://code.google.com/p/log4go/

 

【折腾过程】

1.大概看了看,貌似功能很强大。

有点类似于之前的C#的NLog,为C#的log功能扩展;

此处log4go,是针对go语言的log功能的扩展。

2.此log4go,是go语言的第三方的包,所以,先要去搞懂:

【记录】go语言中安装第三方包package(库):log4go

3.安装完毕后,再去参考官网的:

http://code.google.com/p/log4go/wiki/GettingStarted

去看看如何使用。

4.先去导入:

//import l4g "log4go.googlecode.com/hg"
import l4g "code.google.com/p/log4go"

结果是:

E:\Dev_Root\go\src\EmulateLoginBaidu>go run EmulateLoginBaidu.go
# command-line-arguments
.\EmulateLoginBaidu.go:34: imported and not used: "code.google.com/p/log4go"

这说明:

正确导入了(但只是暂时还没去使用而已)

5.接着去使用。

用如下代码:

//do some init for crifanLib
func initCrifanLib(){
    l4g.Info("init for crifanLib")
    //gLogger.Println("init for crifanLib");
    gCurCookies = nil
    return
}

//init for logger
func initLogger(){
    l4g.Debug("in initLogger")

效果是:

log4c debug and info output in console

6.看到其解释了:

上述用的,是默认的,已经实现了的,对于console的log

默认配置为:DEBUG的level:debug及以上的level都显示。

所有的level,依次是:Finest, Fine, Debug, Trace, Info, Warning, Error, Critical

而此处,我想要实现:

(1)重新更改此console的level为Info

(2)添加此处的log文件作为输出,且设置level所有,即最低一级的Finest

7.先去添加log文件:

但是想要去看对应的文档的,结果原先作者的说明:

先去:

godoc -http=:6060

(我此处实际上本身已经打开godoc的server了)

再去打开地址:

http://localhost:6060/pkg/log4go.googlecode.com/svn/stable/

结果肯定不对的。

后来经过自己的分析,去访问:

http://localhost:6060/pkg/code.google.com/p/log4go/

就可以了。

8.去看看对应的:

http://localhost:6060/pkg/code.google.com/p/log4go/#AddFilter

内容是:

func AddFilter

func AddFilter(name string, lvl level, writer LogWriter)

Wrapper for (*Logger).AddFilter

去试试代码。

结果基本实现了所要的效果:

console only show info

log file can also show debug

即:

对于代码中debug信息,只在文件中显示

对于info及以上的信息,console和文件,都显示。

实现了level的自定义。

9.目前,唯一一个小问题,不是我喜欢的:

对于,我经常调试程序,

希望每次重新运行时,对于log文件,都自动清空。

而不要对于log文件是APPEND模式:

每次的输出,都添加到后面。

而不清空log文件。

10.所以,再去想办法,新建log时,判断是否已经存在文件,如果存在去删除掉:

【已解决】go语言中判断文件是否存在如果有已存在则删除

 

【总结】

最终,基本实现了全部的效果:

1.每次运行程序,可以OVERWRITE旧的log文件,而不是APPEND

2.可以同时输出内容到log文件和console

3.且console和log文件的输出level都可以配置:

此处要的是:

INFO及以上的,都可以在console中显示;

全部信息(包括debug),都可以在log文件中显示。

全部代码如下:

/*
 * [File]
 * EmulateLoginBaidu.go
 * 
 * [Function]
 * 【记录】用go语言实现模拟登陆百度
 * https://www.crifan.com/emulate_login_baidu_using_go_language/
 * 
 * [Version]
 * 2013-09-19
 *
 * [Contact]
 * https://www.crifan.com/about/me/
 */
package main

import (
    //"fmt"
    //"builtin"
    //"log"
    "os"
    "runtime"
    "path"
    "strings"
    //"io"
    "time"
    "io/ioutil"
    "net/http"
    //"net/http/cookiejar"
    //"sync"
    //"net/url"
)

//import l4g "log4go.googlecode.com/hg"
//import l4g "code.google.com/p/log4go"
import "code.google.com/p/log4go"

/***************************************************************************************************
    Global Variables
***************************************************************************************************/
var gCurCookies []*http.Cookie;
//var gLogger *log.Logger;
var gLogger log4go.Logger;

/***************************************************************************************************
    Functions
***************************************************************************************************/
//do init before all others
func initAll(){
    gCurCookies = nil
    gLogger = nil
    
    initLogger()
    initCrifanLib()
}

//de-init for all
func deinitAll(){
    gCurCookies = nil
    if(nil == gLogger) {
        gLogger.Close();
        gLogger = nil
    }
}

//do some init for crifanLib
func initCrifanLib(){
    gLogger.Debug("init for crifanLib")
    gCurCookies = nil
    return
}

//init for logger
func initLogger(){
    var filenameOnly string
    filenameOnly = GetCurFilename()
    var logFilename string =  filenameOnly + ".log";
    
    //gLogger = log4go.NewLogger()
    gLogger = make(log4go.Logger)
    //for console
    //gLogger.AddFilter("stdout", log4go.INFO, log4go.NewConsoleLogWriter())
    gLogger.AddFilter("stdout", log4go.INFO, log4go.NewConsoleLogWriter())
    //for log file
    if _, err := os.Stat(logFilename); err == nil {
        //fmt.Printf("found old log file %s, now remove it\n", logFilename)
        os.Remove(logFilename)
    }
    //gLogger.AddFilter("logfile", log4go.FINEST, log4go.NewFileLogWriter(logFilename, true))
    gLogger.AddFilter("logfile", log4go.FINEST, log4go.NewFileLogWriter(logFilename, false))
    gLogger.Info("Current time is : %s", time.Now().Format("15:04:05 MST 2006/01/02"))

    return
}

// GetCurFilename
// Get current file name, without suffix
func GetCurFilename() string {
    _, fulleFilename, _, _ := runtime.Caller(0)
    //fmt.Println(fulleFilename)
    var filenameWithSuffix string
    filenameWithSuffix = path.Base(fulleFilename)
    //fmt.Println("filenameWithSuffix=", filenameWithSuffix)
    var fileSuffix string
    fileSuffix = path.Ext(filenameWithSuffix)
    //fmt.Println("fileSuffix=", fileSuffix)
    
    var filenameOnly string
    filenameOnly = strings.TrimSuffix(filenameWithSuffix, fileSuffix)
    //fmt.Println("filenameOnly=", filenameOnly)
    
    return filenameOnly
}

//get url response html
func GetUrlRespHtml(url string) string{
    gLogger.Debug("GetUrlRespHtml, url=%s", url)
    var respHtml string = "";
    
    resp, err := http.Get(url)
    if err != nil {
        gLogger.Warn("http get url=%s response errror=%s\n", url, err)
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    //gLogger.Debug("body=%s\n", body)

    gCurCookies = resp.Cookies()
    
    respHtml = string(body)

    return respHtml
}

func printCurCookies() {
    var cookieNum int = len(gCurCookies);
    gLogger.Info("cookieNum=%d", cookieNum)
    for i := 0; i < cookieNum; i++ {
        var curCk *http.Cookie = gCurCookies[i];
        //gLogger.Info("curCk.Raw=%s", curCk.Raw)
        gLogger.Info("------ Cookie [%d]------", i)
        gLogger.Info("Name\t=%s", curCk.Name)
        gLogger.Info("Value\t=%s", curCk.Value)
        gLogger.Info("Path\t=%s", curCk.Path)
        gLogger.Info("Domain\t=%s", curCk.Domain)
        gLogger.Info("Expires\t=%s", curCk.Expires)
        gLogger.Info("RawExpires=%s", curCk.RawExpires)
        gLogger.Info("MaxAge\t=%d", curCk.MaxAge)
        gLogger.Info("Secure\t=%t", curCk.Secure)
        gLogger.Info("HttpOnly=%t", curCk.HttpOnly)
        gLogger.Info("Raw\t=%s", curCk.Raw)
        gLogger.Info("Unparsed=%s", curCk.Unparsed)
    }
}

func main() {
    initAll()

    gLogger.Info("this is EmulateLoginBaidu.go")

    var baiduMainUrl string
    baiduMainUrl = "http://www.baidu.com/";
    //baiduMainUrl := "http://www.baidu.com/";
    //var baiduMainUrl string = "http://www.baidu.com/";
    gLogger.Info("baiduMainUrl=%s", baiduMainUrl)
    respHtml := GetUrlRespHtml(baiduMainUrl)
    gLogger.Debug("respHtml=%s", respHtml)
    printCurCookies()
    
    deinitAll()
}

效果是:

 

console中输出的内容:

E:\Dev_Root\go\src\EmulateLoginBaidu>go run EmulateLoginBaidu.go
[09/20/13 18:39:40] [INFO] Current time is : 18:39:40 +0800 2013/09/20
[09/20/13 18:39:40] [INFO] this is EmulateLoginBaidu.go
[09/20/13 18:39:40] [INFO] baiduMainUrl=http://www.baidu.com/
[09/20/13 18:39:40] [INFO] cookieNum=3
[09/20/13 18:39:40] [INFO] ------ Cookie [0]------
[09/20/13 18:39:40] [INFO] Name =BDSVRTM
[09/20/13 18:39:40] [INFO] Value        =3
[09/20/13 18:39:40] [INFO] Path =/
[09/20/13 18:39:40] [INFO] Domain       =
[09/20/13 18:39:40] [INFO] Expires      =0001-01-01 00:00:00 +0000 UTC
[09/20/13 18:39:40] [INFO] RawExpires=
[09/20/13 18:39:40] [INFO] MaxAge       =0
[09/20/13 18:39:40] [INFO] Secure       =false
[09/20/13 18:39:40] [INFO] HttpOnly=false
[09/20/13 18:39:40] [INFO] Raw  =BDSVRTM=3; path=/
[09/20/13 18:39:40] [INFO] Unparsed=[]
[09/20/13 18:39:40] [INFO] ------ Cookie [1]------
[09/20/13 18:39:40] [INFO] Name =H_PS_PSSID
[09/20/13 18:39:40] [INFO] Value        =3415_1431_2975_2981
[09/20/13 18:39:40] [INFO] Path =/
[09/20/13 18:39:40] [INFO] Domain       =.baidu.com
[09/20/13 18:39:40] [INFO] Expires      =0001-01-01 00:00:00 +0000 UTC
[09/20/13 18:39:40] [INFO] RawExpires=
[09/20/13 18:39:40] [INFO] MaxAge       =0
[09/20/13 18:39:40] [INFO] Secure       =false
[09/20/13 18:39:40] [INFO] HttpOnly=false
[09/20/13 18:39:40] [INFO] Raw  =H_PS_PSSID=3415_1431_2975_2981; path=/; domain=.baidu.com
[09/20/13 18:39:40] [INFO] Unparsed=[]
[09/20/13 18:39:40] [INFO] ------ Cookie [2]------
[09/20/13 18:39:40] [INFO] Name =BAIDUID
[09/20/13 18:39:40] [INFO] Value        =AF99372EE54C9816618EED94475DDD26:FG=1
[09/20/13 18:39:40] [INFO] Path =/
[09/20/13 18:39:40] [INFO] Domain       =.baidu.com
[09/20/13 18:39:40] [INFO] Expires      =0001-01-01 00:00:00 +0000 UTC
[09/20/13 18:39:40] [INFO] RawExpires=Fri, 20-Sep-43 10:39:32 GMT

E:\Dev_Root\go\src\EmulateLoginBaidu>

log文件中输出的内容:

[2013/09/20 18:39:40 ] [INFO] (main.initLogger:91) Current time is : 18:39:40 +0800 2013/09/20
[2013/09/20 18:39:40 ] [DEBG] (main.initCrifanLib:68) init for crifanLib
[2013/09/20 18:39:40 ] [INFO] (main.main:159) this is EmulateLoginBaidu.go
[2013/09/20 18:39:40 ] [INFO] (main.main:165) baiduMainUrl=http://www.baidu.com/
[2013/09/20 18:39:40 ] [DEBG] (main.GetUrlRespHtml:117) GetUrlRespHtml, url=http://www.baidu.com/
[2013/09/20 18:39:40 ] [DEBG] (main.main:167) respHtml=<!DOCTYPE html><!--STATUS OK--><html><head><meta http-equiv="content-type" content="text/html;charset=utf-8"><title>百度一下,你就知道</title><style >html,.......... new Date(_t + 10000).toGMTString()})}catch(e){}</script></html><!--0556c44ca22cac33-->
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:137) cookieNum=3
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:141) ------ Cookie [0]------
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:142) Name	=BDSVRTM
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:143) Value	=3
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:144) Path	=/
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:145) Domain	=
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:146) Expires	=0001-01-01 00:00:00 +0000 UTC
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:147) RawExpires=
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:148) MaxAge	=0
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:149) Secure	=false
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:150) HttpOnly=false
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:151) Raw	=BDSVRTM=3; path=/
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:152) Unparsed=[]
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:141) ------ Cookie [1]------
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:142) Name	=H_PS_PSSID
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:143) Value	=3415_1431_2975_2981
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:144) Path	=/
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:145) Domain	=.baidu.com
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:146) Expires	=0001-01-01 00:00:00 +0000 UTC
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:147) RawExpires=
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:148) MaxAge	=0
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:149) Secure	=false
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:150) HttpOnly=false
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:151) Raw	=H_PS_PSSID=3415_1431_2975_2981; path=/; domain=.baidu.com
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:152) Unparsed=[]
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:141) ------ Cookie [2]------
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:142) Name	=BAIDUID
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:143) Value	=AF99372EE54C9816618EED94475DDD26:FG=1
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:144) Path	=/
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:145) Domain	=.baidu.com
[2013/09/20 18:39:40 ] [INFO] (main.printCurCookies:146) Expires	=0001-01-01 00:00:00 +0000 UTC

整体效果还不错的说。

感谢log4go的作者。

转载请注明:在路上 » 【记录】go语言中通过log4go实现同时输出log信息到log文件和console

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (2)

  1. 日志对生产环境来说是相当重要,使用append模式绝对是首选,要是自己调试,在调用log4go的基础追加fmt就可以了。况且一般的单元测试也不用输出~
    梦在飞11年前 (2013-10-15)回复
    • 哦,我接触日志方面的需求不多,所以不清楚哪种模式更好。只是个人遇到的情况是:每次log时,清除已有log。所以才用新建的配置,而不用append的。
      crifan11年前 (2013-10-16)回复
87 queries in 0.185 seconds, using 22.17MB memory