Documentation
¶
Overview ¶
Package stats provides an abstract, pluggable website metrics collection framework. It defines a unified set of primitives — Counter, Gauge, Set, HyperLogLog, and Timer — behind interfaces, with multiple backend implementations (in-memory, Redis, file-persisted).
Architecture ¶
┌──────────────┐ ┌──────────────────────────────────┐
│ Your App │────▶│ stats.Collector (interface) │
│ (PV/UV/...) │ │ Counter / Gauge / Set / HLL │
└──────────────┘ └──────────┬───────────────────────┘
│
┌───────────┬───────────┼───────────┐
▼ ▼ ▼ ▼
┌──────────┐ ┌────────┐ ┌─────────┐ ┌─────────┐
│ memory │ │ redis │ │ file │ │ custom │
│ (single) │ │(cluster│ │(persist)│ │ (impl) │
└──────────┘ └────────┘ └─────────┘ └─────────┘
Quick start (in-memory) ¶
collector := memory.New()
pv := collector.Counter("pv:2026-08-18:/home")
pv.Incr()
fmt.Println(pv.Get()) // 1
uv := collector.HLL("uv:2026-08-18")
uv.Add("user-123")
fmt.Println(uv.Estimate()) // 1
Quick start (Redis) ¶
collector := redis.New(redisClient)
pv := collector.Counter("pv:2026-08-18:/home")
pv.Incr()
Primitives ¶
- Counter: monotonic increment (PV, clicks, errors, requests)
- Gauge: arbitrary value (queue depth, active connections)
- Set: exact deduplication (retention, new users — small scale)
- HLL: probabilistic deduplication (UV, IP, DAU — large scale, ~12 KB)
- Timer: latency samples + percentiles (response time, first screen)
Index ¶
- Variables
- type ArchiveRecord
- type ArchiveStore
- type Collector
- type Counter
- type Gauge
- type HLL
- type Set
- type Timer
- type TimerSummary
- type WebsiteMetrics
- func (w *WebsiteMetrics) GetAvgSessionDuration(date string) float64
- func (w *WebsiteMetrics) GetBounceRate(date string) float64
- func (w *WebsiteMetrics) GetCTR(date, event string) float64
- func (w *WebsiteMetrics) GetCVR(date, goal string) float64
- func (w *WebsiteMetrics) GetDAU(date string) uint64
- func (w *WebsiteMetrics) GetErrorRate(date string) float64
- func (w *WebsiteMetrics) GetFirstScreenP50(date string) float64
- func (w *WebsiteMetrics) GetFirstScreenP95(date string) float64
- func (w *WebsiteMetrics) GetIP(date string) uint64
- func (w *WebsiteMetrics) GetMAU(month string) uint64
- func (w *WebsiteMetrics) GetPV(date, path string) int64
- func (w *WebsiteMetrics) GetPagesPerVisit(date string) float64
- func (w *WebsiteMetrics) GetQPS(date string) float64
- func (w *WebsiteMetrics) GetResponseTimeP50(date string) float64
- func (w *WebsiteMetrics) GetResponseTimeP95(date string) float64
- func (w *WebsiteMetrics) GetResponseTimeP99(date string) float64
- func (w *WebsiteMetrics) GetRetention(dateA, dateB string) float64
- func (w *WebsiteMetrics) GetTotalUsers() uint64
- func (w *WebsiteMetrics) GetUV(date string) uint64
- func (w *WebsiteMetrics) GetVV(date string) int64
- func (w *WebsiteMetrics) IsNewUser(userID string) bool
- func (w *WebsiteMetrics) RecordBounce(date string)
- func (w *WebsiteMetrics) RecordClick(date, event string)
- func (w *WebsiteMetrics) RecordConversion(date, goal string)
- func (w *WebsiteMetrics) RecordDAU(date, userID string)
- func (w *WebsiteMetrics) RecordDailyUserSet(date, userID string)
- func (w *WebsiteMetrics) RecordError(date string)
- func (w *WebsiteMetrics) RecordFirstScreen(date string, ms float64)
- func (w *WebsiteMetrics) RecordIP(date, ip string)
- func (w *WebsiteMetrics) RecordImpression(date, event string)
- func (w *WebsiteMetrics) RecordMAU(month, userID string)
- func (w *WebsiteMetrics) RecordPV(date, path string)
- func (w *WebsiteMetrics) RecordPVTotal(date string)
- func (w *WebsiteMetrics) RecordRequest(date string)
- func (w *WebsiteMetrics) RecordResponseTime(date string, durationNs int64)
- func (w *WebsiteMetrics) RecordResponseTimeMs(date string, ms float64)
- func (w *WebsiteMetrics) RecordSessionDuration(date string, durationSeconds int64)
- func (w *WebsiteMetrics) RecordUV(date, userID string)
- func (w *WebsiteMetrics) RecordVV(date string)
Constants ¶
This section is empty.
Variables ¶
var ( // ErrMergeIncompatible is returned when merging two HLLs of different types. ErrMergeIncompatible = errors.New("stats: merge incompatible HLL types") // ErrClosed is returned when operating on a closed collector. ErrClosed = errors.New("stats: collector closed") // ErrNotFound is returned when a key is not found. ErrNotFound = errors.New("stats: key not found") )
Common errors returned by stats primitives.
Functions ¶
This section is empty.
Types ¶
type ArchiveRecord ¶ added in v0.2.1
type ArchiveRecord struct {
Key string `json:"key"` // e.g. "pv:2026-08-18:/home"
Type string `json:"type"` // "counter", "gauge", "set", "hll", "timer"
Value any `json:"value"` // type-specific value (int64, uint64, TimerSummary, etc.)
Date string `json:"date"` // extracted "YYYY-MM-DD"
Archived string `json:"archived"` // ISO timestamp of when it was archived
}
ArchiveRecord represents a single archived metrics record. This is the unit of data that gets persisted when a key expires from the in-memory store.
type ArchiveStore ¶ added in v0.2.1
type ArchiveStore interface {
// Save persists a single expired key's value.
// If the key already exists in the archive, it should be upserted
// (replaced with the new value).
Save(record ArchiveRecord) error
// Query retrieves archived records by date range (inclusive).
// dateFrom and dateTo are "YYYY-MM-DD" format.
// Returns records ordered by date, then key.
Query(dateFrom, dateTo string) ([]ArchiveRecord, error)
// QueryByType retrieves archived records by type and date range.
QueryByType(entryType, dateFrom, dateTo string) ([]ArchiveRecord, error)
// Close releases resources held by the store.
Close() error
}
ArchiveStore is the abstraction for long-term metrics persistence. Implementations include SQLite, MySQL, PostgreSQL, etc.
The flow is:
- In-memory collector holds hot data (recent N days).
- When a key expires (TTL), Save is called with the key's final value.
- Historical data can be queried via Query/QueryByType.
All methods must be goroutine-safe.
type Collector ¶
type Collector interface {
// Counter returns a Counter primitive for the given key.
// Multiple calls with the same key return the same logical counter.
Counter(key string) Counter
// Gauge returns a Gauge primitive for the given key.
Gauge(key string) Gauge
// Set returns a Set primitive for exact deduplication.
// Use for small cardinalities (e.g. retention sets up to ~100K).
Set(key string) Set
// HLL returns a HyperLogLog primitive for probabilistic deduplication.
// Use for large cardinalities (UV, IP, DAU). Memory: ~12 KB per key.
HLL(key string) HLL
// Timer returns a Timer primitive for latency tracking.
Timer(key string) Timer
// Flush persists in-memory state to the underlying store (if applicable).
// For Redis, this is a no-op. For file/memory, it writes to disk.
Flush() error
// Close releases any resources held by the collector.
Close() error
}
Collector is the root abstraction for all metrics backends. It acts as a factory for typed primitives, each identified by a string key. Implementations must be goroutine-safe.
type Counter ¶
type Counter interface {
// Incr increments by 1.
Incr() int64
// IncrBy increments by delta and returns the new value.
IncrBy(delta int64) int64
// Get returns the current count.
Get() int64
// Reset sets the counter to 0.
Reset() error
}
Counter is a monotonically increasing counter (PV, clicks, errors, QPS).
type Gauge ¶
type Gauge interface {
// Set sets the gauge to value.
Set(value int64)
// Incr increments the gauge by 1.
Incr() int64
// Decr decrements the gauge by 1.
Decr() int64
// Get returns the current value.
Get() int64
}
Gauge is a value that can go up or down (active connections, queue depth).
type HLL ¶
type HLL interface {
// Add inserts an element into the sketch.
Add(element string)
// Estimate returns the estimated cardinality.
Estimate() uint64
// Merge merges another HLL into this one.
Merge(other HLL) error
// Reset clears the sketch.
Reset() error
}
HLL is a HyperLogLog sketch for probabilistic cardinality estimation. Memory: ~12 KB per key. Error: ~0.81%. Use for UV, IP, DAU, MAU.
type Set ¶
type Set interface {
// Add adds an element to the set. Returns true if newly added.
Add(element string) bool
// Has checks if an element exists in the set.
Has(element string) bool
// Count returns the exact cardinality.
Count() int
// Members returns all elements (use with care on large sets).
Members() []string
// Intersect returns the count of elements also in the other set.
Intersect(other Set) int
// Reset clears the set.
Reset() error
}
Set is an exact set for deduplication (retention, new user detection). For large-scale deduplication (UV, IP), use HLL instead.
type Timer ¶
type Timer interface {
// Record adds a latency sample (in nanoseconds).
Record(duration int64)
// RecordMs adds a latency sample in milliseconds.
RecordMs(ms float64)
// Count returns the number of samples.
Count() int64
// Mean returns the average latency in nanoseconds.
Mean() float64
// Percentile returns the p-th percentile (0-100) in nanoseconds.
// e.g. Percentile(95) for P95.
Percentile(p float64) float64
// Reset clears all samples.
Reset() error
}
Timer tracks latency samples and computes percentiles (P50/P95/P99).
type TimerSummary ¶ added in v0.2.1
type TimerSummary struct {
Count int64 `json:"count"`
Mean float64 `json:"mean"`
P50 float64 `json:"p50"`
P95 float64 `json:"p95"`
P99 float64 `json:"p99"`
}
TimerSummary is a summary of a Timer at archive time.
type WebsiteMetrics ¶
type WebsiteMetrics struct {
// contains filtered or unexported fields
}
WebsiteMetrics is a convenience wrapper that provides ready-made methods for common website indicators (PV, UV, VV, IP, DAU, MAU, etc.) on top of a Collector. It does NOT store any state itself — all data goes through the underlying Collector.
This is an opinionated layer; you can also use the Collector primitives directly for custom metrics.
func NewWebsiteMetrics ¶
func NewWebsiteMetrics(c Collector) *WebsiteMetrics
NewWebsiteMetrics creates a WebsiteMetrics wrapper over the given collector.
func (*WebsiteMetrics) GetAvgSessionDuration ¶
func (w *WebsiteMetrics) GetAvgSessionDuration(date string) float64
GetAvgSessionDuration returns the average session duration in seconds.
func (*WebsiteMetrics) GetBounceRate ¶
func (w *WebsiteMetrics) GetBounceRate(date string) float64
GetBounceRate returns the bounce rate = bounces / VV.
func (*WebsiteMetrics) GetCTR ¶
func (w *WebsiteMetrics) GetCTR(date, event string) float64
GetCTR returns the click-through rate = clicks / impressions.
func (*WebsiteMetrics) GetCVR ¶
func (w *WebsiteMetrics) GetCVR(date, goal string) float64
GetCVR returns the conversion rate = conversions / visits.
func (*WebsiteMetrics) GetDAU ¶
func (w *WebsiteMetrics) GetDAU(date string) uint64
GetDAU returns the estimated daily active users for the given date.
func (*WebsiteMetrics) GetErrorRate ¶
func (w *WebsiteMetrics) GetErrorRate(date string) float64
GetErrorRate returns the error rate = errors / requests.
func (*WebsiteMetrics) GetFirstScreenP50 ¶
func (w *WebsiteMetrics) GetFirstScreenP50(date string) float64
GetFirstScreenP50 returns the P50 first screen load time in milliseconds.
func (*WebsiteMetrics) GetFirstScreenP95 ¶
func (w *WebsiteMetrics) GetFirstScreenP95(date string) float64
GetFirstScreenP95 returns the P95 first screen load time in milliseconds.
func (*WebsiteMetrics) GetIP ¶
func (w *WebsiteMetrics) GetIP(date string) uint64
GetIP returns the estimated unique IP count for the given date.
func (*WebsiteMetrics) GetMAU ¶
func (w *WebsiteMetrics) GetMAU(month string) uint64
GetMAU returns the estimated monthly active users for the given month.
func (*WebsiteMetrics) GetPV ¶
func (w *WebsiteMetrics) GetPV(date, path string) int64
GetPV returns the page view count for the given date and path.
func (*WebsiteMetrics) GetPagesPerVisit ¶
func (w *WebsiteMetrics) GetPagesPerVisit(date string) float64
GetPagesPerVisit returns the average pages per visit = total PV / total VV.
func (*WebsiteMetrics) GetQPS ¶
func (w *WebsiteMetrics) GetQPS(date string) float64
GetQPS returns the average QPS = total requests / seconds in a day.
func (*WebsiteMetrics) GetResponseTimeP50 ¶
func (w *WebsiteMetrics) GetResponseTimeP50(date string) float64
GetResponseTimeP50 returns the P50 response time in milliseconds.
func (*WebsiteMetrics) GetResponseTimeP95 ¶
func (w *WebsiteMetrics) GetResponseTimeP95(date string) float64
GetResponseTimeP95 returns the P95 response time in milliseconds.
func (*WebsiteMetrics) GetResponseTimeP99 ¶
func (w *WebsiteMetrics) GetResponseTimeP99(date string) float64
GetResponseTimeP99 returns the P99 response time in milliseconds.
func (*WebsiteMetrics) GetRetention ¶
func (w *WebsiteMetrics) GetRetention(dateA, dateB string) float64
GetRetention returns the retention rate between two dates. retention = |users on both dates| / |users on the earlier date|.
func (*WebsiteMetrics) GetTotalUsers ¶
func (w *WebsiteMetrics) GetTotalUsers() uint64
GetTotalUsers returns the estimated total unique users (all time).
func (*WebsiteMetrics) GetUV ¶
func (w *WebsiteMetrics) GetUV(date string) uint64
GetUV returns the estimated unique visitor count for the given date.
func (*WebsiteMetrics) GetVV ¶
func (w *WebsiteMetrics) GetVV(date string) int64
GetVV returns the visit view count for the given date.
func (*WebsiteMetrics) IsNewUser ¶
func (w *WebsiteMetrics) IsNewUser(userID string) bool
IsNewUser checks if the user is new (not seen before) and records them. Uses a global HLL for approximate new-user detection.
func (*WebsiteMetrics) RecordBounce ¶
func (w *WebsiteMetrics) RecordBounce(date string)
RecordBounce increments the bounce (single-page session) counter.
func (*WebsiteMetrics) RecordClick ¶
func (w *WebsiteMetrics) RecordClick(date, event string)
RecordClick increments the click counter for an event on a date.
func (*WebsiteMetrics) RecordConversion ¶
func (w *WebsiteMetrics) RecordConversion(date, goal string)
RecordConversion increments the conversion counter for a goal on a date.
func (*WebsiteMetrics) RecordDAU ¶
func (w *WebsiteMetrics) RecordDAU(date, userID string)
RecordDAU adds a user to the DAU HyperLogLog for the given date.
func (*WebsiteMetrics) RecordDailyUserSet ¶
func (w *WebsiteMetrics) RecordDailyUserSet(date, userID string)
RecordDailyUserSet adds a user to the exact daily set (for retention calculation). Uses Set (not HLL) because retention requires exact intersection.
func (*WebsiteMetrics) RecordError ¶
func (w *WebsiteMetrics) RecordError(date string)
RecordError increments the error counter for the given date.
func (*WebsiteMetrics) RecordFirstScreen ¶
func (w *WebsiteMetrics) RecordFirstScreen(date string, ms float64)
RecordFirstScreen adds a first screen load time sample (in milliseconds).
func (*WebsiteMetrics) RecordIP ¶
func (w *WebsiteMetrics) RecordIP(date, ip string)
RecordIP adds an IP to the IP HyperLogLog for the given date.
func (*WebsiteMetrics) RecordImpression ¶
func (w *WebsiteMetrics) RecordImpression(date, event string)
RecordImpression increments the impression counter for an event on a date.
func (*WebsiteMetrics) RecordMAU ¶
func (w *WebsiteMetrics) RecordMAU(month, userID string)
RecordMAU adds a user to the MAU HyperLogLog for the given month.
func (*WebsiteMetrics) RecordPV ¶
func (w *WebsiteMetrics) RecordPV(date, path string)
RecordPV increments the page view counter for the given date and path.
func (*WebsiteMetrics) RecordPVTotal ¶
func (w *WebsiteMetrics) RecordPVTotal(date string)
RecordPVTotal increments the total PV counter for a date (all paths combined).
func (*WebsiteMetrics) RecordRequest ¶
func (w *WebsiteMetrics) RecordRequest(date string)
RecordRequest increments the total request counter for the given date.
func (*WebsiteMetrics) RecordResponseTime ¶
func (w *WebsiteMetrics) RecordResponseTime(date string, durationNs int64)
RecordResponseTime adds a response time sample (in nanoseconds) for the given date.
func (*WebsiteMetrics) RecordResponseTimeMs ¶
func (w *WebsiteMetrics) RecordResponseTimeMs(date string, ms float64)
RecordResponseTimeMs adds a response time sample in milliseconds.
func (*WebsiteMetrics) RecordSessionDuration ¶
func (w *WebsiteMetrics) RecordSessionDuration(date string, durationSeconds int64)
RecordSessionDuration adds a session duration sample (in seconds) for the given date.
func (*WebsiteMetrics) RecordUV ¶
func (w *WebsiteMetrics) RecordUV(date, userID string)
RecordUV adds a user to the UV HyperLogLog for the given date.
func (*WebsiteMetrics) RecordVV ¶
func (w *WebsiteMetrics) RecordVV(date string)
RecordVV increments the visit view (session) counter for the given date.