2015-07-06 11:21:10
我的日志系统中的内容: 1. 时间戳 2. 日志调用地点:文件+行号 3. 报错级别 致命 错误 警告 信息 调试 4. Summary 5. 关键内存Dump
这些信息方便排查故障。
配置文件: 直接使用yaml
包: gopkg.in/yaml.v2
配置文件越简单越好。不然容易出错
package Logger
import (
"encoding/json"
"os"
"runtime"
"strconv"
"time"
)
import "caidanhezi-go/utility"
var outFile *os.File
// Logone 单条Log的结构
type Logone struct {
Timestamp int64
Codeline string
Level int // 出错级别: 0致命 1错误 2警告 3信息 4调试
Info string
Detail map[string]interface{}
}
// init 只负责打开文件
func init() {
outFile, _ = os.OpenFile(utility.Conf.LogFile, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
}
// Write 写入Log
func Write(Level int, Info string, Detail map[string]interface{}) {
var newLog Logone
newLog.Timestamp = time.Now().Unix()
_, file, line, _ := runtime.Caller(1)
newLog.Codeline = file + " " + string(strconv.Itoa(line))
newLog.Level = Level
newLog.Detail = Detail
newLog.Info = Info
outFile.Write(func() []byte {
b, _ := json.Marshal(newLog)
b = append(b, '\n')
return b
}())
}
// CloseLogFile function: close logger file
func CloseLogFile() {
outFile.Close()
}
因为默认log缺少缓存。 缓存系统可以让系统具有日志激增的缓冲措施。
包: “github.com/ActiveState/tail”
var err error
t, _ := tail.TailFile(utility.Conf.LogFile, //日志文件位置
tail.Config{Follow: true, Location: &tail.SeekInfo{0, 2}})
for line := range t.Lines { //每次写入日志都会进入这个循环
for index := 0; index < len(connected); index++ {
if err = websocket.Message.Send(&connected[index], line.Text); err != nil { //对每个连接监控单元都发送日志数据
fmt.Println("Can't send")//掉线的监控T掉。
// index2 := index + 1
connected = append([]websocket.Conn{}, connected[:index]...)
if len(connected) >= index+1 {
connected = append(connected, connected[index+1:]...)
}
continue
}
}
}
我这里是从最尾部开始。(之前文件的内容都忽略了)
经过一个多月的使用。最后log的write参数改成interface,就不用构建map了。 然后半个月前在读代码的时候发现有个包叫debug。 调试的时候非常划算。
write具体代码:
// Write 写入Log
func Write(Level int, Info string, Detail interface{}) {
var newLog Logone
newLog.Timestamp = time.Now().Unix()
_, file, line, _ := runtime.Caller(1)
newLog.Codeline = file + " " + string(strconv.Itoa(line))
newLog.Level = Level
newLog.Detail = Detail
newLog.Info = Info
outFile.Write(func() []byte {
b, _ := json.Marshal(newLog)
b = append(b, '\n')
return b
}())
}
对于不喜欢gdb之类断点,单步调试的我来说对于堆栈的输出是至关重要的。 虽然在golang报错的时候会输出堆栈,但是对于在测试中输出目标执行位置的堆栈还是非常重要的。
UtilLog.Write(1, "gob encode error"+err.Error(), string(debug.Stack()))
如果想从控制台上直接输出堆栈也有个好办法。
debug.PrintStack()
输出这些信息对于异常处理来说是非常划算的。测试调试的过程都轻松了不少。