前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go语言(十六) 日志项目升级

Go语言(十六) 日志项目升级

作者头像
alexhuiwang
发布2020-09-23 11:39:37
5430
发布2020-09-23 11:39:37
举报
文章被收录于专栏:运维博客

日志项目升级

  • 升级功能点
    • 异步刷盘
    • 日志切分

项目结构

代码语言:javascript
复制
xlog/
├── console.go      #console日志输出
├── file.go              #文件输出(本次优化点)
├── level.go           #日志级别类
├── log.go             #日志库
├── log_base.go   # 基类库
└── tool.go            #工具库,用于获取文件名,函数名,所在行

代码拆解

  • log.go
代码语言:javascript
复制
package xlog

//定义全局默认的日志类型
var logger XLog = newXLog(XLogTypeFile,XLogLevelDebug,"","default")

type XLog interface {
    Init() error   //文件初始化
    LogDebug(fmt string, args ...interface{})
    LogTrace(fmt string, args ...interface{})
    LogInfo(fmt string, args ...interface{})
    LogWarn(fmt string, args ...interface{})
    LogError(fmt string, args ...interface{})
    LogFatal(fmt string, args ...interface{})
    Close()
    SetLevel(level int)
}

func newXLog(logType, level int, filename, module string) XLog {
    //定义接口
    var logger XLog
    switch logType {
    case XLogTypeFile:
        logger = NewXFile(level,filename, module)
    case XLogTypeConsole:
        logger = NewXConsole(level, module)
    default:
        logger = NewXFile(level,filename, module)
    }
    return logger
}

//封装接口,后期可以直接调用

func Init(logType, level int, filename, module string) (err error){
    logger = newXLog(logType,level,filename,module)
    return logger.Init()
}

func LogDebug(fmt string, args ...interface{}) {
    logger.LogDebug(fmt, args...)
}

func LogTrace(fmt string, args ...interface{}) {
    logger.LogTrace(fmt, args...)
}

func LogInfo(fmt string, args ...interface{}) {
    logger.LogInfo(fmt, args...)
}

func LogWarn(fmt string, args ...interface{}) {
    logger.LogWarn(fmt, args...)
}

func LogError(fmt string, args ...interface{}) {
    logger.LogError(fmt, args...)
}

func LogFatal(fmt string, args ...interface{}) {
    logger.LogFatal(fmt, args...)
}

func Close() {
    logger.Close()
}

func SetLevel(level int) {
    logger.SetLevel(level)
}
  • log_base.go
代码语言:javascript
复制
package xlog

import (
    "fmt"
    "os"
    "path/filepath"
    "time"
)

type LogData struct {
    timeStr  string
    levelStr string
    module   string
    filename string
    funcName string
    lineNo   int
    data     string
}

type XLogBase struct {
    level   int
    module  string
}

func (l *XLogBase) writeLog(file *os.File,logData *LogData) {
    fmt.Fprintf(file,"%s %s %s (%s:%s:%d) %s\n",
        logData.timeStr, logData.levelStr, logData.module,
        logData.filename, logData.funcName, logData.lineNo, logData.data)
}

func (l *XLogBase) formatLogger(level int, module, format string, args ...interface{}) *LogData {
    now := time.Now()
    timeStr := now.Format("2006-01-02 15:04:05.000")
    levelStr := getLevelStr(level)
    filename, funcName, lineNo := GetLineInfo(5)
    filename = filepath.Base(filename)
    data := fmt.Sprintf(format, args...)
    //fmt.Printf("%s %s %s (%s:%s:%d) %s\n",timeStr,leveStr,module,filename,funcName,lineNo,data)
    return &LogData{
        timeStr:  timeStr,
        levelStr: levelStr,
        module:   module,
        filename: filename,
        funcName: funcName,
        lineNo:   lineNo,
        data:     data,
    }
}
  • level.go
代码语言:javascript
复制
package xlog

const (
    XLogLevelDebug = iota
    XLogLevelTrace
    XLogLevelInfo
    XLogLevelWarn
    XLogLevelError
    XLogLevelFatal
)

const (
    XLogTypeFile = iota
    XLogTypeConsole
)

