Observability

Integrating OpenTelemetry Tracing in GORM

Written by Danang

When our application slows down, one of the main suspects is sub-optimal database queries. By setting up distributed tracing using OpenTelemetry (OTel) and GORM, we can track SQL query details, parameters, and duration directly in a visual dashboard like Grafana Tempo.

Why Use Tracing for Databases?

With tracing, every database query executed during an HTTP request will be recorded as a child span. This makes it easy to see the relation between HTTP requests and the SQL queries running under the hood.

Integration Steps

First, install the GORM tracing plugin:

go get gorm.io/plugin/opentelemetry/tracing

Then, after opening the GORM connection, register the plugin:

import (
    "gorm.io/driver/postgres"
    "gorm.io/gorm"
    "gorm.io/plugin/opentelemetry/tracing"
)

db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
    log.Fatal(err)
}

// Connect GORM with OpenTelemetry
if err := db.Use(tracing.NewPlugin(tracing.WithoutMetrics())); err != nil {
    log.Printf("Failed to register OTel plugin: %v", err)
}

Importance of Context

For tracing to work, you must always pass the request context (ctx) when executing database queries in GORM. Example:

// Span context is passed down via WithContext
err := db.WithContext(r.Context()).Where("id = ?", id).First(&user).Error

Conclusion

Integrating OpenTelemetry with GORM is a crucial step for production-ready applications. It saves hours of debugging time when database performance issues arise.