package middleware import ( "bytes" "encoding/json" "fmt" "git.qianqiusoft.com/qianqiusoft/light-apiengine/config" "github.com/gin-gonic/gin" "github.com/gocql/gocql" "strconv" "strings" "time" ) var __logInfoChan chan *logInfo // cassandra 配置 var _clusterCfg *gocql.ClusterConfig = nil // app名称 var __appName string = "" func init(){ defer func() { if p := recover(); p != nil { fmt.Println("ecover", p) } }() // 设置app名称 __appName = config.AppConfig.GetKey("app_name") __logInfoChan = make(chan *logInfo, 1000) // 设置cassandar 配置 cassandra := config.AppConfig.GetKey("cassandra") keyspace := config.AppConfig.GetKey("keyspace") _clusterCfg = gocql.NewCluster(strings.Split(cassandra, ",")...) _clusterCfg.Keyspace = keyspace _clusterCfg.Consistency = gocql.Quorum //设置连接池的数量,默认是2个(针对每一个host,都建立起NumConns个连接) _clusterCfg.NumConns = 3 session, err := _clusterCfg.CreateSession() if err != nil{ fmt.Println("create session err", err.Error()) return } time.Sleep(1 * time.Second) //Sleep so the fillPool can complete. defer session.Close() // 日志处理 logProcess() } /** * 自定义日志响应类,主要是把resp的响应内容写入到body中 */ type loggerRespWriter struct{ gin.ResponseWriter respBody *bytes.Buffer } // 写字节数组 func (w loggerRespWriter) Write(b []byte) (int, error) { w.respBody.Write(b) // 保存 return w.ResponseWriter.Write(b) } // 写字符串 func (w loggerRespWriter) WriteString(s string) (int, error) { w.respBody.WriteString(s) // 保存 return w.ResponseWriter.WriteString(s) } /** * 日志信息 */ type logInfo struct { ReqClientIp string ReqTime time.Time ReqMethod string ReqUrl string ReqProto string ReqUa string ReqReferer string ReqPostData string RespTime time.Time RespBody string RespCode string // 由 resp body 解析 RespMsg string // 由 resp body 解析 RespData string // 由 resp body 解析 CostTime float64 } func LoggerCassandra()gin.HandlerFunc{ return func(c *gin.Context){ respWriter := &loggerRespWriter{ ResponseWriter: c.Writer, respBody: bytes.NewBuffer([]byte{}), } c.Writer = respWriter // 注入自定writer logInfo := &logInfo{} logInfo.ReqTime = time.Now() // 下一个请求 c.Next() // 设置对象 logInfo.RespBody = respWriter.respBody.String() logInfo.RespTime = time.Now() logInfo.ReqMethod = c.Request.Method logInfo.ReqUrl = c.Request.RequestURI logInfo.ReqProto = c.Request.Proto logInfo.ReqUa = c.Request.UserAgent() logInfo.ReqReferer = c.Request.Referer() logInfo.ReqPostData = c.Request.PostForm.Encode() logInfo.ReqClientIp = c.ClientIP() __logInfoChan <- logInfo } } func logProcess(){ go func(){ for{ select { case logInfo := <- __logInfoChan: insertLogInfo(logInfo) } } }() } func insertLogInfo(logInfo *logInfo){ session, err := _clusterCfg.CreateSession() if err != nil{ fmt.Println("创建cassandra session错误", err.Error()) return } defer session.Close() var respBodyObj struct { Code int Msg string Data interface{} } if logInfo.RespBody != ""{ err = json.Unmarshal([]byte(logInfo.RespBody), &respBodyObj) if err != nil{ fmt.Println("json.Unmarshal 错误", err.Error()) }else { logInfo.RespCode = strconv.Itoa(respBodyObj.Code) logInfo.RespMsg = respBodyObj.Msg if respBodyObj.Data != nil{ str, err := json.Marshal(respBodyObj.Data) if err == nil{ logInfo.RespData = string(str) } } } } logInfo.CostTime = float64(logInfo.RespTime.Sub(logInfo.ReqTime).Seconds()) cqlformat := `insert into log_info(app_name, req_date, req_time, req_method, req_url, req_proto, req_ua, req_referer, req_post_data, resp_time, resp_body, resp_code, resp_msg, resp_data, cost_time) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);` reqDate := logInfo.ReqTime.Format("20060102") //q := session.Query(cqlformat, __appName, reqDate, logInfo.ReqTime.Format("2006-01-02 15:04:05"), logInfo.ReqMethod, logInfo.ReqUrl, logInfo.ReqProto, logInfo.ReqUa, logInfo.ReqReferer, logInfo.ReqPostData, logInfo.RespTime.Format("2006-01-02 15:04:05"), logInfo.RespBody, logInfo.RespCode, logInfo.RespMsg, logInfo.RespData, logInfo.CostTime) batch := session.NewBatch(gocql.UnloggedBatch) // 应该批量插入多条,例如20条 batch.Query(cqlformat, __appName, reqDate, logInfo.ReqTime.Format("2006-01-02 15:04:05"), logInfo.ReqMethod, logInfo.ReqUrl, logInfo.ReqProto, logInfo.ReqUa, logInfo.ReqReferer, logInfo.ReqPostData, logInfo.RespTime.Format("2006-01-02 15:04:05"), logInfo.RespBody, logInfo.RespCode, logInfo.RespMsg, logInfo.RespData, logInfo.CostTime) if err := session.ExecuteBatch(batch); err != nil { fmt.Println("批量插入日志错误:", err) return } }