// HandleRPC implements per-RPC tracing and stats instrumentation.
func (c *statsHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) {
 switch rs := rs.(type) {

  case *stats.InHeader:

     if rs.Client {
        fmt.Printf(rs.Header)
    }

  case *stats.End:
    ign := false
    c.lock.RLock()
    ign = c.ignore
    c.lock.RUnlock()

    if !ign {
        duration := rs.EndTime.Sub(rs.BeginTime)

        var st string
        s, ok := status.FromError(rs.Error)
        if ok {
            st = s.Code().String()
        }

        c.results <- &callResult{rs.Error, st, duration, rs.EndTime}

        if c.hasLog {
            c.log.Debugw("Received RPC Stats",
                "statsID", c.id, "code", st, "error", rs.Error,
                "duration", duration, "stats", rs)
        }
    }
}

}

我在事件*stats.InHeader中输入了response metadata,在事件*stats.End中输入了grpc stats的其余部分,我想在grPC调用结束时将metadatagrpc stats组合成一个 struct 对象callResult.我不知道如何实现这一点,我真的是新手go grPC.有人能帮助我吗,谢谢!

推荐答案

type MutableObject struct {
    InMetadata metadata.MD // Example mutable field
}

// TagRPC implements per-RPC context management.
func (c *statsHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context {

    ctx = context.WithValue(ctx, "InHeader", &MutableObject{})

    return ctx
}

// HandleRPC implements per-RPC tracing and stats instrumentation.
func (c *statsHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) {
    switch rs := rs.(type) {

    case *stats.InHeader:
        var headerValue metadata.MD
        // You can access the `InHeader` field from the `s` object to get the received headers.
        if rs.Client {
            ign := false
            c.lock.RLock()
            ign = c.ignore
            c.lock.RUnlock()
            if !ign {
                headerValue = rs.Header

                if header, ok := ctx.Value("InHeader").(*MutableObject); ok {
                    header.InMetadata = headerValue
                }
            }
        }

    case *stats.End:

        ign := false
        c.lock.RLock()
        ign = c.ignore
        c.lock.RUnlock()

        if !ign {
            duration := rs.EndTime.Sub(rs.BeginTime)

            var st string
            s, ok := status.FromError(rs.Error)
            if ok {
                st = s.Code().String()
            }

            // Retrieve the header value from the context

            
            var ts time.Time
            if header, ok := ctx.Value("InHeader").(*MutableObject); ok {
                databroker_timestamp, err := strconv.ParseInt(header.InMetadata["ts"][0], 10, 64)
                if err == nil {
                    ts = time.Unix(int64(math.Abs(float64(databroker_timestamp)/1000000000)), databroker_timestamp%1000000000)
                }

            }

            c.results <- &callResult{rs.Error, st, duration, rs.EndTime, ts, 10, 10}

            if c.hasLog {
                c.log.Debugw("Received RPC Stats",
                    "statsID", c.id, "code", st, "error", rs.Error,
                    "duration", duration, "stats", rs)
            }
        }
    }

}
  1. TagRPC中将可变对象添加到上下文中
  2. *stats.InHeader事件上修改可变对象
  3. 最后访问*stats.End上的对象

Go相关问答推荐

Zitadel示例Go Webapp加密密钥

如何使用Gorilla WebSockets实现Http.Hijacker&;alexedwards/scs/v2

如何将文件从AWS S3存储桶复制到Azure BLOB存储

无法使用exec从管道中读取.Go中的命令

如何使用 Go 连接到非默认 firestore 数据库?

从 wincrypt API 到 Go 的 RC2 解密

如何绕过深层 xml,没有嵌套循环?

Json.Unmarshal() 和 gin.BindJson() 之间的区别

在 Go sync.Map 中,为什么这部分实现不一致或者我误解了什么?

如何在 fyne-io/fyne 中设置文本的字母间距?

GitHub 中 REST API 的 aws 凭证问题

我的神经网络(从头开始)训练,让它离目标更远

Go 的垃圾收集器在使用时删除 ZeroMQ 套接字

如何在切片增长时自动将切片的新元素添加到函数参数

处理程序后访问 HTTP 请求上下文

Golang Echo Labstack 如何在模板视图中调用函数/方法

Golang API 的 HTTPS

如何获得Ent中数字列的总和

即使没有竞争条件也没有得到任何输出

Gin中测试模式有什么用