OpenTelemetry Beego monitoring [otelbeego]

Vladimir Mihailenco
March 25, 2026
6 min read

OpenTelemetry Beego instrumentation allows developers to monitor and diagnose issues with their Beego applications, providing valuable insights into application behavior in production.

Quick Setup

StepActionCode/Command
1. InstallInstall otelbeego packagego get go.opentelemetry.io/contrib/instrumentation/github.com/astaxie/beego/otelbeego
2. ImportImport otelbeegoimport "go.opentelemetry.io/contrib/instrumentation/github.com/astaxie/beego/otelbeego"
3. InstrumentCreate middleware and run with itmware := otelbeego.NewOTelBeegoMiddleWare("my-service") then beego.RunWithMiddleWares(":8080", mware)
4. VerifyCheck your observability backend for tracesTraces collected automatically

Minimal working example:

go
import (
    "github.com/astaxie/beego"
    "go.opentelemetry.io/contrib/instrumentation/github.com/astaxie/beego/otelbeego"
)

func main() {
    mware := otelbeego.NewOTelBeegoMiddleWare("my-service")

    beego.Router("/", &MainController{})
    beego.RunWithMiddleWares(":8080", mware)
}

This single middleware call automatically captures all incoming HTTP requests, traces request flow, and exports telemetry data to your configured backend.

What is Beego?

Beego is an open-source web framework written in Go that follows the Model-View-Controller (MVC) architectural pattern. It provides a comprehensive set of tools for building web applications and APIs.

Beego's key features include:

  • Full MVC architecture with auto-routing
  • Built-in ORM for database operations
  • Session management and caching
  • Logging, configuration, and task scheduling modules
  • Hot-reload during development

What is OpenTelemetry?

OpenTelemetry is an open-source observability framework that aims to standardize and simplify the collection, processing, and export of telemetry data from applications and systems.

OpenTelemetry enables developers to instrument their code and collect telemetry data, which can then be exported to various OpenTelemetry backends or observability platforms for analysis and visualization. The OpenTelemetry architecture provides a modular, vendor-neutral approach to observability.

Configuration can be managed through OpenTelemetry environment variables, providing a standardized way to configure exporters, resource attributes, and sampling behavior across environments.

Beego instrumentation

OpenTelemetry Beego instrumentation (otelbeego) provides automatic tracing for your Beego applications. It captures HTTP request details, timing information, and error states without requiring manual instrumentation.

To install otelbeego instrumentation:

shell
go get go.opentelemetry.io/contrib/instrumentation/github.com/astaxie/beego/otelbeego

Usage

You can instrument Beego by creating an OpenTelemetry middleware and passing it to RunWithMiddleWares:

go
import (
    "github.com/astaxie/beego"
    "go.opentelemetry.io/contrib/instrumentation/github.com/astaxie/beego/otelbeego"
)

func main() {
    mware := otelbeego.NewOTelBeegoMiddleWare("my-service")

    beego.Router("/api/users", &UserController{})
    beego.Router("/api/orders", &OrderController{})
    beego.RunWithMiddleWares(":8080", mware)
}

Once instrumented, otelbeego automatically creates spans for each incoming HTTP request, capturing method, route, status code, and timing information.

Middleware options

The otelbeego middleware supports several configuration options:

OptionDescription
WithTracerProviderUse a custom TracerProvider instead of the global one
WithMeterProviderUse a custom MeterProvider instead of the global one
WithPropagatorsSpecify propagators for extracting trace context
WithFilterFilter requests (return true to trace, false to skip)

Filtering health checks

Use the WithFilter option to exclude certain endpoints from tracing:

go
import (
    "net/http"

    "github.com/astaxie/beego"
    "go.opentelemetry.io/contrib/instrumentation/github.com/astaxie/beego/otelbeego"
)

mware := otelbeego.NewOTelBeegoMiddleWare("my-service",
    otelbeego.WithFilter(func(r *http.Request) bool {
        // Return true to trace, false to skip
        return r.URL.Path != "/health" && r.URL.Path != "/ready"
    }),
)
beego.RunWithMiddleWares(":8080", mware)

Custom tracer provider

For more control over telemetry collection, you can specify a custom provider:

go
import (
    "github.com/astaxie/beego"
    "go.opentelemetry.io/contrib/instrumentation/github.com/astaxie/beego/otelbeego"
    "go.opentelemetry.io/otel"
)

mware := otelbeego.NewOTelBeegoMiddleWare("my-service",
    otelbeego.WithTracerProvider(otel.GetTracerProvider()),
    otelbeego.WithMeterProvider(otel.GetMeterProvider()),
)
beego.RunWithMiddleWares(":8080", mware)

HTTP metrics

The otelbeego middleware automatically collects the following HTTP server metrics:

MetricDescription
http.server.request.durationDuration of HTTP server requests
http.server.request.body.sizeSize of HTTP server request bodies
http.server.response.body.sizeSize of HTTP server response bodies

These metrics follow the OpenTelemetry semantic conventions for HTTP and include attributes like method, route, and status code.

Instrumenting template rendering

To instrument template rendering, disable autorender and use helpers from otelbeego package:

