I am building a grpc server using go. Currently the server provides three methods:
I'm using datadog to log some metrics such as request count, duration, etc. The submitjob method looks like this:
func (s *myserver) submitjob(ctx context.context, request *submitjobrequest) (*submitjobresponse, error) { s.dd_client.logrequestcount("submitjob") start_time := time.now() defer s.dd_client.logrequestduration("submitjob", time.since(start_time)) resp := somefunc() return resp, nil }
The logging code in these three different server methods is almost identical. So I want to know how to avoid this duplication.
I noticed that golang grpc has the concept of interceptor. Basically I can define an interceptor function and use it to do pre/post processing of server method calls.
Following the documentation, I wrote an interceptor as follows:
func unaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler, ) (interface{}, error) { dd_client := NewDatadogClient() defer dd_client.Close() dd_client.LogRequestCount(info.FullMethod) start_time := time.Now() resp, err := handler(ctx, req) dd_client.LogRequestDuration(info.FullMethod, time.Since(start_time)) return resp, err }
The problem is that every time the interceptor is called, it creates and destroys a new datadog client. I think this is unnecessary. But since unaryinterceptor is just a method and not a class, I don't see a way to create the datadog client once and reuse it later? Is there a way to meet my needs?
Yes, don't create it on the spot, but move it to another file/package, let's call it datadog.go
You need to declare it as a singleton, so it only has 1 pointer in all usages, like...
(I use the type "datadogtype" to refer to the data type returned by the function "newdatadogclient", please specify the package and version to give more precise sample code)
//your package code.... var dataDog DataDogType //access it through a wrapper, the wrapper will init the var the first time, //the remaining times it will be reused func GetDataDog()(*DataDogType) { if dataDog == nil { dataDog = NewDatadogClient() } return dataDog }
Now, depending on your use case, if you return it as a pointer and close it, you will close all uses of it, so return the pointer itself and omit the part that closes it, or return the value, so it is a copy of the original of
BTW, can you share what datadog version and specific package you are using?
The above is the detailed content of Reuse logging client in interceptor of Golang grpc server method. For more information, please follow other related articles on the PHP Chinese website!