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 ¶
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 ¶
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.
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.