---
title: Go Observability with OpenTelemetry | Pydantic Logfire
description: >-
  Send Go traces to Pydantic Logfire with the standard OpenTelemetry Go SDK.
  Three environment variables, a tracer provider, then query traces, metrics,
  and logs with SQL.
canonical: 'https://pydantic.dev/logfire/go'
---

> Markdown version of [Trace, monitor and debug your Go app](https://pydantic.dev/logfire/go) — the canonical HTML page.
>
> Site index: [/llms.txt](https://pydantic.dev/llms.txt)

---

# Trace, monitor and debug your Go app

Logfire for Go

Go Observability from the team behind Pydantic: keep the standard OTel SDK and contrib packages you already use, keep vendor code out of your binary and query everything in plain SQL. Standard OpenTelemetry, no lock-in.

[Try Logfire for free](https://logfire.pydantic.dev/login?intent=signup) [See the Go docs](https://pydantic.dev/docs/logfire/instrument/go/)

Set up Logfire with your coding agent:

uvx logfire-cli wizard

Install and configure

```bash
export OTEL_EXPORTER_OTLP_ENDPOINT=https://logfire-us.pydantic.dev
export OTEL_EXPORTER_OTLP_HEADERS='Authorization=your-write-token'
export OTEL_SERVICE_NAME=hello-go
```

Instrument your app

View code

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

    exporter, err := otlptracehttp.New(ctx)
    if err != nil {
        log.Fatal(err)
    }

    tracerProvider := sdktrace.NewTracerProvider(sdktrace.WithBatcher(exporter))
    defer tracerProvider.Shutdown(ctx)

    otel.SetTracerProvider(tracerProvider)
    otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(
        propagation.TraceContext{}, propagation.Baggage{},
    ))
}
```

Full details are in the [Go setup guide](https://pydantic.dev/docs/logfire/instrument/go/).

Trusted by teams building production software and AI

**Customers:** Motorola, Sophos, Airbyte, Pictet, Vox Media, Weaviate, Amboss, Tiger Data

What you get

## One request, one trace

![A Logfire trace of a Go request: the otelhttp handler, otelsql queries and the outbound call, with an errored request below](https://pydantic.dev/assets/logfire/language-traces/go-trace.png)

**What lands in Logfire:**

* the `otelhttp` server span, with route and status
* each `database/sql` query, timed, via `otelsql`
* your own handler and business functions, nested underneath
* the outbound HTTP call the request made
* a failed lookup, marked red at the span that failed
* goroutine count, GC pause time and heap in use, as metrics beside the spans

Try it on your stack

## See your own Go trace

Start free with 10 million spans, logs, and metrics each month. No credit card required.

[Start free](https://logfire.pydantic.dev/login?intent=signup) [Read the Go setup guide](https://pydantic.dev/docs/logfire/instrument/go/)

How it works

## Standard OpenTelemetry, hosted backend

### Standard OTLP over HTTP

Logfire accepts http/protobuf, which is exactly what otlptracehttp sends. Set the endpoint and the Authorization header, build a tracer provider with a batch processor, and register it. There is no vendor SDK to learn and no wrapper around the OpenTelemetry API.

### The contrib instrumentation you already use works

otelhttp wraps net/http handlers and clients, otelgrpc covers RPC, and there are contrib packages for gin, echo, chi, database/sql, and the AWS SDK. All of them export to Logfire unchanged, because Logfire is a backend rather than a framework. If it emits OTLP, it arrives.

### Context propagation stays idiomatic

Spans follow context.Context the way Go code already passes it, so nested work inside a process is attributed to the right parent across goroutines. You are not adopting a second, parallel way of threading request state through your program. Crossing a service boundary is the propagator's job: register TraceContext once, as in the setup above, and otelhttp puts the traceparent header on outbound requests and reads it on inbound ones.

### Agent frameworks: Genkit and Eino

Building agents in Go? Firebase Genkit registers a standard OTLP exporter as its global tracer provider, and CloudWeGo Eino traces through the same path, so agent and tool telemetry lands in the same traces as your HTTP handlers and database calls. No separate agent-observability tool to run alongside.

### One backend for Go's three signals

Export spans, metrics, and structured logs from Go services over OTLP into one project. Resource attributes such as service.name stay attached, so the same service filter works in a trace search, dashboard, or alert.

### SQL instead of a query language you have to learn

Use PostgreSQL-compatible SQL to group Go telemetry by route, gRPC method, dependency, or any attribute your instrumentation records. Save the result as a dashboard or alert when the investigation becomes something you want to keep.

Query

## Query your Go telemetry with SQL

If you can ask it, SQL can find out

* Query your traces, metrics and logs with real SQL
* No proprietary query language to learn
* AI models are great at writing SQL
* From a one-off investigation to an alert, dashboard, or SLO

```sql
select
  attributes->>'http.route' as route,
  count(*) as requests,
  avg(duration) as avg_seconds
from records
where duration > 1
group by route
order by avg_seconds desc;
```

Proof

## In production

> You can tell that Pydantic Logfire was built by people who use it.

Dennis Griffin, VP of Engineering, Sophos [Read the case study](https://pydantic.dev/case-studies/sophos)

Decision guide

## Is Logfire right for you?

### Choose Logfire if

* You already use the OpenTelemetry Go SDK and want a hosted backend for it
* You want no vendor-specific imports in your Go codebase
* You want to query traces, metrics, and logs with PostgreSQL-compatible SQL
* You do not want to run Jaeger, Prometheus, and storage yourself
* You want the option to repoint at another backend without a rewrite

### Choose a vendor APM if

* You want a vendor-maintained Go SDK with vendor-specific APIs
* You are already deeply integrated with a specific APM vendor's ecosystem
* You need a vendor-only integration or compliance capability Logfire does not offer

FAQ

## Common questions

### Is there a Logfire SDK for Go?

No. Go uses the standard OpenTelemetry Go SDK, and Logfire is the OTLP backend it exports to. Nothing proprietary enters your codebase. First-party Logfire SDKs exist for Python, TypeScript, and Rust.

### Why does Go need code changes when Java does not?

Java has a JVM agent that rewrites bytecode as classes load, so instrumentation can be attached at startup with a flag. Go compiles to a static binary, so there is nothing to attach to at runtime. Instrumentation has to be wired in explicitly: create an exporter, build a tracer provider, and register it.

### Why is nothing arriving in Logfire?

Check three things. Use the HTTP exporter, otlptracehttp, unless you have deliberately configured gRPC, since Logfire expects http/protobuf. Confirm the endpoint matches your project's data region. Finally make sure the tracer provider is shut down cleanly on exit, because the batch processor flushes on shutdown and a killed process loses buffered spans.

### Do the OpenTelemetry contrib packages work?

Yes. otelhttp, otelgrpc, and the database instrumentation wrappers all work unchanged, because Logfire is a backend rather than a framework. Anything that exports OTLP reaches Logfire.

### Am I locked in to Logfire?

No. Configuration is standard OTEL\_ environment variables against the standard SDK, so your application code has no Logfire-specific imports. Repoint the endpoint at another OpenTelemetry-compatible backend, or at your own collector, whenever you want.

## Start seeing your Go service

Get started with 10 million free spans, logs, and metrics per month. No credit card required.

* [Start free](https://logfire.pydantic.dev/login?intent=signup)
* [Book a demo](https://pydantic.dev/contact)
* [View pricing plans](https://pydantic.dev/pricing)
