sentinel

package module
v0.9.0 Latest Latest
Warning

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

Go to latest
Published: Nov 17, 2025 License: MIT Imports: 12 Imported by: 0

README

Sentinel

Go Version Go Report Card codecov GoDoc

Sentinel wraps Go functions to automatically expose Prometheus metrics with reliability handlers. For functions, the library will: recover panic occurances as errors, configure retry handling, and track metrics of successes, errors, panics, retries, timeouts, and execution durations. Sentinel is designed to be minimal, robust, and immediately integrate with existing applications.

Metrics

Default configurations will automatically export the following Prometheus metrics:

Metric Type Description
sentinel_in_flight Gauge Active number of running tasks
sentinel_pending_total Gauge Active number of pending tasks
sentinel_successes_total Counter Total successful tasks
sentinel_failures_total Counter Total failed tasks
sentinel_errors_total Counter Total errors over all attempts
sentinel_panics_total Counter Total panic occurrences
sentinel_durations_seconds Histogram Task execution durations in buckets
sentinel_timeouts_total Counter Total errors based on timeouts
sentinel_retries_total Counter Total retry attempts for tasks

Installation

Library requires Go version >= 1.23:

go get github.com/mcwalrus/go-sentinel

Usage Examples

Basic Usage

Configure an observer and observe a task:

package main

import (
    "context"
    "log"
    
    sentinel "github.com/mcwalrus/go-sentinel"
)

func main() {
    // New observer
    observer := sentinel.NewObserver(nil)
    
    // Execute task
    err := observer.Run(func() error {
        log.Println("Processing task...")
        return nil
    })
    // Handle error
    if err != nil {
        log.Printf("Task failed: %v\n", err)
    }
}
Failure Handlers

Observer records errors via metrics with returning errors:

package main

import (
    "errors"
    "log"
    
    sentinel "github.com/mcwalrus/go-sentinel"
)

func main() {
    // New observer
    observer := sentinel.NewObserver(nil)
    
    // Task fails
    err := observer.Run(func() error {
        return errors.New("task failed")
    })
    // Handle error
    if err != nil {
        log.Printf("Task failed: %v\n", err)
    }
}
Timeout Handling

Observer provides context timeouts based on ObserverConfig:

package main

import (
    "context"
    "errors"
    "time"
    
    sentinel "github.com/mcwalrus/go-sentinel"
)

func main() {
    // New observer
    observer := sentinel.NewObserver(nil)

    // Set tasks timeout
    observer.UseConfig(sentinel.ObserverConfig{
        Timeout: 10 * time.Second,
    })

    // Task respects context timeout
    err := observer.RunFunc(func(ctx context.Context) error {
            <-ctx.Done()
            return ctx.Err()
        },
    )
    if !errors.Is(err, context.DeadlineExceeded) {
        panic("expected timeout error, got:", err)
    }
}

Timeout errors are recorded by both timeouts_total and errors_total counters.

Panic Handling

Panic occurrences are just returned as errors by the observer:

package main

import (
    "context"
    "errors"
    "math/rand"
    "time"
    
    sentinel "github.com/mcwalrus/go-sentinel"
    "github.com/prometheus/client_golang/prometheus"
)

func main() {
    // New observer
    observer := sentinel.NewObserver(nil)
    
    // Task panics
    err := observer.Run(func() error {
        panic("stations!:0")
    })
    
    // Handle error
    if err != nil {
        log.Printf("Task failed: %v\n", err)
    }

    // Recover panic value
    if r, ok := sentinel.IsPanicError(err); ok {
        log.Printf("panic value: %v\n", r)
    }
}

Panics are always recorded with panics_total and errors_total counters.

Disable Panic Recovery

By default, the observer recovers panics and converts them to errors. You can disable this behavior to let panics propagate normally:

package main

import (
    "context"
    "log"
    
    sentinel "github.com/mcwalrus/go-sentinel"
)

func main() {
    // New observer
    observer := sentinel.NewObserver(nil)
    
    // Disabled recovery
    observer.DisablePanicRecovery(true)
    
    // Panic propogates
    err := observer.Run(func() error {
        panic("some failure")
    })

    // Unreachable code
    log.Printf("err was: %v\n", err)
}
Observe Durations

