feat: 添加mml日志和操作日志收集中间件
This commit is contained in:
68
lib/midware/mml_log.go
Normal file
68
lib/midware/mml_log.go
Normal 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
136
lib/midware/operate_log.go
Normal 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)
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,6 +30,7 @@ import (
|
|||||||
"ems.agt/features/ue"
|
"ems.agt/features/ue"
|
||||||
"ems.agt/lib/midware"
|
"ems.agt/lib/midware"
|
||||||
"ems.agt/lib/services"
|
"ems.agt/lib/services"
|
||||||
|
"ems.agt/src/framework/middleware/collectlogs"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
@@ -169,12 +170,12 @@ func init() {
|
|||||||
//ne service action handle
|
//ne service action handle
|
||||||
Register("POST", cm.UriNeInstance, cm.PostNeInstanceAction, nil)
|
Register("POST", cm.UriNeInstance, cm.PostNeInstanceAction, nil)
|
||||||
// Post MML command to NF
|
// 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.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.CustomUriMML, mml.PostMMLToNF, midware.LogMML)
|
||||||
Register("POST", mml.CustomUriOmMmlExt, mml.PostMMLToOMC, nil)
|
Register("POST", mml.CustomUriOmMmlExt, mml.PostMMLToOMC, midware.LogMML)
|
||||||
// Northbound Get NRM
|
// Northbound Get NRM
|
||||||
Register("GET", nbi.GetNRMUri, nbi.NBIGetNRMFromNF, nil)
|
Register("GET", nbi.GetNRMUri, nbi.NBIGetNRMFromNF, nil)
|
||||||
|
|
||||||
@@ -219,9 +220,9 @@ func init() {
|
|||||||
Register("POST", cm.CustomUriLicenseExt, cm.UploadLicenseFileData, nil)
|
Register("POST", cm.CustomUriLicenseExt, cm.UploadLicenseFileData, nil)
|
||||||
|
|
||||||
// Trace management
|
// Trace management
|
||||||
Register("POST", trace.UriTraceTask, trace.PostTraceTaskToNF, nil)
|
Register("POST", trace.UriTraceTask, trace.PostTraceTaskToNF, midware.LogOperate(collectlogs.OptionNew("跟踪任务", collectlogs.BUSINESS_TYPE_INSERT)))
|
||||||
Register("PUT", trace.UriTraceTask, trace.PutTraceTaskToNF, nil)
|
Register("PUT", trace.UriTraceTask, trace.PutTraceTaskToNF, midware.LogOperate(collectlogs.OptionNew("跟踪任务", collectlogs.BUSINESS_TYPE_UPDATE)))
|
||||||
Register("DELETE", trace.UriTraceTask, trace.DeleteTraceTaskToNF, nil)
|
Register("DELETE", trace.UriTraceTask, trace.DeleteTraceTaskToNF, midware.LogOperate(collectlogs.OptionNew("跟踪任务", collectlogs.BUSINESS_TYPE_DELETE)))
|
||||||
Register("GET", trace.UriTraceDecMsg, trace.ParseRawMsg2Html, nil)
|
Register("GET", trace.UriTraceDecMsg, trace.ParseRawMsg2Html, nil)
|
||||||
|
|
||||||
Register("POST", trace.CustomUriTraceTask, trace.PostTraceTaskToNF, nil)
|
Register("POST", trace.CustomUriTraceTask, trace.PostTraceTaskToNF, nil)
|
||||||
@@ -229,14 +230,14 @@ func init() {
|
|||||||
Register("DELETE", trace.CustomUriTraceTask, trace.DeleteTraceTaskToNF, nil)
|
Register("DELETE", trace.CustomUriTraceTask, trace.DeleteTraceTaskToNF, nil)
|
||||||
|
|
||||||
// 网元发送执行 pcap抓包
|
// 网元发送执行 pcap抓包
|
||||||
Register("POST", trace.UriTcpdumpTask, 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.Authorize(nil))
|
Register("POST", trace.CustomUriTcpdumpTask, trace.TcpdumpNeTask, midware.LogOperate(collectlogs.OptionNew("抓包任务", collectlogs.BUSINESS_TYPE_INSERT)))
|
||||||
// 网元发送执行 抓包下载pcap文件
|
// 网元发送执行 抓包下载pcap文件
|
||||||
Register("POST", trace.UriTcpdumpPcapDownload, 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.Authorize(nil))
|
Register("POST", trace.CustomUriTcpdumpPcapDownload, trace.TcpdumpPcapDownload, midware.LogOperate(collectlogs.OptionNew("抓包任务", collectlogs.BUSINESS_TYPE_EXPORT)))
|
||||||
// 网元发送执行UPF pcap抓包
|
// 网元发送执行UPF pcap抓包
|
||||||
Register("POST", trace.UriTcpdumpNeUPFTask, trace.TcpdumpNeUPFTask, nil)
|
Register("POST", trace.UriTcpdumpNeUPFTask, trace.TcpdumpNeUPFTask, midware.LogOperate(collectlogs.OptionNew("抓包任务", collectlogs.BUSINESS_TYPE_INSERT)))
|
||||||
Register("POST", trace.CustomUriTcpdumpNeUPFTask, trace.TcpdumpNeUPFTask, nil)
|
Register("POST", trace.CustomUriTcpdumpNeUPFTask, trace.TcpdumpNeUPFTask, midware.LogOperate(collectlogs.OptionNew("抓包任务", collectlogs.BUSINESS_TYPE_INSERT)))
|
||||||
|
|
||||||
// file management
|
// file management
|
||||||
Register("POST", file.UriFile, file.UploadFile, nil)
|
Register("POST", file.UriFile, file.UploadFile, nil)
|
||||||
|
|||||||
Reference in New Issue
Block a user