Class: Judoscale::Reporter

Inherits:
Object
  • Object
show all
Includes:
Logger, Singleton
Defined in:
lib/judoscale/reporter.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Logger

#logger

Class Method Details

.start(config = Config.instance, adapters = Judoscale.adapters) ⇒ Object



15
16
17
# File 'lib/judoscale/reporter.rb', line 15

def self.start(config = Config.instance, adapters = Judoscale.adapters)
  instance.start!(config, adapters) unless instance.started?
end

Instance Method Details

#run_loop(config, metrics_collectors) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/judoscale/reporter.rb', line 47

def run_loop(config, metrics_collectors)
  @_thread = Thread.new do
    # Advise multi-threaded app servers to ignore this thread for the purposes of fork safety warnings.
    Thread.current.thread_variable_set(:fork_safe, true)

    loop do
      # Stagger reporting to spread out reports from many processes
      multiplier = 1 - (rand / 4) # between 0.75 and 1.0
      sleep config.report_interval_seconds * multiplier

      run_metrics_collection(config, metrics_collectors)
    end
  end
end

#run_metrics_collection(config, metrics_collectors) ⇒ Object



62
63
64
65
66
67
68
# File 'lib/judoscale/reporter.rb', line 62

def run_metrics_collection(config, metrics_collectors)
  metrics = metrics_collectors.flat_map do |metric_collector|
    log_exceptions { metric_collector.collect } || []
  end

  log_exceptions { report(config, metrics) }
end

#start!(config, adapters) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/judoscale/reporter.rb', line 19

def start!(config, adapters)
  @pid = Process.pid

  if config.api_base_url.nil? || config.api_base_url.strip.empty?
    logger.debug "Set api_base_url to enable metrics reporting"
    return
  end

  enabled_adapters, skipped_adapters = adapters.partition { |adapter|
    adapter.metrics_collector&.collect?(config)
  }
  metrics_collectors_classes = enabled_adapters.map(&:metrics_collector)
  adapters_msg = enabled_adapters.map(&:identifier).concat(
    skipped_adapters.map { |adapter| "#{adapter.identifier}[skipped]" }
  ).join(", ")

  if metrics_collectors_classes.empty?
    logger.debug "No metrics need to be collected (adapters: #{adapters_msg})"
    return
  end

  logger.info "Reporter starting, will report every ~#{config.report_interval_seconds} seconds (adapters: #{adapters_msg})"

  metrics_collectors = metrics_collectors_classes.map(&:new)

  run_loop(config, metrics_collectors)
end

#started?Boolean



70
71
72
# File 'lib/judoscale/reporter.rb', line 70

def started?
  @pid == Process.pid
end

#stop!Object



74
75
76
77
78
# File 'lib/judoscale/reporter.rb', line 74

def stop!
  @_thread&.terminate
  @_thread = nil
  @pid = nil
end