Set histogram buckets with the observer to export durations_seconds metrics:

package main

import (
    "context"
    "errors"
    "log"
    "math/rand"
    "time"
    
    sentinel "github.com/mcwalrus/go-sentinel"
)

func main() {
    // New observer with durations
    observer := sentinel.NewObserver(
        []float64{0.100, 0.250, 0.400, 0.500, 1.000}, // in seconds
    )
    
    // Run tasks for 50-1000ms before returning
    for i := 0; i < 100; i++ {
        _ = observer.RunFunc(func(ctx context.Context) error {
            sleep := time.Duration(rand.Intn(950)+50) * time.Millisecond
            log.Printf("Sleeping for %v...\n", sleep)
            time.Sleep(sleep)
            return nil
        })
    }
}

Timeouts are always recorded with timeouts_total and errors_total counters.

Retry Handling

Configure retry with wait strategies for resilient task execution:

package main

import (
    "context"
    "errors"
    "log"
    "math/rand"
    "time"
    
    sentinel "github.com/mcwalrus/go-sentinel"
    "github.com/mcwalrus/go-sentinel/retry"
)

func main() {
    // New observer
    observer := sentinel.NewObserver(nil)

    // Set retry behavior
    observer.UseConfig(sentinel.ObserverConfig{
        MaxRetries:    3,
        RetryStrategy: retry.WithJitter(
            time.Second,
            retry.Exponential(100*time.Millisecond),
        ),
    })

    // Fail every attempt
    err := observer.Run(func() error {
        return errors.New("task failed")
    })
    
    // Unwrap join errors
    errUnwrap, ok := (err).(interface {Unwrap() []error})
    if !ok {
        panic("not unwrap")
    }

    // Handle each error
    errs := errUnwrap.Unwrap()
    for i, err := range errs {
        log.Printf("Task failed: %d: %v", i, err)
    }
}

Tasks called with MaxRetries=3 may be called up to four times total.

Use sentinel.RetryCount(ctx) to read the current retry attempt count within an observed function.

Prometheus Integration

Use template for integrating sentinel with a prometheus endpoint:

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

    sentinel "github.com/mcwalrus/go-sentinel"
    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp"
)

func main() {
    // New observer
    observer := sentinel.NewObserver(nil,
	    sentinel.WithNamespace("myapp"),
	    sentinel.WithSubsystem("workers"),
    )

    // Register observer
    registry := prometheus.NewRegistry()
	observer.MustRegister(registry)
    
    // Expose metrics endpoint
    http.Handle("/metrics", promhttp.HandlerFor(registry, promhttp.HandlerOpts{}))
    go func() {
        err := http.ListenAndServe(":8080", nil)
        if err != nil {
            log.Fatal(err)
        }
    }()

    // Your application code
    for range time.NewTicker(3 * time.Second).C {
        err := observer.Run(doFunc)
        if err != nil {
            log.Printf("error occurred: %v\n", err)
        }
    }
}

Prometheus metrics will be exposed with names myapp_workers_... on host localhost:8080/metrics.

Advanced Usage

Circuit Breaker

Configure circuit breaker to stop retries based on particular errors:

package main

import (
    "errors"
    "log"
    "time"
    
    sentinel "github.com/mcwalrus/go-sentinel"
    "github.com/mcwalrus/go-sentinel/circuit"
    "github.com/mcwalrus/go-sentinel/retry"
)

var ErrCustom = errors.New("unrecoverable error")

func main() {
    // New observer
    observer := sentinel.NewObserver(nil)

    // Configure circuit breaker
    observer.UseConfig(sentinel.ObserverConfig{
        MaxRetries: 5,
        RetryBreaker: func(err error) bool {
            return errors.Is(err, ErrCustom)
        },
    })
    
    // Task runs once on custom error
    var count int
    err := observer.Run(func() error {
        count++
        return ErrCustom
    })
    if err != nil && count == 1 {
        log.Printf("Task stopped early: %v\n", err)
    }
}
Control Handler

Use a control handler to prevent task execution or retries, useful for graceful shutdown:

package main

