Documentation
¶
Overview ¶
Package metricz provides a type-safe, zero-dependency metrics collection library designed for high-performance applications requiring compile-time safety guarantees.
Core Philosophy ¶
Metricz enforces type safety through its Key-based API, preventing raw string usage that commonly leads to metric naming inconsistencies and runtime errors. All metric operations require explicit Key types, providing compile-time verification of metric names and eliminating string-based typos.
Key-Enforced API ¶
The foundation of metricz is the Key type, which wraps strings and forces explicit declaration of all metric names:
const (
RequestCount = metricz.Key("http_requests_total")
ResponseTime = metricz.Key("http_response_duration_seconds")
)
Raw strings are rejected by the API - all methods accept only Key parameters, ensuring metric names are declared as constants and preventing runtime typos.
Four Metric Types ¶
Metricz implements four core metric types with atomic operations:
Counter: Monotonically increasing values for event counting
counter := registry.Counter(RequestCount) counter.Inc() counter.Add(5)
Gauge: Arbitrary values that can increase or decrease
gauge := registry.Gauge(MemoryUsage) gauge.Set(1024) gauge.Add(512) gauge.Sub(256)
Histogram: Distribution tracking with configurable buckets
hist := registry.Histogram(ResponseSize, []float64{100, 1000, 10000})
hist.Observe(756.5)
Histograms are general-purpose primitives requiring explicit bucket configuration. For common use cases, consider predefined buckets (DefaultSizeBuckets, DefaultDurationBuckets) or specialized metrics like Timer.
Timer: Duration tracking with sensible latency defaults
timer := registry.Timer(ProcessingTime) // uses DefaultLatencyBuckets stop := timer.Start() // ... work ... stop()
Timer is a specialized histogram optimized for latency tracking in milliseconds. For custom buckets, use TimerWithBuckets.
Registry Pattern ¶
The Registry provides complete instance isolation, allowing multiple independent metric collections within the same application. Each registry maintains its own metric instances with no cross-registry interference:
registry := metricz.New() counter := registry.Counter(RequestCount)
Registry operations are thread-safe and use atomic operations where possible for optimal performance under concurrent access.
Thread-Safety Guarantees ¶
All metric operations are thread-safe and designed for high-concurrency environments:
- Metric value updates use atomic operations (sync/atomic) for zero-lock performance - Registry operations use read-write mutexes for efficient concurrent access - Multiple goroutines can safely access the same metrics simultaneously - No external synchronization required for any operations
Zero-Allocation Performance ¶
Metricz is optimized for zero-allocation metric updates in steady-state operation:
- Metric instances are created once and reused - Value updates use atomic operations without allocation - String conversions are minimized and cached where possible - Memory pools are avoided in favor of atomic operations
Zero Dependencies ¶
Metricz depends only on the Go standard library, specifically: - sync (for mutexes and atomic operations) - time (for timer functionality) - No external dependencies for maximum compatibility and minimal attack surface
Example Usage ¶
// Declare metric keys as constants
const (
RequestsTotal = metricz.Key("http_requests_total")
ResponseDuration = metricz.Key("http_response_duration_seconds")
)
// Create registry
metrics := metricz.New()
// Use metrics with type safety
counter := metrics.Counter(RequestsTotal)
timer := metrics.Timer(ResponseDuration)
// Thread-safe operations
counter.Inc()
stop := timer.Start()
defer stop()
This design ensures metric collection adds minimal overhead while providing maximum safety and consistency across application boundaries.
Index ¶
- Variables
- type Counter
- type Gauge
- type Histogram
- type Key
- type Registry
- func (r *Registry) Counter(key Key) Counter
- func (r *Registry) Gauge(key Key) Gauge
- func (r *Registry) GetCounters() map[Key]Counter
- func (r *Registry) GetGauges() map[Key]Gauge
- func (r *Registry) GetHistograms() map[Key]Histogram
- func (r *Registry) GetTimers() map[Key]Timer
- func (r *Registry) Histogram(key Key, buckets []float64) Histogram
- func (r *Registry) Reset()
- func (r *Registry) Timer(key Key) Timer
- func (r *Registry) TimerWithBuckets(key Key, buckets []float64) Timer
- func (r *Registry) WithClock(clock clockz.Clock) *Registry
- type Stopwatch
- type Timer
Constants ¶
This section is empty.
Variables ¶
var ( // DefaultLatencyBuckets provides reasonable latency buckets in milliseconds. DefaultLatencyBuckets = []float64{ 1, 2, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000, } // DefaultSizeBuckets provides reasonable size buckets in bytes. DefaultSizeBuckets = []float64{ 64, 256, 1024, 4096, 16384, 65536, 262144, 1048576, 4194304, } // DefaultDurationBuckets provides reasonable duration buckets in seconds. DefaultDurationBuckets = []float64{ 0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0, } )
Standard bucket definitions for different types of histograms.
Functions ¶
This section is empty.
Types ¶
type Histogram ¶
type Histogram interface {
Observe(float64)
Buckets() ([]float64, []uint64)
Sum() float64
Count() uint64
Overflow() uint64
}
Histogram interface for distributional metrics.
type Key ¶
type Key string
Key is the mandatory key type for all metric operations. No raw strings allowed - compile-time enforcement.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry is the metric collection with complete instance isolation. Only accepts Key type - no raw strings, no generics.
func New ¶
func New() *Registry
New creates a Registry that accepts ONLY Key types. No raw strings allowed - forces explicit Key usage. Uses production clock for all timing operations.
func (*Registry) GetCounters ¶
GetCounters returns a copy of all counters for export tools.
func (*Registry) GetHistograms ¶
GetHistograms returns a copy of all histograms for export tools.
func (*Registry) Histogram ¶
Histogram returns a histogram metric, creating it if it doesn't exist. Requires explicit bucket configuration - this is a general-purpose primitive where bucket design depends entirely on your domain (bytes, counts, percentages, etc).
For common cases, consider using predefined buckets:
- DefaultSizeBuckets for byte measurements
- DefaultDurationBuckets for duration in seconds
- DefaultLatencyBuckets via Timer() for latency in milliseconds
func (*Registry) Timer ¶
Timer returns a timer metric with DefaultLatencyBuckets (in milliseconds). This covers typical web/API latencies from 1ms to 10s and is suitable for most HTTP request timing, RPC calls, and general operation latency tracking.
Timer is a convenience wrapper for the common latency-tracking use case. For custom buckets, use TimerWithBuckets.
func (*Registry) TimerWithBuckets ¶
TimerWithBuckets returns a timer metric with custom buckets (in milliseconds), creating it if it doesn't exist. Use this when your latency profile differs significantly from typical web requests (e.g., database queries, batch operations).