gosupport

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 18, 2026 License: MIT Imports: 8 Imported by: 0

README

gosupport

Turn server-side errors in a Go app into Support tickets that carry the real server detail — no Sentry or other error tracker required (Support is the store).

Report-gated: on a 5xx the middleware buffers the error detail locally (short TTL), keyed by a correlation id it stamps on the response. The detail is pushed to Support only when a user reports it (via the Flush handler you mount), so Support never stores errors nobody reported, and the detail stays server-side until then.

Install

go get github.com/deftstar/gosupport

Use

r := gosupport.New(gosupport.Config{
    IngestURL: "https://support-api.deftstar.dev/api/ingest/errors",
    SecretKey: os.Getenv("SUPPORT_SECRET_KEY"), // project secret (sk_…); never sent to the browser
})

// Mount the flush endpoint behind your own auth, and wrap your router:
mux.Handle("/support/errors/flush", requireAuth(http.HandlerFunc(r.Flush)))
http.ListenAndServe(":8080", r.Middleware(mux))

On a 5xx (or panic) the correlation id is set on the X-Request-Id response header and the detail is buffered. The browser reads that header; when the user reports, the frontend POSTs {"requestId": "…"} to your flush route → that one error is pushed to Support and the ticket links to it.

Options

field default notes
IngestURL, SecretKey required
Source "local" error-source label
HeaderName "X-Request-Id" correlation-id header; reuses an inbound one
TTL 30m how long a 5xx is buffered awaiting a report
Store in-process TTL map provide a shared (Redis) store if you run multiple instances
Sample status >= 500 what to buffer
Client, NewID, OnError sensible HTTP client / id generator / failure observer

Get the id in a handler with gosupport.RequestID(r.Context()); buffer explicitly with r.Buffer(id, msg, detail); flush programmatically with r.FlushID(id).

Release

git tag v0.1.0 && git push origin v0.1.0

Public module — go get github.com/deftstar/gosupport@v0.1.0 works immediately via the Go proxy; no registry account needed.

Documentation

Overview

Package gosupport turns server-side errors in a Go app into Support tickets that carry the real server detail — no error tracker (Sentry etc.) required.

It is report-gated: on a 5xx the middleware BUFFERS the error detail locally (short TTL), keyed by a correlation id it stamps on the response. The detail is pushed to Support only when a user reports it (via the Flush handler you mount), so Support never stores errors nobody reported and the detail stays server-side until then.

r := gosupport.New(gosupport.Config{
    IngestURL: "https://support-api.deftstar.dev/api/ingest/errors",
    SecretKey: os.Getenv("SUPPORT_SECRET_KEY"),
})
mux.Handle("/support/errors/flush", authOnly(http.HandlerFunc(r.Flush))) // protect it
http.ListenAndServe(":8080", r.Middleware(mux))

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RequestID

func RequestID(ctx context.Context) string

RequestID returns the correlation id stamped on the request, if any.

Types

type Config

type Config struct {
	IngestURL  string        // Support ingest endpoint, e.g. https://support-api.deftstar.dev/api/ingest/errors
	SecretKey  string        // project secret key (sk_...)
	Source     string        // error source label; defaults to "local"
	HeaderName string        // correlation-id response header; defaults to "X-Request-Id"
	TTL        time.Duration // how long to buffer an error awaiting a report; defaults to 30m
	Client     *http.Client  // HTTP client for pushes; defaults to a 5s-timeout client
	NewID      func() string // correlation-id generator; defaults to a random hex id
	// Store buffers errors awaiting a report. Defaults to an in-process TTL store —
	// fine for a single instance; provide a shared (e.g. Redis-backed) store if you
	// run several, so the flush hits wherever the error was buffered.
	Store Store
	// Sample decides whether a completed request's status should be buffered.
	// Defaults to "status >= 500".
	Sample  func(r *http.Request, status int) bool
	OnError func(error) // observe push failures (best-effort)
}

Config configures a Reporter. Only IngestURL and SecretKey are required.

type Reporter

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

Reporter buffers errors and, on report, pushes them to Support.

func New

func New(cfg Config) *Reporter

New builds a Reporter, filling in defaults.

func (*Reporter) Buffer

func (r *Reporter) Buffer(id, message string, detail map[string]any)

Buffer stores an error explicitly (e.g. from a custom handler).

func (*Reporter) Flush

func (r *Reporter) Flush(w http.ResponseWriter, req *http.Request)

Flush is an HTTP handler the app mounts (behind its own auth). It reads a correlation id (JSON body {"requestId":...} or the correlation header) and pushes that one buffered error to Support. Responds {"ok":true,"pushed":<bool>}.

func (*Reporter) FlushID

func (r *Reporter) FlushID(id string) bool

FlushID pushes a single buffered error to Support. Returns true if one was buffered and sent.

func (*Reporter) Middleware

func (r *Reporter) Middleware(h http.Handler) http.Handler

Middleware wraps h: it stamps a correlation id, recovers panics as 500s, and BUFFERS qualifying errors (no push). Nothing leaves the process until Flush.

type Store

type Store interface {
	Put(id string, payload []byte, ttl time.Duration)
	Take(id string) ([]byte, bool)
}

Store buffers captured errors by correlation id. Get is one-shot (delete on read).

Jump to

Keyboard shortcuts

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