import (
    "context"

    sentinel "github.com/mcwalrus/go-sentinel"
    "github.com/mcwalrus/go-sentinel/circuit"
)

func main() {
    // New observer
    observer := sentinel.NewObserver(nil)
    
    // Configure control
    done := make(chan struct{})
    observer.UseConfig(sentinel.ObserverConfig{
        Control: circuit.WhenClosed(done),
    })

    // Control to reject new requests
    close(done)

    // Expect early termination error
    var count int
    err := observer.Run(func() error {
        count++
        return nil
    })
    if err != nil && count == 0 {
        log.Printf("error: %T\n", err)
    }
}
Concurrency Limits

Manage the observer to control the number of tasks that can executing concurrently:

package main

import (
    "context"
    "fmt"
    "sync"
    "time"

    sentinel "github.com/mcwalrus/go-sentinel"
)

func main() {
    // New observer
    observer := sentinel.NewObserver(nil)

    // Set concurrency limit
    observer.UseConfig(sentinel.ObserverConfig{
        MaxConcurrency: 5,
    })

    // Run concurrent routines 
    var wg sync.WaitGroup
    for i := 0; i < 20; i++ {
        go func (id int) {
            defer wg.Done()
            _ = observer.Run(func() error {
                fmt.Printf("Task %d executing...", id)
                time.Sleep(100 * time.Millisecond)
                return nil
            })
        }(i)
    }

    // Wait for task completions
    wg.Wait()
}

The metric sentinel_pending_total tracks the number of tasks waiting for a concurrency slot.

Labeled Observers

VecObserver enables creating multiple observers that share the same underlying metrics but are differentiated by Prometheus labels:

package main

import (
    "net/http"
    "time"

    sentinel "github.com/mcwalrus/go-sentinel"
    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp"
)

func main() {
    // Create VecObserver with label names
    vecObserver := sentinel.NewVecObserver(
        []float64{0.1, 0.5, 1, 2, 5},
        []string{"service", "pipeline"},
    )
    
    // Register VecObserver metrics just once
    registry := prometheus.NewRegistry()
    vecObserver.MustRegister(registry)

    // Create observers with different labels
    mObserver, _ := vecObserver.WithLabels("api", "main")
    bgObserver, _ := vecObserver.WithLabels("api", "background")

    // Set observer configurations
    mObserver.UseConfig(sentinel.ObserverConfig{
        Timeout:    60 * time.Second,
        MaxRetries: 2,
    })
    bgObserver.UseConfig(sentinel.ObserverConfig{
        Timeout:    120 * time.Second,
        MaxRetries: 4,
    })

    // Use observers
    _ = prodObserver.Run(func() error {
        return nil
    })    
    _ = stagingObserver.Run(func() error {
        return nil
    })
}

Using VecObserver instead of creating multiple Observers would be recommended best practise for most cases.

Contributing

Please report any issues or feature requests to the GitHub repository.

I am particularly keen to hear feedback around how to appropriately present the library alongside issues.

Please reach out to me directly for issues which require urgent fixes.

About

This module is maintained by Max Collier under an MIT License Agreement.

Documentation

Overview

Package sentinel provides reliability handling and observability monitoring for Go applications. It wraps task execution with Prometheus metrics, observing errors, panic occurrences, retries, and timeouts — making critical routines safe, measurable, and reliable.

Index

Constants

View Source
const (
	MetricInFlight  = "inFlight"
	MetricSuccesses = "successes"
	MetricFailures  = "failures"
	MetricErrors    = "errors"
	MetricTimeouts  = "timeouts"
	MetricPanics    = "panics"
	MetricDurations = "durations"
	MetricRetries   = "retries"
	MetricPending   = "pending"
)

Metric names that can be enabled/disabled

Variables

This section is empty.

Functions

func IsPanicError added in v0.5.0

func IsPanicError(err error) (any, bool)

IsPanicError checks if the given error was caused by a panic that was recovered by the Observer. It returns the panic value and a boolean indicating whether a panic occurred.

Example usage:

err := observer.RunTask(myTask)
if panicValue, isPanic := IsPanicError(err); isPanic {
	log.Printf("Task panicked with value: %v", panicValue)
	// Handle panic-specific logic
} else if err != nil {
	log.Printf("Task failed with error: %v", err)
	// Handle regular error
}

