← Back to Cecep Azhar
Cecep Azhar #observability#logging#monitoring#tracing#golang#devops

Observability in Production: Logging, Monitoring, dan Tracing untuk Aplikasi Go

Cecep Saeful Azhar • 16 Oct 2026
Observability in Production: Logging, Monitoring, dan Tracing untuk Aplikasi Go
Panduan observability untuk aplikasi Go di production. Structured logging, Prometheus metrics, dan distributed tracing dengan best practices.

Observability: Mata untuk Production Systems

Sebagai developer, kita sering fokus membangun fitur. Tapi di production, pertanyaan yang lebih penting adalah: 'Apa yang terjadi dengan sistem saya?' Observability memberikan jawaban melalui tiga pilar: logging, metrics, dan tracing. Dari pengalaman saya handle production systems di Bandung, ini adalah aspek yang paling sering di-skip tapi paling kritis saat ada masalah.

Structured Logging dengan Zerolog

Logging yang baik harus structured (bukan text biasa) dan contextual. Saya menggunakan zerolog karena performanya yang excellent:

import "github.com/rs/zerolog"

// Setup logger
func SetupLogger(level string) zerolog.Logger {
    l, _ := zerolog.ParseLevel(level)
    
    return zerolog.New(
        zerolog.ConsoleWriter{Out: os.Stderr},
    ).Level(l).With().
        Timestamp().
        Str("service", "myapp").
        Str("version", os.Getenv("APP_VERSION")).
        Logger()
}

// Usage dalam code
func handleRequest(ctx context.Context, req Request) error {
    logger := zerolog.Ctx(ctx)
    
    logger.Info().
        Str("user_id", req.UserID).
        Str("action", req.Action).
        Int("payload_size", len(req.Body)).
        Msg("processing request")
    
    // ... process request
    
    logger.Info().
        Str("user_id", req.UserID).
        Dur("duration", time.Since(start)).
        Int("status", 200).
        Msg("request completed")
    
    return nil
}

Setiap log entry harus punya context yang cukup untuk debugging: user ID, request ID, duration, dan status code. Ini memudahkan kita mencari logs spesifik di Elasticsearch atau Loki.

Prometheus Metrics

Metrics memberikan gambaran quantitative tentang kesehatan sistem. Berikut pattern metrics yang saya gunakan di semua service:

import "github.com/prometheus/client_golang/prometheus"

var (
    requestDuration = prometheus.NewHistogramVec(
        prometheus.HistogramOpts{
            Name:    "http_request_duration_seconds",
            Help:    "Duration of HTTP requests",
            Buckets: []float64{0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 5},
        },
        []string{"method", "path", "status"},
    )
    
    requestTotal = prometheus.NewCounterVec(
        prometheus.CounterOpts{
            Name: "http_requests_total",
            Help: "Total number of HTTP requests",
        },
        []string{"method", "path", "status"},
    )
    
    activeConnections = prometheus.NewGauge(
        prometheus.GaugeOpts{
            Name: "active_connections",
            Help: "Number of active connections",
        },
    )
)

// Middleware untuk auto-record metrics
func MetricsMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
    return func(c echo.Context) error {
        start := time.Now()
        
        err := next(c)
        
        duration := time.Since(start).Seconds()
        status := strconv.Itoa(c.Response().Status)
        
        requestDuration.WithLabelValues(c.Request().Method, c.Path(), status).Observe(duration)
        requestTotal.WithLabelValues(c.Request().Method, c.Path(), status).Inc()
        
        return err
    }
}

Distributed Tracing dengan OpenTelemetry

Di microservices, tracing memungkinkan kita melihat bagaimana request mengalir dari satu service ke service lain:

import (
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
    "go.opentelemetry.io/otel/sdk/trace"
)

func InitTracing(serviceName string) (*trace.TracerProvider, error) {
    exporter, err := otlptracehttp.New(
        context.Background(),
        otlptracehttp.WithEndpoint("localhost:4318"),
        otlptracehttp.WithInsecure(),
    )
    if err != nil {
        return nil, err
    }
    
    tp := trace.NewTracerProvider(
        trace.WithBatcher(exporter),
        trace.WithResource(resource.NewWithAttributes(
            semconv.SchemaURL,
            semconv.ServiceNameKey.String(serviceName),
        )),
    )
    
    otel.SetTracerProvider(tp)
    return tp, nil
}

Alerting yang Meaningful

Metrics tanpa alerting tidak ada artinya. Saya menyarankan untuk alert hanya pada hal yang benar-benar actionable: error rate > 1%, latency p99 > 2s, atau disk usage > 80%. Jangan alert untuk setiap anomali - alert fatigue adalah musuh dari good monitoring.

Kesimpulan

Observability bukan optional untuk production systems. Investasi di logging, monitoring, dan tracing akan terbayar berkali-kali saat ada incident di production. Dari pengalaman saya, 80% debugging time bisa dipotong dengan observability yang baik.

← More articles from Cecep Azhar Central Content Hub Home →