Skill 76 · Instrument Error Tracking
Subchapter 76.12
references/go.mdMarkdown5 KBView on GitHub
AI agents: this is one page from PostHog’s docs. Full index of Markdown docs for LLMs: https://posthog.com/llms.txt (opens in a new tab)
1
Required
Install the PostHog Go SDK (opens in a new tab):
Terminal
go get github.com/posthog/posthog-goDebug symbol uploads
The Go SDK resolves stack traces in-process, so captured frames include file names, line numbers, function names, and inlined calls without any symbol uploads. To also see source context (the surrounding lines of code in the error tracking UI), upload debug symbols (opens in a new tab). That needs posthog-go 1.22.0 or later.
2
Required
Go
package main
import (
"github.com/posthog/posthog-go"
)
func main() {
client, _ := posthog.NewWithConfig(
"<ph_project_token>",
3
Required
There are two ways to capture exceptions with the Go SDK:
Use NewDefaultException to capture errors directly. This automatically generates a UUID and stack trace for you.
Go
import (
"time"
4
Recommended
Trigger a test exception to confirm events are being sent to PostHog. You should see them appear in the activity feed (opens in a new tab).
Go
exception := posthog.NewDefaultException(
time.Now(),
"test_user",
"TestError",
Ask PostHog AI
HelpfulCould be better
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 (opens in a new tab).
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:
| Option | Description | Default |
|---|---|---|
WithMinCaptureLevel(level) | Minimum log level to capture | slog.LevelWarn |
WithDistinctIDFn(fn) | Function to extract distinct ID from context/record | Returns "" (skips capture) |
WithFingerprintFn(fn) | Custom fingerprint for error grouping | nil (PostHog assigns) |
WithSkip(n) | Stack frames to skip | 5 |
WithStackTraceExtractor(e) | Custom stack trace extractor | DefaultStackTraceExtractor |
WithDescriptionExtractor(e) | Custom description extractor | ErrorExtractor |
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.