go語言記log: glog剖析

首發(fā): legendtkl.com
log的一個(gè)典型應(yīng)用場景就是實(shí)現(xiàn)log分級,比如線上環(huán)境不需要記錄DEBUG的log信息。今天介紹一下glog。先看一個(gè)glog的簡單例子。

//file name: glog.go
package main

import (
    "flag"
    "github.com/golang/glog"
)

func main() {
    flag.Parse()    // 1

    glog.Info("This is a Info log")         // 2
    glog.Warning("This is a Warning log")
    glog.Error("This is a Error log")

    glog.V(1).Infoln("level 1")     // 3
    glog.V(2).Infoln("level 2")

    glog.Flush()    // 4
}

如果你之前沒有用過glog,需要使用go get安裝一下,你需要像下面這樣執(zhí)行這個(gè)go程序。上面標(biāo)注的幾個(gè)地方可以先注意一下,等文章讀完就理解了。

$ go get
$ go build glog.go
$ ./glog -log_dir="./"

這時(shí)候不出意外的話,會(huì)在同級目錄下生成下面幾個(gè)類似的log文件。

glog.kltao-mac.kltao.log.ERROR.20160312-173205.22052
glog.kltao-mac.kltao.log.INFO.20160312-173205.22052
glog.kltao-mac.kltao.log.WARNING.20160312-173205.22052

這就是產(chǎn)生的log文件,打開第一個(gè)ERROR的log文件,文件內(nèi)容如下。前面4行是文件響應(yīng)信息,最后一行就是上面第14行代碼記錄的log內(nèi)容。

Log file created at: 2016/03/12 17:32:05
Running on machine: kltao-mac
Binary: Built with gc go1.4.2 for darwin/amd64
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
E0312 17:32:05.568597   22052 glog.go:15] This is a Error log

這個(gè)時(shí)候如果你打開另外兩個(gè)INFO和WARNING的log文件,會(huì)發(fā)現(xiàn)WARNING日志文件中除了WARNING信息還記錄了Error信息(This is a Error log),而INFO日志文件中則記錄了所有的log信息(This is a Info/Warning/Error log)。很容易理解,這些log是有等級的(ERROR>WARNING>INFO),高等級的日志內(nèi)容會(huì)同時(shí)會(huì)被記錄到低等級的日志文件中去。那么glog提供了一個(gè)等級呢?答案是4個(gè),除了上面提出的3個(gè),還有一個(gè)FALTAL。

這時(shí)候又有一個(gè)問題來了,為什么第3處的日志信息沒有記錄下來呢?不急,這個(gè)時(shí)候如下重新執(zhí)行一下。就可以在新的INFO日志文件中找到了對應(yīng)的信息了。

./glog -log_dir="./" -v=3

對,就是這個(gè)-v參數(shù)。再說V之前,先說一下glog的命令行解析,對應(yīng)代碼就是標(biāo)注的第1處。那么glog有多少種參數(shù)呢?

// By default, all log statements write to files in a temporary directory.
// This package provides several flags that modify this behavior.
// As a result, flag.Parse must be called before any logging is done.
//
//  -logtostderr=false
//      Logs are written to standard error instead of to files.
//  -alsologtostderr=false
//      Logs are written to standard error as well as to files.
//  -stderrthreshold=ERROR
//      Log events at or above this severity are logged to standard
//      error as well as to files.
//  -log_dir=""
//      Log files will be written to this directory instead of the
//      default temporary directory.
//
//  Other flags provide aids to debugging.
//
//  -log_backtrace_at=""
//      When set to a file and line number holding a logging statement,
//      such as
//          -log_backtrace_at=gopherflakes.go:234
//      a stack trace will be written to the Info log whenever execution
//      hits that statement. (Unlike with -vmodule, the ".go" must be
//      present.)
//  -v=0
//      Enable V-leveled logging at the specified level.
//  -vmodule=""
//      The syntax of the argument is a comma-separated list of pattern=N,
//      where pattern is a literal file name (minus the ".go" suffix) or
//      "glob" pattern and N is a V level. For instance,
//          -vmodule=gopher*=3
//      sets the V level to 3 in all Go files whose names begin "gopher".

glog.V(1).Infoln("level 1")這行代碼表示設(shè)置的-v參數(shù)大于V()里面的參數(shù)才執(zhí)行后面的Infoln。如果不加-v參數(shù),默認(rèn)等級為0,所以第三處的代碼沒有執(zhí)行。具體實(shí)現(xiàn)不妨看一下源碼實(shí)現(xiàn),一目了然。

type Verbose bool

func V(level Level) Verbose {
    // This function tries hard to be cheap unless there's work to do.
    // The fast path is two atomic loads and compares.

    // Here is a cheap but safe test to see if V logging is enabled globally.
    if logging.verbosity.get() >= level {
        return Verbose(true)
    }

    // It's off globally but it vmodule may still be set.
    // Here is another cheap but safe test to see if vmodule is enabled.
    if atomic.LoadInt32(&logging.filterLength) > 0 {
        // Now we need a proper lock to use the logging structure. The pcs field
        // is shared so we must lock before accessing it. This is fairly expensive,
        // but if V logging is enabled we're slow anyway.
        logging.mu.Lock()
        defer logging.mu.Unlock()
        if runtime.Callers(2, logging.pcs[:]) == 0 {
            return Verbose(false)
        }
        v, ok := logging.vmap[logging.pcs[0]]
        if !ok {
            v = logging.setV(logging.pcs[0])
        }
        return Verbose(v >= level)
    }
    return Verbose(false)
}

func (v Verbose) Info(args ...interface{}) {
    if v {
        logging.print(infoLog, args...)
    }
}

func (v Verbose) Infoln(args ...interface{}) {
    if v {
        logging.println(infoLog, args...)
    }
}

func (v Verbose) Infof(format string, args ...interface{}) {
    if v {
        logging.printf(infoLog, format, args...)
    }
}

程序中標(biāo)注的4個(gè)地方,除了第4個(gè)地方,其他都說了,F(xiàn)lush的作用清空緩沖區(qū),就是把日志寫到文件。golog初始化的時(shí)候,起了一個(gè)Flush的守護(hù)進(jìn)程,然后定期去執(zhí)行I/O操作,所以退出的時(shí)候需要顯示清除一下緩沖區(qū)。glog啟動(dòng)的初始化代碼如下。

func init() {
    ...
    go logging.flushDaemon()
}

上面應(yīng)該是glog的大部分使用方法了,更詳細(xì)的信息可以參考github.com/golang/glog

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • http://192.168.136.131/sqlmap/mysql/get_int.php?id=1 當(dāng)給sq...
    xuningbo閱讀 10,434評論 2 22
  • sqlmap用戶手冊 說明:本文為轉(zhuǎn)載,對原文中一些明顯的拼寫錯(cuò)誤進(jìn)行修正,并標(biāo)注對自己有用的信息。 ======...
    wind_飄閱讀 2,114評論 0 5
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,991評論 19 139
  • 在應(yīng)用程序中添加日志記錄總的來說基于三個(gè)目的:監(jiān)視代碼中變量的變化情況,周期性的記錄到文件中供其他應(yīng)用進(jìn)行統(tǒng)計(jì)分析...
    時(shí)待吾閱讀 5,030評論 0 6
  • 當(dāng)身體給我們發(fā)出信號,你胖了、瘦了、健康了、生病了、衣服穿不上了,這時(shí)我們才會(huì)在意我們的身體。我們?nèi)メt(yī)院,找醫(yī)生,...
    Dflower閱讀 261評論 0 0