func getLevelStr(level int) string {
    switch level {
    case XLogLevelDebug:
        return "DEBUG"
    case XLogLevelTrace:
        return "TRACE"
    case XLogLevelInfo:
        return "INFO"
    case XLogLevelWarn:
        return "WARN"
    case XLogLevelError:
        return "ERROR"
    case XLogLevelFatal:
        return "FATAL"
    default:
        return "UNKNOWN"
    }
}
  • console.go 本次无更新
代码语言:javascript
复制
package xlog

import (
    "os"
)

type XConsole struct {
    *XLogBase //指针实现
}

func NewXConsole(level int, module string) XLog {
    logger := &XConsole{}
    //初始化指针,防止panic
    logger.XLogBase = &XLogBase{
        level: level,
        module: module,
    }
    return logger
}

//不需要初始化文件写入
func (c *XConsole)Init() error {
    return nil
}

func (c *XConsole) LogDebug(format string, args ...interface{}) {
    if c.level > XLogLevelDebug {
        return
    }
    logData := c.formatLogger(XLogLevelDebug, c.module, format, args...)
    c.writeLog(os.Stdout,logData)
}

func (c *XConsole) LogTrace(format string, args ...interface{}) {
    if c.level > XLogLevelTrace {
        return
    }
    logData := c.formatLogger(XLogLevelTrace, c.module, format, args...)
    c.writeLog(os.Stdout,logData)
}

func (c *XConsole) LogInfo(format string, args ...interface{}) {
    if c.level > XLogLevelInfo {
        return
    }
    logData := c.formatLogger(XLogLevelInfo, c.module, format, args...)
    c.writeLog(os.Stdout,logData)
}

func (c *XConsole) LogWarn(format string, args ...interface{}) {
    if c.level > XLogLevelWarn {
        return
    }
    logData := c.formatLogger(XLogLevelWarn, c.module, format, args...)
    c.writeLog(os.Stdout,logData)
}

func (c *XConsole) LogError(format string, args ...interface{}) {
    if c.level > XLogLevelError {
        return
    }
    logData := c.formatLogger(XLogLevelError, c.module, format, args...)
    c.writeLog(os.Stdout,logData)
}

func (c *XConsole) LogFatal(format string, args ...interface{}) {
    if c.level > XLogLevelFatal {
        return
    }
    logData := c.formatLogger(XLogLevelFatal, c.module, format, args...)
    c.writeLog(os.Stdout,logData)
}
func (c *XConsole) SetLevel(level int) {
    c.level = level
}

func (c *XConsole) Close() {}
  • file.go 本次更新异步刷盘&日志切分
代码语言:javascript
复制
package xlog

import (
    "fmt"
    "os"
    "sync"
    "time"
)

type XFile struct {
    filename string
    file     *os.File
    *XLogBase
    logChan chan *LogData
    wg *sync.WaitGroup
    curDay int   //也可以按小时去切割,curHour int
}

func (c *XFile) Init() (err error) {
    c.file,err = os.OpenFile(c.filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY,0755)
    if err != nil {
        return
    }
    return
}

func NewXFile(level int, filename, module string) XLog {
    logger := &XFile{
        filename: filename,
    }
    logger.XLogBase = &XLogBase{
        module: module,
        level: level,
    }

    logger.curDay = time.Now().Day()           // 初始化结构体logger.curHour = time.Now().Hour()
    logger.wg = &sync.WaitGroup{}              //防止主进程退出,不执行子进程
    logger.logChan = make(chan *LogData,10000) //管道初始化

    //异步刷日志到磁盘
    logger.wg.Add(1)
    go logger.syncLog()
    return logger
}

func (c *XFile) syncLog() {
    //从管道读取日志,然后写入文件
    for data := range c.logChan {
        c.splitLog()  //调用切分日志的操作
        c.writeLog(c.file,data)
    }
    c.wg.Done()
}

