package traces import ( "basic.com/valib/bhomeclient.git" "basic.com/valib/logc.git" "basic.com/valib/logger.git" "bytes" "fmt" "github.com/gin-gonic/gin" "github.com/pkg/errors" "io/ioutil" "mime" "net/url" "strings" "sync" "time" "vamicro/api-gateway/auth" "vamicro/api-gateway/models" "vamicro/api-gateway/service" "vamicro/config" ) type OperationPara struct { Context *gin.Context Error error Reply *bhomeclient.Reply } var ( blockSet = map[string]interface{}{} allowSet = map[string]interface{}{} methodBlockSet = map[string]map[string]interface{}{} methodAllowSet = map[string]map[string]interface{}{} moduleMap = map[string]string{} wg sync.WaitGroup done chan struct{} cModule string ) func DeInit() { close(done) wg.Wait() } func Init(logCallback logc.LogReportCallback) { done = make(chan struct{}) wg.Add(1) log := &logc.Log{ FatalLog: logger.Fatal, ErrorLog: logger.Error, WarnLog: logger.Warn, InfoLog: logger.Info, } logc.Init(logCallback, log, service.ProcName, service.ProcName, &wg, done) } func SetModuleMap(newmoduleMap map[string]string) { moduleMap = newmoduleMap } func SetBlockMethod(list [] models.Operations) { for _, v := range list { if v.Method == "*" || v.Method == "" || true { if v.Exclude { blockSet[v.Path] = v } else { allowSet[v.Path] = v } } else { if v.Exclude { if m, ok := methodBlockSet[v.Method]; ok { m[v.Path] = true } else { m := make(map[string]interface{}) m[v.Path] = v methodBlockSet[v.Method] = m } } else { if m, ok := methodAllowSet[v.Method]; ok { m[v.Path] = v } else { m := make(map[string]interface{}) m[v.Path] = v methodAllowSet[v.Method] = m } } } } } func blockOrAllow(method, path string) (string, bool) { var module models.Modules if len (strings.Split(path, "/")) > 3 { modulePart := strings.Split(path, "/")[3] module.NameZh = modulePart module.ProcName = modulePart isNew := module.Insert() cModule = modulePart if isNew { moduleMap[cModule] = cModule } } //logger.Debug(method,methodAllowSet[method]) if m, exist := methodAllowSet[method]; exist { if v, ok := m[path]; ok { return v.(models.Operations).Name, true } } //logger.Debug(allowSet,path) if v, ok := allowSet[path]; ok { return v.(models.Operations).Name, true } var name string if config.Traceconf.UseBlockList != 0 { if m, exist := methodBlockSet[method]; exist { if v, ok := m[path]; ok { return v.(models.Operations).Name, false } } if v, ok := blockSet[path]; ok { return v.(models.Operations).Name, false } //return name, true } var op models.Operations op.Name = path op.Exclude = false op.Method = method op.Path = path op.Module = cModule op.Insert() if _, ok := allowSet[path]; ok { } else { allowSet[path] = op } return name, true } func TraceOperation(op *OperationPara) { defer func() { if r := recover(); r != nil { logger.Error("TraceOperation recover...", r) } }() funcName, allow := blockOrAllow(op.Context.Request.Method, op.Context.Request.URL.Path) if !allow { logger.Debug(op.Context.Request.URL.Path, " op log skipped") return } serviceName := moduleMap[cModule] var success bool = false var msg string if op.Error != nil { msg = op.Error.Error() } else { if !op.Reply.Success { msg = op.Reply.Msg } else { success = true } } var buffer = new(bytes.Buffer) n, err := buffer.ReadFrom(op.Context.Request.Body) if nil == err && n > 0 { _ = op.Context.Request.Body.Close(); op.Context.Request.Body = ioutil.NopCloser(buffer) } queries, err := url.ParseQuery(op.Context.Request.URL.RawQuery) if nil != err { logger.Error("TraceOperation recover...", err) queries = url.Values{} } var userName string authDriver := auth.GenerateAuthDriver() user := (*authDriver).User(op.Context) if nil != user { userName = user["username"].(string) } else { logger.Warn("TraceOperations failed to get user...", op.Context.Request.URL.Path, op.Context.Request.Method) } contentType := op.Context.Request.Header.Get("Content-Type") body, err := parseContent(contentType, buffer) var bodyString string if nil == err { bodyString = fmt.Sprint(body) } else { bodyString = buffer.String() } var queryString string if len(queries) > 0 { queryString = fmt.Sprint(queries) } var result string var paraBuf bytes.Buffer paraBuf.WriteString(bodyString) paraBuf.WriteString(queryString) if success { result = "成功" } else { result = "失败" } if funcName == "" { funcName = op.Context.Request.URL.Path } log := &logc.OperationLog{ Timestamp: time.Now().Unix(), UserName: userName, Module: serviceName, Function: funcName, Result: result, Para: paraBuf.String(), Msg: msg, Ip: op.Context.ClientIP(), AddTime: time.Now().Format("2006-01-02 15:04:05"), } logger.Debug(log) logc.SaveOperationLog(log, 500 * time.Millisecond) } func parseContent(contentType string, buf* bytes.Buffer) (url.Values, error) { if "" == contentType { contentType = "application/octet-stream" } ct, _, err := mime.ParseMediaType(contentType) if nil == err { if ct == "application/x-www-form-urlencoded" { return url.ParseQuery(buf.String()) } } return nil, errors.New("not supported") } //func TraceOperations() gin.HandlerFunc { // return func(c *gin.Context) { // c.Next() // // defer func() { // if r := recover(); r != nil { // logger.Error("TraceOperations recover...", r) // } // }() // // var buffer = new(bytes.Buffer) // n, err := buffer.ReadFrom(c.Request.Body) // if nil == err && n > 0 { // _ = c.Request.Body.Close(); // c.Request.Body = ioutil.NopCloser(buffer) // } // // //contentType := c.Request.Header.Get("Content-Type") // // formValues, err := url.ParseQuery(c.Request.URL.RawQuery) // if nil == err { // fmt.Print("formValues in hood:", formValues) // } else { // fmt.Print("formValues in hood:", err) // } // // var userName string // authDriver := auth.GenerateAuthDriver() // user := (*authDriver).User(c) // if nil != user { // userName = user["username"].(string) // } else { // logger.Warn("TraceOperations failed to get user...", c.Request.URL.Path, c.Request.Method) // } // // var module string // if m, exists := c.Get("module"); exists { // module = m.(string) // } // // c.JSON(200, "") // // // contentType := c.Request.Header.Get("Content-Type") // logc.Log(userName, c.Request.Method, c.Request.URL.Path, contentType, module, buffer, formValues) // } //}