这是很容易可行,因为log.Logger
类型保证每个日志消息被传递到目的地io.Writer
用单Writer.Write()
电话:
每个测井作业,使笔者的Write方法的单一调用。记录器可以在多个goroutines中同时使用;它保证序列化对Writer的访问。
所以基本上你只需要创建一个实现io.Writer
有型,且其Write()
方法创建字节片的内容的新文件,并在MongoDB中保存它。
这里有一个简单的实现这确实是:
type MongoWriter struct {
sess *mgo.Session
}
func (mw *MongoWriter) Write(p []byte) (n int, err error) {
c := mw.sess.DB("").C("log")
err = c.Insert(bson.M{
"created": time.Now(),
"msg": string(p),
})
if err != nil {
return
}
return len(p), nil
}
使用它:
sess := ... // Get a MongoDB session
mw := &MongoWriter{sess}
log.SetOutput(mw)
// Now the default Logger of the log package uses our MongoWriter.
// Generate a log message that will be inserted into MongoDB:
log.Println("I'm the first log message.")
log.Println("I'm multi-line,\nbut will still be in a single log message.")
显然,如果你使用的是其他log.Logger
例如,设置MongoWriter
到,例如:
mylogger := log.New(mw, "", 0)
mylogger.Println("Custom logger")
请注意,日志消息以换行符结尾为即使日志消息本身不以换行符结尾,它也会追加它。如果您不想记录结束换行符,则可以简单地将其剪切,例如:
func (mw *MongoWriter) Write(p []byte) (n int, err error) {
origLen := len(p)
if len(p) > 0 && p[len(p)-1] == '\n' {
p = p[:len(p)-1] // Cut terminating newline
}
c := mw.sess.DB("").C("log")
// ... the rest is the same
return origLen, nil // Must return original length (we resliced p)
}
太棒了!我假设我们不能在Write函数中处理额外的参数,因为所有的方法都可以接收到一个字节的slice是正确的?将额外的参数发送到该函数,比如堆栈跟踪或其他重要的数据是非常好的,但是我们必须通过该字节片段发送它,然后将其分割正确吗? – 17xande
@ 17xande更正,'Write()'方法只需要一个字节片。你也可以从'Write()'中访问堆栈跟踪,这不是问题(参见''runtime.Callers()'](https://golang.org/pkg/runtime/#Caller)和['runtime。CallersFrames()'](https://golang.org/pkg/runtime/#CallersFrames))。如果您希望记录其他重要数据,请将其包含在日志消息中(例如,将它们传递给'Logger.Printf()')。 – icza