func (c *XFile) splitLog() {
    now := time.Now()
    if now.Day() == c.curDay {
        return
    }
    c.curDay = now.Day() //更新时间 //按小时切分的配置,c.curHour = now.Hour()
    c.file.Sync()
    c.file.Close()

    newFilename := fmt.Sprintf("%s-%04d-%02d-%02d",c.filename,
        now.Year(),now.Month(),now.Day())
    /*
    按小时切分配置
    newFilename := fmt.Sprintf("%s-%04d-%02d-%02d-%02d", c.filename,now.Year(), now.Month(), now.Day(), now.Hour())
     */
    os.Rename(c.filename,newFilename)
    c.Init()
}

func (c *XFile) writeToChan(level int,module string,format string,args ...interface{})  {
    logData := c.formatLogger(level, module, format, args...)
    select {
    case c.logChan <- logData:
    default:
    }
}

func (c *XFile) LogDebug(format string, args ...interface{}) {
    if c.level > XLogLevelDebug {
        return
    }
    c.writeToChan(XLogLevelDebug, c.module, format, args...)
}

func (c *XFile) LogTrace(format string, args ...interface{}) {
    if c.level > XLogLevelTrace {
        return
    }
    c.writeToChan(XLogLevelTrace, c.module, format, args...)
}

func (c *XFile) LogInfo(format string, args ...interface{}) {
    if c.level > XLogLevelInfo {
        return
    }
    c.writeToChan(XLogLevelInfo, c.module, format, args...)
}

func (c *XFile) LogWarn(format string, args ...interface{}) {
    if c.level > XLogLevelWarn {
        return
    }
    c.writeToChan(XLogLevelWarn, c.module, format, args...)
}

func (c *XFile) LogError(format string, args ...interface{}) {
    if c.level > XLogLevelError {
        return
    }
    c.writeToChan(XLogLevelError, c.module, format, args...)
}

func (c *XFile) LogFatal(format string, args ...interface{}) {
    if c.level > XLogLevelFatal {
        return
    }
    c.writeToChan(XLogLevelFatal, c.module, format, args...)
}

func (c *XFile) SetLevel(level int) {
    c.level = level
}

func (c *XFile)Close()  {
    //管道为空要关闭
    if c.logChan != nil {
        close(c.logChan)
    }
    c.wg.Wait()
    if c.file != nil {
        c.file.Sync()  //同步写磁盘
        c.file.Close()
    }
}
  • tool.go
代码语言:javascript
复制
package xlog

import "runtime"

func GetLineInfo(skip int) (filename, funcName string, lineNo int) {
    pc, file, line, ok := runtime.Caller(skip)
    if ok {
        fun := runtime.FuncForPC(pc)
        funcName = fun.Name()
    }
    filename = file
    lineNo = line
    return
}

测试样例

  • 注意事项:
    • 可以通过xlog.Debug("xxx")直接打印
    • 不同的模块与需要初始化操作
代码语言:javascript
复制
打印落盘需要定义好对应的日志路径以及,模块名
err := xlog.Init(logType, xlog.XLogLevelDebug, "./xlog.log", "xlog_example")
    if err != nil {
        fmt.Printf("logger init failed\n")
        return
    }
  • xlog_example/main.go
代码语言:javascript
复制
package main

import (
    "flag"
    "fmt"
    _"fmt"
    "oldBoy/xlog"
)

//写日志测试
func logic() {
    for {
        xlog.LogDebug("dads1,user_id:%d,username:%s", 12331, "sadsaf")
        xlog.LogTrace("dads2")
        xlog.LogInfo("dads3")
        xlog.LogWarn("dads4")
        xlog.LogError("sss1")
        xlog.LogFatal("sss2")
    }
}

func main() {
    var logTypeStr string
    flag.StringVar(&logTypeStr, "type", "console",  "please input logger type")
    flag.Parse()

    var logType int
    if (logTypeStr == "file") {
        logType = xlog.XLogTypeFile
    } else {
        logType = xlog.XLogTypeConsole

    }

    xlog.LogDebug("log type is %v", logType)

    _ = logType
    err := xlog.Init(logType, xlog.XLogLevelDebug, "./xlog.log", "xlog_example")
    if err != nil {
        fmt.Printf("logger init failed\n")
        return
    }
    logic()
    xlog.Close()
    fmt.Printf("close return")
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/04/27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 日志项目升级
    • 项目结构
      • 代码拆解
        • 测试样例
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档