Adding logging to microservices

Logging is a crucial aspect of microservices. We can write middleware to capture all requests and responses going into and out of a service. Even for a client, we can capture logs while making RPC calls to a service.

Go Micro is a lean framework and doesn't enforce logging by default. We can easily wrap a service handler with our own custom logger. For example, in the encryptService example, we have a file called handlers.go.

In order to activate logging for each request in a custom format, we have to define a wrapper, and then link it to the service. As an example, if we have to log every incoming encryption request, follow these steps:

  1. Create a new wrapper function. It takes Context, Request, and Response as arguments. Here, we just print the time of the request arrival, like this:
func logWrapper(fn server.HandlerFunc) server.HandlerFunc {
return func(ctx context.Context, req *proto.Request,
rsp *proto.Response) error {
fmt.Printf("encryption request at time: %v", time.Now())
return fn(ctx, req, rsp)
}
}
  1. In service, we can attach the wrapper, like this:
service := micro.NewService(
micro.Name("encrypter"),
// wrap the client
micro.WrapClient(logWrap),
)

Now, the service logs every request in the format defined in the wrapper function, like so:

encryption request at time: 2019/12/22 23:07:3
For more information about logging, see the documentation at https://micro.mu/docs/go-micro.html#wrappers.

The instrumentation of services is out of the scope of this book, but there is an open standard called OpenTracing (https://opentracing.io/). It defines a standard for how to metricize API endpoints, number of requests, and so on. Please feel free to explore it.

The APIs we created in this chapter are RPC-based. To convert them to REST, you just have to use a plugin called Micro Web. For more information, see this link for easy conversion to REST (https://micro.mu/docs/go-web.html).