golang 实现带缓存的log package

Tangs_ · · 3050 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

        又一周了,最近的生活,hhhe, 学习的过程真的是非常非常缓慢的,不过慢慢的,不急,不怕,不怂。

        最近写某个东西,封装了一个数据库操作的包,可是有个大bug,暂时不贴出来,因为还没有解决。但是封装了这个log包,其实没写完整的,不过感觉还好,反正比即时log好。
        顺便说说,这个操作做缓存,为什么?其实原因非常简单,这就用到操作系统的知识了。因为当我们执行写数据库,或者写日志到文件的时候,会发生io中断,io中断会让操作系统来处理这些中断,这时我们的程序执行时,就会从用户级切换到核心级,处理结束后再从核心级返回到用户级,这一个转换过程的代价是很大的,当频繁执行这样的操作,整个系统的性能会非常的差,这些都助攻于以前写遗传算法算皇后问题时,在遗传迭代的过程中有使用到 C++ 的cout ,于是8皇后都需要5,6秒,16 皇后要跑好几分钟,原来一直以为是算法问题,找了好久好久,突然反应过来cout的io中断,注释掉以后,全是秒执行。这就io操作的代价。

        还有这也有助于高并发的处理,这一部分之后再说,我还有些问题没有解决。

        接下来说说log日志实现,也很简单,当需要打印某条日志时,先将日志信息保存在内存中,而不是立即打印,如果在一段时间内又有其他日志信息需要打印,就将所有的日志信息一起拼接起来,一起写入文件。一次写多多条语句到文件的效率比多次写入一条的效率高出NNNNNNN倍了。
        贴贴自己封装的log包,不完整版,之后使用的过程中,完善了会更新。

封装的包,感觉代码风格挺不错,哈哈哈


package mylog

import (
    "log"
    "os"
    "fmt"
    "time"
    "runtime"
    "strconv"
)

var fileStr     LogFileInfo
var logType     LogType
var logBuffer   LogBuffer

func Init() {
    fileStr     =   LogFileInfo{}
    logType     =   LogType{}
    logBuffer   =   LogBuffer{}

    logBufferInit()
    defineLogType()
    defineLogInfo()

    go autoLog()
}

func logBufferInit() {
    logBuffer.Log       = []string{}
    logBuffer.Assert    = []string{}
    logBuffer.Warning   = []string{}
    logBuffer.Error     = []string{}
    logBuffer.Exception = []string{}
}

func defineLogType() {
    filename := "mylog/logTxt.txt"
    fPtr, err :=  createLogFile(filename)
    if err != nil {
        fmt.Println(err)
        //失败了怎么办,应该不允许失败这里
    }
    fileStr.logTxt = fPtr

    filename = "mylog/assTxt.txt"
    fPtr, err =  createLogFile(filename)
    if err != nil {
        fmt.Println(err)
        //失败了怎么办,应该不允许失败这里
    }
    fileStr.assTxt = fPtr

    filename = "mylog/warTxt.txt"
    fPtr, err =  createLogFile(filename)
    if err != nil {
        fmt.Println(err)
        //失败了怎么办,应该不允许失败这里
    }
    fileStr.warTxt = fPtr

    filename = "mylog/errTxt.txt"
    fPtr, err =  createLogFile(filename)
    if err != nil {
        fmt.Println(err)
        //失败了怎么办,应该不允许失败这里
    }
    fileStr.errTxt = fPtr

    filename = "mylog/excTxt.txt"
    fPtr, err =  createLogFile(filename)
    if err != nil {
        fmt.Println(err)
        //失败了怎么办,应该不允许失败这里
    }
    fileStr.excTxt = fPtr

}

func createLogFile(filename string) (*os.File, error) {
    if _, err := os.Stat(filename); err != nil {
        file, err := os.Create(filename)
        if err != nil {
            return nil, err
        }
        return file, nil
    } else {
        file, err := os.OpenFile(filename, os.O_RDWR|os.O_APPEND, os.ModePerm)
        if err != nil {
            return nil, err
        }
        return file, nil
    }
}

func defineLogInfo() {

    logType.LogLog          = log.New(fileStr.logTxt,       "",     0)
    logType.LogAssert       = log.New(fileStr.assTxt,       "",     0)
    logType.LogWar          = log.New(fileStr.warTxt,       "",     0)
    logType.LogErr          = log.New(fileStr.errTxt,       "",     0)
    logType.LogException    = log.New(fileStr.excTxt,       "",     0)
}

