diff options
-rw-r--r-- | app/controllers/projects/environments_controller.rb | 2 | ||||
-rw-r--r-- | app/services/metrics_dashboard_service.rb | 33 | ||||
-rw-r--r-- | lib/gitlab/metrics_dashboard/common_metrics_inserter.rb | 32 | ||||
-rw-r--r-- | lib/gitlab/metrics_dashboard/processor.rb | 20 | ||||
-rw-r--r-- | lib/gitlab/metrics_dashboard/project_metrics_inserter.rb | 70 | ||||
-rw-r--r-- | lib/gitlab/metrics_dashboard/service.rb | 37 | ||||
-rw-r--r-- | lib/gitlab/metrics_dashboard/sorter.rb | 26 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics_dashboard/processor_spec.rb (renamed from spec/services/metrics_dashboard_processing_service_spec.rb) | 4 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics_dashboard/service_spec.rb (renamed from spec/services/metrics_dashboard_service_spec.rb) | 2 |
9 files changed, 189 insertions, 37 deletions
diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb index db0253a9183..69ceeab5b99 100644 --- a/app/controllers/projects/environments_controller.rb +++ b/app/controllers/projects/environments_controller.rb @@ -162,7 +162,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController respond_to do |format| format.json do - dashboard = MetricsDashboardService.new(@project).get_dashboard + dashboard = Gitlab::MetricsDashboard::Service.new(@project).get_dashboard render json: dashboard, status: :ok end diff --git a/app/services/metrics_dashboard_service.rb b/app/services/metrics_dashboard_service.rb deleted file mode 100644 index b72095744b2..00000000000 --- a/app/services/metrics_dashboard_service.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -# Fetches the metrics dashboard layout and supplemented the output with DB info. -class MetricsDashboardService - SYSTEM_DASHBOARD_NAME = 'common_metrics' - SYSTEM_DASHBOARD_PATH = Rails.root.join('config', 'prometheus', "#{SYSTEM_DASHBOARD_NAME}.yml") - - def initialize(project) - @project = project - end - - # Returns a DB-supplemented json representation of a dashboard config file. - def get_dashboard - dashboard = Rails.cache.fetch(cache_key) { system_dashboard } - - process_dashboard(dashboard) - end - - private - - # Returns the base metrics shipped with every GitLab service. - def system_dashboard - YAML.load_file(SYSTEM_DASHBOARD_PATH) - end - - def cache_key - "metrics_dashboard_#{SYSTEM_DASHBOARD_NAME}" - end - - def process_dashboard(dashboard) - MetricsDashboardProcessingService.new(dashboard, @project).process - end -end diff --git a/lib/gitlab/metrics_dashboard/common_metrics_inserter.rb b/lib/gitlab/metrics_dashboard/common_metrics_inserter.rb new file mode 100644 index 00000000000..5bc83e6266e --- /dev/null +++ b/lib/gitlab/metrics_dashboard/common_metrics_inserter.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module Gitlab + module MetricsDashboard + class CommonMetricsInserter + class << self + # For each metric in the dashboard config, attempts to find a corresponding + # database record. If found, includes the record's id in the dashboard config. + def transform!(dashboard, _project) + common_metrics = ::PrometheusMetric.common + + for_metrics(dashboard) do |metric| + metric_record = common_metrics.find { |m| m.identifier == metric[:id] } + metric[:metric_id] = metric_record.id if metric_record + end + end + + private + + def for_metrics(dashboard) + dashboard[:panel_groups].each do |panel_group| + panel_group[:panels].each do |panel| + panel[:metrics].each do |metric| + yield metric + end + end + end + end + end + end + end +end diff --git a/lib/gitlab/metrics_dashboard/processor.rb b/lib/gitlab/metrics_dashboard/processor.rb new file mode 100644 index 00000000000..9e254aa2b37 --- /dev/null +++ b/lib/gitlab/metrics_dashboard/processor.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Gitlab + module MetricsDashboard + class Processor + STAGES = [CommonMetricsInserter, Sorter, ProjectMetricsInserter] + + def initialize(dashboard, project) + @dashboard = dashboard.deep_transform_keys(&:to_sym) + @project = project + end + + def process + STAGES.each { |stage| stage.transform!(@dashboard, @project) } + + @dashboard.to_json + end + end + end +end diff --git a/lib/gitlab/metrics_dashboard/project_metrics_inserter.rb b/lib/gitlab/metrics_dashboard/project_metrics_inserter.rb new file mode 100644 index 00000000000..67300c79e57 --- /dev/null +++ b/lib/gitlab/metrics_dashboard/project_metrics_inserter.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +module Gitlab + module MetricsDashboard + class ProjectMetricsInserter + DEFAULT_PANEL_TYPE = 'area-chart' + + class << self + # Inserts project-specific metrics into the dashboard config. + # If there are no project-specific metrics, this will have no effect. + def transform!(dashboard, project) + project.prometheus_metrics.each do |project_metric| + group = find_or_create(:panel_group, dashboard[:panel_groups], project_metric) + panel = find_or_create(:panel, group[:panels], project_metric) + find_or_create(:metric, panel[:metrics], project_metric) + end + end + + # Looks for an instance of the named resource corresponding to the provided + # metric object. If unavailable, inserts one. + # @param name [Symbol, String] One of :panel_group, :panel, or :metric + # @param existing_resources [Array<Hash>] + # @param metric [PrometheusMetric] + def find_or_create(name, existing_resources, metric) + target = self.send("find_#{name}", existing_resources, metric) + return target if target + + target = self.send("new_#{name}", metric) + existing_resources << target + + target + end + + def find_panel_group(panel_groups, metric) + panel_groups.find { |group| group[:group] == metric.group_title } + end + + def find_panel(panels, metric) + panel_identifiers = [DEFAULT_PANEL_TYPE, metric.title, metric.y_label] + target_panel = panels.find { |panel| panel.values_at(:type, :title, :y_label) == panel_identifiers } + end + + def find_metric(metrics, metric) + metrics.find { |m| m[:id] == metric.identifier } + end + + def new_panel_group(metric) + { + group: metric.group_title, + priority: metric.priority, + panels: [] + } + end + + def new_panel(metric) + { + type: DEFAULT_PANEL_TYPE, + title: metric.title, + y_label: metric.y_label, + metrics: [] + } + end + + def new_metric(metric) + metric.queries.first.merge(metric_id: metric.id) + end + end + end + end +end diff --git a/lib/gitlab/metrics_dashboard/service.rb b/lib/gitlab/metrics_dashboard/service.rb new file mode 100644 index 00000000000..22e1771cbea --- /dev/null +++ b/lib/gitlab/metrics_dashboard/service.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +# Fetches the metrics dashboard layout and supplemented the output with DB info. +module Gitlab + module MetricsDashboard + class Service + SYSTEM_DASHBOARD_NAME = 'common_metrics' + SYSTEM_DASHBOARD_PATH = Rails.root.join('config', 'prometheus', "#{SYSTEM_DASHBOARD_NAME}.yml") + + def initialize(project) + @project = project + end + + # Returns a DB-supplemented json representation of a dashboard config file. + def get_dashboard + dashboard = Rails.cache.fetch(cache_key) { system_dashboard } + + process_dashboard(dashboard) + end + + private + + # Returns the base metrics shipped with every GitLab service. + def system_dashboard + YAML.load_file(SYSTEM_DASHBOARD_PATH) + end + + def cache_key + "metrics_dashboard_#{SYSTEM_DASHBOARD_NAME}" + end + + def process_dashboard(dashboard) + Processor.new(dashboard, @project).process + end + end + end +end diff --git a/lib/gitlab/metrics_dashboard/sorter.rb b/lib/gitlab/metrics_dashboard/sorter.rb new file mode 100644 index 00000000000..ba30c1e4656 --- /dev/null +++ b/lib/gitlab/metrics_dashboard/sorter.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module Gitlab + module MetricsDashboard + class Sorter + class << self + def transform!(dashboard, _project) + sort_groups!(dashboard) + sort_panels!(dashboard) + end + + # Sorts the groups in the dashboard by the :priority key + def sort_groups!(dashboard) + dashboard[:panel_groups] = dashboard[:panel_groups].sort_by { |group| group[:priority] } + end + + # Sorts the panels in the dashboard by the :weight key + def sort_panels!(dashboard) + dashboard[:panel_groups].each do |group| + group[:panels] = group[:panels].sort_by { |panel| panel[:weight] } + end + end + end + end + end +end diff --git a/spec/services/metrics_dashboard_processing_service_spec.rb b/spec/lib/gitlab/metrics_dashboard/processor_spec.rb index 917ae582afe..de1702d3314 100644 --- a/spec/services/metrics_dashboard_processing_service_spec.rb +++ b/spec/lib/gitlab/metrics_dashboard/processor_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe MetricsDashboardProcessingService do +describe Gitlab::MetricsDashboard::Processor do let(:project) { build(:project) } let(:dashboard_yml) { YAML.load_file('spec/fixtures/services/metrics_dashboard_processing_service.yml') } @@ -40,7 +40,7 @@ describe MetricsDashboardProcessingService do end it 'orders groups by priority and panels by weight' do - expected_metrics_order = %w('metric_b metric_a2 metric_a1') + expected_metrics_order = %w(metric_b metric_a2 metric_a1) actual_metrics_order = all_metrics.map { |m| m[:id] } expect(actual_metrics_order).to eq expected_metrics_order diff --git a/spec/services/metrics_dashboard_service_spec.rb b/spec/lib/gitlab/metrics_dashboard/service_spec.rb index db59ec3a3a4..e4b7b35763a 100644 --- a/spec/services/metrics_dashboard_service_spec.rb +++ b/spec/lib/gitlab/metrics_dashboard/service_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe MetricsDashboardService, :use_clean_rails_memory_store_caching do +describe Gitlab::MetricsDashboard::Service, :use_clean_rails_memory_store_caching do let(:project) { build(:project) } describe 'get_dashboard' do |