summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js
blob: 57f9cec96825a68431bceaaf78f7fe8e49c3a647 (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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import $ from 'jquery';
import { escape } from 'lodash';
import { s__, n__, sprintf } from '~/locale';
import axios from '../lib/utils/axios_utils';
import PANEL_STATE from './constants';
import { backOff } from '../lib/utils/common_utils';

export default class PrometheusMetrics {
  constructor(wrapperSelector) {
    this.backOffRequestCounter = 0;

    this.$wrapper = $(wrapperSelector);

    this.$monitoredMetricsPanel = this.$wrapper.find('.js-panel-monitored-metrics');
    this.$monitoredMetricsCount = this.$monitoredMetricsPanel.find('.js-monitored-count');
    this.$monitoredMetricsLoading = this.$monitoredMetricsPanel.find('.js-loading-metrics');
    this.$monitoredMetricsEmpty = this.$monitoredMetricsPanel.find('.js-empty-metrics');
    this.$monitoredMetricsList = this.$monitoredMetricsPanel.find('.js-metrics-list');

    this.$missingEnvVarPanel = this.$wrapper.find('.js-panel-missing-env-vars');
    this.$panelToggleRight = this.$missingEnvVarPanel.find('.js-panel-toggle-right');
    this.$panelToggleDown = this.$missingEnvVarPanel.find('.js-panel-toggle-down');
    this.$missingEnvVarMetricCount = this.$missingEnvVarPanel.find('.js-env-var-count');
    this.$missingEnvVarMetricsList = this.$missingEnvVarPanel.find('.js-missing-var-metrics-list');

    this.activeMetricsEndpoint = this.$monitoredMetricsPanel.data('activeMetrics');
    this.helpMetricsPath = this.$monitoredMetricsPanel.data('metrics-help-path');

    this.$panelToggleRight.on('click', (e) => this.handlePanelToggle(e));
    this.$panelToggleDown.on('click', (e) => this.handlePanelToggle(e));
  }

  init() {
    this.loadActiveMetrics();
  }

  handlePanelToggle(e) {
    const $toggleBtn = $(e.currentTarget);
    const $currentPanelBody = $toggleBtn.closest('.card').find('.card-body');
    $currentPanelBody.toggleClass('hidden');
    if ($toggleBtn.hasClass('js-panel-toggle-right')) {
      $toggleBtn.addClass('hidden');
      this.$panelToggleDown.removeClass('hidden');
    } else if ($toggleBtn.hasClass('js-panel-toggle-down')) {
      $toggleBtn.addClass('hidden');
      this.$panelToggleRight.removeClass('hidden');
    }
  }

  showMonitoringMetricsPanelState(stateName) {
    switch (stateName) {
      case PANEL_STATE.LOADING:
        this.$monitoredMetricsLoading.removeClass('hidden');
        this.$monitoredMetricsEmpty.addClass('hidden');
        this.$monitoredMetricsList.addClass('hidden');
        break;
      case PANEL_STATE.LIST:
        this.$monitoredMetricsLoading.addClass('hidden');
        this.$monitoredMetricsEmpty.addClass('hidden');
        this.$monitoredMetricsList.removeClass('hidden');
        break;
      default:
        this.$monitoredMetricsLoading.addClass('hidden');
        this.$monitoredMetricsEmpty.removeClass('hidden');
        this.$monitoredMetricsList.addClass('hidden');
        break;
    }
  }

  populateActiveMetrics(metrics) {
    let totalMonitoredMetrics = 0;
    let totalMissingEnvVarMetrics = 0;
    let totalExporters = 0;

    metrics.forEach((metric) => {
      if (metric.active_metrics > 0) {
        totalExporters += 1;
        this.$monitoredMetricsList.append(
          `<li>${escape(metric.group)}<span class="badge">${escape(
            metric.active_metrics,
          )}</span></li>`,
        );
        totalMonitoredMetrics += metric.active_metrics;
        if (metric.metrics_missing_requirements > 0) {
          this.$missingEnvVarMetricsList.append(`<li>${escape(metric.group)}</li>`);
          totalMissingEnvVarMetrics += 1;
        }
      }
    });

    if (totalMonitoredMetrics === 0) {
      const emptyCommonMetricsText = sprintf(
        s__('PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found'),
        {
          docsUrlStart: `<a href="${this.helpMetricsPath}">`,
          docsUrlEnd: '</a>',
        },
        false,
      );
      this.$monitoredMetricsEmpty.empty();
      this.$monitoredMetricsEmpty.append(`<p class="text-tertiary">${emptyCommonMetricsText}</p>`);
      this.showMonitoringMetricsPanelState(PANEL_STATE.EMPTY);
    } else {
      const metricsCountText = sprintf(
        s__('PrometheusService|%{exporters} with %{metrics} were found'),
        {
          exporters: n__('%d exporter', '%d exporters', totalExporters),
          metrics: n__('%d metric', '%d metrics', totalMonitoredMetrics),
        },
      );
      this.$monitoredMetricsCount.text(metricsCountText);
      this.showMonitoringMetricsPanelState(PANEL_STATE.LIST);

      if (totalMissingEnvVarMetrics > 0) {
        this.$missingEnvVarPanel.removeClass('hidden');
        this.$missingEnvVarMetricCount.text(totalMissingEnvVarMetrics);
      }
    }
  }

  loadActiveMetrics() {
    this.showMonitoringMetricsPanelState(PANEL_STATE.LOADING);
    backOff((next, stop) => {
      axios
        .get(this.activeMetricsEndpoint)
        .then(({ data }) => {
          if (data && data.success) {
            stop(data);
          } else {
            this.backOffRequestCounter += 1;
            if (this.backOffRequestCounter < 3) {
              next();
            } else {
              stop(data);
            }
          }
        })
        .catch(stop);
    })
      .then((res) => {
        if (res && res.data && res.data.length) {
          this.populateActiveMetrics(res.data);
        } else {
          this.showMonitoringMetricsPanelState(PANEL_STATE.EMPTY);
        }
      })
      .catch(() => {
        this.showMonitoringMetricsPanelState(PANEL_STATE.EMPTY);
      });
  }
}