Dette er nemt muligt, fordi log.Logger
type garanterer, at hver logmeddelelse leveres til destinationen io.Writer
med en enkelt Writer.Write()
ring:
Hver logning foretager et enkelt kald til Writer's Write-metoden. En Logger kan bruges samtidigt fra flere goroutiner; det garanterer at serialisere adgang til Writer.
Så dybest set skal du bare oprette en type, som implementerer io.Writer
, og hvis Write()
metoden opretter et nyt dokument med indholdet af byte-udsnittet og gemmer det i MongoDB.
Her er en simpel implementering, der gør det:
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
}
Bruger det:
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.")
Selvfølgelig, hvis du bruger en anden log.Logger
forekomst, skal du indstille MongoWriter
til det, f.eks.:
mylogger := log.New(mw, "", 0)
mylogger.Println("Custom logger")
Bemærk, at logmeddelelserne slutter med newline som log.Logger
tilføjer det, selvom selve logmeddelelsen ikke slutter med ny linje. Hvis du ikke ønsker at logge den afsluttende nylinje, kan du blot klippe den, f.eks.:
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)
}