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