feat: 添加mml日志和操作日志收集中间件

This commit is contained in:
TsMask
2023-10-20 18:34:18 +08:00
parent b52a08aeb3
commit 0633f38ca0
3 changed files with 218 additions and 13 deletions

68
lib/midware/mml_log.go Normal file
View File

@@ -0,0 +1,68 @@
package midware
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"time"
"ems.agt/lib/core/datasource"
"ems.agt/lib/core/utils/ctx"
"ems.agt/lib/core/utils/date"
"ems.agt/lib/dborm"
"ems.agt/lib/log"
)
// LogMML mml操作日志搜集
func LogMML(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 读取请求体内容
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
// 解析json内参数
var bodyArgs map[string]any
_ = json.Unmarshal(bytes.Clone(body), &bodyArgs)
// 将请求体内容存储在临时缓冲区中
buffer := bytes.NewBuffer(body)
r.Body = io.NopCloser(buffer)
next.ServeHTTP(w, r)
// 收尾存入数据库的参数
mmlCmd := bodyArgs["mml"].([]any)[0]
ipAddr := strings.Split(r.RemoteAddr, ":")[0]
neType := ctx.Param(r, "elementTypeValue")
neId := ctx.GetQuery(r, "ne_id")
timeStr := date.ParseDateToStr(time.Now(), date.YYYY_MM_DD_HH_MM_SS)
// 响应内容长度和状态码作为结果
str := strings.TrimSuffix(fmt.Sprintf("%v", w), "}")
strArr := strings.Split(str, " ")
size := strArr[1]
status := strArr[2]
contentType := w.Header().Get("Content-Type")
resultStr := fmt.Sprintf(`{"status":"%s","size":"%s","content-type":"%s"}`, status, size, contentType)
// 用户名
username := "-"
accessToken := r.Header.Get("AccessToken")
if accessToken != "" {
// 验证令牌 == 这里直接查数据库session
se, _ := dborm.XormUpdateSessionShakeTime(accessToken)
username = se.AccountId
}
// 执行插入
sql := "insert into mml_log (user,ip,ne_type,ne_id,mml,result,log_time)values(?,?,?,?,?,?,?)"
_, sqlerr := datasource.ExecDB("", sql, []any{username, ipAddr, neType, neId, mmlCmd, resultStr, timeStr})
if sqlerr != nil {
log.Errorf("insert row : %v", err.Error())
}
})
}

136
lib/midware/operate_log.go Normal file
View File

@@ -0,0 +1,136 @@
package midware
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"reflect"
"runtime"
"strings"
"time"
"ems.agt/lib/core/utils/parse"
"ems.agt/lib/dborm"
"ems.agt/src/framework/constants/common"
"ems.agt/src/framework/middleware/collectlogs"
"ems.agt/src/framework/utils/ip2region"
"ems.agt/src/modules/system/model"
"ems.agt/src/modules/system/service"
)
// 敏感属性字段进行掩码
var maskProperties []string = []string{
"password",
"oldPassword",
"newPassword",
"confirmPassword",
}
// LogOperate 操作日志搜集
func LogOperate(options collectlogs.Options) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
startTime := time.Now()
// 函数名
funcName := runtime.FuncForPC(reflect.ValueOf(next).Pointer()).Name()
lastDotIndex := strings.LastIndex(funcName, "/")
funcName = funcName[lastDotIndex+1:]
// 用户名
username := "-"
accessToken := r.Header.Get("AccessToken")
if accessToken != "" {
// 验证令牌 == 这里直接查数据库session
se, _ := dborm.XormUpdateSessionShakeTime(accessToken)
username = se.AccountId
}
// 解析ip地址
ip := strings.Split(r.RemoteAddr, ":")[0]
ipaddr := ip2region.ClientIP(ip)
location := ip2region.RealAddressByIp(ipaddr)
// 操作日志记录
operLog := model.SysLogOperate{
Title: options.Title,
BusinessType: options.BusinessType,
OperatorType: collectlogs.OPERATOR_TYPE_MANAGE,
Method: funcName,
OperURL: r.RequestURI,
RequestMethod: r.Method,
OperIP: ipaddr,
OperLocation: location,
OperName: username,
DeptName: "",
}
// 是否需要保存request参数和值
if options.IsSaveRequestData && (r.Method == "POST" || r.Method == "PUT") {
// 读取请求体内容
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
// 解析json内参数
var bodyArgs map[string]any
_ = json.Unmarshal(bytes.Clone(body), &bodyArgs)
// 将请求体内容存储在临时缓冲区中
buffer := bytes.NewBuffer(body)
r.Body = io.NopCloser(buffer)
params := bodyArgs
for k, v := range params {
// 敏感属性字段进行掩码
for _, s := range maskProperties {
if s == k {
params[k] = parse.SafeContent(v.(string))
break
}
}
}
jsonStr, _ := json.Marshal(params)
paramsStr := string(jsonStr)
if len(paramsStr) > 2000 {
paramsStr = paramsStr[:2000]
}
operLog.OperParam = paramsStr
}
next.ServeHTTP(w, r)
// 响应内容长度和状态码作为结果
str := strings.TrimSuffix(fmt.Sprintf("%v", w), "}")
strArr := strings.Split(str, " ")
size := strArr[1]
status := strArr[2]
// 响应状态
if status == "200" {
operLog.Status = common.STATUS_YES
} else {
operLog.Status = common.STATUS_NO
}
// 是否需要保存response参数和值
if options.IsSaveResponseData {
contentDisposition := w.Header().Get("Content-Disposition")
contentType := w.Header().Get("Content-Type")
content := contentType + contentDisposition
msg := fmt.Sprintf(`{"status":"%s","size":"%s","content-type":"%s"}`, status, size, content)
operLog.OperMsg = msg
}
// 日志记录时间
duration := time.Since(startTime)
operLog.CostTime = duration.Milliseconds()
operLog.OperTime = time.Now().UnixMilli()
// 保存操作记录到数据库
service.NewSysLogOperateImpl.InsertSysLogOperate(operLog)
})
}
}

View File

@@ -30,6 +30,7 @@ import (
"ems.agt/features/ue"
"ems.agt/lib/midware"
"ems.agt/lib/services"
"ems.agt/src/framework/middleware/collectlogs"
"github.com/gorilla/mux"
)
@@ -169,12 +170,12 @@ func init() {
//ne service action handle
Register("POST", cm.UriNeInstance, cm.PostNeInstanceAction, nil)
// Post MML command to NF
Register("POST", mml.UriMML, mml.PostMMLToNF, nil)
Register("POST", mml.UriMML, mml.PostMMLToNF, midware.LogMML)
Register("POST", mml.UriMMLDiscard, mml.PostMMLToNF, nil)
Register("POST", mml.UriOmMmlExt, mml.PostMMLToOMC, nil)
Register("POST", mml.UriOmMmlExt, mml.PostMMLToOMC, midware.LogMML)
Register("POST", mml.CustomUriMML, mml.PostMMLToNF, nil)
Register("POST", mml.CustomUriOmMmlExt, mml.PostMMLToOMC, nil)
Register("POST", mml.CustomUriMML, mml.PostMMLToNF, midware.LogMML)
Register("POST", mml.CustomUriOmMmlExt, mml.PostMMLToOMC, midware.LogMML)
// Northbound Get NRM
Register("GET", nbi.GetNRMUri, nbi.NBIGetNRMFromNF, nil)
@@ -219,9 +220,9 @@ func init() {
Register("POST", cm.CustomUriLicenseExt, cm.UploadLicenseFileData, nil)
// Trace management
Register("POST", trace.UriTraceTask, trace.PostTraceTaskToNF, nil)
Register("PUT", trace.UriTraceTask, trace.PutTraceTaskToNF, nil)
Register("DELETE", trace.UriTraceTask, trace.DeleteTraceTaskToNF, nil)
Register("POST", trace.UriTraceTask, trace.PostTraceTaskToNF, midware.LogOperate(collectlogs.OptionNew("跟踪任务", collectlogs.BUSINESS_TYPE_INSERT)))
Register("PUT", trace.UriTraceTask, trace.PutTraceTaskToNF, midware.LogOperate(collectlogs.OptionNew("跟踪任务", collectlogs.BUSINESS_TYPE_UPDATE)))
Register("DELETE", trace.UriTraceTask, trace.DeleteTraceTaskToNF, midware.LogOperate(collectlogs.OptionNew("跟踪任务", collectlogs.BUSINESS_TYPE_DELETE)))
Register("GET", trace.UriTraceDecMsg, trace.ParseRawMsg2Html, nil)
Register("POST", trace.CustomUriTraceTask, trace.PostTraceTaskToNF, nil)
@@ -229,14 +230,14 @@ func init() {
Register("DELETE", trace.CustomUriTraceTask, trace.DeleteTraceTaskToNF, nil)
// 网元发送执行 pcap抓包
Register("POST", trace.UriTcpdumpTask, trace.TcpdumpNeTask, midware.Authorize(nil))
Register("POST", trace.CustomUriTcpdumpTask, trace.TcpdumpNeTask, midware.Authorize(nil))
Register("POST", trace.UriTcpdumpTask, trace.TcpdumpNeTask, midware.LogOperate(collectlogs.OptionNew("抓包任务", collectlogs.BUSINESS_TYPE_INSERT)))
Register("POST", trace.CustomUriTcpdumpTask, trace.TcpdumpNeTask, midware.LogOperate(collectlogs.OptionNew("抓包任务", collectlogs.BUSINESS_TYPE_INSERT)))
// 网元发送执行 抓包下载pcap文件
Register("POST", trace.UriTcpdumpPcapDownload, trace.TcpdumpPcapDownload, midware.Authorize(nil))
Register("POST", trace.CustomUriTcpdumpPcapDownload, trace.TcpdumpPcapDownload, midware.Authorize(nil))
Register("POST", trace.UriTcpdumpPcapDownload, trace.TcpdumpPcapDownload, midware.LogOperate(collectlogs.OptionNew("抓包任务", collectlogs.BUSINESS_TYPE_EXPORT)))
Register("POST", trace.CustomUriTcpdumpPcapDownload, trace.TcpdumpPcapDownload, midware.LogOperate(collectlogs.OptionNew("抓包任务", collectlogs.BUSINESS_TYPE_EXPORT)))
// 网元发送执行UPF pcap抓包
Register("POST", trace.UriTcpdumpNeUPFTask, trace.TcpdumpNeUPFTask, nil)
Register("POST", trace.CustomUriTcpdumpNeUPFTask, trace.TcpdumpNeUPFTask, nil)
Register("POST", trace.UriTcpdumpNeUPFTask, trace.TcpdumpNeUPFTask, midware.LogOperate(collectlogs.OptionNew("抓包任务", collectlogs.BUSINESS_TYPE_INSERT)))
Register("POST", trace.CustomUriTcpdumpNeUPFTask, trace.TcpdumpNeUPFTask, midware.LogOperate(collectlogs.OptionNew("抓包任务", collectlogs.BUSINESS_TYPE_INSERT)))
// file management
Register("POST", file.UriFile, file.UploadFile, nil)