func RetryCount added in v0.8.0

func RetryCount(ctx context.Context) int

RetryCount returns the current retry count from the context. Returns 0 if the retry count is not set in the context.

Example usage:

observer := sentinel.NewObserver(nil)
observer.UseConfig(sentinel.ObserverConfig{
	MaxRetries: 3,
})
_ = observer.RunFunc(func(ctx context.Context) error {
	retryCount := sentinel.RetryCount(ctx)
	log.Printf("Current retry count: %d\n", retryCount)
	return nil
})

Types

type ErrControlBreaker added in v0.6.0

type ErrControlBreaker struct{}

ErrControlBreaker is the error returned when a control breaker is triggered. This occurs when ObserverConfig.Control returns true, preventing task execution before it even begins (during PhaseNewRequest) or stopping retry attempts (during PhaseRetry).

func (*ErrControlBreaker) Error added in v0.6.0

func (e *ErrControlBreaker) Error() string

type Observer

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

Observer monitors and measures task executions, collecting Prometheus metrics for successes, failures, timeouts, panics, retries, and observed runtimes. It provides methods to execute tasks with various ObserverConfig options.

func NewObserver

func NewObserver(durationBuckets []float64, opts ...ObserverOption) *Observer

NewObserver configures a new Observer with duration buckets and optional configuration. The Observer will need to be registered with a Prometheus registry to expose metrics. Please refer to Observer.MustRegister and Observer.Register for more information.

Example usage:

// Default configuration
observer := sentinel.NewObserver(nil)

// With duration metrics
observer := sentinel.NewObserver([]float64{0.05, 1, 5, 30, 600})

// With custom namespace and subsystem
observer := sentinel.NewObserver(
  []float64{0.1, 0.5, 1, 2, 5},
  sentinel.WithNamespace("my_app"),
  sentinel.WithSubsystem("workers"),
)

func (*Observer) Collect added in v0.8.0

func (o *Observer) Collect(ch chan<- prometheus.Metric)

Collect implements the prometheus.Collector interface by collecting metrics. This can be useful to register the Observer with the default Prometheus registry.

func (*Observer) Describe added in v0.8.0

func (o *Observer) Describe(ch chan<- *prometheus.Desc)

Describe implements the prometheus.Collector interface by describing metrics. This can be useful to register the Observer with the default Prometheus registry.

func (*Observer) DisablePanicRecovery added in v0.6.0

func (o *Observer) DisablePanicRecovery(disable bool)

DisablePanicRecovery sets whether panic recovery should be disabled for the observer. Recovery is enabled by default, meaning panics are caught and converted to errors. When disabled, panics will propagate normally and may crash the program.

func (*Observer) MustRegister

func (o *Observer) MustRegister(registry prometheus.Registerer)

MustRegister registers all Observer metrics with the provided Prometheus registry. This method panics if any metric registration failures occur. Use Observer.Register if you prefer to handle registration errors gracefully instead of panicking.

Example usage:

registry := prometheus.NewRegistry()
observer.MustRegister(registry) // Will panic if registration fails

func (*Observer) Register

func (o *Observer) Register(registry prometheus.Registerer) error

Register registers all Observer metrics with the provided Prometheus registry. This method returns an error if any metric registration fails. Use Observer.MustRegister if you want the program to panic on registration conflicts instead of handling errors.

Example usage:

registry := prometheus.NewRegistry()
if err := observer.Register(registry); err != nil {
	log.Fatalf("Failed to register metrics: %v", err)
}

func (*Observer) Run

func (o *Observer) Run(fn func() error) error

Run executes fn and records metrics according to the observer's configuration. This method does not respect timeouts set in the observer's ObserverConfig. Use RunFunc if you need timeout support.

The function is executed with panic recovery enabled by default. Panics are converted to errors and recorded in metrics. Use DisablePanicRecovery(true) to propagate panics instead.

If the function returns context.DeadlineExceeded, it will be recorded as a timeout when timeout metrics are enabled.

Example usage:

