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 Collector
- type Counter
- type ExpireFunc
- type ExpiredKey
- 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 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 ExpireFunc ¶ added in v0.2.2
type ExpireFunc func(ek ExpiredKey) error
ExpireFunc is the callback invoked when a key expires from the in-memory store. The implementation is entirely up to the caller — write to a database, send to a message queue, append to a file, or simply ignore it.
If the function returns an error, the key is NOT removed from memory and will be retried on the next cleanup cycle.
Example (write to any database):
c := memory.New(
memory.WithTTL(memory.TTLConfig{
RetentionDays: 7,
OnExpire: func(ek stats.ExpiredKey) error {
_, err := db.Exec(
"INSERT INTO stats_archive (key, type, value, date) VALUES (?, ?, ?, ?)",
ek.Key, ek.Type, toJSON(ek.Value), ek.Date,
)
return err
},
}),
)
type ExpiredKey ¶ added in v0.2.2
type ExpiredKey struct {
Key string `json:"key"`
Type string `json:"type"`
Value any `json:"value"`
Date string `json:"date"`
ExpiredAt string `json:"expiredAt"`
}
ExpiredKey represents a single key that has been evicted from the in-memory store by the TTL cleanup mechanism. It is passed to the ExpireFunc callback so the caller can persist it to any destination (SQLite, MySQL, PostgreSQL, Kafka, file, remote API, etc.).
Fields:
- Key: the full stats key, e.g. "pv:2026-08-18:/home"
- Type: primitive type: "counter", "gauge", "set", "hll", "timer"
- Value: type-specific value: counter → int64 gauge → int64 set → int (count) hll → uint64 (estimated cardinality) timer → TimerSummary
- Date: extracted "YYYY-MM-DD" from the key (empty if no date found)
- ExpiredAt: ISO 8601 timestamp of when the key was expired
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 expiration time. It is the Value field of ExpiredKey when Type == "timer".
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.