DebugBundle
SDKs

Go SDK

Install DebugBundle in Go services with net/http, Gin, Echo, structured logging, probes, and browser relay capture.

The Go SDK ships as github.com/debugbundle/debugbundle-go and supports standard Go services, net/http, Gin, Echo, log/slog, zap, zerolog, local file transport, connected HTTP transport, remote capture policy, probes, and a full same-origin browser relay handler.

Installation

go get github.com/debugbundle/debugbundle-go

The module requires Go 1.21 or newer.

net/http

package main

import (
	"context"
	"net/http"

	debugbundle "github.com/debugbundle/debugbundle-go"
	"github.com/debugbundle/debugbundle-go/debugbundlehttp"
	"github.com/debugbundle/debugbundle-go/relay"
)

func main() {
	client := debugbundle.New(debugbundle.Config{
		ProjectToken: "dbundle_proj_...",
		Service:      "checkout-api",
		Environment:  "production",
	})
	defer func() { _ = client.Flush(context.Background()) }()

	mux := http.NewServeMux()
	mux.HandleFunc("/checkout", func(writer http.ResponseWriter, request *http.Request) {
		client.Probe(request.Context(), "checkout.state", map[string]any{"phase": "authorize"})
		http.Error(writer, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
	})
	mux.Handle("/debugbundle/browser", debugbundlehttp.RelayHandler(client, relay.Options{}))

	handler := debugbundlehttp.Middleware(client, debugbundlehttp.Options{RecoverPanics: true})(mux)
	_ = http.ListenAndServe(":8080", handler)
}

The middleware captures 5xx request events, request IDs, X-DebugBundle-Trace-Id, route patterns when provided, and panics without changing normal handler flow unless panic recovery is explicitly enabled.

Gin

router := gin.New()
router.Use(gin.Recovery())
router.Use(debugbundlegin.Middleware(client))

Gin events include the matched route from c.FullPath(), status code, duration, request correlation, Gin errors, and panic capture.

Echo

app := echo.New()
app.Use(debugbundleecho.Middleware(client))

Echo events include the matched route from c.Path(), status code, duration, request correlation, Echo errors, and panic capture.

Logging

log/slog support is built in:

logger := slog.New(debugbundleslog.NewHandler(client, slog.NewJSONHandler(os.Stdout, nil)))
logger.ErrorContext(ctx, "checkout failed", "request_id", "req_123")

Optional zap and zerolog adapters are available without adding those dependencies to the core package:

zapLogger := zap.New(debugbundlezap.NewCore(client, zapcore.NewCore(encoder, sink, zap.InfoLevel)))
zerologLogger := zerolog.New(debugbundlezerolog.NewWriter(client, os.Stdout)).With().Timestamp().Logger()

Browser Relay

Mount the same-origin relay on your backend so browser events never need a server-side project token in client JavaScript:

mux.Handle("/debugbundle/browser", debugbundlehttp.RelayHandler(client, relay.Options{}))

The relay validates origin, Content-Type, body size, event schema, event type, credential stripping, rate limits, local-only event files, connected durable spool files, and connected forwarding with the server-side project token.

Transport Modes

Connected production and staging services send batches to POST /v1/events and poll GET /v1/sdk/config for server-owned capture policy and probe activation.

client := debugbundle.New(debugbundle.Config{
	ProjectToken: "dbundle_proj_...",
	Service:      "checkout-api",
	Environment:  "production",
	ProjectMode:  debugbundle.ProjectModeConnected,
})

Local-only mode writes event batches to .debugbundle/local/events/ with owner-only permissions and atomic temp-file rename.

client := debugbundle.New(debugbundle.Config{
	ProjectToken:   "dbundle_proj_local",
	Service:        "checkout-api",
	Environment:    "development",
	ProjectMode:    debugbundle.ProjectModeLocalOnly,
	LocalEventsDir: ".debugbundle/local/events",
})

Probes And Capture Policy

Always-on probes buffer diagnostic snapshots in process and flush them with exception events by default:

client.Probe(ctx, "checkout.cart", map[string]any{"items": 3})

Heavy probes stay dormant unless a matching remote activation or signed request-scoped trigger token enables them:

client.ProbeLazy(ctx, "checkout.sql.plan", func() any {
	return expensiveExplainPlan()
}, debugbundle.WithHeavyProbe())

If startup remote config fails, the SDK falls back to the safe minimal capture policy while keeping always-on probe buffers available for failure context.

Privacy Defaults

Go defaults are conservative for healthcare, financial, and enterprise systems:

  • request and response bodies are off by default,
  • request headers are allowlisted,
  • sensitive fields are recursively redacted before buffering or transport,
  • existing request IDs are preserved,
  • X-DebugBundle-Trace-Id links browser and backend events,
  • SDK failures are swallowed internally and never panic into host application code.

Add project-specific redaction keys with Config.RedactFields.

Runtime Support

The SDK supports Go 1.21 and newer. CI validates Go 1.21 through the current planned Go 1.26 lane, including race tests on the current lane.

On this page