errortrack

package
v0.67.0 Latest Latest
Warning

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

Go to latest
Published: Aug 18, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package errortrack turns the $exception events the SDK already captures into an error report: grouped, ranked by the people they hit, and joined to the funnel they broke.

The join is the whole reason this lives here rather than in a separate tool. Sentry knows your errors and nothing about your funnel. Product analytics knows your funnel and nothing about your errors. Everyone ends up correlating two dashboards by eye and guessing. This instance holds both streams as the same events, so "this exception is on the checkout step and the 41 people who hit it never came back" is one query rather than a meeting.

Index

Constants

View Source
const ExceptionEvent = "$exception"

ExceptionEvent is what sdk.js records for an uncaught error or a rejected promise.

Variables

This section is empty.

Functions

func Fingerprint

func Fingerprint(msg, source string, line int) string

Fingerprint identifies an error across occurrences.

Source and line are included when present because the same generic message ("Cannot read properties of undefined") from two different files is two different bugs, and merging them produces a row nobody can fix. The COLUMN is deliberately excluded: it moves when a minifier reflows a line, which would split one bug into a new group on every deploy.

func Normalise

func Normalise(msg string) string

Normalise reduces a message to its shape. Order matters: URLs before numbers, or a URL's port and path segments become <n> and the URL stops being recognisable as one.

Types

type Group

type Group struct {
	// Fingerprint identifies the error ACROSS occurrences and releases. Stable by construction —
	// it is what makes "is this the same bug as last week" answerable.
	Fingerprint string `json:"fingerprint"`
	// Title is the normalised message: the shape of the error, with the varying parts removed.
	Title   string    `json:"title"`
	Sample  string    `json:"sample"`           // one verbatim message, so nothing is lost to normalisation
	Source  string    `json:"source,omitempty"` // file
	Line    int       `json:"line,omitempty"`
	Kind    string    `json:"kind,omitempty"`  // "unhandledrejection" when it was a promise
	Count   int       `json:"count"`           // occurrences
	Users   int       `json:"users"`           // DISTINCT people — the number that should rank this list
	Paths   []string  `json:"paths,omitempty"` // where it fires, most common first
	FirstAt time.Time `json:"first_at"`
	LastAt  time.Time `json:"last_at"`
	// New says this error was not seen before the window opened. A regression and a long-standing
	// annoyance need opposite reactions, and a list that cannot tell them apart is a backlog.
	New bool `json:"new"`
}

Group is one distinct error, however many times it fired.

type Impact

type Impact struct {
	Fingerprint string `json:"fingerprint"`
	Title       string `json:"title"`
	// Step is where the affected users were furthest along when they hit it — the actionable
	// half, because it names the screen to go and look at.
	Step string `json:"step,omitempty"`
	// Affected/Clean are conversion rates for the two populations, as percentages.
	AffectedUsers int     `json:"affected_users"`
	AffectedConv  float64 `json:"affected_conversion_pct"`
	CleanUsers    int     `json:"clean_users"`
	CleanConv     float64 `json:"clean_conversion_pct"`
	// GapPct is CleanConv - AffectedConv: how many points worse the affected group did. Positive
	// means the error is associated with worse conversion.
	GapPct float64 `json:"gap_pct"`
	// Read is the sentence, and it is careful about the difference between association and cause.
	Read string `json:"read"`
	// Thin says the comparison is too small to mean anything. It is still returned rather than
	// hidden, because "we cannot tell yet" is an answer and an empty row is not.
	Thin bool `json:"thin"`
}

Impact is one error group measured against the funnel.

func FunnelImpact

func FunnelImpact(evs []event.Event, groups []Group, steps []funnel.Step, window time.Duration) []Impact

FunnelImpact measures each error group against the funnel the caller is already showing.

Passing the page's own steps in — rather than detecting a funnel here — is deliberate: a report that quietly measures a different funnel than the one on screen is the contradiction this codebase spent a week removing.

type Result

type Result struct {
	Groups []Group `json:"groups"`
	// Users and UsersAffected are the crash-free read: how many people were active, and how many
	// of them hit at least one error. A rate is more honest than a count — 400 errors is
	// meaningless without knowing whether that is four users or four hundred.
	Users         int     `json:"users"`
	UsersAffected int     `json:"users_affected"`
	CrashFreePct  float64 `json:"crash_free_pct"`
	Total         int     `json:"total"` // total exception events in the window
	Note          string  `json:"note,omitempty"`
}

Result is the error report for a window.

func Compute

func Compute(evs []event.Event, from, to, priorFrom time.Time) Result

Compute builds the error report over [from, to).

`priorFrom` is the start of the preceding equal window, used only to decide New. Zero disables the new/known split rather than guessing.

Jump to

Keyboard shortcuts

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