MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Go:Erstellen Sie eine io.Writer-Schnittstelle für die Protokollierung in der Mongodb-Datenbank

Dies ist leicht machbar, da der log.Logger Typ garantiert, dass jede Protokollnachricht an das Ziel io.Writer zugestellt wird mit einem einzigen Writer.Write() Aufruf:

Jeder Protokollierungsvorgang ruft die Methode Writer's Write einmal auf. Ein Logger kann gleichzeitig von mehreren Goroutinen verwendet werden; es garantiert den Zugriff auf den Writer zu serialisieren.

Im Grunde müssen Sie also nur einen Typ erstellen, der io.Writer implementiert , und deren Write() -Methode erstellt ein neues Dokument mit dem Inhalt des Byte-Slice und speichert es in der MongoDB.

Hier ist eine einfache Implementierung, die das tut:

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
}

Verwendung:

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.")

Offensichtlich, wenn Sie einen anderen log.Logger verwenden Legen Sie beispielsweise den MongoWriter fest dazu z.B.:

mylogger := log.New(mw, "", 0)
mylogger.Println("Custom logger")

Beachten Sie, dass die Log-Meldungen mit Newline als log.Logger enden hängt es an, auch wenn die Protokollnachricht selbst nicht mit Zeilenumbruch endet. Wenn Sie den Zeilenumbruch am Ende nicht protokollieren möchten, können Sie ihn einfach abschneiden, z. B.:

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)
}