Documentation
¶
Overview ¶
Package autotix ships Go errors and panics to Autotix, which turns them into Jira or GitHub tickets and, when enabled, AI-generated fix PRs.
The package has no dependencies outside the standard library. Create one Client per process, keep it for the lifetime of the process, and Close it on shutdown so queued events are delivered:
client, err := autotix.New(os.Getenv("AUTOTIX_WEBHOOK_TOKEN"),
autotix.WithEnvironment("production"),
autotix.WithProject("WEB"),
)
if err != nil {
log.Fatal(err)
}
defer client.Close(context.Background())
if err := doWork(); err != nil {
client.Capture(err)
}
Delivery is asynchronous and bounded. Capture never blocks the caller and never returns an error: a full queue drops the event, a failed request is logged and counted in Stats. Error tracking that can take down the app it watches is a footgun, so the SDK fails soft everywhere.
A nil *Client is safe to use. Every method is a no-op, which lets an app leave the client unset in environments where Autotix is disabled.
Index ¶
- Constants
- Variables
- func CaptureStack(skip int) string
- type Client
- func (c *Client) Capture(err error, opts ...EventOption)
- func (c *Client) CaptureMessage(message string, opts ...EventOption)
- func (c *Client) CapturePanic(recovered any, opts ...EventOption)
- func (c *Client) Close(ctx context.Context) bool
- func (c *Client) Flush(ctx context.Context) bool
- func (c *Client) Middleware(next http.Handler) http.Handler
- func (c *Client) Recover(opts ...EventOption)
- func (c *Client) Stats() Stats
- func (c *Client) TriggerTestError(opts ...EventOption)
- type DualOption
- type Event
- type EventOption
- type GitContext
- type Level
- type Option
- func WithBeforeSend(fn func(*Event) *Event) Option
- func WithEndpoint(url string) Option
- func WithEnvironment(env string) Option
- func WithGitContext(g GitContext) Option
- func WithHMACSecret(secret string) Option
- func WithHTTPClient(hc *http.Client) Option
- func WithLogger(l *slog.Logger) Option
- func WithQueueSize(n int) Option
- func WithRelease(release string) Option
- func WithSampleRate(rate float64) Option
- func WithServerName(name string) Option
- func WithTimeout(d time.Duration) Option
- func WithWorkers(n int) Option
- type Stats
- type User
Examples ¶
Constants ¶
const ( // DefaultEndpoint is the production server-side ingest endpoint. DefaultEndpoint = "https://app.autotix.io/api/webhook/error" // DefaultTimeout bounds each delivery request. The webhook endpoint // creates the ticket before it answers, so it is slower than a plain // ingest call; this matches the PHP integrations. DefaultTimeout = 15 * time.Second // DefaultQueueSize is how many events may wait for delivery. DefaultQueueSize = 100 // DefaultWorkers is how many deliveries run at once. DefaultWorkers = 2 )
Defaults for New. Override them with the matching With option.
const Source = "go"
Source is the webhook `source` value every event carries. The Autotix dashboard labels Go events with it and dedup keys include it.
const Version = "0.1.0"
Version is the SDK version, sent in the User-Agent and in each event.
Variables ¶
var ErrMissingCredentials = errors.New("autotix: a webhook token or HMAC secret is required")
ErrMissingCredentials is returned by New when neither a token nor an HMAC secret was supplied.
Functions ¶
func CaptureStack ¶
CaptureStack returns the calling goroutine's stack, formatted like Go's own panic output: a function name line followed by a tab-indented file:line. Frames inside the SDK are left out, so the first frame is the code that called into Autotix. skip drops that many additional caller frames; 0 starts at the caller of CaptureStack.
Capture and CapturePanic call this for you. Use it directly when you build an event elsewhere and want to attach the stack with WithStackTrace.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client delivers events to Autotix. Create one with New and share it across goroutines; all methods are safe for concurrent use.
func New ¶
New creates a client authenticated with the org's webhook token (from Settings in the Autotix dashboard). The token is a server secret; keep it in configuration, never in client code. New returns an error when no credentials are given or an option is invalid.
Example ¶
package main
import (
"context"
"errors"
"log"
"os"
autotix "github.com/HelloWorldDevs/autotix-go"
)
func main() {
client, err := autotix.New(os.Getenv("AUTOTIX_WEBHOOK_TOKEN"),
autotix.WithEnvironment("production"),
autotix.WithRelease("v1.4.2"),
autotix.WithProject("WEB"),
)
if err != nil {
log.Fatal(err)
}
// Drain the queue before the process exits so nothing is lost.
defer client.Close(context.Background())
if err := doWork(); err != nil {
client.Capture(err, autotix.WithTag("module", "billing"))
}
}
func doWork() error { return errors.New("example") }
Output:
func (*Client) Capture ¶
func (c *Client) Capture(err error, opts ...EventOption)
Capture reports an error with the stack of the calling goroutine. A nil error is ignored. The call returns immediately; delivery happens in the background.
func (*Client) CaptureMessage ¶
func (c *Client) CaptureMessage(message string, opts ...EventOption)
CaptureMessage reports a message that is not an error, at LevelInfo unless WithLevel says otherwise. No stack trace is attached, so identical messages dedupe together on the server.
func (*Client) CapturePanic ¶
func (c *Client) CapturePanic(recovered any, opts ...EventOption)
CapturePanic reports a recovered panic value at LevelFatal. Call it from your own deferred recover when you want to decide what happens next, for example to re-panic:
defer func() {
if r := recover(); r != nil {
client.CapturePanic(r)
panic(r)
}
}()
func (*Client) Close ¶
Close stops accepting events, delivers what is already queued, and stops the workers. It returns false when ctx ends before the queue drains. Calling Close more than once is safe.
func (*Client) Flush ¶
Flush waits until every queued and in-flight event has been delivered or has failed. It returns false when ctx ends first. Call it before a short-lived process exits.
Example ¶
package main
import (
"context"
"log"
"time"
autotix "github.com/HelloWorldDevs/autotix-go"
)
func main() {
client, _ := autotix.New("your-org-webhook-token")
client.CaptureMessage("deploy finished", autotix.WithLevel(autotix.LevelInfo))
// In short-lived processes (CLIs, Lambdas, cron jobs) wait for delivery.
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if !client.Flush(ctx) {
log.Println("autotix: some events were still in flight")
}
}
Output:
func (*Client) Middleware ¶
Middleware reports panics raised by next, then re-panics so the recovery you already have (your own middleware or net/http's default) keeps working. Mount it closest to your handlers, inside any recovery middleware, so it sees the panic first. http.ErrAbortHandler is passed through without being reported.
Example ¶
package main
import (
"context"
"net/http"
autotix "github.com/HelloWorldDevs/autotix-go"
)
func main() {
client, _ := autotix.New("your-org-webhook-token", autotix.WithProject("API"))
defer client.Close(context.Background())
mux := http.NewServeMux()
mux.HandleFunc("/orders", func(w http.ResponseWriter, r *http.Request) {
if err := placeOrder(r); err != nil {
// Attach the request so the event carries the full URL.
client.Capture(err, autotix.WithRequest(r))
http.Error(w, "order failed", http.StatusInternalServerError)
return
}
})
// Panics in handlers are reported, then re-raised for your own recovery
// middleware (or net/http's default) to handle.
srv := &http.Server{Addr: ":8080", Handler: client.Middleware(mux)}
_ = srv
}
func placeOrder(*http.Request) error { return nil }
Output:
func (*Client) Recover ¶
func (c *Client) Recover(opts ...EventOption)
Recover is meant to be deferred directly: it recovers a panic in the current goroutine, reports it, and lets the goroutine end normally. It must be the deferred call itself (defer client.Recover()), not called from inside another deferred function, or recover has no effect.
The panic is swallowed even on a nil client, so disabling Autotix never changes how your program behaves. Use CapturePanic to re-panic instead.
Example ¶
package main
import (
"context"
autotix "github.com/HelloWorldDevs/autotix-go"
)
func main() {
client, _ := autotix.New("your-org-webhook-token")
defer client.Close(context.Background())
go func() {
// Report a panic in this goroutine and keep the process alive.
defer client.Recover(autotix.WithTag("job", "nightly-report"))
runNightlyReport()
}()
}
func runNightlyReport() {}
Output:
func (*Client) TriggerTestError ¶
func (c *Client) TriggerTestError(opts ...EventOption)
TriggerTestError sends one clearly labeled event through the normal pipeline to verify the setup end to end. It bypasses sampling and tags the event autotix_test=true so it is easy to filter out later.
type DualOption ¶
type DualOption interface {
Option
EventOption
}
DualOption is accepted by both New (as a default for every event) and the capture methods (for one event). WithProject, WithTag, and WithTags are dual options.
func WithProject ¶
func WithProject(key string) DualOption
WithProject routes events to a project key (a Jira key or owner/repo) instead of matching on the event URL. Passed to New it applies to every event; passed to a capture method it applies to that event. Background jobs, queue consumers, and CLIs should always pin a project because their errors carry no URL to match.
func WithTag ¶
func WithTag(key, value string) DualOption
WithTag attaches one searchable tag. Per-event tags override client defaults with the same key.
func WithTags ¶
func WithTags(tags map[string]string) DualOption
WithTags attaches several searchable tags at once.
type Event ¶
type Event struct {
// Message is the error text. Required.
Message string
// Level defaults to LevelError for errors, LevelInfo for messages, and
// LevelFatal for panics.
Level Level
// StackTrace is formatted like a Go panic trace: a function name line
// followed by a tab-indented file:line.
StackTrace string
// ErrorType is the Go type of the captured value, such as "*fs.PathError".
ErrorType string
// URL is the full request URL the error belongs to. Autotix matches it
// against each project's URL patterns when no Project is pinned.
URL string
// RequestMethod and UserAgent are filled by WithRequest.
RequestMethod string
UserAgent string
// Project pins the event to a project key (a Jira key or owner/repo),
// skipping URL matching. Background jobs should always set one.
Project string
Environment string
Release string
// ServerName is the reporting host, os.Hostname by default.
ServerName string
Timestamp time.Time
// Tags are searchable key/value pairs.
Tags map[string]string
// Extra holds any other detail worth attaching.
Extra map[string]any
User *User
Git *GitContext
}
Event is one error as the SDK sees it before encoding. A WithBeforeSend hook receives a pointer to it and may change any field or drop it.
type EventOption ¶
type EventOption interface {
// contains filtered or unexported methods
}
EventOption adjusts a single event. Pass options to Capture, CaptureMessage, CapturePanic, Recover, or TriggerTestError.
func WithExtra ¶
func WithExtra(key string, value any) EventOption
WithExtra attaches one non-searchable detail, such as a request id.
func WithRequest ¶
func WithRequest(r *http.Request) EventOption
WithRequest fills the event's URL, method, and user agent from an incoming request so Autotix can route it by URL. A nil request is ignored.
func WithStackTrace ¶
func WithStackTrace(stack string) EventOption
WithStackTrace replaces the stack the SDK captured, for errors that carry their own trace.
func WithURL ¶
func WithURL(url string) EventOption
WithURL sets the full URL the error belongs to. Send the whole URL including scheme and host; a bare path matches no project.
type GitContext ¶
type GitContext struct {
// Provider is the lowercase host name: "github", "gitlab", "bitbucket".
// Autotix acts on GitHub today and ignores the rest.
Provider string `json:"provider"`
// PR is the pull or merge request number.
PR int `json:"pr"`
// Ref is the branch name, informational only.
Ref string `json:"ref,omitempty"`
// Preview is a label for the preview environment, such as a Tugboat
// preview name.
Preview string `json:"preview,omitempty"`
}
GitContext names the pull request an error was observed inside, so Autotix can comment on the PR instead of opening a ticket. It is detected from the environment at startup (see DetectGitContext) or set with WithGitContext.
func DetectGitContext ¶
func DetectGitContext() *GitContext
DetectGitContext reads the pull request a process runs inside from the environment. It returns nil outside a recognized PR preview.
A generic AUTOTIX_GIT_PROVIDER / AUTOTIX_GIT_PR pair (plus optional AUTOTIX_GIT_REF and AUTOTIX_GIT_PREVIEW) wins, so any CI can opt in. Tugboat previews are recognized out of the box through their per-provider variables (TUGBOAT_GITHUB_PR, TUGBOAT_GITLAB_MR, TUGBOAT_BITBUCKET_PR, TUGBOAT_STASH_PR) together with TUGBOAT_PREVIEW_REF and TUGBOAT_PREVIEW_NAME.
New calls this once at construction. Override the result with WithGitContext.
type Option ¶
type Option interface {
// contains filtered or unexported methods
}
Option configures a Client. Pass options to New.
func WithBeforeSend ¶
WithBeforeSend runs fn on every event right before it is queued. Return nil to drop the event. A panic inside fn is recovered and the event is sent as it was.
func WithEndpoint ¶
WithEndpoint overrides the ingest URL. Use it for a self-hosted Autotix or a staging environment. Defaults to DefaultEndpoint.
func WithEnvironment ¶
WithEnvironment tags every event with a deployment environment such as "production" or "staging".
func WithGitContext ¶
func WithGitContext(g GitContext) Option
WithGitContext pins the pull request context attached to every event, replacing what DetectGitContext would find in the environment.
func WithHMACSecret ¶
WithHMACSecret signs each request body with HMAC-SHA256 and sends the hex digest in X-Webhook-Signature instead of sending the token. When set, the token passed to New may be empty.
func WithHTTPClient ¶
WithHTTPClient sends requests through the given client, for custom transports, proxies, or tests.
func WithLogger ¶
WithLogger routes the SDK's own log lines. Failed deliveries log at Warn, successful ones at Debug. Defaults to slog.Default. Pass a logger backed by io.Discard to silence the SDK.
func WithQueueSize ¶
WithQueueSize bounds how many events can wait for delivery. When the queue is full new events are dropped and counted in Stats. Defaults to DefaultQueueSize.
func WithRelease ¶
WithRelease tags every event with an app version or commit SHA.
func WithSampleRate ¶
WithSampleRate ships only the given fraction of events, from 0 (none) to 1 (all, the default). Sampling runs before any network work, so dropped events cost nothing. TriggerTestError always bypasses it.
func WithServerName ¶
WithServerName overrides the hostname reported with each event. Defaults to os.Hostname.
func WithTimeout ¶
WithTimeout bounds each delivery request. Defaults to DefaultTimeout.
func WithWorkers ¶
WithWorkers sets how many deliveries run concurrently. Defaults to DefaultWorkers.
type Stats ¶
type Stats struct {
// Sent is the number of events the server accepted with a 2xx.
Sent int64
// Failed is the number of events that got a non-2xx or a network error.
Failed int64
// Dropped is the number of events discarded because the queue was full
// or the client was already closed.
Dropped int64
}
Stats counts delivery outcomes since the client was created.