Module: ThrottleMachines::Instrumentation

Defined in:
lib/throttle_machines/instrumentation.rb

Overview

Instrumentation module for emitting events via ActiveSupport::Notifications

Defined Under Namespace

Classes: NullBackend

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.backendObject



14
15
16
# File 'lib/throttle_machines/instrumentation.rb', line 14

def backend
  @backend ||= ActiveSupport::Notifications
end

.enabledObject



9
10
11
12
# File 'lib/throttle_machines/instrumentation.rb', line 9

def enabled
  @enabled = true if @enabled.nil?
  @enabled
end

Class Method Details

.cascade_triggered(primary_key, cascaded_key) ⇒ Object

Cascade events



124
125
126
127
128
129
130
# File 'lib/throttle_machines/instrumentation.rb', line 124

def cascade_triggered(primary_key, cascaded_key)
  payload = {
    primary_key: primary_key,
    cascaded_key: cascaded_key
  }
  instrument('cascade.triggered', payload)
end

.circuit_closed(breaker) ⇒ Object



77
78
79
80
81
82
83
84
# File 'lib/throttle_machines/instrumentation.rb', line 77

def circuit_closed(breaker)
  payload = {
    key: (breaker.respond_to?(:name) ? breaker.name : breaker.to_s),
    failure_threshold: (breaker.respond_to?(:configuration) ? breaker.configuration[:failure_threshold] : nil),
    timeout: (breaker.respond_to?(:configuration) ? breaker.configuration[:reset_timeout] : nil)
  }
  instrument('circuit_breaker.closed', payload)
end

.circuit_failure(breaker, error: nil) ⇒ Object



104
105
106
107
108
109
110
111
112
# File 'lib/throttle_machines/instrumentation.rb', line 104

def circuit_failure(breaker, error: nil)
  payload = {
    key: (breaker.respond_to?(:name) ? breaker.name : breaker.to_s),
    state: (breaker.respond_to?(:to_h) ? breaker.to_h[:state] : nil),
    error_class: error&.class&.name,
    error_message: error&.message
  }
  instrument('circuit_breaker.failure', payload)
end

.circuit_half_opened(breaker) ⇒ Object



86
87
88
89
90
91
92
93
94
# File 'lib/throttle_machines/instrumentation.rb', line 86

def circuit_half_opened(breaker)
  payload = {
    key: (breaker.respond_to?(:name) ? breaker.name : breaker.to_s),
    failure_threshold: (breaker.respond_to?(:configuration) ? breaker.configuration[:failure_threshold] : nil),
    timeout: (breaker.respond_to?(:configuration) ? breaker.configuration[:reset_timeout] : nil),
    half_open_requests: (breaker.respond_to?(:configuration) ? breaker.configuration[:half_open_calls] : nil)
  }
  instrument('circuit_breaker.half_opened', payload)
end

.circuit_opened(breaker, failure_count:) ⇒ Object

Circuit breaker events



67
68
69
70
71
72
73
74
75
# File 'lib/throttle_machines/instrumentation.rb', line 67

def circuit_opened(breaker, failure_count:)
  payload = {
    key: (breaker.respond_to?(:name) ? breaker.name : breaker.to_s),
    failure_threshold: (breaker.respond_to?(:configuration) ? breaker.configuration[:failure_threshold] : nil),
    timeout: (breaker.respond_to?(:configuration) ? breaker.configuration[:reset_timeout] : nil),
    failure_count: failure_count
  }
  instrument('circuit_breaker.opened', payload)
end

.circuit_rejected(breaker) ⇒ Object



114
115
116
117
118
119
120
121
# File 'lib/throttle_machines/instrumentation.rb', line 114

def circuit_rejected(breaker)
  payload = {
    key: (breaker.respond_to?(:name) ? breaker.name : breaker.to_s),
    failure_threshold: (breaker.respond_to?(:configuration) ? breaker.configuration[:failure_threshold] : nil),
    timeout: (breaker.respond_to?(:configuration) ? breaker.configuration[:reset_timeout] : nil)
  }
  instrument('circuit_breaker.rejected', payload)
end

.circuit_success(breaker) ⇒ Object



96
97
98
99
100
101
102
# File 'lib/throttle_machines/instrumentation.rb', line 96

def circuit_success(breaker)
  payload = {
    key: (breaker.respond_to?(:name) ? breaker.name : breaker.to_s),
    state: (breaker.respond_to?(:to_h) ? breaker.to_h[:state] : nil)
  }
  instrument('circuit_breaker.success', payload)
end

.hedged_request_started(request_id, attempts:) ⇒ Object

Hedged request events



133
134
135
136
137
138
139
# File 'lib/throttle_machines/instrumentation.rb', line 133

def hedged_request_started(request_id, attempts:)
  payload = {
    request_id: request_id,
    max_attempts: attempts
  }
  instrument('hedged_request.started', payload)
end

.hedged_request_winner(request_id, attempt:, duration:) ⇒ Object



141
142
143
144
145
146
147
148
# File 'lib/throttle_machines/instrumentation.rb', line 141

def hedged_request_winner(request_id, attempt:, duration:)
  payload = {
    request_id: request_id,
    winning_attempt: attempt,
    duration: duration
  }
  instrument('hedged_request.winner', payload)
end

.instrument(event_name, payload = {}, &block) ⇒ Object



18
19
20
21
22
23
24
25
26
27
# File 'lib/throttle_machines/instrumentation.rb', line 18

def instrument(event_name, payload = {}, &block)
  if !enabled || backend.nil?
    return yield if block_given?

    return
  end

  full_event_name = "#{event_name}.throttle_machines"
  backend.instrument(full_event_name, payload, &block)
end

.rate_limit_allowed(limiter, remaining: nil) ⇒ Object



44
45
46
47
48
49
50
51
52
53
# File 'lib/throttle_machines/instrumentation.rb', line 44

def rate_limit_allowed(limiter, remaining: nil)
  payload = {
    key: limiter.key,
    limit: limiter.limit,
    period: limiter.period,
    algorithm: limiter.algorithm,
    remaining: remaining
  }
  instrument('rate_limit.allowed', payload)
end

.rate_limit_checked(limiter, allowed:, remaining: nil) ⇒ Object

Rate limiter events



32
33
34
35
36
37
38
39
40
41
42
# File 'lib/throttle_machines/instrumentation.rb', line 32

def rate_limit_checked(limiter, allowed:, remaining: nil)
  payload = {
    key: limiter.key,
    limit: limiter.limit,
    period: limiter.period,
    algorithm: limiter.algorithm,
    allowed: allowed,
    remaining: remaining
  }
  instrument('rate_limit.checked', payload)
end

.rate_limit_throttled(limiter, retry_after: nil) ⇒ Object



55
56
57
58
59
60
61
62
63
64
# File 'lib/throttle_machines/instrumentation.rb', line 55

def rate_limit_throttled(limiter, retry_after: nil)
  payload = {
    key: limiter.key,
    limit: limiter.limit,
    period: limiter.period,
    algorithm: limiter.algorithm,
    retry_after: retry_after
  }
  instrument('rate_limit.throttled', payload)
end