go-admin框架分析(3—1)—日志系统遗留问题分析

此前分析日志系统时,有两个中间件没搞明白它的作用,后面再看了下,大概理解了。这里再记录下。

	// 添加 requestID
	r.Use(RequestId(pkg.TrafficKey))
	// 添加 go-admin-logger-request
	r.Use(api.SetRequestLogger)

这两个中间件,加了和没加,记录的日志是一样的。当时没搞明白,再看了一下框架的源码,大概理解了:

中间件Use(RequestId(pkg.TrafficKey))

首先呢,RequestId(pkg.TrafficKey)的目的是检测请求头里面是否包含"X-Request-Id",如果不包含,使用uuid生成一个,这个过程好理解,但是为什么不用他,日志也会生成该请求头呢?

发现框架里还有个类似的方法:“github.com\go-admin-team\go-admin-core\sdk@v1.3.10\pkg\utils.go”

// GenerateMsgIDFromContext 生成msgID
func GenerateMsgIDFromContext(c *gin.Context) string {
	requestId := c.GetHeader(TrafficKey)
	if requestId == "" {
		requestId = uuid.New().String()
		c.Header(TrafficKey, requestId)
	}
	return requestId
}

这个方法,乍一看功能也是一样的,其实不同,c.Header(TrafficKey, requestId)是在response的请求头写入,而c.Set(trafficKey, requestId)是给request的请求头写入,这是两回事。

PS: RequestId(pkg.TrafficKey)里面没有将X-Request-Id转化成全小写,所以在我们仅引入该中间件时,日志里的id key是大写的:

if requestId == "" {
	requestId = c.GetHeader(strings.ToLower(trafficKey)) // ToLower转化成小写再检查
}

我看http请求头好像都是用小写的,所以最好就转化成小的。

所以:该中间件做了一下事情:

  1. 检查 X-Request-Id,如果没有,则生成X-Request-Id
  2. 将 X-Request-Id写入request的请求头中
  3. 将logger对象写入request的请求头中

中间件Use(api.SetRequestLogger)

首先呢,她会调用下面这个方法,这个方法前面分析了,其实它是给response写入请求头的,而如果我们启用了前一个中间件,那么这个方法是不执行的。意味着没有给response写入X-Request-Id这个请求头,实测也确实是如此。
PS:所以该框架的本意是想给response写还是不写呢?

requestId := pkg.GenerateMsgIDFromContext(c)

然后呢,在RequestId(pkg.TrafficKey)这个中间件里,就有添加该请求头的代码:

		c.Set(pkg.LoggerKey,
			logger.NewHelper(logger.DefaultLogger).
				WithFields(map[string]interface{}{
					trafficKey: requestId,
				}))

而在本中间件里,也有一样的功能:

	log := logger.NewHelper(sdk.Runtime.GetLogger()).WithFields(map[string]interface{}{
		strings.ToLower(pkg.TrafficKey): requestId,
	})
	c.Set(pkg.LoggerKey, log)

我感觉这里内容重复了。。。可以择其一

所以:该中间件做了一下事情:

  1. 检查X-Request-Id,如果没有,则给response的请求头写入新的X-Request-Id
  2. 将logger对象写入request的请求头中

中间件Use(LoggerToFile())

而在 r.Use(LoggerToFile())这个中间件里,不包含设置pkg.LoggerKey这个请求头的内容,它里面有一句关联紧密的代码:

log := api.GetRequestLogger(c)

这个函数的源代码:

// GetRequestLogger 获取上下文提供的日志
func GetRequestLogger(c *gin.Context) *logger.Helper {
	var log *logger.Helper
	l, ok := c.Get(pkg.LoggerKey)
	if ok {
		ok = false
		log, ok = l.(*logger.Helper)
		if ok {
			return log
		}
	}
	//如果没有在上下文中放入logger
	requestId := pkg.GenerateMsgIDFromContext(c)
	log = logger.NewHelper(sdk.Runtime.GetLogger()).WithFields(map[string]interface{}{
		strings.ToLower(pkg.TrafficKey): requestId,
	})
	return log
}

首先呢,看这里的上半部分代码,它尝试获取“c.Get(pkg.LoggerKey)”,前面两个中间件写入这个LoggerKey请求头,实际上就是将本次请求的logger对象放到c *gin.Context这个对象中,然后后续的业务都会把这个logger对象一直传递下去,保证记录日志的时候都是使用同一个logger对象,这样日志之间才能关联起来。

而下半部分代码,就是在没有获取到这个请求头的情况下,再自己创建这个log 对象,再返回出去。
但是呢,如果抛掉前面两个中间件的话,这样在c *gin.Context就没有放入logger对象,这样呢,后续的步骤写入日志的时候就关联不到该日志对象,也就无法做到日志关联了。

PS:这个中间件实现了一些前面两个中间件没有做的事,所以这个中间件肯定得要

