aboutsummaryrefslogtreecommitdiff
path: root/lib/longboat/collector.rb
blob: 01bb7f059d52d95d80378b67775aa9938f3f37b6 (plain)
1
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
module Longboat
  class CollectorTransactionError < Exception; end

  class Collector
    def initialize(config)
      @metrics = {}
      @config = config
      @transaction = nil
    end

    def report!(name, value, help: nil, type: nil, labels: {}, timestamp: Time.now)
      raise CollectorTransactionError if @tranaction.nil?

      name = prefix(name)

      @transaction[name] ||= {help: help, type: type}
      @transaction[name][labels] = {value: value, timestamp: timestamp}
    end

    def redact!(name, labels: nil)
      raise CollectorTransactionError if @tranaction.nil?

      name = prefix(name)

      if labels.nil?
        @transaction.delete(name)
      else
        @transaction[name].delete(labels)
      end
    end

    def begin!
      @transaction = clone_metrics
    end

    def abort!
      @transaction = nil
    end

    def commit!
      @metrics = @transaction
      @transaction = nil
    end

    def prometheus_metrics
      res = ""
      @metrics.each do |name, metric|
        res << ?\n unless res.empty?
        res << "#HELP #{name} #{metric[:help]}\n" unless metric[:help].nil?
        res << "#TYPE #{name} #{metric[:type]}\n" unless metric[:type].nil?

        metric.each do |labels, value|
          next if labels == :help
          next if labels == :type

          labellist = []
          labels.each do |k, v|
            labellist << "#{k}=\"#{v}\""
          end
          labellist = labellist.join(",")

          res << "#{name}{#{labellist}} #{value[:value]} #{(value[:timestamp].to_f * 1000).to_i}\n"
        end
      end
      res
    end

    private

    def prefix(name)
      "#{@config[:metric_prefix]}#{name}"
    end
    
    def clone_metrics
      clone = {}

      @metrics.each do |metric, attributes|
        clone[metric] = {}
        clone[metric][:help] = attributes[:help]
        clone[metric][:type] = attributes[:type]

        attributes.each do |labels, value|
          next if [:help, :type].include?(labels)

          clone[metric][labels.clone] = value.clone
        end
      end

      clone
    end
  end
end