Monitoring gRPC dengan Jaeger + OpenTelemetry
Monitoring layanan microservices berbasis gRPC semakin penting sejalan dengan meningkatnya kompleksitas arsitektur aplikasi modern — terutama saat tracing permintaan antar microservices menjadi kebutuhan utama untuk observabilitas dan troubleshooting. Salah satu kombinasi powerful yang bisa diadopsi adalah Jaeger sebagai distributed tracing backend, dikombinasikan dengan OpenTelemetry (OTel) sebagai SDK dan framework pengumpulan telemetri lintas bahasa.
Pada artikel ini, saya akan membahas praktik implementasi monitoring pada aplikasi gRPC menggunakan OpenTelemetry dan Jaeger. Kita akan membedah arsitektur tracing distributed, mengintegrasikan tracing pada aplikasi, simulasi tracing permintaan sederhana, serta membandingkan overhead dan benefit dari implementasinya.
Sekilas tentang Jaeger dan OpenTelemetry
Jaeger
Jaeger adalah distributed tracing platform open-source yang dirancang awalnya oleh Uber Technologies. Jaeger digunakan untuk memonitor dan memecahkan masalah performa dalam microservices, dengan fitur utama seperti:
- Distributed context propagation
- Tracing
- Node monitoring
- Visualisasi tracing antar services
OpenTelemetry (OTel)
OpenTelemetry adalah proyek CNCF yang mendefinisikan standar observability modern lintas platform dan bahasa pemrograman. OTel mendukung collection, transformation, dan exporting metric, tracing, dan log data, serta dapat di-integrasikan dengan beberapa backend seperti Jaeger, Prometheus, grafana, dan Elasticsearch.
Arsitektur: Alur Data Tracing
Sebelum hands-on, mari kita lihat diagram sederhana alur tracing dengan Jaeger + OpenTelemetry.
flowchart TD
subgraph A["Aplikasi (gRPC Client/Server)"]
G1[gRPC Client (OTel SDK)] -->|TraceContext| G2[gRPC Server (OTel SDK)]
end
G2 -->|Batch Trace Data| C[Collector]
C -->|Batch| J[Jaeger Backend]
J --> D[Jaeger UI]
Penjelasan:
- Aplikasi (baik client maupun server) menginstrumentasi trace melalui OpenTelemetry SDK.
- Trace context diinjeksi & dipropagasi secara otomatis dalam metadata permintaan gRPC.
- Collector (bisa pake otel-collector, atau langsung Jaeger Agent) menerima batch trace dari aplikasi.
- Data trace masuk ke Jaeger backend lalu divisualisasikan di Jaeger UI untuk root-cause analysis.
Instalasi Jaeger dan OpenTelemetry Collector
Untuk keperluan demonstrasi lokal, kita akan menjalankan Jaeger via Docker.
docker run -d --name jaeger \
-e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
-p 6831:6831/udp -p 6832:6832/udp \
-p 5778:5778 -p 16686:16686 -p 14268:14268 -p 14250:14250 \
jaegertracing/all-in-one:1.39
Jaeger UI sekarang bisa diakses via http://localhost:16686.
Hands-on: gRPC Server dan Client dengan OpenTelemetry
Skema Sederhana
Kita akan buat dua service:
user-servicesebagai gRPC serverclient-appsebagai gRPC client
Keduanya akan menggunakan OpenTelemetry SDK dan mengexport trace ke Jaeger.
Dependensi
Instalasi package (contoh menggunakan Golang):
go get go.opentelemetry.io/otel
go get go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc
go get go.opentelemetry.io/otel/exporters/jaeger
go get google.golang.org/grpc
Setup Tracing Otel & Jaeger
Fungsi inisialisasi exporter Jaeger dan tracer provider:
// tracing.go
package main
import (
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/jaeger"
"go.opentelemetry.io/otel/sdk/trace"
"log"
)
func initTracer() func() {
exporter, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint("http://localhost:14268/api/traces")))
if err != nil {
log.Fatal(err)
}
tp := trace.NewTracerProvider(
trace.WithBatcher(exporter),
)
otel.SetTracerProvider(tp)
return func() {
_ = tp.Shutdown(nil)
}
}
Server: Integrasi gRPC Interceptor OTel
import (
"google.golang.org/grpc"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
)
func main() {
shutdown := initTracer()
defer shutdown()
s := grpc.NewServer(
grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor()),
)
// ... register services & start server
}
Client: Propagasi Trace Context
import (
"google.golang.org/grpc"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
)
func main() {
shutdown := initTracer()
defer shutdown()
conn, _ := grpc.Dial(
"localhost:50051",
grpc.WithInsecure(),
grpc.WithUnaryInterceptor(otelgrpc.UnaryClientInterceptor()),
)
// ... buat stub client dan panggil endpoint user-service
}
Simulasi Tracing
Agar tracing menarik, tambahkan beberapa span manual di dalam method handler server.
import (
"context"
"go.opentelemetry.io/otel"
)
func (s *server) GetUser(ctx context.Context, req *pb.UserRequest) (*pb.UserResponse, error) {
tracer := otel.Tracer("user-service")
ctx, span := tracer.Start(ctx, "GetUser")
defer span.End()
// Simulasi proses DB query
time.Sleep(80 * time.Millisecond)
// Set attribute trace
span.SetAttributes(attribute.String("user.name", "alvin"))
return &pb.UserResponse{Id: req.Id, Name: "alvin"}, nil
}
Hasil di Jaeger UI
Setelah client mengirim request ke server, buka Jaeger UI (http://localhost:16686):
- Pilih service
user-service. - Cari trace terakhir & klik.
- Anda akan melihat end-to-end trace lengkap dari client-call sampai handler, lengkap dengan span time breakdown.
Analisis: Monitoring & Overhead
Tabel berikut menunjukan simulasi overhead penambahan tracing pada latency permintaan (angka ilustratif):
| Konfigurasi | Rata-rata Latency (ms) | Keterangan |
|---|---|---|
| Tanpa Tracing | 100 | Aplikasi gRPC saja |
| Dengan OTel+Jaeger | 110 | OTel Exporter aktif |
| Dengan Sampling 5% | 104 | Sampling span rendah |
Catatan: Overhead tracing bisa dikelola dengan pengaturan sampling rate di production, sehingga tracing tetap memberikan insight tanpa membebani performa.
Production Checklist
| Checklist | Tips Praktis |
|---|---|
| Sampling Rate | Gunakan probabilistic sampling (misal 5%) |
| Context Propagation | Pastikan propagate konteks ke semua layanan |
| Trace Attribute | Tambahkan info bisnis relevan (userID, method) |
| Data Retention | Atur retensi trace Jaeger (default 7 hari) |
| Resource Tag | Gunakan tag resource agar trace mudah difilter |
| Security | Jaga agar endpoint Jaeger tidak terbuka lebar |
Kesimpulan
Melalui Jaeger dan OpenTelemetry, tim engineering dapat membangun observabilitas mendalam pada request flow lintas service di ekosistem gRPC. Distributed tracing memudahkan root cause analysis, analisis bottleneck, dan resource profiling secara real-time.
Implementasi tracing dengan OTel relatif mudah untuk gRPC, hanya dengan menambah beberapa baris kode, namun membawa value besar untuk reliability dan monitoring sistem.
Jangan lupa gunakan sampling yang bijak, dan pastikan propagate trace context ke seluruh panggilan service chain agar tracing menjadi utuh dan informatif.
Happy instrumentation! 🚀