上篇文章 Go - 实现我的项目内链路追踪 分享了,通过 链路 ID 能够将 申请信息响应信息调用第三方接口的信息调试信息执行的 SQL 信息执行的 Redis 信息 串起来,记录的具体参数在文件中都有介绍。

这篇文章在下面的根底上,新增 2 个性能点:

  1. 新增将 调用 gRPC 接口信息 记录到 Trace 中;
  2. 新增对记录的敏感信息进行脱敏解决;

调用 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 后 4132**7986定长 11 位数字
邮箱地址前 1 后 1l**w@gmail.com仅对 @ 之前的邮箱名称进行掩码
姓名隐姓*鸿章将姓氏暗藏
明码不输入
银行卡卡号前 6 后 46228885676银行卡卡号最多 19 位数字
身份证号前 1 后 117定长 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 个实用的性能点,大家连忙应用起来吧。对于 敏感信息脱敏 期待各位大佬不吝赐教,提出更好的解决方案,谢谢!

以上代码都在 go-gin-api 我的项目中,地址:https://github.com/xinliangno...