Class: PrometheusExporter::Instrumentation::ActiveRecord

Inherits:
Object
  • Object
show all
Defined in:
lib/prometheus_exporter/instrumentation/active_record.rb

Constant Summary collapse

ALLOWED_CONFIG_LABELS =
%i(database username host port)

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(metric_labels, config_labels) ⇒ ActiveRecord

Returns a new instance of ActiveRecord.



51
52
53
54
55
# File 'lib/prometheus_exporter/instrumentation/active_record.rb', line 51

def initialize(metric_labels, config_labels)
  @metric_labels = metric_labels
  @config_labels = config_labels
  @hostname = nil
end

Class Method Details

.start(client: nil, frequency: 30, custom_labels: {}, config_labels: []) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/prometheus_exporter/instrumentation/active_record.rb', line 8

def self.start(client: nil, frequency: 30, custom_labels: {}, config_labels: [])

  # Not all rails versions support coonection pool stats
  unless ::ActiveRecord::Base.connection_pool.respond_to?(:stat)
    STDERR.puts("ActiveRecord connection pool stats not supported in your rails version")
    return
  end

  config_labels.map!(&:to_sym)
  validate_config_labels(config_labels)

  active_record_collector = new(custom_labels, config_labels)

  client ||= PrometheusExporter::Client.default

  stop if @thread

  @thread = Thread.new do
    while true
      begin
        metrics = active_record_collector.collect
        metrics.each { |metric| client.send_json metric }
      rescue => e
        STDERR.puts("Prometheus Exporter Failed To Collect Process Stats #{e}")
      ensure
        sleep frequency
      end
    end
  end
end

.stopObject



44
45
46
47
48
49
# File 'lib/prometheus_exporter/instrumentation/active_record.rb', line 44

def self.stop
  if t = @thread
    t.kill
    @thread = nil
  end
end

.validate_config_labels(config_labels) ⇒ Object



39
40
41
42
# File 'lib/prometheus_exporter/instrumentation/active_record.rb', line 39

def self.validate_config_labels(config_labels)
  return if config_labels.size == 0
  raise "Invalid Config Labels, available options #{ALLOWED_CONFIG_LABELS}" if (config_labels - ALLOWED_CONFIG_LABELS).size > 0
end

Instance Method Details

#collectObject



67
68
69
70
71
# File 'lib/prometheus_exporter/instrumentation/active_record.rb', line 67

def collect
  metrics = []
  collect_active_record_pool_stats(metrics)
  metrics
end

#collect_active_record_pool_stats(metrics) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/prometheus_exporter/instrumentation/active_record.rb', line 77

def collect_active_record_pool_stats(metrics)
  ObjectSpace.each_object(::ActiveRecord::ConnectionAdapters::ConnectionPool) do |pool|
    next if pool.connections.nil?

    labels_from_config = pool.spec.config
      .select { |k, v| @config_labels.include? k }
      .map { |k, v| [k.to_s.prepend("dbconfig_"), v] }

    labels = @metric_labels.merge(pool_name: pool.spec.name).merge(Hash[labels_from_config])

    metric = {
      pid: pid,
      type: "active_record",
      hostname: hostname,
      metric_labels: labels
    }
    metric.merge!(pool.stat)
    metrics << metric
  end
end

#hostnameObject



57
58
59
60
61
62
63
64
65
# File 'lib/prometheus_exporter/instrumentation/active_record.rb', line 57

def hostname
  @hostname ||=
    begin
      `hostname`.strip
    rescue => e
      STDERR.puts "Unable to lookup hostname #{e}"
      "unknown-host"
    end
end

#pidObject



73
74
75
# File 'lib/prometheus_exporter/instrumentation/active_record.rb', line 73

def pid
  @pid = ::Process.pid
end