func GetLog() *LogType {
    if fileStr.logTxt == nil || fileStr.assTxt == nil || fileStr.warTxt == nil || fileStr.errTxt == nil || fileStr.excTxt == nil {
        fmt.Println("fileStr has invalid pointer or nil ptr", fileStr)
        logType.LogWar.Println("fileStr has invalid pointer or nil ptr")
    }
    return &logType
}

func autoLog() {

    for {
        bufferLength := 0
        bufferLength += checkBuffer(&logBuffer.Log,         1)
        bufferLength += checkBuffer(&logBuffer.Assert,      2)
        bufferLength += checkBuffer(&logBuffer.Warning,     4)
        bufferLength += checkBuffer(&logBuffer.Error,       8)
        bufferLength += checkBuffer(&logBuffer.Exception,   16)
        if bufferLength == 0 {
            time.Sleep(4 * time.Second)
        }
    }
}

func checkBuffer(str *[]string, parame int) int {

    length := len((*str))
    if length != 0 {
        buffer := (*str)[0:length]
        logInfo := ""
        for i := 0; i < length; i++ {
            logInfo = logInfo + buffer[i] + "\r\n"
        }
        //@parame & 速度最快
        if parame & 1 != 0 {
            logType.LogLog.Println(logInfo)
        } else if parame & 2 != 0 {
            logType.LogAssert.Println(logInfo)
        } else if parame & 4 != 0 {
            logType.LogWar.Println(logInfo)
        } else if parame & 8 != 0 {
            logType.LogErr.Println(logInfo)
        } else if parame & 16 != 0 {
            logType.LogException.Println(logInfo)
        }

        length2 := len((*str))
        if length2 != length {
            (*str) = (*str)[length:length2]
            return len(*str)
        } else {
            (*str) = (*str)[:0]
        }
    }
    return 0
}

//@logFormat
//[log]: 2016/03/24 01:02:04 /Users/tangs/IdeaProjects/MoodleServe3/mylog/log.go:150: logBuffer.Log

//runtime.Caller(Depth)
//Depth should be 1, 2 or bigger.How finish it.

func AddLog (msg string)  {
    _, file, line, ok := runtime.Caller(1)
    s := ""
    if ok {
        t := time.Now()
        s = "[Log] : " + t.String() + " " + file + ":" + strconv.Itoa(line)
    }
    msg = s + " " + msg
    logBuffer.Log = append(logBuffer.Log, msg)
}

func AddAssert (msg string) {
    _, file, line, ok := runtime.Caller(1)
    s := ""
    if ok {
        t := time.Now()
        s = "[Assert] : " + t.String() + " " + file + ":" + strconv.Itoa(line)
    }
    msg = s + " " + msg
    logBuffer.Assert = append(logBuffer.Assert, msg)
}

func AddWarning (msg string) {
    _, file, line, ok := runtime.Caller(1)
    s := ""
    if ok {
        t := time.Now()
        s = "[Warning] : " + t.String() + " " + file + ":" + strconv.Itoa(line)
    }
    msg = s + " " + msg
    logBuffer.Warning = append(logBuffer.Warning, msg)
}

func AddError(msg string) {
    _, file, line, ok := runtime.Caller(1)
    s := ""
    if ok {
        t := time.Now()
        s = "[Error] : " + t.String() + " " + file + ":" + strconv.Itoa(line)
    }
    msg = s + " " + msg
    logBuffer.Error = append(logBuffer.Error, msg)
}

func AddException(msg string) {
    _, file, line, ok := runtime.Caller(1)
    s := ""
    if ok {
        t := time.Now()
        s = "[Exception] : " + t.String() + " " + file + ":" + strconv.Itoa(line)
    }
    msg = s + " " + msg
    logBuffer.Exception = append(logBuffer.Exception, msg)
}

func Flush() {
    //todo 立即将缓存写入文件
}

定义的结构体,

package mylog

import (
    "log"
    "os"
)

type LogType struct {
    LogLog          *log.Logger     //用于错误的日志类型。
    LogAssert       *log.Logger     //用于断言(Assert)的日志类型(这些表明Unity自身的一个错误)。
    LogWar          *log.Logger     //用于警告(Warning)的日志类型。
    LogErr          *log.Logger     //用于普通日志消息的日志类型。
    LogException    *log.Logger     //用于异常的日志类型。
}

type LogFileInfo struct {
    logTxt  *os.File
    assTxt  *os.File
    warTxt  *os.File
    errTxt  *os.File
    excTxt  *os.File
}

type LogBuffer struct {
    Log         []string
    Assert      []string
    Warning     []string
    Error       []string
    Exception   []string
}

有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:Tangs_

查看原文:golang 实现带缓存的log package

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

3050 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传