Dashboard Get started

Go Instrumentation

Instrument any Go HTTP server or service using the OpenTelemetry Go SDK. Go requires a small init function — there's no equivalent of NODE_OPTIONS — but the setup is under 20 lines and only needed once.

1. Install

bash
go get go.opentelemetry.io/otel \
  go.opentelemetry.io/otel/sdk \
  go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp

2. Set environment variables

.env
LA_DSN=la_live_YOUR_TOKEN_HERE
OTEL_SERVICE_NAME=my-go-service
ENVIRONMENT=production

3. Add the init function

Create otel.go in your project root:

otel.go
package main

import (
    "context"
    "os"

    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
    sdktrace "go.opentelemetry.io/otel/sdk/trace"
    semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
    "go.opentelemetry.io/otel/sdk/resource"
)

func initTracer(ctx context.Context) func() {
    exp, _ := otlptracehttp.New(ctx,
        otlptracehttp.WithEndpoint("la-ingest-gateway.lightarch.workers.dev"),
        otlptracehttp.WithHeaders(map[string]string{"x-la-dsn": os.Getenv("LA_DSN")}),
    )
    res, _ := resource.New(ctx, resource.WithAttributes(
        semconv.ServiceName(os.Getenv("OTEL_SERVICE_NAME")),
        semconv.DeploymentEnvironment(os.Getenv("ENVIRONMENT")),
    ))
    tp := sdktrace.NewTracerProvider(sdktrace.WithBatcher(exp), sdktrace.WithResource(res))
    otel.SetTracerProvider(tp)
    return func() { tp.Shutdown(ctx) }
}

4. Call it from main

main.go
func main() {
    ctx := context.Background()
    defer initTracer(ctx)()

    // ... rest of your app
}
defer initTracer(ctx)() initialises OTel and registers a shutdown hook in one line. The double () is intentional — it calls the cleanup function returned by initTracer.

Screenshot needed

Traces page showing Go service spans with service='my-go-service', waterfall with multiple Go spans.

Custom spans

go
func processPayment(ctx context.Context, orderID string) error {
    tracer := otel.Tracer("my-go-service")
    ctx, span := tracer.Start(ctx, "payment.process")
    defer span.End()

    span.SetAttributes(attribute.String("order.id", orderID))

    if err := chargeCard(ctx, orderID); err != nil {
        span.RecordError(err)
        span.SetStatus(codes.Error, err.Error())
        return err
    }
    return nil
}