所以:该中间件做了一下事情:

  1. 检查X-Request-Id,如果没有,则给response的请求头写入新的X-Request-Id
  2. 其他事,前面两个中间件没做的事

结论

  1. 总结下来,第一个中间件可以不用,因为 X-Request-Id被包含在logger对象中,完全不需要再把它放到request的请求头中。第二个中间件可以把第一个中间件的其他事做了。
  2. 如果需要用别的方式生成 X-Request-Id那么可以使用第一个中间件

PS: 从记录的日志看,我觉得还是有问题没搞明白,因为我启动程序后首次访问的日志是这样的:

2022-02-26 17:21:48.800+0800 file:apis/health.go:40 level:info 默认值
2022-02-26 17:21:48.800+0800 file:middleware/logger.go:90 latencyTime:530.9µs level:info method:GET statusCode:200 uri:/v1/health x-request-id:5a4b2943-5fdb-4a80-a3fb-da8ad8e2aec3 

第一条日志是我logger.Info(name)这样记录的,它没有完整的信息,但是当我第二次及之后请求接口,它的日志又是完整的:

2022-02-26 17:23:35.336+0800 file:apis/health.go:40 latencyTime:530.9µs level:info method:GET statusCode:200 uri:/v1/health x-request-id:5a4b2943-5fdb-4a80-a3fb-da8ad8e2aec3 默认值
2022-02-26 17:23:35.336+0800 file:middleware/logger.go:90 latencyTime:518.7µs level:info method:GET statusCode:200 uri:/v1/health x-request-id:232c4ac0-eba2-4999-ba15-2d113f6efebe 

时间有限,还得琢磨。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Vue Element Admin是一个基于Vue.js和Element UI的后台管理系统框架。它提供了一个现代化的UI界面,支持灵活的布局和组件,可以快速定制和集成不同的插件和功能模块,适用于各种类型的企业级应用程序。Vue Element Admin还提供了许多有用的功能,如动态路由,权限管理,多语言支持等,可以大大提高开发效率和用户体验。如果你需要一个功能强大,易于使用的后台管理框架,Vue Element Admin是一个不错的选择。 ### 回答2: vue-element-admin是一个基于Vue.js和Element UI的开源框架,用于构建企业级的管理后台系统。它提供了丰富的功能组件和强大的扩展性,可以快速搭建起一个功能完善、美观大气的管理系统。 首先,vue-element-admin框架采用了Vue.js作为前端开发的基础框架,Vue.js具有简单、灵活和高效的特点,能够让开发者快速上手并进行快速开发。而Element UI则是一个基于Vue.js的UI组件库,提供了丰富的组件和样式,使得界面设计简单而美观。 其次,vue-element-admin框架内置了许多常用的功能组件,如表格、表单、图表等,这些组件完善了管理系统的基本功能,开发者可以直接调用这些组件,省去了自己编写这些组件的麻烦。同时,vue-element-admin还支持动态路由和权限控制,可以根据用户的权限动态生成路由和菜单,实现灵活的权限管理。 另外,vue-element-admin框架具有很好的扩展性,开发者可以根据自己的需求对框架进行定制和扩展,包括添加自定义的组件、修改现有组件等。而且,该框架支持国际化,能够适应不同语言和文化的需求,使得项目能够面向全球用户。 总之,vue-element-admin框架是一个功能强大、易于使用的开源框架,能够帮助开发者快速构建出高效、美观的企业级管理后台系统。无论是小型项目还是大型项目,都能够得到较好的支持和满足。 ### 回答3: vue-element-admin是一个基于Vue.js和Element UI的开源后台管理系统框架。它提供了一套完整的解决方案,用于快速构建现代化的后台管理系统。该框架具有丰富的功能和灵活的扩展性。 首先,vue-element-admin框架基于Vue.js和Element UI,这意味着我们可以充分利用Vue.js的响应式特性、组件化开发和虚拟DOM等优势,快速构建可维护、高性能的前端应用程序。同时,Element UI提供了丰富的UI组件和样式,使我们能够轻松地构建用户友好的界面。 其次,vue-element-admin框架提供了一套完整的后台管理系统解决方案。它包括登录、权限控制、菜单导航、数据展示和编辑等常见功能,以及用户管理、角色管理、系统设置等高级功能。我们只需要按照规范进行配置和开发,就能够快速搭建出一个功能完善的后台管理系统。 此外,vue-element-admin框架还具有灵活的扩展性。我们可以根据项目需求进行定制化开发,添加新的功能模块或修改已有模块。同时,该框架支持国际化和多主题切换,方便适应不同地区和用户的需求。 总的来说,vue-element-admin框架是一个强大而易用的后台管理系统框架,它能够帮助开发者快速构建出现代化的用户界面和功能丰富的后台管理系统。无论是小型项目还是大型企业级应用,都能够从该框架中受益。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lsjweiyi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值