GoGogoroutineGo
Go
日志包的选择
Goprintpanicfatallogruszapglog
log标准库
Gologlogger
logrus
logrusJSONJSONGoJSON
logrusWithFieldsInfo()Warn()Error()logrusJSON
package main
import (
log "github.com/sirupsen/logrus"
)
func main() {
log.SetFormatter(&log.JSONFormatter{})
standardFields := log.Fields{
"hostname": "staging-1",
"appname": "foo-app",
"session": "1ce3f6v",
}
requestLogger := log.withFields(standardFields)
requestLogger.WithFields(log.Fields{"string": "foo", "int": 1, "float": 1.1}).Info("My first ssl event from Golang")
}
JSON
{"appname":"foo-app","float":1.1,"hostname":"staging-1","int":1,"level":"info","msg":"My first ssl event from Golang","session":"1ce3f6v","string":"foo","time":"2019-03-06T13:37:12-05:00"}
glog
glogifV()GoInfo()Warning()Error()Fatal()03
if err != nil && glog.V(2){
glog.Error(err)
}
日志库的选择
loglogrusgloglogrusDockerPrometheuslogrus
logrus的使用介绍
logrusGithubstarforklogrusDockerPrometheuslogrus
logrusGodebuginfowarnerrorfatalpanicGologrusHookhooklogstashelasticsearchmqlogrusJSONFormatterTextFormatterFieldlogrusFieldEntrylogrus.WithFields*EntryEntrytime
基本用法
logrusGologrus
package main
import (
"os"
log "github.com/sirupsen/logrus"
)
func init() {
// 设置日志格式为json格式
log.SetFormatter(&log.JSONFormatter{})
// 设置将日志输出到指定文件(默认的输出为stderr,标准错误)
// 日志消息输出可以是任意的io.writer类型
logFile := ...
file, _ := os.OpenFile(logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
log.SetOutput(file)
// 设置只记录日志级别为warn及其以上的日志
log.SetLevel(log.WarnLevel)
}
func main() {
log.WithFields(log.Fields{
"animal": "walrus",
"size": 10,
}).Info("A group of walrus emerges from the ocean")
log.WithFields(log.Fields{
"omg": true,
"number": 122,
}).Warn("The group's number increased tremendously!")
log.WithFields(log.Fields{
"omg": true,
"number": 100,
}).Fatal("The ice breaks!")
}
自定义Logger
logLogger
package main
import (
"github.com/sirupsen/logrus"
"os"
)
// logrus提供了New()函数来创建一个logrus的实例.
// 项目中,可以创建任意数量的logrus实例.
var log = logrus.New()
func main() {
// 为当前logrus实例设置消息的输出,同样地,
// 可以设置logrus实例的输出到任意io.writer
log.Out = os.Stdout
// 为当前logrus实例设置消息输出格式为json格式.
// 同样地,也可以单独为某个logrus实例设置日志级别和hook,这里不详细叙述.
log.Formatter = &logrus.JSONFormatter{}
log.WithFields(logrus.Fields{
"animal": "walrus",
"size": 10,
}).Info("A group of walrus emerges from the ocean")
}
Fields
logrusFields
log.Fatalf("Failed to send event %s to topic %s with key %d", event, topic, key)
logruslogrus
log.WithFields(log.Fields{
"event": event,
"topic": topic,
"key": key,
}).Fatal("Failed to send event")
WithFieldsWithFields
Default Fields
HTTPrequest_iduser_ip。
log.WithFields(log.Fields{“request_id”: request_id, “user_ip”: user_ip})
logrus.EntryFieldslogrus.EntryLogger
requestLogger := log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})
requestLogger.Info("something happened on that request") # will log request_id and user_ip
requestLogger.Warn("something not great happened")
Hook接口
logrusHOOKlogrushooklogrus
logrushooklogrus.Entry
// logrus在记录Levels()返回的日志级别的消息时会触发HOOK,
// 按照Fire方法定义的内容修改logrus.Entry.
type Hook interface {
Levels() []Level
Fire(*Entry) error
}
hookDefaultFieldHookappName=”myAppName”
type DefaultFieldHook struct {
}
func (hook *DefaultFieldHook) Fire(entry *log.Entry) error {
entry.Data["appName"] = "MyAppName"
return nil
}
func (hook *DefaultFieldHook) Levels() []log.Level {
return log.AllLevels
}
hooklog.AddHook(hook)hookHooksentry
logrussysloghookGithubhooksentryhook
sentry-hook
SentrySentryGitLabSentryDSNSentry
import (
"github.com/sirupsen/logrus"
"github.com/evalphobia/logrus_sentry"
)
func main() {
log := logrus.New()
hook, err := logrus_sentry.NewSentryHook(YOUR_DSN, []logrus.Level{
logrus.PanicLevel,
logrus.FatalLevel,
logrus.ErrorLevel,
})
if err == nil {
log.Hooks.Add(hook)
}
}
logrus 是线程安全的
Loggermutexmutexlogger.SetNoLock()
不需要锁的情况包括:
hookhooklogger.Outlogger.Outlogger.OutAppend
日志写入和存储的一些建议
Go
goroutineHTTP
避免在goroutine中使用日志记录器
goroutineio.Writergoroutinegoroutine
总是将日志写入文件
ElasticsearchLogstash
使用日志处理平台集中处理日志
ELK
使用唯一ID跨微服务跟踪Go日志
HTTP
参考链接: