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

Inherits:
Object
  • Object
show all
Includes:
Domain::_MetricsStore
Defined in:
lib/stoplight/infrastructure/memory/storage/unbounded_metrics.rb,
sig/_private/stoplight/infrastructure/memory/storage/unbounded_metrics.rbs

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 Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(clock:) ⇒ UnboundedMetrics

Returns a new instance of UnboundedMetrics.

Parameters:



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 Attribute Details

#clockDomain::_Clock (readonly)

Returns the value of attribute clock.

Returns:



87
88
89
# File 'lib/stoplight/infrastructure/memory/storage/unbounded_metrics.rb', line 87

def clock
  @clock
end

#consecutive_errorsInteger

Returns the value of attribute consecutive_errors.

Returns:

  • (Integer)


81
82
83
# File 'lib/stoplight/infrastructure/memory/storage/unbounded_metrics.rb', line 81

def consecutive_errors
  @consecutive_errors
end

#consecutive_successesInteger

Returns the value of attribute consecutive_successes.

Returns:

  • (Integer)


82
83
84
# File 'lib/stoplight/infrastructure/memory/storage/unbounded_metrics.rb', line 82

def consecutive_successes
  @consecutive_successes
end

#last_errorDomain::Failure?

Returns the value of attribute last_error.

Returns:



83
84
85
# File 'lib/stoplight/infrastructure/memory/storage/unbounded_metrics.rb', line 83

def last_error
  @last_error
end

#last_success_atTime?

Returns the value of attribute last_success_at.

Returns:

  • (Time, nil)


84
85
86
# File 'lib/stoplight/infrastructure/memory/storage/unbounded_metrics.rb', line 84

def last_success_at
  @last_success_at
end

#mutexMutex (readonly)

Returns the value of attribute mutex.

Returns:

  • (Mutex)


86
87
88
# File 'lib/stoplight/infrastructure/memory/storage/unbounded_metrics.rb', line 86

def mutex
  @mutex
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

#last_error_atTime?

Returns:

  • (Time, nil)


96
97
98
# File 'lib/stoplight/infrastructure/memory/storage/unbounded_metrics.rb', line 96

def last_error_at
  last_error&.occurred_at
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