go-micro icon indicating copy to clipboard operation
go-micro copied to clipboard

How to add value to metadata?

Open seaguest opened this issue 2 years ago • 16 comments

Hello,

I want to add some value to metadata from grpc method, then process in wrapper, however I found since grpc 1.40, we can't modify the context, the proposed solution is to use metadata.NewIncomingContext.

https://github.com/grpc/grpc-go/issues/4363

I don't know how to do it in micro?

func (s *ServerImpl) Location(ctx context.Context, req *pb.LocationRequest, rsp *pb.City) error {
// add value to context
	md, _ := metadata.FromContext(ctx)
	if md != nil {
		md.Set("tag", "value")
	}
}

func LogWrapper(fn server.HandlerFunc) server.HandlerFunc {
	return func(ctx context.Context, req server.Request, rsp interface{}) error {
 		err := fn(ctx, req, rsp)
 		value, _ := md.Get("tag")  // value is empty
}
}

seaguest avatar Nov 19 '21 07:11 seaguest

After you modify the metadata, you need to convert back to context, and pass it in your request.

xpunch avatar Nov 19 '21 09:11 xpunch

@xpunch

sorry, I don't get you, could you show me the example code? in Location method, ctx only exposed Value, Deadline, Done, Err methods, I don't know how to make the modification take effect.

seaguest avatar Nov 19 '21 12:11 seaguest

...
ctx, err = metadata.NewContext(ctx, md)
metadata.Set(ctx, k,v)

xpunch avatar Nov 22 '21 03:11 xpunch

@xpunch

This is not working.ctx can't be modified.

As the one mentioned in the issue https://github.com/grpc/grpc-go/issues/4363

func (w *wrappedStream) Context() context.Context {
  ctx := w.ServerStream.Context()
  md := metadata.FromIncomingContext(ctx)
  newMD := md.Copy()
  newMD.Append("uuid", id)
  newCtx := metadata.NewIncomingContext(ctx, newMD)
  return newCtx
}

However I don't find the proper way to do so.

seaguest avatar Nov 22 '21 05:11 seaguest

Sorry, I misunderstand your issue. HandlerWrapper As the context cannot be modify, and there is no way to pass the context back to previous wrapper, we cannot pass metadata to log wrapper.

xpunch avatar Nov 22 '21 06:11 xpunch

@JeffreyBool

根据grpc最新的设计,outbound的context修改必须用metadata.NewIncomingContext,所以只能从micro框架内部做相应的修改,如果你选择grpc1.38.0,你会发现简单的set,get依然还是可以的。

我的需求很简单,本想统一处理错误码(读取response的code),现在只能通过json解析response了。 等待micro出一个官方的方案吧。

seaguest avatar Dec 06 '21 08:12 seaguest

@JeffreyBool 业务层级的错误码,譬如response都有的固定结构,err_code, err_msg这样的。 既然context没法修改,可以尝试在rsp interface{}里面增加对应的临时字段,当然这个只是没有办法的办法。

seaguest avatar Dec 06 '21 13:12 seaguest

@JeffreyBool 的确我也正在做接口监控统计的事情,目前遇到的问题是我可以在wrapper里面检测到错误码(err),业务层次的错误码(rsp提取),但是我没办法在wrapper里面上报到influxdb。

我看你用的是monitor.DefaultMetrics(应该是默认的配置吧,我希望能够自定义),如果希望传个对象给wrapper(比如处理上报influxdb的逻辑),有没有办法实现?如果context能存对象,这个就很方便了。

seaguest avatar Dec 07 '21 04:12 seaguest

@JeffreyBool 想了一圈,发现还是你的这个接口监控,错误方案比较靠谱。 对了,NewClientWrapper这个怎么使用,似乎client.Wrapper用法说明比较少,我下面这么用server.HandlerWrapper是可以的,但是NewClientWrapper没反应。


	service := micro.NewService(
		micro.Name(constant.UtilServiceName),
		micro.Version("latest"),
		micro.RegisterTTL(time.Second*30),
		micro.RegisterInterval(time.Second*15),
		micro.Server(grpc.NewServer(server.Address(""), server.Name(constant.UtilServiceName))),
		micro.Registry(reg),
		micro.WrapHandler(NewHandlerWrapper()),
		micro.WrapClient(NewClientWrapper()),
	)

seaguest avatar Dec 29 '21 12:12 seaguest