tutorial

  1. Monitoring gRPC dengan Jaeger + OpenTelemetry

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-service sebagai gRPC server
  • client-app sebagai 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):

  1. Pilih service user-service.
  2. Cari trace terakhir & klik.
  3. 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):

KonfigurasiRata-rata Latency (ms)Keterangan
Tanpa Tracing100Aplikasi gRPC saja
Dengan OTel+Jaeger110OTel Exporter aktif
Dengan Sampling 5%104Sampling span rendah

Catatan: Overhead tracing bisa dikelola dengan pengaturan sampling rate di production, sehingga tracing tetap memberikan insight tanpa membebani performa.


Production Checklist

ChecklistTips Praktis
Sampling RateGunakan probabilistic sampling (misal 5%)
Context PropagationPastikan propagate konteks ke semua layanan
Trace AttributeTambahkan info bisnis relevan (userID, method)
Data RetentionAtur retensi trace Jaeger (default 7 hari)
Resource TagGunakan tag resource agar trace mudah difilter
SecurityJaga 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! 🚀

comments powered by Disqus