errorgap

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 6, 2026 License: MIT Imports: 14 Imported by: 0

README

errorgap-go

Go notifier for Errorgap. Captures errors and panics, walks the goroutine stack, and ships notices to an Errorgap server. Ships a net/http recovery middleware; gin/chi/echo/fiber adapters will follow in 0.2.

Install

go get github.com/errorgaphq/errorgap-go

Requires Go 1.22+.

Configure

package main

import (
    "context"
    "os"

    errorgap "github.com/errorgaphq/errorgap-go"
)

func main() {
    err := errorgap.Init(errorgap.Config{
        Endpoint:    os.Getenv("ERRORGAP_ENDPOINT"),
        ProjectSlug: os.Getenv("ERRORGAP_PROJECT_SLUG"),
        APIKey:      os.Getenv("ERRORGAP_API_KEY"),
        Environment: os.Getenv("APP_ENV"),
    })
    if err != nil {
        panic(err)
    }
    defer errorgap.Close(context.Background())
    // ... your app ...
}

Init reads the same values from ERRORGAP_ENDPOINT, ERRORGAP_PROJECT_SLUG, ERRORGAP_PROJECT_ID, and ERRORGAP_API_KEY if you leave them empty.

Manual notification

if err := risky(); err != nil {
    errorgap.Notify(err, errorgap.NoticeOptions{
        Context: map[string]any{"component": "billing"},
    })
    return err
}

Notify returns a Result ({Status, Body, Err, Queued}). The SDK never panics — recoverable failures are logged via the configured slog.Logger.

net/http

mux := http.NewServeMux()
mux.HandleFunc("/", handler)
http.ListenAndServe(":8080", stdhttp.Recover(mux))

The middleware catches panics, reports them, and returns a 500 response.

Recover helper

For background goroutines or workers without HTTP middleware:

func worker() {
    defer errorgap.Recover()
    // ... risky code that may panic ...
}

Recover reports the panic and re-panics so the host's normal panic handling still runs.

Graceful shutdown

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_ = errorgap.Flush(ctx) // wait for queued notices
_ = errorgap.Close(ctx) // shut down the worker goroutine

Configuration reference

Field Default Notes
Endpoint ERRORGAP_ENDPOINT or http://127.0.0.1:3030 Base URL, no trailing slash
ProjectSlug ERRORGAP_PROJECT_SLUG Required
ProjectID ERRORGAP_PROJECT_ID Optional, embedded in payload
APIKey ERRORGAP_API_KEY Sent as x-errorgap-project-key
Environment ERRORGAP_ENVIRONMENT or "production"
Release Embedded in context.release
Async true (via Init) Background goroutine delivery
Logger slog.New(...io.Discard) Replace to surface SDK warnings
FilterKeys ["password", "token", ...] Substring, case-insensitive
HTTPClient &http.Client{Timeout: 5s} Plug in your own transport
QueueSize 100 Drops oldest notice when full

Verify

curl -sS -X POST "$ERRORGAP_ENDPOINT/api/projects/$ERRORGAP_PROJECT_SLUG/notices" \
  -H "content-type: application/json" \
  -H "x-errorgap-project-key: $ERRORGAP_API_KEY" \
  -d '{"errors":[{"type":"ErrorgapInstallTest","message":"Errorgap install verification"}],"context":{"environment":"development"}}'

Then trigger a real error and confirm it appears in the Errorgap UI.

Development

go test ./...

License

MIT.

Documentation

Overview

Package errorgap is the Go notifier for the Errorgap error-tracking platform. Use Init to configure the package-level default client and Notify / Flush / Close as the simple, package-level entry points.

For libraries or apps that want isolated state (e.g. tests), instantiate a Client directly with NewClient.

Index

Constants

View Source
const Version = "0.1.0"

Version is the SDK version, embedded in every notice's User-Agent header.

Variables

View Source
var (
	// ErrMissingProjectSlug is returned from validation when ProjectSlug
	// is empty.
	ErrMissingProjectSlug = errors.New("errorgap: ProjectSlug is required")
	// ErrMissingEndpoint is returned from validation when Endpoint is
	// empty.
	ErrMissingEndpoint = errors.New("errorgap: Endpoint is required")
)
View Source
var DefaultFilterKeys = []string{
	"password",
	"password_confirmation",
	"token",
	"secret",
	"api_key",
	"authorization",
	"cookie",
}

DefaultFilterKeys are matched (case-insensitive substring) against param keys to mask sensitive values before delivery.

Functions

func Close

func Close(ctx context.Context) error

Close drains and shuts down the package-level client.

func FilterParams

func FilterParams(params map[string]any, filterKeys []string) map[string]any

FilterParams masks sensitive keys (case-insensitive substring match) in a params map. Nested maps are walked; arrays/slices are not recursed into.

func Flush

func Flush(ctx context.Context) error

Flush blocks until in-flight async deliveries finish.

func Init

func Init(cfg Config) error

Init configures the package-level default client. Subsequent calls replace the existing default. The previous client is closed in the background so in-flight deliveries still finish.

func Recover

func Recover()

Recover wraps a deferred panic recovery: any non-nil recovered value is reported to Errorgap, then re-panicked so caller stacks observe it.

defer errorgap.Recover()

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client posts notices to an Errorgap server. Safe for concurrent use.

func NewClient

func NewClient(cfg Config) (*Client, error)

NewClient validates the config, applies defaults, and starts the async delivery goroutine. The caller should defer Close() to flush in-flight deliveries during shutdown.

func (*Client) Close

func (c *Client) Close(ctx context.Context) error

Close drains the queue and stops the background worker. Idempotent.

func (*Client) Config

func (c *Client) Config() Config

Config returns a copy of the client's effective configuration.

func (*Client) Flush

func (c *Client) Flush(ctx context.Context) error

Flush blocks until in-flight async deliveries complete.

func (*Client) Notify

func (c *Client) Notify(err error, opts ...NoticeOptions) Result

Notify queues an error for delivery and returns immediately when Async is true. When Async is false, it blocks until the HTTP call completes.

type Config

type Config struct {
	// Endpoint is the base URL of the Errorgap server (no trailing slash).
	// Defaults to $ERRORGAP_ENDPOINT or http://127.0.0.1:3030.
	Endpoint string

	// ProjectSlug is the slug used in the ingestion URL.
	// Defaults to $ERRORGAP_PROJECT_SLUG. Required.
	ProjectSlug string

	// ProjectID is optional and embedded in the notice payload.
	// Defaults to $ERRORGAP_PROJECT_ID.
	ProjectID string

	// APIKey is sent as the x-errorgap-project-key header.
	// Defaults to $ERRORGAP_API_KEY.
	APIKey string

	// Environment labels the deployment ("production", "staging").
	// Defaults to $ERRORGAP_ENVIRONMENT or "production".
	Environment string

	// Release is the application version embedded in the notice context.
	Release string

	// Async controls fire-and-forget delivery. Defaults to true.
	Async bool

	// Logger receives SDK warnings. Defaults to slog.Default().
	// Set to a no-op handler to silence.
	Logger *slog.Logger

	// FilterKeys overrides DefaultFilterKeys.
	FilterKeys []string

	// HTTPClient lets callers plug in a custom transport.
	// Defaults to a copy of http.DefaultClient with a 5s timeout.
	HTTPClient *http.Client

	// Timeout for the default HTTP client. Ignored if HTTPClient is set.
	Timeout time.Duration

	// QueueSize bounds the in-flight notice channel when Async is true.
	// Drops oldest in-flight notice when full. Defaults to 100.
	QueueSize int

	// CaptureGlobals installs a recover-and-log hook at the entry point.
	// (Go doesn't allow process-wide panic handlers; use the middleware
	// adapters instead.) Currently unused; reserved for future use.
	CaptureGlobals bool
}

Config controls notifier behavior.

type ErrorEntry

type ErrorEntry struct {
	Type      string  `json:"type"`
	Message   string  `json:"message"`
	Backtrace []Frame `json:"backtrace"`
}

ErrorEntry is one entry in the notice's errors array.

type Frame

type Frame struct {
	File     string `json:"file,omitempty"`
	Line     int    `json:"line,omitempty"`
	Function string `json:"function,omitempty"`
	InApp    bool   `json:"in_app"`
	Index    int    `json:"index"`
}

Frame is a single backtrace entry in the notice envelope.

type Notice

type Notice struct {
	ProjectID   string         `json:"project_id,omitempty"`
	ReceivedAt  string         `json:"received_at"`
	Errors      []ErrorEntry   `json:"errors"`
	Context     map[string]any `json:"context"`
	Environment map[string]any `json:"environment"`
	Session     map[string]any `json:"session"`
	Params      map[string]any `json:"params"`
}

Notice is the wire envelope POSTed to /api/projects/:slug/notices.

type NoticeOptions

type NoticeOptions struct {
	Context     map[string]any
	Environment map[string]any
	Session     map[string]any
	Params      map[string]any

	// Skip extra runtime.Caller frames when capturing the backtrace.
	// Useful when Notify is wrapped by another helper.
	BacktraceSkip int
}

NoticeOptions allows callers to add per-notice context.

type Result

type Result struct {
	Status int
	Body   []byte
	Err    error
	Queued bool
}

Result records the outcome of a single Notify call.

func Notify

func Notify(err error, opts ...NoticeOptions) Result

Notify sends an error via the package-level client. Returns an empty Result if Init has not been called.

func (Result) Success

func (r Result) Success() bool

Success reports whether delivery returned a 2xx.

Directories

Path Synopsis
internal
testutil
Package testutil hosts test helpers shared across the package.
Package testutil hosts test helpers shared across the package.
Package stdhttp provides a net/http middleware that reports panics to Errorgap.
Package stdhttp provides a net/http middleware that reports panics to Errorgap.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL