一个logger代码,大家帮忙指正

quetzal · 2016-12-16 09:04:24 · 3467 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2016-12-16 09:04:24 的主题,其中的信息可能已经有所发展或是发生改变。

刚上手golang的时候看log库,为了练手就写了个logger库自己用 主要是设定几个日志级别,然后可以按照大小轮转日志,并限定日志个数。

####模拟linux的syslog轮转xxx.log.1 xxx.log.2 .... 这样

####希望大家帮忙看看,有什么问题,谢谢

####logger.go package logger

import (
    "fmt"
    "os"
    "sync"
    "path/filepath"
    "strings"
    "strconv"
    "time"
    "runtime"
)

// 检查文件或目录是否存在
// 如果由 filename 指定的文件或目录存在则返回 true,否则返回 false
func Exist(filename string) bool {
    _, err := os.Stat(filename)
    return err == nil || os.IsExist(err)
}

type level int

const (
    DetailLog level = iota
    DebugLog 
    InfoLog
    WarnLog
    ErrorLog
    PanicLog
    LevelNum = 6
)

const levelChar = "TDIWEP"

var levelName = []string{
    DetailLog:  "DETAIL",
    DebugLog:   "DEBUG",
    InfoLog:    "INFO",
    WarnLog:    "WARN",
    ErrorLog:   "ERROR",
    PanicLog:   "PANIC",
}


var logging = &loggingT{toStderr:true, outputLevel:DetailLog, w:os.Stderr}


func SetLevel(l level) {
    logging.outputLevel = l
}

func SetRotatingFile(path string, maxBytes int64, backCount int) bool {
    dir := filepath.Dir(path)
    if !strings.EqualFold(dir, ".") {
        if err := os.MkdirAll(dir, 0755); err != nil {
            fmt.Printf("ERROR - MkdirAll(%s): %s\n", dir, err.Error())
            return false
        }
    }

    f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
    if err != nil {
        fmt.Printf("ERROR - OpenFile(%s): %s\n", path, err.Error())
        return false
    }

    logging.toStderr  = false
    logging.filename  = path
    logging.w         = f
    logging.maxBytes  = maxBytes
    logging.backCount = backCount

    //fmt.Printf("%#v", logging)
    return true
}

func Detail(format string, v ...interface{}) {
    logging.printf(DetailLog, format, v...)
}

func Debug(format string, v ...interface{}) {
    logging.printf(DebugLog, format, v...)
}

func Info(format string, v ...interface{}) {
    logging.printf(InfoLog, format, v...)
}
func Warn(format string, v ...interface{}) {
    logging.printf(WarnLog, format, v...)
}

func Error(format string, v ...interface{}) {
    logging.printf(ErrorLog, format, v...)
}

func Panic(format string, v ...interface{}) {
    logging.printf(PanicLog, format, v...)
}


// loggingT collects all the global state of the logging setup.
type loggingT struct {
    // 是否打印到终端
    toStderr     bool

    // 日志的输出级别
    outputLevel level

    // mu protects the remaining elements of this structure and is
    // used to synchronize logging.
    mu sync.Mutex

    // 日志文件名称 用于打开文件和轮转日志
    filename string

    // 写日志的对象
    //文件对象
    w *os.File

    // 保留的日志个数  main.log.1 
    backCount int

    // 单文件大小
    maxBytes int64
}


func (self *loggingT) rotatingFile() {
    self.w.Close()
    self.w = nil

    for i := self.backCount; i >= 0; i-- {
        backFilename     := self.filename + "." + strconv.Itoa(i)
        backFilename_obj := self.filename + "." + strconv.Itoa(i+1)

        if i > 0 && !Exist(backFilename) { continue }

        if  i == self.backCount {
            os.Remove(backFilename)
        } else if i == 0 {
            os.Rename(self.filename, backFilename_obj)
        } else {
            os.Rename(backFilename, backFilename_obj)
        }
    }

    f, err := os.OpenFile(self.filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
    if err != nil {
        println(err)
        return
    }

    self.w = f
}

func (self *loggingT) printf(l level, format string, v ...interface{}) {
    if self.outputLevel > l { return }

    msg := fmt.Sprintf(format, v...)

    self.mu.Lock()
    defer self.mu.Unlock()

    if self.toStderr == false {
        info, err := self.w.Stat();
        if err == nil && info.Size() >= self.maxBytes {
            self.rotatingFile()
        }
    }

    _, file, line, ok := runtime.Caller(2)
    if !ok {
        file = "???"
        line = 1
    } else {
        slash := strings.LastIndex(file, "/")
        if slash >= 0 {
            file = file[slash+1:]
        }
    }
    fmt.Fprintf(self.w, "%s %s - %s [%s:%d]\n", time.Now().Format("2006-01-02 15:04:05"), levelName[l], msg, file, line)
}

####logger_test.go package logger

import (
    "testing"
)

func TestNormal(t *testing.T) {
    SetLevel(DetailLog)
    Detail("%d", DetailLog)
    Debug("%d", DebugLog)
    Info("%d",  InfoLog)
    Error("%d",  ErrorLog)
    Panic("%d",  PanicLog)
}

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

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

3467 次点击  
加入收藏 微博
7 回复  |  直到 2016-12-22 02:58:33
jokeyone
jokeyone · #1 · 8年之前

wide的share有一段iframe的代码贴过来就可以了

quetzal
quetzal · #2 · 8年之前
jokeyonejokeyone #1 回复

wide的share有一段iframe的代码贴过来就可以了

代码贴到wide里,然后点share,没反应

jokeyone
jokeyone · #3 · 8年之前
quetzalquetzal #2 回复

#1楼 @jokeyone 代码贴到wide里,然后点share,没反应

有可能是浏览器不兼容吧。

quetzal
quetzal · #4 · 8年之前
jokeyonejokeyone #3 回复

#2楼 @quetzal 有可能是浏览器不兼容吧。

chrome

jokeyone
jokeyone · #5 · 8年之前
quetzalquetzal #4 回复

#3楼 @jokeyone chrome

F12研究一下吧~

polaris
polaris · #6 · 8年之前

编辑器使用的markdown语法,发布框右侧有使用说明。不支持直接使用 html 标签。

quetzal
quetzal · #7 · 8年之前
polarispolaris #6 回复

编辑器使用的markdown语法,发布框右侧有使用说明。不支持直接使用 html 标签。

谢谢,是我看文档没看仔细,直接看兼容html标签就直接用了

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