Cómo instrumentar servicios gRPC en Go con OpenTelemetry: Métricas clave para APM

Introducción

Instrumentar servicios gRPC en Go con OpenTelemetry es esencial para obtener visibilidad completa en tus microservicios. Esta guía te llevará paso a paso a través de la implementación, desde la configuración inicial hasta la captura de métricas clave para APM (Application Performance Monitoring).

Configuración inicial del proyecto

Requisitos previos

Antes de comenzar, asegúrate de tener instalado Go y las herramientas necesarias para trabajar con gRPC y OpenTelemetry. Necesitarás:

  • Go 1.16 o superior
  • Protocol Buffers (protobuf)
  • gRPC y herramientas de generación de código
  • OpenTelemetry SDK para Go

Estructura del proyecto

Crea una nueva estructura de proyecto para tu servicio gRPC:

mkdir grpc-opentelemetry
cd grpc-opentelemetry
go mod init github.com/tu-usuario/grpc-opentelemetry

Implementación de gRPC en Go

Definición del servicio gRPC

Define tu servicio gRPC en un archivo .proto:

syntax = "proto3";

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

Genera el código Go a partir de la definición del servicio:

protoc --go_out=. --go-grpc_out=. greeter.proto

Implementación del servidor gRPC

Implementa el servidor gRPC en Go:

package main

import (
	"context"
	"log"
	"net"

	"google.golang.org/grpc"
)

type server struct{}

func (s *server) SayHello(ctx context.Context, req *HelloRequest) (*HelloReply, error) {
	return &HelloReply{Message: "Hello " + req.Name}, nil
}

func main() {
	lis, err := net.Listen("tcp", ":50051")
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	s := grpc.NewServer()
	RegisterGreeterServer(s, &server{})
	log.Printf("server listening at %v", lis.Addr())
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

Instrumentación con OpenTelemetry

Configuración de OpenTelemetry

Agrega las dependencias necesarias para OpenTelemetry:

go get go.opentelemetry.io/otel \
	go.opentelemetry.io/otel/exporters/jaeger \
	go.opentelemetry.io/otel/sdk \
	go.opentelemetry.io/otel/trace

Configura OpenTelemetry en tu aplicación:

import (
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/exporters/jaeger"
	"go.opentelemetry.io/otel/sdk/trace"
)

func initTracer() (*trace.TracerProvider, error) {
	exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint("http://localhost:14268/api/traces")))
	if err != nil {
		return nil, err
	}
	tp := trace.NewTracerProvider(
		trace.WithBatcher(exp),
		trace.WithResource(resource.NewWithAttributes(
			semconv.SchemaURL,
			semconv.ServiceNameKey.String("grpc-opentelemetry"),
		)),
	)
	otel.SetTracerProvider(tp)
	return tp, nil
}

Instrumentación del servidor gRPC

Instrumenta el servidor gRPC con OpenTelemetry:

import (
	"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
)

func main() {
	lis, err := net.Listen("tcp", ":50051")
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	tp, err := initTracer()
	if err != nil {
		log.Fatalf("failed to initialize tracer: %v", err)
	}

defer func() {
		if err := tp.Shutdown(context.Background()); err != nil {
			log.Fatalf("failed to shutdown tracer: %v", err)
		}
	}()
	s := grpc.NewServer(
		grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor()),
		grpc.StreamInterceptor(otelgrpc.StreamServerInterceptor()),
	)
	RegisterGreeterServer(s, &server{})
	log.Printf("server listening at %v", lis.Addr())
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

Métricas clave para APM

Latencia de llamadas

La latencia de las llamadas gRPC es una métrica crítica para APM. Con OpenTelemetry, puedes capturar la duración de cada llamada y analizar los percentiles para identificar cuellos de botella.

Tasa de errores

La tasa de errores en tus servicios gRPC puede indicar problemas subyacentes. Instrumenta tus servicios para capturar y analizar los errores por tipo y código de estado.

Tracing distribuido

El tracing distribuido te permite seguir una solicitud a través de múltiples servicios. Con OpenTelemetry, puedes correlacionar las trazas entre diferentes servicios y obtener una vista completa de tus microservicios.

Conclusión

Instrumentar servicios gRPC en Go con OpenTelemetry es un proceso esencial para obtener visibilidad completa en tus microservicios. Con las métricas clave para APM, puedes identificar y resolver problemas de rendimiento y errores de manera más eficiente.

Para profundizar, la documentación de Lescopr detalla la implementación paso a paso.