2016-11-03 64 views
3

使用转到(golang):去,因为登录到MongoDB的创建io.Writer inteface数据库

有没有一种方法来创建输出到一个数据库中的记录?

或者更准确地说,我可以实现某种io.Writer接口,我可以将其作为第一个参数传递给log.New()

EG:(dbLogger将接收日志的输出,并将其写入数据库)

logger := log.New(dbLogger, "dbLog: ", log.Lshortfile) logger.Print("This message will be stored in the database")

我会假设,我应该创建自己的数据库记录功能,但我对使用语言中的现有工具是否已经有这种方法感到好奇。

对于某些情况下,我使用mgo.v2来处理我的mongodb数据库,但除GridFS之外我没有看到任何io.Writer接口,我认为这解决了另一个问题。

我也对我的语言很感兴趣,所以我可能已经使用了一些不合适的术语。任何更正都非常受欢迎。

回答

4

这是很容易可行,因为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) 
} 
+0

太棒了!我假设我们不能在Write函数中处理额外的参数,因为所有的方法都可以接收到一个字节的slice是正确的?将额外的参数发送到该函数,比如堆栈跟踪或其他重要的数据是非常好的,但是我们必须通过该字节片段发送它,然后将其分割正确吗? – 17xande

+1

@ 17xande更正,'Write()'方法只需要一个字节片。你也可以从'Write()'中访问堆栈跟踪,这不是问题(参见''runtime.Callers()'](https://golang.org/pkg/runtime/#Caller)和['runtime。CallersFrames()'](https://golang.org/pkg/runtime/#CallersFrames))。如果您希望记录其他重要数据,请将其包含在日志消息中(例如,将它们传递给'Logger.Printf()')。 – icza