Files
ant-black 70132417ad publish: 1.2.0 snapshot (f3d7ec5)
channel: master

version: 1.2.0

source-ref: D:\code\open_source\ant-chrome master

source-commit: f3d7ec5

merged-public-base: 3d264eb
2026-05-05 18:08:10 +08:00

156 lines
3.9 KiB
Go

package logger
import (
"fmt"
"runtime"
"strings"
"time"
)
// beforeCall 方法调用前的处理
func (m *MethodInterceptor) beforeCall(methodName string, params []interface{}) *CallContext {
ctx := &CallContext{
RequestID: GenerateRequestID(),
MethodName: methodName,
StartTime: time.Now(),
Parameters: params,
}
// 记录方法入口日志
entry := NewLogEntry(INFO, "interceptor", fmt.Sprintf("Method call started: %s", methodName))
entry.WithRequestID(ctx.RequestID)
entry.WithMethod(methodName)
// 添加参数信息
if m.config.LogParameters && len(params) > 0 {
maskedParams := m.maskSensitiveParams(params)
entry.WithFields(map[string]interface{}{
"parameters": maskedParams,
})
}
// 添加调用位置
if file, line := m.getCaller(); file != "" {
entry.WithCaller(file, line)
}
m.safeLog(entry)
return ctx
}
// afterCallRecover 方法调用后的处理(带 panic 恢复)
func (m *MethodInterceptor) afterCallRecover(ctx *CallContext, result interface{}, err error) {
// 捕获 panic,确保日志错误不影响业务
if r := recover(); r != nil {
m.handlePanic(ctx, r)
// 重新抛出 panic,让业务代码处理
panic(r)
}
m.afterCall(ctx, result, err)
}
// afterCall 方法调用后的处理
func (m *MethodInterceptor) afterCall(ctx *CallContext, result interface{}, err error) {
duration := time.Since(ctx.StartTime).Milliseconds()
var entry *LogEntry
if err != nil {
// 错误情况
entry = NewLogEntry(ERROR, "interceptor", fmt.Sprintf("Method call failed: %s", ctx.MethodName))
entry.WithError(err.Error())
// 获取堆栈信息
stack := m.getStackTrace()
if stack != "" {
if entry.Fields == nil {
entry.Fields = make(map[string]interface{})
}
entry.Fields["stack_trace"] = stack
}
} else {
// 成功情况
entry = NewLogEntry(INFO, "interceptor", fmt.Sprintf("Method call completed: %s", ctx.MethodName))
// 记录返回结果
if m.config.LogResults && result != nil {
maskedResult := m.maskSensitiveValue("result", result)
if entry.Fields == nil {
entry.Fields = make(map[string]interface{})
}
entry.Fields["result"] = maskedResult
}
}
entry.WithRequestID(ctx.RequestID)
entry.WithMethod(ctx.MethodName)
entry.WithDuration(duration)
m.safeLog(entry)
}
// handlePanic 处理 panic
func (m *MethodInterceptor) handlePanic(ctx *CallContext, panicValue interface{}) {
duration := time.Since(ctx.StartTime).Milliseconds()
entry := NewLogEntry(ERROR, "interceptor", fmt.Sprintf("Method call panicked: %s", ctx.MethodName))
entry.WithRequestID(ctx.RequestID)
entry.WithMethod(ctx.MethodName)
entry.WithDuration(duration)
entry.WithError(fmt.Sprintf("panic: %v", panicValue))
// 获取堆栈信息
stack := m.getStackTrace()
if stack != "" {
if entry.Fields == nil {
entry.Fields = make(map[string]interface{})
}
entry.Fields["stack_trace"] = stack
}
m.safeLog(entry)
}
// safeLog 安全地记录日志(捕获所有错误)
func (m *MethodInterceptor) safeLog(entry *LogEntry) {
defer func() {
if r := recover(); r != nil {
// 日志系统出错,静默处理,不影响业务
fmt.Printf("[INTERCEPTOR ERROR] Failed to log: %v\n", r)
}
}()
if m.logger != nil {
m.logger.LogEntry(entry)
}
}
// getCaller 获取调用位置
func (m *MethodInterceptor) getCaller() (string, int) {
// 跳过拦截器内部的调用栈
for i := 3; i < 10; i++ {
_, file, line, ok := runtime.Caller(i)
if !ok {
break
}
// 跳过拦截器自身的文件
if !strings.Contains(file, "interceptor.go") && !strings.Contains(file, "interceptor_") {
// 只保留文件名
parts := strings.Split(file, "/")
if len(parts) > 0 {
return parts[len(parts)-1], line
}
return file, line
}
}
return "", 0
}
// getStackTrace 获取堆栈信息
func (m *MethodInterceptor) getStackTrace() string {
buf := make([]byte, 4096)
n := runtime.Stack(buf, false)
return string(buf[:n])
}