上篇文章 Go - 实现项目内链路追踪 分享了,通过 链路 ID 可以将 请求信息、响应信息、调用第三方接口的信息、调试信息、执行的 SQL 信息、执行的 Redis 信息 串起来,记录的具体参数在文件中都有介绍。
这篇文章在上面的基础上,新增 2 个功能点:
- 新增将 调用 gRPC 接口信息 记录到 Trace 中;
- 新增对记录的敏感信息进行脱敏处理;
调用 gRPC 接口信息
记录参数
Object,结构如下:
type Grpc struct { Timestamp string `json:"timestamp"` // 时间,格式:2006-01-02 15:04:05 Addr string `json:"addr"` // 地址 Method string `json:"method"` // 操作方法 Meta metadata.MD `json:"meta"` // Mate 信息 Request map[string]interface{} `json:"request"` // 请求信息 Response map[string]interface{} `json:"response"` // 返回信息 CostSeconds float64 `json:"cost_seconds"` // 执行时间(单位秒) Code string `json:"err_code,omitempty"` // 错误码 Message string `json:"err_message,omitempty"` // 错误信息 }
如何收集参数
封装了一个 grpclient 包:
- 支持设置 DialTimeout;
- 支持设置 UnaryInterceptor;
- 支持设置 KeepaliveParams;
- 支持设置 TransportCredentials;
主要是在拦截器 Interceptor 中进行收集。
示例代码
实例化 gRPC client
// TODO 需从配置文件中获取 target := "127.0.0.1:9988" secret := "abcdef" clientInterceptor := NewClientInterceptor(func(message []byte) (authorization string, err error) { return GenerateSign(secret, message) }) conn, err := grpclient.New(target, grpclient.WithKeepAlive(keepAlive), grpclient.WithDialTimeout(time.Second*5), grpclient.WithUnaryInterceptor(clientInterceptor.UnaryInterceptor), ) return &clientConn{ conn: conn, }, err
调用具体方法
// 核心:传递 core.Context 给 Interceptor 使用 client := hello.NewHelloClient(d.grpconn.Conn()) client.SayHello(grpc.ContextWithValueAndTimeout(c, time.Second*3), &hello.HelloRequest{Name: "Hello World"})
敏感信息脱敏
敏感信息脱敏又称为动态数据掩码(Dynamic Data Masking,简称为DDM)能够防止把敏感数据暴露给未经授权的用户。
根据项目要求可以约定一些规范,例如:
类型 | 要求 | 示例 | 说明 |
---|---|---|---|
手机号 | 前 3 后 4 | 132****7986 | 定长 11 位数字 |
邮箱地址 | 前 1 后 1 | l**w@gmail.com | 仅对 @ 之前的邮箱名称进行掩码 |
姓名 | 隐姓 | *鸿章 | 将姓氏隐藏 |
密码 | 不输出 | ****** | |
银行卡卡号 | 前 6 后 4 | 622888******5676 | 银行卡卡号最多 19 位数字 |
身份证号 | 前 1 后 1 | 1******7 | 定长 18 位 |
如何实现
我现在的实现方案是:自定义 MarshalJSON(),欢迎大佬们提出更好的方案。
示例代码
// 定义 Mobile 类型 type Mobile string // 自定义 MarshalJSON() func (m Mobile) MarshalJSON() ([]byte, error) { if len(m) != 11 { return []byte(`"` + m + `"`), nil } v := fmt.Sprintf("%s****%s", m[:3], m[len(m)-4:]) return []byte(`"` + v + `"`), nil }
测试
type message struct { Mobile ddm.Mobile `json:"mobile"` } msg := new(message) msg.Mobile = ddm.Mobile("13288889999") marshal, _ := json.Marshal(msg) fmt.Println(string(marshal)) // 输出:{"mobile":"132****9999"}
小结
本篇文章新增了 2 个实用的功能点,大家赶紧使用起来吧。关于 敏感信息脱敏 期待各位大佬不吝赐教,提出更好的解决方案,谢谢!
有疑问加站长微信联系(非本文作者)