observer := sentinel.NewObserver()
err := observer.Run(func() error {
	return nil
})
if err != nil {
	log.Printf("Task failed: %v", err)
}

func (*Observer) RunFunc

func (o *Observer) RunFunc(fn func(ctx context.Context) error) error

RunFunc executes fn and records metrics according to the observer's configuration. For timeouts specified by the observer's ObserverConfig, the fn will be passed a context with the timeout. This is the recommended method when you need timeout support.

The function is executed with panic recovery enabled by default. Panics are converted to errors and recorded in metrics. Use DisablePanicRecovery(true) to propagate panics instead.

If the function returns context.DeadlineExceeded, it will be recorded as a timeout when timeout metrics are enabled.

Example usage:

observer := sentinel.NewObserver()
observer.UseConfig(sentinel.ObserverConfig{
	Timeout: 10 * time.Second,
})

err := observer.RunFunc(func(ctx context.Context) error {
	// Your task logic here with timeout support
	select {
	case <-ctx.Done():
		return ctx.Err()
	case <-time.After(5 * time.Second):
		return nil
	}
})
if err != nil {
	log.Printf("Task failed: %v", err)
}

func (*Observer) UseConfig added in v0.6.0

func (o *Observer) UseConfig(config ObserverConfig)

UseConfig configures the observer for how to handle Run methods. This sets the ObserverConfig that will be used for all subsequent Run, RunFunc calls. See ObserverConfig for more information on available configuration options.

Example usage:

observer.UseConfig(sentinel.ObserverConfig{
	Timeout:    10 * time.Second,
	MaxRetries: 3,
	RetryStrategy: retry.Exponential(100 * time.Millisecond),
	RetryBreaker: circuit.OnPanic(),
	MaxConcurrency: 10, // Limit to 10 concurrent executions
})

type ObserverConfig

type ObserverConfig struct {
	// Timeout sets a context deadline for functions passed to [Observer.RunFunc].
	// The observer records timeout occurrences under the "timeouts" metric when enabled.
	// The timeout is applied per iterative attempt to run the function.
	Timeout time.Duration

	// MaxRetries specifies the number of retry attempts for tasks on errors. If a task
	// fails for all attempts, the observer groups errors from multiple attempts using
	// [errors.Join]. By default, no retries are performed.
	MaxRetries int

	// RetryStrategy is a handler which returns wait durations between retry attempts.
	// The first retry attempt will call the handler with retryCount=1. By default,
	// no wait strategy is applied (immediate retry).
	RetryStrategy retry.WaitFunc

	// RetryBreaker is a handler that skips following retry attempts for a task when
	// returning true. The handler will be provided the error from the previous attempt.
	// When nil, the observer will always attempt the next retry. This is useful to stop
	// retries on particular errors.
	RetryBreaker circuit.Breaker

	// Control receives the execution phase (PhaseNewRequest for new task executions, or
	// PhaseRetry for retry attempts) and returns true to cancel execution. This is useful
	// to manage or avoid new task executions on shutdown signals, or handling of specific
	// errors. When nil, all requests and retries are allowed.
	Control circuit.Control

	// MaxConcurrency limits the number of concurrent task executions. When set to a value
	// greater than 0, the observer will use a semaphore to limit concurrent executions.
	// This is useful for rate limiting or preventing resource exhaustion from too many
	// concurrent operations.
	MaxConcurrency int
}

type ObserverOption added in v0.5.0

type ObserverOption func(*config)

ObserverOption defines prometheus metrics options for an Observer. Options are provided to NewObserver on setting up the Observer.

func WithConstLabels added in v0.5.0

func WithConstLabels(labels prometheus.Labels) ObserverOption

WithConstLabels sets constant labels to exported metrics from the Observer. By convention, ConstLabels are not a recommended practice for Prometheus metrics. For more information, please refer to prometheus.Opts.ConstLabels documentation.

Example usage:

observer := sentinel.NewObserver(
    sentinel.WithConstLabels(
        prometheus.Labels{"env": "production"},
    ),
)

func WithDescription added in v0.5.0

func WithDescription(description string) ObserverOption

