stats

package module
v0.2.2 Latest Latest
Warning

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

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

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

Constants

This section is empty.

Variables

View Source
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.

Directories

Path Synopsis
file module
memory module
redis module

Jump to

Keyboard shortcuts

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