Class: Stoplight::Infrastructure::Memory::Storage::UnboundedMetrics

Inherits:
Object
  • Object
show all
Defined in:
lib/stoplight/infrastructure/memory/storage/unbounded_metrics.rb

Overview

Note:

The #errors and #successes fields in the returned Stoplight::Domain::Metrics are always nil since totals aren’t tracked.

Thread-safe metrics storage for consecutive-error light strategies.

Unlike WindowMetrics, this class does not track event counts within a time window. It only maintains:

  • Consecutive success/failure counters (reset on opposite outcome)

  • Most recent error with timestamp

  • Most recent success timestamp

This is appropriate for circuit breakers using threshold-based strategies (e.g., “open after 5 consecutive failures”) rather than rate-based strategies (e.g., “open when error rate exceeds 50%”).

Direct Known Subclasses

RecoveryMetrics

Instance Method Summary collapse

Constructor Details

#initialize(clock:) ⇒ UnboundedMetrics

Returns a new instance of UnboundedMetrics.



23
24
25
26
27
# File 'lib/stoplight/infrastructure/memory/storage/unbounded_metrics.rb', line 23

def initialize(clock:)
  initialize_metrics
  @clock = clock
  @mutex = Mutex.new
end

Instance Method Details

#clearObject



73
74
75
76
77
# File 'lib/stoplight/infrastructure/memory/storage/unbounded_metrics.rb', line 73

def clear
  mutex.synchronize do
    initialize_metrics
  end
end

#metrics_snapshotObject

Get metrics for the current light



30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/stoplight/infrastructure/memory/storage/unbounded_metrics.rb', line 30

def metrics_snapshot
  mutex.synchronize do
    Domain::MetricsSnapshot.new(
      errors: nil,
      successes: nil,
      consecutive_errors: consecutive_errors.to_i,
      consecutive_successes: consecutive_successes.to_i,
      last_error: last_error,
      last_success_at: last_success_at
    )
  end
end

#record_failure(exception) ⇒ Object

Records failed circuit breaker execution



58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/stoplight/infrastructure/memory/storage/unbounded_metrics.rb', line 58

def record_failure(exception)
  current_time = clock.current_time
  failure = Domain::Failure.from_error(exception, time: current_time)
  last_error_at = self.last_error_at

  mutex.synchronize do
    if last_error_at.nil? || failure.occurred_at > last_error_at
      self.last_error = failure
    end

    self.consecutive_errors += 1
    self.consecutive_successes = 0
  end
end

#record_successObject

Records successful circuit breaker execution



44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/stoplight/infrastructure/memory/storage/unbounded_metrics.rb', line 44

def record_success
  current_time = clock.current_time

  mutex.synchronize do
    if last_success_at.nil? || current_time > last_success_at
      self.last_success_at = current_time
    end

    self.consecutive_errors = 0
    self.consecutive_successes += 1
  end
end