A Comprehensive Guide to OpenTelemetry
Modern software development often leverages distributed architectures to achieve faster development cycles …
gRPC is an open-source, high-performance framework for developing remote procedure call (RPC) applications. It was created by Google and is now a part of the Cloud Native Computing Foundation (CNCF). Interceptor support is one of gRPC’s key features. In this blog, we will look at interceptors and how to use them in gRPC applications written in the Go programming language with monitoring example.
Interceptors in gRPC are useful because they allow developers to add custom logic to the request/response processing pipeline. One exciting reason for the need for gRPC interceptors is that they allow us to implement cross-cutting concerns in a modular and reusable manner. Assume we want to add authentication to all of our gRPC services. Rather than modifying each service separately, we can write a single interceptor that checks the authentication token and adds the user ID to the request context. This interceptor can then be added to any gRPC service we create without requiring any changes to the service code. Another interesting reason for using gRPC interceptors is that they enable us to implement features like tracing and monitoring. We can easily trace the flow of requests through our system and identify any performance or reliability issues by including an interceptor that logs the start and end of each request. Similarly, by incorporating an interceptor that collects metrics on request/response sizes and latencies, we can monitor our system’s health and detect any anomalies.
Interceptors are one of the powerful gRPC features that allows you to intercept and modify client-server requests and responses. Interceptors are middleware that sits between the client and server handlers, intercepting requests and responses as they traverse the network stack.
In this blog, We are going to create a logging middleware which helps to log the messages. Follow the below steps to achieve it.
Please refer the code here
Install the required modules from go package
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
Create a proto file with the messages and services required.
syntax = "proto3";
package demo;
option go_package="./;demo";
message DemoRequest {
string message = 1;
}
message DemoResponse {
string message = 1;
}
// gRPC service which has a Demo method returns message as response
service MyService {
rpc DemoMethod(DemoRequest) returns (DemoResponse) {}
}
Compile this proto file using protoc with the following command:
mkdir pb && protoc --go_out=./pb --go-grpc_out=./pb proto/*.proto
Start building your server using Go as explained below. Open Terminal and type the following commands:
# Please use your module name for the further references
go mod init YourModuleNameGoesHere
# This line will create a main.go file in root dir
touch main.go
Open main.go file and Try this code:
package main
import (
"context"
"log"
"net"
pb "YourModuleNameGoesHere/pb"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
)
// gRPC loggingInterceptor which helps to log
func loggingInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
log.Printf("Received request: %v", req)
resp, err := handler(ctx, req)
return resp, err
}
type Server struct {
pb.UnimplementedMyServiceServer
}
func main() {
// Create a new gRPC server with the logging interceptor
s := grpc.NewServer(
grpc.UnaryInterceptor(loggingInterceptor),
)
// Register your gRPC service with the server
myService := &Server{}
pb.RegisterMyServiceServer(s, myService)
reflection.Register(s)
// Listen on port 50051
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
log.Printf("Starting server in port :%d\n", 50051)
// Start the server
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
How to check this code……??? Well, I have used Evans CLI, which is a development tool for creating and testing gRPC APIs. It includes an interactive shell with auto-completion and syntax highlighting, as well as the ability to automatically generate client and server stubs. It accelerates and shortens the development and testing of gRPC APIs. You can also test it by creating client side code. Just to make it simple, I’m using Evans CLI method.
First, run the server using the following step in the terminal:
go run main.go
Open a new terminal and run the evans cli which works like a client:
evans -r repl -p 50051
# This command helps to choose the package
package demo
# To check the services defined
show services
:'
# Output generated
+-----------+------------+--------------+---------------+
| SERVICE | RPC | REQUEST TYPE | RESPONSE TYPE |
+-----------+------------+--------------+---------------+
| MyService | DemoMethod | DemoRequest | DemoResponse |
+-----------+------------+--------------+---------------+
'
# To call this method use this command
call DemoMethod
:'
# Output generated
# Example 1
demo.MyService@127.0.0.1:50051> call DemoMethod
message (TYPE_STRING) => Dr.Strange
{
"message": "Hello Dr.Strange"
}
# Example 2
demo.MyService@127.0.0.1:50051> call DemoMethod
message (TYPE_STRING) => Compage
{
"message": "Hello Compage"
}
#logs generated from server
2023/03/31 23:37:40 Received request: message:"Dr.Strange"
2023/03/31 23:39:16 Received request: message:"Compage"
'
# To stop CLI use this command
exit
Finally, we’ve seen how to use Go to implement an interceptor in a gRPC server. Interceptors enable us to extend the functionality of our gRPC server, such as logging or authentication, by intercepting incoming requests and modifying or performing additional actions on them before they are handled by our server. We saw how to define a server struct that implements the protobuf interface, how to define a logging interceptor function, and how to create a new gRPC server with the interceptor and register our service with it in this example. We also tested how it works with Evans CLI. Please feel free to add your suggestions.
Modern software development often leverages distributed architectures to achieve faster development cycles …
We’ve all been there—you’re working, and suddenly, your apps or tools stop working. Recently, this …
We have been working on an open source project which runs on K8s cluster. We had a need to persist some data, …
Finding the right talent is pain. More so, keeping up with concepts, culture, technology and tools. We all have been there. Our AI-based automated solutions helps eliminate these issues, making your teams lives easy.
Contact Us