這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
log的一個典型應用情境就是實現log分級,比如線上環境不需要記錄DEBUG的log資訊。今天介紹一下glog。先看一個glog的簡單例子。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
//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
安裝一下,你需要像下面這樣執行這個go程式。上面標註的幾個地方可以先注意一下,等文章讀完就理解了。
1 2 3
|
$ go get $ go build glog.go $ ./glog -log_dir="./"
|
這時候不出意外的話,會在同級目錄下產生下面幾個類似的log檔案。
1 2 3
|
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
|
這就是產生的log檔案,開啟第一個ERROR的log檔案,檔案內容如下。前面4行是檔案響應資訊,最後一行就是上面第14行代碼記錄的log內容。
1 2 3 4 5
|
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
|
這個時候如果你開啟另外兩個INFO和WARNING的log檔案,會發現WARNING記錄檔中除了WARNING資訊還記錄了Error資訊(This is a Error log
),而INFO記錄檔中則記錄了所有的log資訊(This is a Info/Warning/Error log
)。很容易理解,這些log是有等級的(ERROR>WARNING>INFO),高等級的日誌內容會同時會被記錄到低等級的記錄檔中去。那麼glog提供了一個等級呢?答案是4個,除了上面提出的3個,還有一個FALTAL。
這時候又有一個問題來了,為什麼第3處的日誌資訊沒有記錄下來呢?不急,這個時候如下重新執行一下。就可以在新的INFO記錄檔中找到了對應的資訊了。
1
|
./glog -log_dir="./" -v=3
|
對,就是這個-v
參數。再說V之前,先說一下glog的命令列解析,對應代碼就是標註的第1處。那麼glog有多少種參數呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
// 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")
這行代碼錶示設定的-v參數大於V()裡面的參數才執行後面的Infoln。如果不加-v參數,預設等級為0,所以第三處的代碼沒有執行。具體實現不妨看一下源碼實現,一目瞭然。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
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...) } }
|
程式中標註的4個地方,除了第4個地方,其他都說了,Flush的作用清空緩衝區,就是把日誌寫到檔案。golog初始化的時候,起了一個Flush的守護進程,然後定期去執行I/O操作,所以退出的時候需要顯示清除一下緩衝區。glog啟動的初始化代碼如下。
1 2 3 4
|
func init() { ... go logging.flushDaemon() }
|
上面應該是glog的大部分使用方法了,更詳細的資訊可以參考github.com/golang/glog。