Module: TjScaleRuby

Defined in:
lib/tj-scale.rb,
lib/tj_scale_ruby/version.rb,
lib/tj_scale_ruby/job_backends.rb,
lib/tj_scale_ruby/configuration.rb,
lib/tj_scale_ruby/job_backends/sidekiq.rb,
lib/tj_scale_ruby/models/tj_scale_ruby.rb,
lib/tj_scale_ruby/job_backends/delayed_job.rb,
lib/tj_scale_ruby/rack_queue_time_middleware.rb

Overview

Version module for TjScaleRuby gem

Defined Under Namespace

Modules: JobBackends Classes: Configuration, JobMonitor, RackQueueTimeMiddleware, Railtie

Constant Summary collapse

VERSION =
"1.1.0"

Class Method Summary collapse

Class Method Details

.clear_monitoring_memo!Object



94
95
96
# File 'lib/tj-scale.rb', line 94

def self.clear_monitoring_memo!
  remove_instance_variable(:@monitor_on_this_dyno) if defined?(@monitor_on_this_dyno)
end

.clear_web_queue_time_snapshot!Object



114
115
116
# File 'lib/tj_scale_ruby/configuration.rb', line 114

def clear_web_queue_time_snapshot!
  web_queue_mutex.synchronize { @web_queue_time_ms = nil }
end

.clear_web_traffic_stats!Object



143
144
145
146
147
148
# File 'lib/tj_scale_ruby/configuration.rb', line 143

def clear_web_traffic_stats!
  web_traffic_mutex.synchronize do
    @web_request_count = 0
    @web_response_time_sum_ms = 0
  end
end

.configurationObject



85
86
87
# File 'lib/tj_scale_ruby/configuration.rb', line 85

def configuration
  @configuration ||= Configuration.new
end

.configuration=(config) ⇒ Object



89
90
91
# File 'lib/tj_scale_ruby/configuration.rb', line 89

def configuration=(config)
  @configuration = config
end

.flush_web_traffic_stats_for_payload!Hash

Returns :job_count requests since last flush; :response_time_ms average ms or nil.

Returns:

  • (Hash)

    :job_count requests since last flush; :response_time_ms average ms or nil



132
133
134
135
136
137
138
139
140
141
# File 'lib/tj_scale_ruby/configuration.rb', line 132

def flush_web_traffic_stats_for_payload!
  web_traffic_mutex.synchronize do
    c = @web_request_count || 0
    sum = @web_response_time_sum_ms || 0
    @web_request_count = 0
    @web_response_time_sum_ms = 0
    avg = c.positive? ? (sum.to_f / c).round : nil
    { job_count: c, response_time_ms: avg }
  end
end

.last_web_queue_time_msObject



110
111
112
# File 'lib/tj_scale_ruby/configuration.rb', line 110

def last_web_queue_time_ms
  web_queue_mutex.synchronize { @web_queue_time_ms }
end

.monitor_on_this_dyno?Boolean

True when this dyno should run the metrics loop: the first dyno (.1) of the monitored process type (auto-detected from DYNO, or TJ_SCALE_MONITOR_PROCESS). Result is memoized; cleared by reset_configuration!.

Returns:

  • (Boolean)


77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/tj-scale.rb', line 77

def self.monitor_on_this_dyno?
  return @monitor_on_this_dyno if defined?(@monitor_on_this_dyno)

  dyno = ENV["DYNO"]
  @monitor_on_this_dyno = if dyno.nil? || dyno.empty?
    false
  else
    parts = dyno.split(".", 2)
    if parts.size != 2
      false
    else
      process, index = parts
      process == configuration.monitor_process && index.to_i == 1
    end
  end
end

.record_web_queue_time_ms!(ms) ⇒ Object

Latest web router queue time (ms) captured by RackQueueTimeMiddleware; thread-safe.



101
102
103
104
105
106
107
108
# File 'lib/tj_scale_ruby/configuration.rb', line 101

def record_web_queue_time_ms!(ms)
  v = Integer(ms)
  return if v.negative?

  web_queue_mutex.synchronize { @web_queue_time_ms = v }
rescue ArgumentError, TypeError
  nil
end

.record_web_request_finished!(duration_ms) ⇒ Object

Request volume + response time for web metrics (flushed each ingest tick).



119
120
121
122
123
124
125
126
127
128
129
# File 'lib/tj_scale_ruby/configuration.rb', line 119

def record_web_request_finished!(duration_ms)
  v = Integer(duration_ms)
  return if v.negative?

  web_traffic_mutex.synchronize do
    @web_request_count = (@web_request_count || 0) + 1
    @web_response_time_sum_ms = (@web_response_time_sum_ms || 0) + v
  end
rescue ArgumentError, TypeError
  nil
end

.reset_configuration!Object



93
94
95
96
97
98
# File 'lib/tj_scale_ruby/configuration.rb', line 93

def reset_configuration!
  @configuration = nil
  TjScaleRuby.clear_monitoring_memo!
  TjScaleRuby.clear_web_queue_time_snapshot!
  TjScaleRuby.clear_web_traffic_stats!
end

.start_monitoring_loop!Object

Starts a background thread on the designated first dyno (see #monitor_on_this_dyno?).



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/tj-scale.rb', line 57

def self.start_monitoring_loop!
  return unless monitor_on_this_dyno?

  interval = configuration.interval_seconds
  Thread.new do
    loop do
      begin
        JobMonitor.send_log
      rescue StandardError => e
        Rails.logger.error("TjScaleRuby: Error in monitoring loop: #{e.message}")
      end

      sleep(interval)
    end
  end
end

.web_queue_mutexObject



150
151
152
# File 'lib/tj_scale_ruby/configuration.rb', line 150

def web_queue_mutex
  @web_queue_mutex ||= Mutex.new
end

.web_traffic_mutexObject



155
156
157
# File 'lib/tj_scale_ruby/configuration.rb', line 155

def web_traffic_mutex
  @web_traffic_mutex ||= Mutex.new
end