WithDescription sets the description used in the help text for generated prometheus metrics to describe the tasks being observed. For example, "background processes" results in help text like: "Number of successes from observed background processes". Defaults to "tasks" to convey a generic process if not specified.

Example usage:

observer := sentinel.NewObserver(
    sentinel.WithDescription("background processes"),
)

func WithMetrics added in v0.8.0

func WithMetrics(metricNames ...string) ObserverOption

WithMetrics enables only the specified metrics for export. If not called, all metrics are enabled by default. Metrics that are not included will not be registered or exported.

Example usage:

// Only export successes and failures
observer := sentinel.NewObserver(
    nil,
    sentinel.WithMetrics(
        sentinel.MetricSuccesses,
        sentinel.MetricFailures,
    ),
)

// Export all metrics except durations
observer := sentinel.NewObserver(
    nil,
    sentinel.WithMetrics(
        sentinel.MetricInFlight,
        sentinel.MetricSuccesses,
        sentinel.MetricFailures,
        sentinel.MetricErrors,
        sentinel.MetricTimeouts,
        sentinel.MetricPanics,
        sentinel.MetricRetries,
    ),
)

func WithNamespace added in v0.5.0

func WithNamespace(namespace string) ObserverOption

WithNamespace sets the prometheus namespace for all metrics generated by this observer. For example, "myapp" with no subsystem results in metrics like "myapp_success_total". If empty with subsystem, no namespace prefix is used.

Example usage:

observer := sentinel.NewObserver(
    sentinel.WithNamespace("myapp"),
)

func WithSubsystem added in v0.5.0

func WithSubsystem(subsystem string) ObserverOption

WithSubsystem sets the prometheus subsystem for all metrics generated by this observer. For example, "workers" with no namespace results in metrics like "workers_success_total". If empty with namespace, defaults to "sentinel" if not specified.

Example usage:

observer := sentinel.NewObserver(
    sentinel.WithSubsystem("workers"),
)

type RecoveredPanic added in v0.9.0

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

ErrRecoveredPanic is the error returned when a panic occurs and is recovered by the Observer. The panic value can be retrieved from the error directly.

func (RecoveredPanic) Callers added in v0.9.0

func (e RecoveredPanic) Callers() []uintptr

Callers returns the program counters of the call stack at the time of panic. This can be used with runtime.CallersFrames to inspect the call stack.

func (RecoveredPanic) Error added in v0.9.0

func (e RecoveredPanic) Error() string

func (RecoveredPanic) Stack added in v0.9.0

func (e RecoveredPanic) Stack() []byte

Stack returns the stack trace captured at the time of panic recovery. The stack trace is formatted as a byte slice, similar to debug.Stack().

func (RecoveredPanic) Value added in v0.9.0

func (e RecoveredPanic) Value() any

Value returns the original panic value that was recovered. This is the value that was passed to panic() when the panic occurred.

type VecObserver added in v0.8.0

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

VecObserver is an Observer that supports Prometheus labels for multi-dimensional metrics. It follows the same pattern as Prometheus's GaugeVec and CounterVec, providing methods to create child observers with specific label combinations.

Example usage:

vecObserver := sentinel.NewVecObserver(
	[]float64{0.1, 0.5, 1, 2, 5},
	[]string{"service", "environment"},
)
apiObserver, _ := vecObserver.WithLabels("api", "production")
dbObserver, _ := vecObserver.WithLabels("db", "staging")

func NewVecObserver added in v0.8.0

func NewVecObserver(durationBuckets []float64, labelNames []string, opts ...ObserverOption) *VecObserver

NewVecObserver creates a new VecObserver with label support. When LabelNames is set in the VecObserverConfig, Vec metrics are used instead of direct metrics.

Example usage:

observer := sentinel.NewVecObserver(
	[]float64{0.1, 0.5, 1, 2, 5},
	[]string{"service", "status"},
	sentinel.WithNamespace("myapp"),
)

func (*VecObserver) Collect added in v0.8.0

func (vo *VecObserver) Collect(ch chan<- prometheus.Metric)

Collect implements the prometheus.Collector interface by collecting metrics. This can be useful to register the Observer with the default Prometheus registry.

func (*VecObserver) CurryWith added in v0.8.0

