log包改造

This commit is contained in:
2025-11-05 14:58:13 +08:00
parent 09898ec5c2
commit 349fc3e129
2 changed files with 120 additions and 8 deletions

View File

@@ -0,0 +1,63 @@
package logs
import (
"context"
"fmt"
)
// contextKey 是用于在 context.Context 中存储值的私有类型,避免键冲突。
type contextKey string
const (
// compNameKey 用于存储组件名称。
compNameKey contextKey = "compName"
// chainKey 用于存储调用链。
chainKey contextKey = "chain"
)
// AddCompName 将一个组件名(对象名)存入 Context并返回一个包含该信息的新 Context。
// 这通常在依赖注入时完成,用于创建组件的“身份名牌” selfCtx。
func AddCompName(ctx context.Context, compName string) context.Context {
return context.WithValue(ctx, compNameKey, compName)
}
// AddFuncName 这是构建调用链的核心原子操作。它智能地合并上游的调用链和当前组件的信息,
// 生成并返回一个包含更新后调用链和当前组件名的 新 Context。
// 此函数用于只需要传递调用链而不需要立即打印日志的场景。
func AddFuncName(upstreamCtx context.Context, selfCtx context.Context, funcName string) context.Context {
// 1. 获取上游调用链
var oldChain []string
if val := upstreamCtx.Value(chainKey); val != nil {
if chain, ok := val.([]string); ok {
oldChain = chain
}
}
// 2. 获取当前组件名
compName, ok := selfCtx.Value(compNameKey).(string)
if !ok {
// 如果 selfCtx 中没有 compName则无法构建节点直接返回 upstreamCtx
// 这种情况通常不应该发生,因为 selfCtx 应该在依赖注入时通过 AddCompName 初始化
return upstreamCtx
}
// 3. 构建新节点
newNode := fmt.Sprintf("%s.%s", compName, funcName)
// 4. 生成新调用链
// 创建一个新的切片,并将旧链和新节点复制进去
newChain := make([]string, len(oldChain)+1)
copy(newChain, oldChain)
newChain[len(oldChain)] = newNode
// 5. 创建新的 Context
// 使用 context.WithValue以 chainKey 为键,将 newChain 存入一个新的 Context我们称之为 tmpCtx。
tmpCtx := context.WithValue(upstreamCtx, chainKey, newChain)
// 接着,基于 tmpCtx再次调用 context.WithValue以 compNameKey 为键,
// 将从 selfCtx 中获取的 compName 存入,得到最终的 newCtx。
// 这确保了传向下游的 Context 正确地标识了当前组件。
newCtx := context.WithValue(tmpCtx, compNameKey, compName)
return newCtx
}