nxlog4go 的配置驅動

ccpaging發表於2018-03-27

剛開始接觸log4go專案時,沒有注意到配置的重要性。

閱讀了log4j、log4net、log4cpp、log4cplus的部分程式碼,發現它們都是以xml配置來驅動日誌系統執行的。


多個原始檔共享一個logger

最簡單的方式是新建一個logger.go檔案。

package main

import (
    l4g "github.com/ccpaging/nxlog4go"
    "github.com/ccpaging/nxlog4go/color"
    "github.com/ccpaging/nxlog4go/file"
    "github.com/ccpaging/nxlog4go/socket"
)

var log = l4g.GetLogger()

l4g.GetLogger() 從nxlog4go中取出預定義的logger。

或者用l4g.New(l4g.DEBUG) 新建全域性 Logger。

var log = l4g.New(l4g.DEBUG)

初始化logger

可以在新建時直接連結配置函式。

var log = l4g.GetLogger().SetCaller(false).SetPattern("[%T] [%L] (%s) %M\n")

或者在init()中配置,如果不使用配置檔案的話。

var log = l4g.GetLogger()

init() {
    log = log.SetCaller(false).SetPattern("[%T] [%L] (%s) %M\n")
}

準備 xml 配置檔案

準備xml配置檔案。詳見:config.xml

方便的辦法是參照以上檔案進行修改。

以 color term appender 為例

<logging>
    <filter enabled="true">
        <tag>color</tag>
        <level>DEBUG</level>
        <property name="pattern">[%D %T] [%L] (%s) %M%R</property>
    </filter>
</logging>
  • enabled - filter attribute

    Filter或稱為 Appender的使能屬性。enabled = true,開啟。enabled = false,關閉。

  • tag

    在log4go裡用了兩個欄位——tag和type。在 nxlog4go 中合併成一個,標識 Appender 的型別。

    在程式中,nxlog4go預裝載(Preload)所有可能用到的 Appender,指定每個 Appender 的 tag。

    然後裝載配置檔案,用 tag 欄位匹配 Appender。

    通過 Preload - tag - Load 機制,nxlog4go 可以用配置驅動未知的擴充套件 Appender。

  • level

    日誌過濾級別。nxlog4go僅處理大於等於 level 的日誌。

  • property - attribute

    每種 Appender 都有自己的 Options。

    例如上例中設定 PatternLayout 的Pattern。“%R”表示回車換行,即程式中的“\n”。

    通過參看原始檔可以獲得詳細的資訊。例如:filelog.go

func (fa *FileAppender) SetOption(name string, v interface{}) error {
    fa.mu.Lock()
    defer fa.mu.Unlock()

    switch name {
    case "filename":
        ...
    case "flush":
        ...
    case "maxbackup":
        ...
    case "cycle":
        ...
    case "clock", "delay0":
        ...
    case "daily":
        ...
    case "maxsize":
        ...
    case "pattern", "format", "utc":
        ...
    case "head":
        ...
    case "foot":
        ...
    default:
        return l4g.ErrBadOption
    }
    return nil
}

裝載 xml 配置驅動nxlog4go執行

func main() {
    // 開啟xml配置檔案
    fd, err := os.Open(filename)
    if err != nil {
        panic(fmt.Sprintf("Can't load xml config file: %s %v", filename, err))
    }
    // 讀取xml內容到buf
    buf, err := ioutil.ReadAll(fd)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Could not read %q: %s\n", filename, err)
        os.Exit(1)
    }
    // 關閉配置檔案
    fd.Close()

    // 新建logger config, 具體結構詳見filters.go, appender.go
    xc := new(l4g.LoggerConfig)
    if err := xml.Unmarshal(buf, xc); err != nil {
        fmt.Fprintf(os.Stderr, "Could not parse XML configuration. %s\n", err)
        os.Exit(1)
    }

    // 新建filters
    fs := l4g.NewFilters()

    // 預裝載所有可能用到的 Appender
    fs.Preload("color", colorlog.NewAppender())
    fs.Preload("file", filelog.NewAppender("_test.log", 0))
    fs.Preload("socket", socketlog.NewAppender("udp", "127.0.0.1:12124"))

    // 預裝載 xml 格式日誌檔案
    xa := filelog.NewAppender("_test.log", 0)
    xa.SetOption("head","<log created=\"%D %T\">%R")

    xa.SetOption("pattern", 
`   <record level="%L">
        <timestamp>%D %T</timestamp>
        <source>%S</source>
        <message>%M</message>
    </record>%R`)

    xa.SetOption("foot", "</log>%R")
    fs.Preload("xml", xa)

    fmt.Println(len(*fs), "appenders pre-installed")

    // 裝載配置並自動刪除未用的appender
    fs.LoadConfiguration(xc.Filters)
    if filt, isExist := (*fs)["color"]; isExist {
        // 已有 color term appender. 關閉預設的 writer
        log.SetOutput(nil)
    }
    log.SetFilters(fs)
    fmt.Println(len(*fs), "appenders configured ok")

    // And now we're ready!
    log.Finest("This will only go to those of you really cool UDP kids!  If you change enabled=true.")
    log.Debug("Oh no!  %d + %d = %d!", 2, 2, 2+2)
    log.Trace("Oh no!  %d + %d = %d!", 2, 2, 2+2)
    log.Info("About that time, eh chaps?")

    log.Shutdown()

    // 或者分步執行

    // 解除安裝filters
    // log.SetFilters(nil)
    // 關閉全部filters
    // fs.Close()
}

xml 格式的日誌檔案

附帶實現了xml格式的日誌檔案。簡單的設定 Head, Foot, 和PatternLayout就可以。例如:

    xa := filelog.NewAppender("_test.log", 0)
    xa.SetOption("head","<log created=\"%D %T\">%R")

    xa.SetOption("pattern", 
`   <record level="%L">
        <timestamp>%D %T</timestamp>
        <source>%S</source>
        <message>%M</message>
    </record>%R`)

    xa.SetOption("foot", "</log>%R")

生成的日誌檔案內容如下:

<log created="2018/03/26 13:50:25">
    <record level="TRAC">
        <timestamp>2018/03/26 13:50:25</timestamp>
        <source>f:/go/src/github.com/ccpaging/nxlog4go/examples/xmlconfig.go</source>
        <message>Oh no!  2 + 2 = 4!</message>
    </record>
    <record level="INFO">
        <timestamp>2018/03/26 13:50:25</timestamp>
        <source>f:/go/src/github.com/ccpaging/nxlog4go/examples/xmlconfig.go</source>
        <message>About that time, eh chaps?</message>
    </record>
  • 只有滾動日誌檔案時才會寫入 Foot

參考原始檔

jsonconfig.go

xmlconfig.go

相關文章