go
import (
    "github.com/astaxie/beego"
    "go.opentelemetry.io/contrib/instrumentation/github.com/astaxie/beego/otelbeego"
)

func init() {
    beego.BConfig.WebConfig.AutoRender = false
}

func (c *MainController) Get() {
    // Creates a child span for template rendering
    err := otelbeego.Render(&c.Controller)
    if err != nil {
        c.Abort("500")
    }
}

Available render helpers:

Instrumenting outgoing HTTP requests

To trace outgoing HTTP calls from your Beego controllers, use otelhttp to wrap the http.Client transport. This creates client spans that link to the parent server span, giving you end-to-end visibility across service boundaries:

go
import (
    "io"
    "net/http"

    "github.com/astaxie/beego"
    "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
)

// Create an instrumented HTTP client for outgoing requests
var httpClient = &http.Client{
    Transport: otelhttp.NewTransport(http.DefaultTransport),
}

type ProxyController struct {
    beego.Controller
}

func (c *ProxyController) Get() {
    ctx := c.Ctx.Request.Context()

    req, err := http.NewRequestWithContext(ctx, "GET", "https://api.example.com/data", nil)
    if err != nil {
        c.Abort("500")
        return
    }

    resp, err := httpClient.Do(req)
    if err != nil {
        c.Abort("502")
        return
    }
    defer resp.Body.Close()

    body, _ := io.ReadAll(resp.Body)
    c.Ctx.Output.Body(body)
}

Creating custom spans

In addition to automatic instrumentation, you can create custom spans to trace specific operations within your controllers:

go
import (
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/attribute"
    "go.opentelemetry.io/otel/codes"
)

var tracer = otel.Tracer("my-service")

func (c *UserController) Get() {
    ctx := c.Ctx.Request.Context()

    // Create a custom span for database operation
    ctx, span := tracer.Start(ctx, "fetch-user-from-database")
    defer span.End()

    userID := c.Ctx.Input.Param(":id")
    span.SetAttributes(attribute.String("user.id", userID))

    user, err := db.FindUser(ctx, userID)
    if err != nil {
        span.RecordError(err)
        span.SetStatus(codes.Error, err.Error())
        c.Abort("500")
        return
    }

    span.SetAttributes(attribute.Bool("user.found", user != nil))
    c.Data["json"] = user
    c.ServeJSON()
}

Error handling

OpenTelemetry Beego instrumentation automatically captures panics and errors. You can also manually record errors in your controllers:

go
import (
    "go.opentelemetry.io/otel/codes"
    "go.opentelemetry.io/otel/trace"
)

func (c *OrderController) Post() {
    // Get the span from the request context
    span := trace.SpanFromContext(c.Ctx.Request.Context())

    order, err := processOrder(c.Ctx.Request.Context())
    if err != nil {
        // Record the error in the span
        span.RecordError(err)
        span.SetStatus(codes.Error, "order processing failed")
        c.Abort("500")
        return
    }

    c.Data["json"] = order
    c.ServeJSON()
}

What is Uptrace?

Uptrace is an OpenTelemetry APM that supports distributed tracing, metrics, and logs. You can use it to monitor applications and troubleshoot issues.

Uptrace Overview

Uptrace comes with an intuitive query builder, rich dashboards, alerting rules with notifications, and integrations for most languages and frameworks.

Uptrace can process billions of spans and metrics on a single server and allows you to monitor your applications at 10x lower cost.

In just a few minutes, you can try Uptrace by visiting the cloud demo (no login required) or running it locally with Docker. The source code is available on GitHub.

FAQ

What is otelbeego? The otelbeego package is the official OpenTelemetry instrumentation for the Beego framework. It provides middleware that automatically creates spans for incoming HTTP requests, capturing method, route, status code, and timing information. It also instruments template rendering through dedicated helper functions.

How do I filter health check endpoints? Use the WithFilter option when creating the middleware. Return false for paths like /health or /ready to skip tracing those requests. This reduces noise in your traces and lowers telemetry export costs.

Does otelbeego work with Beego's built-in filters? Yes, otelbeego works alongside Beego's built-in filters and middleware. The OpenTelemetry middleware wraps the entire request lifecycle, so all filters and handlers are captured within the trace. Place otelbeego first to ensure panics are captured before recovery middleware handles them.

What's the performance impact of otelbeego? The performance impact is minimal — typically a few microseconds per request for span creation and context propagation. For high-traffic applications, configure sampling to control the volume of exported spans.

Can I use otelbeego with Beego's namespace routing? Yes, the middleware is applied at the server level via RunWithMiddleWares, so all routes including namespaced routes are automatically instrumented. The http.route attribute in spans reflects the matched route pattern.

How do I instrument Beego's ORM alongside HTTP tracing? Beego's ORM uses database/sql internally. Use otelsql to instrument the database driver, giving you database query spans that nest under your HTTP request spans for end-to-end visibility.

How do I pass context to downstream services? The otelbeego middleware injects trace context into the request. Use c.Ctx.Request.Context() to retrieve it, then pass it to your database clients, HTTP clients, or gRPC calls to propagate tracing across services.

What's next?

With OpenTelemetry Beego instrumentation in place, you can monitor request latency, track error rates, and trace requests across your distributed systems.

Next steps to enhance your observability: