metrics

package
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Dec 30, 2025 License: MIT Imports: 7 Imported by: 0

README

Metrics Package

A pluggable metrics collection system with Prometheus implementation.

Quick Start

import "github.com/bitechdev/ResolveSpec/pkg/metrics"

// Initialize Prometheus provider
provider := metrics.NewPrometheusProvider()
metrics.SetProvider(provider)

// Apply middleware to your router
router.Use(provider.Middleware)

// Expose metrics endpoint
http.Handle("/metrics", provider.Handler())

Provider Interface

The package uses a provider interface, allowing you to plug in different metric systems:

type Provider interface {
    RecordHTTPRequest(method, path, status string, duration time.Duration)
    IncRequestsInFlight()
    DecRequestsInFlight()
    RecordDBQuery(operation, table string, duration time.Duration, err error)
    RecordCacheHit(provider string)
    RecordCacheMiss(provider string)
    UpdateCacheSize(provider string, size int64)
    Handler() http.Handler
}

Recording Metrics

HTTP Metrics (Automatic)

When using the middleware, HTTP metrics are recorded automatically:

router.Use(provider.Middleware)

Collected:

  • Request duration (histogram)
  • Request count by method, path, and status
  • Requests in flight (gauge)
Database Metrics
start := time.Now()
rows, err := db.Query("SELECT * FROM users WHERE id = ?", userID)
duration := time.Since(start)

metrics.GetProvider().RecordDBQuery("SELECT", "users", duration, err)
Cache Metrics
// Record cache hit
metrics.GetProvider().RecordCacheHit("memory")

// Record cache miss
metrics.GetProvider().RecordCacheMiss("memory")

// Update cache size
metrics.GetProvider().UpdateCacheSize("memory", 1024)

Prometheus Metrics

When using PrometheusProvider, the following metrics are available:

Metric Name Type Labels Description
http_request_duration_seconds Histogram method, path, status HTTP request duration
http_requests_total Counter method, path, status Total HTTP requests
http_requests_in_flight Gauge - Current in-flight requests
db_query_duration_seconds Histogram operation, table Database query duration
db_queries_total Counter operation, table, status Total database queries
cache_hits_total Counter provider Total cache hits
cache_misses_total Counter provider Total cache misses
cache_size_items Gauge provider Current cache size

Prometheus Queries

HTTP Request Rate
rate(http_requests_total[5m])
HTTP Request Duration (95th percentile)
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
Database Query Error Rate
rate(db_queries_total{status="error"}[5m])
Cache Hit Rate
rate(cache_hits_total[5m]) / (rate(cache_hits_total[5m]) + rate(cache_misses_total[5m]))

No-Op Provider

If metrics are disabled:

// No provider set - uses no-op provider automatically
metrics.GetProvider().RecordHTTPRequest(...) // Does nothing

Custom Provider

Implement your own metrics provider:

type CustomProvider struct{}

func (c *CustomProvider) RecordHTTPRequest(method, path, status string, duration time.Duration) {
    // Send to your metrics system
}

// Implement other Provider interface methods...

func (c *CustomProvider) Handler() http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // Return your metrics format
    })
}

// Use it
metrics.SetProvider(&CustomProvider{})

Complete Example

package main

import (
    "database/sql"
    "log"
    "net/http"
    "time"

    "github.com/bitechdev/ResolveSpec/pkg/metrics"
    "github.com/gorilla/mux"
)

func main() {
    // Initialize metrics
    provider := metrics.NewPrometheusProvider()
    metrics.SetProvider(provider)

    // Create router
    router := mux.NewRouter()

    // Apply metrics middleware
    router.Use(provider.Middleware)

    // Expose metrics endpoint
    router.Handle("/metrics", provider.Handler())

    // Your API routes
    router.HandleFunc("/api/users", getUsersHandler)

    log.Fatal(http.ListenAndServe(":8080", router))
}

func getUsersHandler(w http.ResponseWriter, r *http.Request) {
    // Record database query
    start := time.Now()
    users, err := fetchUsers()
    duration := time.Since(start)

    metrics.GetProvider().RecordDBQuery("SELECT", "users", duration, err)

    if err != nil {
        http.Error(w, "Internal Server Error", 500)
        return
    }

    // Return users...
}

Docker Compose Example

version: '3'
services:
  app:
    build: .
    ports:
      - "8080:8080"

  prometheus:
    image: prom/prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'

  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    depends_on:
      - prometheus

prometheus.yml:

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'resolvespec'
    static_configs:
      - targets: ['app:8080']

Best Practices

  1. Label Cardinality: Keep labels low-cardinality

    • ✅ Good: method, status_code
    • ❌ Bad: user_id, timestamp
  2. Path Normalization: Normalize dynamic paths

    // Instead of /api/users/123
    // Use /api/users/:id
    
  3. Metric Naming: Follow Prometheus conventions

    • Use _total suffix for counters
    • Use _seconds suffix for durations
    • Use base units (seconds, not milliseconds)
  4. Performance: Metrics collection is lock-free and highly performant

    • Safe for high-throughput applications
    • Minimal overhead (<1% in most cases)

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func SetProvider

func SetProvider(p Provider)

SetProvider sets the global metrics provider

Types

type NoOpProvider

type NoOpProvider struct{}

NoOpProvider is a no-op implementation of Provider

func (*NoOpProvider) DecRequestsInFlight

func (n *NoOpProvider) DecRequestsInFlight()

func (*NoOpProvider) Handler

func (n *NoOpProvider) Handler() http.Handler

func (*NoOpProvider) IncRequestsInFlight

func (n *NoOpProvider) IncRequestsInFlight()

func (*NoOpProvider) RecordCacheHit

func (n *NoOpProvider) RecordCacheHit(provider string)

func (*NoOpProvider) RecordCacheMiss

func (n *NoOpProvider) RecordCacheMiss(provider string)

func (*NoOpProvider) RecordDBQuery

func (n *NoOpProvider) RecordDBQuery(operation, table string, duration time.Duration, err error)

func (*NoOpProvider) RecordEventProcessed added in v0.0.107

func (n *NoOpProvider) RecordEventProcessed(source, eventType, status string, duration time.Duration)

func (*NoOpProvider) RecordEventPublished added in v0.0.107

func (n *NoOpProvider) RecordEventPublished(source, eventType string)

func (*NoOpProvider) RecordHTTPRequest

func (n *NoOpProvider) RecordHTTPRequest(method, path, status string, duration time.Duration)

func (*NoOpProvider) RecordPanic added in v0.0.122

func (n *NoOpProvider) RecordPanic(methodName string)

func (*NoOpProvider) UpdateCacheSize

func (n *NoOpProvider) UpdateCacheSize(provider string, size int64)

func (*NoOpProvider) UpdateEventQueueSize added in v0.0.107

func (n *NoOpProvider) UpdateEventQueueSize(size int64)

type PrometheusProvider

type PrometheusProvider struct {
	// contains filtered or unexported fields
}

PrometheusProvider implements the Provider interface using Prometheus

func NewPrometheusProvider

func NewPrometheusProvider() *PrometheusProvider

NewPrometheusProvider creates a new Prometheus metrics provider

func (*PrometheusProvider) DecRequestsInFlight

func (p *PrometheusProvider) DecRequestsInFlight()

DecRequestsInFlight implements Provider interface

func (*PrometheusProvider) Handler

func (p *PrometheusProvider) Handler() http.Handler

Handler implements Provider interface

func (*PrometheusProvider) IncRequestsInFlight

func (p *PrometheusProvider) IncRequestsInFlight()

IncRequestsInFlight implements Provider interface

func (*PrometheusProvider) Middleware

func (p *PrometheusProvider) Middleware(next http.Handler) http.Handler

Middleware returns an HTTP middleware that collects metrics

func (*PrometheusProvider) RecordCacheHit

func (p *PrometheusProvider) RecordCacheHit(provider string)

RecordCacheHit implements Provider interface

func (*PrometheusProvider) RecordCacheMiss

func (p *PrometheusProvider) RecordCacheMiss(provider string)

RecordCacheMiss implements Provider interface

func (*PrometheusProvider) RecordDBQuery

func (p *PrometheusProvider) RecordDBQuery(operation, table string, duration time.Duration, err error)

RecordDBQuery implements Provider interface

func (*PrometheusProvider) RecordHTTPRequest

func (p *PrometheusProvider) RecordHTTPRequest(method, path, status string, duration time.Duration)

RecordHTTPRequest implements Provider interface

func (*PrometheusProvider) RecordPanic added in v0.0.122

func (p *PrometheusProvider) RecordPanic(methodName string)

RecordPanic implements the Provider interface

func (*PrometheusProvider) UpdateCacheSize

func (p *PrometheusProvider) UpdateCacheSize(provider string, size int64)

UpdateCacheSize implements Provider interface

type Provider

type Provider interface {
	// RecordHTTPRequest records metrics for an HTTP request
	RecordHTTPRequest(method, path, status string, duration time.Duration)

	// IncRequestsInFlight increments the in-flight requests counter
	IncRequestsInFlight()

	// DecRequestsInFlight decrements the in-flight requests counter
	DecRequestsInFlight()

	// RecordDBQuery records metrics for a database query
	RecordDBQuery(operation, table string, duration time.Duration, err error)

	// RecordCacheHit records a cache hit
	RecordCacheHit(provider string)

	// RecordCacheMiss records a cache miss
	RecordCacheMiss(provider string)

	// UpdateCacheSize updates the cache size metric
	UpdateCacheSize(provider string, size int64)

	// RecordEventPublished records an event publication
	RecordEventPublished(source, eventType string)

	// RecordEventProcessed records an event processing with its status
	RecordEventProcessed(source, eventType, status string, duration time.Duration)

	// UpdateEventQueueSize updates the event queue size metric
	UpdateEventQueueSize(size int64)

	// RecordPanic records a panic event
	RecordPanic(methodName string)

	// Handler returns an HTTP handler for exposing metrics (e.g., /metrics endpoint)
	Handler() http.Handler
}

Provider defines the interface for metric collection

func GetProvider

func GetProvider() Provider

GetProvider returns the current metrics provider

type ResponseWriter

type ResponseWriter struct {
	http.ResponseWriter
	// contains filtered or unexported fields
}

ResponseWriter wraps http.ResponseWriter to capture status code

func NewResponseWriter

func NewResponseWriter(w http.ResponseWriter) *ResponseWriter

func (*ResponseWriter) WriteHeader

func (rw *ResponseWriter) WriteHeader(code int)

Jump to

Keyboard shortcuts

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