Go error tracking installation

Contents

  1. Install the Go SDK

    Required

    Install the PostHog Go SDK:

    Terminal
    go get github.com/posthog/posthog-go
    Source context not yet supported

    The Go SDK captures stack traces with file names, line numbers, and function names, but does not yet support source context (displaying the surrounding lines of code in the error tracking UI).

  2. Initialize the client

    Required
    Go
    package main
    import (
    "github.com/posthog/posthog-go"
    )
    func main() {
    client, _ := posthog.NewWithConfig(
    "<ph_project_token>",
    posthog.Config{
    Endpoint: "https://us.i.posthog.com",
    },
    )
    defer client.Close()
    }
  3. Capture exceptions

    Required

    There are two ways to capture exceptions with the Go SDK:

    Option A: Direct capture

    Use NewDefaultException to capture errors directly. This automatically generates a UUID and stack trace for you.

    Go
    import (
    "time"
    "github.com/posthog/posthog-go"
    )
    exception := posthog.NewDefaultException(
    time.Now(),
    "user_distinct_id",
    "DatabaseError", // type - rendered as title in the UI
    "connection refused", // value - rendered as description in the UI
    )
    client.Enqueue(exception)

    For more control, build the Exception struct manually:

    Go
    import (
    "time"
    "github.com/posthog/posthog-go"
    )
    handled := true
    fingerprint := "my-custom-fingerprint"
    exception := posthog.Exception{
    DistinctId: "user_distinct_id",
    Timestamp: time.Now(),
    ExceptionList: []posthog.ExceptionItem{
    {
    Type: "DatabaseError",
    Value: "connection refused",
    Mechanism: &posthog.ExceptionMechanism{
    Handled: &handled,
    },
    },
    },
    ExceptionFingerprint: &fingerprint,
    }
    client.Enqueue(exception)

    To see how net/http services can automatically associate backend exceptions with frontend users, view the Go request context documentation.

    Option B: Automatic capture with slog

    The SDK provides a SlogCaptureHandler that wraps Go's standard log/slog logger and automatically captures log records as exceptions.

    By default, it captures logs at Warning level and above.

    Go
    import (
    "context"
    "fmt"
    "log/slog"
    "os"
    "github.com/posthog/posthog-go"
    )
    client, _ := posthog.NewWithConfig(
    "<ph_project_token>",
    posthog.Config{
    Endpoint: "https://us.i.posthog.com",
    },
    )
    defer client.Close()
    baseHandler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
    Level: slog.LevelInfo,
    })
    logger := slog.New(posthog.NewSlogCaptureHandler(baseHandler, client,
    posthog.WithDistinctIDFn(func(ctx context.Context, r slog.Record) string {
    // Return the user ID from context or another source
    return "user_distinct_id"
    }),
    ))
    // This warning is automatically captured as an exception in PostHog
    logger.Warn("Something broke",
    "error", fmt.Errorf("connection refused"),
    )

    The handler supports several configuration options:

    OptionDescriptionDefault
    WithMinCaptureLevel(level)Minimum log level to captureslog.LevelWarn
    WithDistinctIDFn(fn)Function to extract distinct ID from context/recordReturns "" (skips capture)
    WithFingerprintFn(fn)Custom fingerprint for error groupingnil (PostHog assigns)
    WithSkip(n)Stack frames to skip5
    WithStackTraceExtractor(e)Custom stack trace extractorDefaultStackTraceExtractor
    WithDescriptionExtractor(e)Custom description extractorErrorExtractor

    Error extraction

    The slog handler automatically extracts error descriptions from log attributes with keys err or error (case-insensitive). It also supports wrapped errors via the Unwrap() interface.

  4. Verify error tracking

    Recommended

    Trigger a test exception to confirm events are being sent to PostHog. You should see them appear in the activity feed.

    Go
    exception := posthog.NewDefaultException(
    time.Now(),
    "test_user",
    "TestError",
    "This is a test exception from Go",
    )
    client.Enqueue(exception)
    // Flush the queue before exiting
    client.Close()
  5. Upload debug symbols (macOS)

    Optional

    For production Go binaries on macOS, uploading debug symbols enables server-side symbolication with full stack traces including inlined frames.

    Build with uncompressed DWARF

    Go compresses its embedded DWARF by default, which the symbolication server cannot read. Disable compression when building:

    Terminal
    go build -ldflags="-compressdwarf=false" -o myapp .

    Upload the binary

    After building, upload the binary with the PostHog CLI:

    Terminal
    posthog-cli symbol-sets upload --directory ./

    The CLI finds the Go executable, extracts its LC_UUID, and uploads the debug symbols. Run this as part of the same pipeline that produces your production binary — each build has its own UUID, so symbols must be re-uploaded for every build you deploy.

    Version requirements

    Mach-O executable uploads require CLI 0.8.2 or later.

Community questions

Was this page useful?