Module: PrometheusParser

Defined in:
lib/stack-service-base/prometheus_parser.rb

Class Method Summary collapse

Class Method Details

.parse_metrics(text) ⇒ Object



2
3
4
5
6
7
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
38
39
40
# File 'lib/stack-service-base/prometheus_parser.rb', line 2

def self.parse_metrics(text)
  metrics = Hash.new { |h, k| h[k] = { series: [] } }

  series = ->(name, labels) do
    metrics[name][:series].find { _1[:labels] == labels } ||
      metrics[name][:series] << { labels: labels } and metrics[name][:series].last
  end

  text.each_line(chomp: true) do |l|
    case l
    when /\A#\s*HELP\s+(\S+)\s+(.+)/
      metrics[$1.to_sym][:help] = $2
    when /\A#\s*TYPE\s+(\S+)\s+(\S+)/
      metrics[$1.to_sym][:type] = $2.to_sym
    when /\A([^ {]+)(?:\{([^}]*)\})?\s+([0-9eE+\-\.]+)\z/
      name, lbls, val = $1.to_sym, $2, $3.to_f
      labels = lbls.to_s.split(',').to_h { |kv| k, v = kv.split('='); [k.to_sym, v.delete('"')] }

      case
      when name.to_s.end_with?('_bucket')
        base = name.to_s.sub(/_bucket\z/, '').to_sym
        le   = labels.delete(:le)
        (entry = series[base, labels])[:buckets] ||= {}
        entry[:buckets][le] = val
      when name.to_s =~ /(.*)_(sum|count)\z/
        base, field = Regexp.last_match(1).to_sym, Regexp.last_match(2).to_sym
        (series[base, labels])[field] = val
      when labels.key?(:quantile)                           # Summary quantile
        q = labels.delete(:quantile)
        (entry = series[name, labels])[:quantiles] ||= {}
        entry[:quantiles][q] = val
      else                                                  # Counter/Gauge sample
        metrics[name][:series] << { labels: labels, value: val }
      end
    end
  end

  metrics
end