Home  >  Article  >  Backend Development  >  Reuse logging client in interceptor of Golang grpc server method

Reuse logging client in interceptor of Golang grpc server method

PHPz
PHPzforward
2024-02-06 09:03:12400browse

在 Golang grpc 服务器方法的拦截器中重用日志客户端

Question content

I am building a grpc server using go. Currently the server provides three methods:

  • submit homework
  • Cancel job
  • Get job status

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?


Correct answer


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!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete