summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsyasonik <syasonik@gitlab.com>2019-04-16 17:09:10 +0800
committersyasonik <syasonik@gitlab.com>2019-04-24 18:23:03 +0800
commit35c412327cd0a0897d4d81aa80c88782c98fdd89 (patch)
treef593de4da583df8bccb9a9e2153d33f9a6e7c288
parentd307f446d807b03ddc7d55705df5602c275e61fb (diff)
downloadgitlab-ce-35c412327cd0a0897d4d81aa80c88782c98fdd89.tar.gz
Refactor dashboard proccesing into stages
-rw-r--r--app/controllers/projects/environments_controller.rb2
-rw-r--r--app/services/metrics_dashboard_service.rb33
-rw-r--r--lib/gitlab/metrics_dashboard/common_metrics_inserter.rb32
-rw-r--r--lib/gitlab/metrics_dashboard/processor.rb20
-rw-r--r--lib/gitlab/metrics_dashboard/project_metrics_inserter.rb70
-rw-r--r--lib/gitlab/metrics_dashboard/service.rb37
-rw-r--r--lib/gitlab/metrics_dashboard/sorter.rb26
-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