Read about our upcoming Code of Conduct on this issue

common_metrics_importer.rb 2.37 KB
Newer Older
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
93
94
95
96
97
98
99
100
101
# frozen_string_literal: true

module Importers
  class PrometheusMetric < ActiveRecord::Base
    enum group: {
      # built-in groups
      nginx_ingress: -1,
      ha_proxy: -2,
      aws_elb: -3,
      nginx: -4,
      kubernetes: -5,
  
      # custom groups
      business: 0,
      response: 1,
      system: 2,
    }

    scope :common, -> { where(common: true) }

    GROUP_TITLES = {
      business: _('Business metrics (Custom)'),
      response: _('Response metrics (Custom)'),
      system: _('System metrics (Custom)'),
      nginx_ingress: _('Response metrics (NGINX Ingress)'),
      ha_proxy: _('Response metrics (HA Proxy)'),
      aws_elb: _('Response metrics (AWS ELB)'),
      nginx: _('Response metrics (NGINX)'),
      kubernetes: _('System metrics (Kubernetes)')
    }.freeze
  end

  class CommonMetricsImporter
    MissingQueryId = Class.new(StandardError)

    attr_reader :content

    def initialize(file = 'config/prometheus/common_metrics.yml')
      @content = YAML.load_file(file)
    end
    
    def execute
      process_content do |id, attributes|
        find_or_build_metric!(id)
          .update!(**attributes)
      end
    end

    private

    def process_content(&blk)
      content.map do |group|
        process_group(group, &blk)
      end
    end

    def process_group(group, &blk)
      attributes = {
        group: find_group_title_key(group['group'])
      }

      group['metrics'].map do |metric|
        process_metric(metric, attributes, &blk)
      end
    end

    def process_metric(metric, attributes, &blk)
      attributes = attributes.merge(
        title: metric['title'],
        y_label: metric['y_label'])

      metric['queries'].map do |query|
        process_metric_query(query, attributes, &blk)
      end
    end

    def process_metric_query(query, attributes, &blk)
      attributes = attributes.merge(
        legend: query['label'],
        query: query['query_range'],
        unit: query['unit'])

      blk.call(query['id'], attributes)
    end

    def find_or_build_metric!(id)
      raise MissingQueryId unless id
    
      PrometheusMetric.common.find_by(identifier: id) ||
        PrometheusMetric.new(common: true, identifier: id)
    end

    def find_group_title_key(title)
      PrometheusMetric.groups[find_group_title(title)]
    end

    def find_group_title(title)
      PrometheusMetric::GROUP_TITLES.invert[title]
    end
  end
end