trends

package
v0.9.2 Latest Latest
Warning

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

Go to latest
Published: Jul 15, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package trends computes time-series — how many times an event happened per day (optionally unique users), the third core analysis primitive alongside funnels and retention. Deterministic and storage-agnostic.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NumericProps added in v0.9.0

func NumericProps(events []event.Event) []string

NumericProps returns the property names that carry at least one numeric value across the events — the columns a measure (sum/avg/p90) can aggregate. Sorted for determinism. Lets the ask bar resolve "revenue" to a real numeric property, or say honestly that none exists.

Types

type Interval added in v0.9.1

type Interval string

Interval is a bucketing grain for the series.

const (
	Hour  Interval = "hour"
	Day   Interval = "day"
	Week  Interval = "week"  // ISO weeks, Monday start
	Month Interval = "month" // calendar months
)

func ParseInterval added in v0.9.1

func ParseInterval(s string) (Interval, error)

ParseInterval maps a request string to a grain; empty = day. Unknown grains are an error, never silently day — a wrong-grain chart is a silent-wrong answer.

type Measure added in v0.9.0

type Measure string

Measure is a numeric aggregation over an event property — the money/growth questions Count can't answer: revenue (sum of "amount"), average order value (avg), p90 latency, min/max. This is the single most common "it can't do X" a new user hits on day one.

const (
	Sum    Measure = "sum"
	Avg    Measure = "avg"
	Min    Measure = "min"
	Max    Measure = "max"
	Median Measure = "median"
	P90    Measure = "p90"
)

func ParseMeasure added in v0.9.0

func ParseMeasure(s string) (Measure, bool)

ParseMeasure maps a string (query param, MCP arg) to a Measure, defaulting to Sum for a bare/unknown value so a caller that asks for a numeric aggregation always gets one.

type MeasurePoint added in v0.9.0

type MeasurePoint struct {
	Date  time.Time `json:"date"`
	Value float64   `json:"value"`
	N     int       `json:"n"`
}

MeasurePoint is one day's aggregated numeric value. N is how many events contributed — 0 marks an empty day so avg/median/p90 read as "no data", not a real zero.

type MeasureResult added in v0.9.0

type MeasureResult struct {
	Event    string         `json:"event"`
	Property string         `json:"property"`
	Measure  Measure        `json:"measure"`
	Points   []MeasurePoint `json:"points"`
	Total    float64        `json:"total"`
	N        int            `json:"n"` // total events that carried a numeric value
}

MeasureResult is the daily numeric series plus the aggregate over the WHOLE window (so Total for avg/median/p90 is correct, not a misleading mean-of-daily-means).

func ComputeMeasure added in v0.9.0

func ComputeMeasure(events []event.Event, eventName, property string, m Measure, from, to time.Time) MeasureResult

ComputeMeasure aggregates a numeric event property per day between from and to. Events missing the property, or whose value isn't numeric, are skipped (never coerced to 0). Deterministic and storage-agnostic, same as Compute.

type Point

type Point struct {
	Date  time.Time `json:"date"`
	Count int       `json:"count"`
}

Point is one day's value.

type Result

type Result struct {
	Event  string  `json:"event"`
	Unique bool    `json:"unique"` // true = distinct users, false = raw count
	Points []Point `json:"points"`
	Total  int     `json:"total"`
}

Result is the daily series for one event.

func Compute

func Compute(events []event.Event, eventName string, from, to time.Time, unique bool) Result

Compute returns daily counts for eventName (empty = all events) between from and to. unique=true counts distinct users per day instead of raw events. Days with no activity are filled with zero so the line/bars are continuous.

func ComputeInterval added in v0.9.1

func ComputeInterval(events []event.Event, eventName string, from, to time.Time, unique bool, iv Interval) Result

ComputeInterval is Compute with a bucketing grain. Buckets with no activity fill with zero so the series is continuous. Hourly output is capped at 31 days of buckets (744) — the guardrail every incumbent applies to keep charts readable.

func ComputeXAU added in v0.9.1

func ComputeXAU(events []event.Event, eventName string, from, to time.Time, windowDays int) Result

ComputeXAU plots DAU/WAU/MAU as a daily series: each point = distinct users active in the rolling half-open window (point − windowDays, point], per the TRENDS-XAU contract (mixpanel XAU semantics; posthog words it "the N days leading up to the label"). The Total echoes the LAST point (the current value) — summing rolling actives would double-count meaninglessly.

type Series

type Series struct {
	Value  string  `json:"value"`
	Points []Point `json:"points"`
	Total  int     `json:"total"`
}

Series is one line of a broken-down trend (e.g. signups from "google" over time).

func ComputeBreakdown

func ComputeBreakdown(events []event.Event, eventName, property string, from, to time.Time, unique bool) []Series

ComputeBreakdown splits a trend into one series per value of property — the multi-line "signups by source over time" report. Events missing the property fall into "(none)". Series are sorted by total descending.

Jump to

Keyboard shortcuts

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