func (vo *VecObserver) CurryWith(labels prometheus.Labels) (*VecObserver, error)

CurryWith returns a VecObserver curried with the provided labels. Currying allows you to pre-set some labels, creating a new VecObserver that requires fewer labels for subsequent operations. This is useful when you have a common label value (like "environment") that you want to apply to multiple observers.

An error will be returned if the labels do not match initially configured label names.

Example usage:

vecObserver := sentinel.NewVecObserver(
	[]float64{0.1, 0.5, 1, 2, 5},
	[]string{"service", "environment"},
)
// Curry with environment="production", now only service label is needed
prodObserver, err := vecObserver.CurryWith(prometheus.Labels{"environment": "production"})
if err != nil {
	log.Fatal(err)
}
// Create observers with only the service label
apiObserver, _ := prodObserver.WithLabels("api")
dbObserver, _ := prodObserver.WithLabels("db")

func (*VecObserver) Describe added in v0.8.0

func (vo *VecObserver) Describe(ch chan<- *prometheus.Desc)

Describe implements the prometheus.Collector interface by describing metrics. This can be useful to register the Observer with the default Prometheus registry.

func (*VecObserver) MustRegister added in v0.8.0

func (vo *VecObserver) MustRegister(registry prometheus.Registerer)

MustRegister registers all VecObserver metrics with the provided Prometheus registry. This method panics if any metric registration failures occur. Use VecObserver.Register if you prefer to handle registration errors gracefully instead of panicking.

Example usage:

registry := prometheus.NewRegistry()
vecObserver.MustRegister(registry) // Will panic if registration fails

func (*VecObserver) Register added in v0.8.0

func (vo *VecObserver) Register(registry prometheus.Registerer) error

Register registers all VecObserver metrics with the provided Prometheus registry. This method returns an error if any metric registration fails. Use VecObserver.MustRegister if you want the program to panic on registration conflicts instead of handling errors.

Example usage:

registry := prometheus.NewRegistry()
if err := vecObserver.Register(registry); err != nil {
	log.Fatalf("Failed to register metrics: %v", err)
}

func (*VecObserver) Reset added in v0.8.0

func (vo *VecObserver) Reset()

Reset deletes all metrics in this VecObserver.

This method affects all child observers created from this VecObserver. After reset:

  • All metric values tracked by the VecObserver are cleared
  • Existing child observers created before Reset() can still be called without panicking, but their metrics will not be tracked by the VecObserver (they record to old metric instances that were removed from the Vec's internal map)
  • To continue tracking metrics after Reset(), create new child observers using VecObserver.WithLabels or VecObserver.With

This method follows the same pattern as Prometheus's GaugeVec.Reset method.

func (*VecObserver) With added in v0.8.0

func (vo *VecObserver) With(labels prometheus.Labels) (*Observer, error)

With returns a new Observer with the given labels. The observer will share the same underlying metrics as the original, but will record metrics with the specified label values. An error will be returned if the labels do not match initially configured label names.

Example usage:

vecObserver := sentinel.NewVecObserver(
	[]float64{0.1, 0.5, 1, 2, 5},
	[]string{"service", "environment"},
)
observer, err := vecObserver.With(prometheus.Labels{
	"service":     "api",
	"environment": "production",
})
if err != nil {
	log.Fatal(err)
}

func (*VecObserver) WithLabels added in v0.8.0

func (vo *VecObserver) WithLabels(labelValues ...string) (*Observer, error)

WithLabels returns a new Observer with the given label values. An error will be returned if the label values do not match initially configured label names.

Example usage:

vecObserver := sentinel.NewVecObserver(
	[]float64{0.1, 0.5, 1, 2, 5},
	[]string{"service", "environment"},
)
observer, err := vecObserver.WithLabels("api", "production")
if err != nil {
	log.Fatal(err)
}

Directories

Path Synopsis
Package circuit provides circuit breaker predicates for sentinel's retry logic.
Package circuit provides circuit breaker predicates for sentinel's retry logic.
Package retry provides WaitFunc implementations for the sentinel package.
Package retry provides WaitFunc implementations for the sentinel package.

Jump to

Keyboard shortcuts

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