duandeng2011 2016-11-03 08:05
浏览 46
已采纳

转到:创建io.Writer接口以登录到mongodb数据库

Using go (golang):

Is there a way to create a logger that outputs to a database?

Or more precisely, can I implement some kind of io.Writer interface that I can pass as the first argument to log.New()?

EG: (dbLogger would receive the output of the log and write it to the database)

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

I would assume that I should just create my own database logging function, but I was curious to see if there is already a way of doing this using the existing tools in the language.

For some context, I'm using mgo.v2 to handle my mongodb database, but I don't see any io.Writer interfaces there other than in GridFS, which I think solves a different problem.

I'm also still getting my head around the language, so I may have used some terms above incorrecly. Any corrections are very welcome.

  • 写回答

1条回答 默认 最新

  • douji0073 2016-11-03 08:41
    关注

    This is easily doable, because the log.Logger type guarantees that each log message is delivered to the destination io.Writer with a single Writer.Write() call:

    Each logging operation makes a single call to the Writer's Write method. A Logger can be used simultaneously from multiple goroutines; it guarantees to serialize access to the Writer.

    So basically you just need to create a type which implements io.Writer, and whose Write() method creates a new document with the contents of the byte slice, and saves it in the MongoDB.

    Here's a simple implementation which does that:

    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
    }
    

    Using it:

    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,
    but will still be in a single log message.")
    

    Obviously if you're using another log.Logger instance, set the MongoWriter to that, e.g.:

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

    Note that the log messages end with newline as log.Logger appends it even if the log message itself does not end with newline. If you don't want to log the ending newline, you may simply cut it, e.g.:

    func (mw *MongoWriter) Write(p []byte) (n int, err error) {
        origLen := len(p)
        if len(p) > 0 && p[len(p)-1] == '
    ' {
            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)
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 求螺旋焊缝的图像处理
  • ¥15 blast算法(相关搜索:数据库)
  • ¥15 请问有人会紧聚焦相关的matlab知识嘛?
  • ¥15 网络通信安全解决方案
  • ¥50 yalmip+Gurobi
  • ¥20 win10修改放大文本以及缩放与布局后蓝屏无法正常进入桌面
  • ¥15 itunes恢复数据最后一步发生错误
  • ¥15 关于#windows#的问题:2024年5月15日的win11更新后资源管理器没有地址栏了顶部的地址栏和文件搜索都消失了
  • ¥100 H5网页如何调用微信扫一扫功能?
  • ¥15 讲解电路图,付费求解