GF框架接口日志优化

GF框架接口日志优化

 次点击
12 分钟阅读

先看效果

优化前

日志杂乱无章,阅读难度高,想要找某个接口的相关信息基本上找不到

优化后

接口信息一目了然

优化教程

utility -> utils.go

// PrettyPrint函数用于将传入的interface{}类型的变量v格式化为JSON字符串并打印出来
func PrettyPrint(v interface{}) string {
	// 将v转换为JSON字符串
	b, err := json.Marshal(v)
	// 如果转换失败,则直接打印v
	if err != nil {
		fmt.Println(v)
		return ""
	}

	// 创建一个bytes.Buffer类型的变量out,用于存储格式化后的JSON字符串
	var out bytes.Buffer
	// 使用json.Indent函数将b格式化为JSON字符串,并存储在out中
	err = json.Indent(&out, b, "", "  ")
	// 如果格式化失败,则直接打印v
	if err != nil {
		fmt.Println(v)
		return ""
	}

	// 打印格式化后的JSON字符串
	return out.String()
}

// RequestLogBeautification 请求日志美化
func RequestLogBeautification(r *ghttp.Request) (logInfo string) {
	// 获取请求上下文
	ctx := contexts.Get(r.Context())
	// 解析日志数据
	logData := service.SysLog().AnalysisLog(r.Context())
	// 默认用户名为“用户未登录”
	userName := "用户未登录"
	// 获取用户信息
	userInfo := contexts.GetUser(r.Context())
	// 如果用户信息不为空,则设置用户名为用户名和ID的组合
	if userInfo != nil {
		userName = fmt.Sprintf("%s[%d]", userInfo.Username, userInfo.Id)
	}
	// 初始化日志信息
	logInfo = "\n"
	// 获取请求处理程序
	handler := r.GetServeHandler().Handler
	// 如果处理程序类型为空或参数数量不为2,则返回错误
	if handler.Info.Type == nil || handler.Info.Type.NumIn() != 2 {
		logInfo = "err"
		return
	}
	// 创建请求参数对象
	var objectReq = reflect.New(handler.Info.Type.In(1))
	// 获取请求参数的tags和summary
	tags := gmeta.Get(objectReq, "tags")
	summary := gmeta.Get(objectReq, "summary")
	// 设置日志信息
	logInfo = fmt.Sprintf("%s\n————————————————————>  %s — %s  <————————————————————\n", logInfo, tags, summary)
	// 获取日志时间戳并格式化
	timestamp := time.Unix(logData.Timestamp, 0).Format("2006-01-02 15:04:05")

	// 设置日志信息
	logInfo = fmt.Sprintf(
		"%s\n请求模块:%s\n操作用户:%s\n请求方法:%s\n接口路径:%s\n请求耗时:%s\nIP地址:%s\n响应时间:%s\nGET数据:%s\nPOST数据:%s\n",
		logInfo,
		logData.Module,
		userName,
		logData.Method,
		logData.Url,
		AutomaticTimeConversion(strconv.FormatInt(logData.TakeUpTime, 10)),
		logData.Ip,
		timestamp,
		PrettyPrint(logData.GetData),
		PrettyPrint(logData.PostData),
	)
	// 获取响应数据并格式化
	data := PrettyPrint(ctx.Response)
	// 设置日志信息
	logInfo = fmt.Sprintf("%s报错信息:%s\n", logInfo, logData.ErrorData.String())
	logInfo = fmt.Sprintf("%s响应结果:%s\n", logInfo, data)
	// 设置日志信息
	logInfo = fmt.Sprintf("%s\n————————————————————请求完成————————————————————\n\n", logInfo)
	// 返回日志信息
	return
}

// AutomaticTimeConversion 自动时间转换
func AutomaticTimeConversion(timeStr string) string {
	// 将毫秒转换为time.Duration类型
	duration, err := time.ParseDuration(timeStr + "ms")
	if err != nil {
		return "Invalid time"
	}

	if duration > time.Minute {
		minute := int(duration.Minutes())
		seconds := int(duration.Seconds()) % 60
		return fmt.Sprintf("%d分%d秒", minute, seconds)
	}

	// 如果时间间隔小于1秒,则直接返回毫秒数
	if duration < time.Second {
		return fmt.Sprintf("%d毫秒", int(duration.Milliseconds()))
	}

	// 如果时间间隔大于等于1秒,则转换为秒和毫秒
	seconds := int(duration.Seconds())
	milliseconds := int(duration.Milliseconds()) % 1000
	return fmt.Sprintf("%d秒%d毫秒", seconds, milliseconds)
}

internal -> logic -> hook -> init.go

func (s *sHook) AfterOutput(r *ghttp.Request) {
	s.accessLog(r)
	s.lastAdminActive(r)
	logStr := ""
	if logStr = utility.RequestLogBeautification(r); logStr != "err" {
		g.Log().Infof(gctx.New(), "%s", logStr)
	}
}

© 本文著作权归作者所有,未经许可不得转载使用。