Add unit tests and fix broken endpoint
This commit is contained in:
parent
18183f404e
commit
3d302879f4
6 changed files with 186 additions and 20 deletions
|
@ -158,11 +158,11 @@ class Projects::EnvironmentsController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def metrics_dashboard
|
||||
access_denied! unless Feature.enabled?(:environment_metrics_use_prometheus_endpoint, project)
|
||||
render_403 and return unless Feature.enabled?(:environment_metrics_use_prometheus_endpoint, project)
|
||||
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
dashboard = MetricsDashboardService.new.get_dashboard
|
||||
dashboard = MetricsDashboardService.new(@project).get_dashboard
|
||||
|
||||
render json: dashboard, status: :ok
|
||||
end
|
||||
|
|
|
@ -9,40 +9,68 @@ class MetricsDashboardProcessingService
|
|||
end
|
||||
|
||||
def process
|
||||
insert_persisted_metrics!
|
||||
insert_metric_ids!
|
||||
sort_groups!
|
||||
sort_panels!
|
||||
insert_project_metrics!
|
||||
@dashboard.to_json
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Inserts project-specific metrics into the dashboard config.
|
||||
# If there are no project-specific metrics, this will have no effect.
|
||||
def insert_persisted_metrics!
|
||||
@project.prometheus_metrics.each do |persisted_metric|
|
||||
group = find_or_create_group(@dashboard[:panel_groups], persisted_metric)
|
||||
panel = find_or_create_panel(group[:panels], persisted_metric)
|
||||
find_or_create_metric(panel[:metrics], persisted_metric)
|
||||
# ------- Processing Steps -----------
|
||||
|
||||
# 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 insert_metric_ids!
|
||||
for_metrics do |metric|
|
||||
metric_record = common_metrics.find { |m| m.identifier == metric[:id] }
|
||||
metric[:metric_id] = metric_record.id if metric_record
|
||||
end
|
||||
end
|
||||
|
||||
# For each metric in the dashboard config, attempts to find a corresponding
|
||||
# persisted record. If found, includes the record id in the config.
|
||||
def insert_metric_ids!
|
||||
@dashboard[:panel_groups].each do |group|
|
||||
group[:panels].each do |panel|
|
||||
panel[:metrics].each do |metric|
|
||||
metric_record = common_metrics.find {|m| m.identifier == metric[:id] }
|
||||
metric[:metric_id] = metric_record.id if metric_record
|
||||
end
|
||||
end
|
||||
# Inserts project-specific metrics into the dashboard config.
|
||||
# If there are no project-specific metrics, this will have no effect.
|
||||
def insert_project_metrics!
|
||||
project_metrics.each do |project_metric|
|
||||
group = find_or_create_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
|
||||
|
||||
# Sorts the groups in the dashboard by the :priority key
|
||||
def sort_groups!
|
||||
@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[:panel_groups].each do |group|
|
||||
group[:panels] = group[:panels].sort_by { |panel| panel[:weight] }
|
||||
end
|
||||
end
|
||||
|
||||
# ------- Processing Helpers -----------
|
||||
|
||||
def project_metrics
|
||||
@project.prometheus_metrics
|
||||
end
|
||||
|
||||
def common_metrics
|
||||
@common_metrics ||= ::PrometheusMetric.common
|
||||
end
|
||||
|
||||
def for_metrics
|
||||
@dashboard[:panel_groups].each do |panel_group|
|
||||
panel_group[:panels].each do |panel|
|
||||
panel[:metrics].each do |metric|
|
||||
yield metric
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def find_or_create_group(panel_groups, metric)
|
||||
target_group = panel_groups.find { |group| group[:group] == metric.group_title }
|
||||
|
||||
|
|
|
@ -461,6 +461,30 @@ describe Projects::EnvironmentsController do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'metrics_dashboard' do
|
||||
context 'when prometheus endpoint is disabled' do
|
||||
before do
|
||||
stub_feature_flags(environment_metrics_use_prometheus_endpoint: false)
|
||||
end
|
||||
|
||||
it 'responds with status code 403' do
|
||||
get :metrics_dashboard, params: environment_params(format: :json)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:forbidden)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when prometheus endpoint is enabled' do
|
||||
it 'returns a json representation of the environment dashboard' do
|
||||
get :metrics_dashboard, params: environment_params(format: :json)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(json_response).to include('dashboard', 'order', 'panel_groups')
|
||||
expect(json_response['panel_groups']).to all( include('group', 'priority', 'panels') )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #search' do
|
||||
before do
|
||||
create(:environment, name: 'staging', project: project)
|
||||
|
|
36
spec/fixtures/services/metrics_dashboard_processing_service.yml
vendored
Normal file
36
spec/fixtures/services/metrics_dashboard_processing_service.yml
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
dashboard: 'Test Dashboard'
|
||||
order: 1
|
||||
panel_groups:
|
||||
- group: Group A
|
||||
priority: 10
|
||||
panels:
|
||||
- title: "Super Chart A1"
|
||||
type: "area-chart"
|
||||
y_label: "y_label"
|
||||
weight: 2
|
||||
metrics:
|
||||
- id: metric_a1
|
||||
query_range: 'query'
|
||||
unit: unit
|
||||
label: Legend Label
|
||||
- title: "Super Chart A2"
|
||||
type: "area-chart"
|
||||
y_label: "y_label"
|
||||
weight: 1
|
||||
metrics:
|
||||
- id: metric_a2
|
||||
query_range: 'query'
|
||||
label: Legend Label
|
||||
unit: unit
|
||||
- group: Group B
|
||||
priority: 1
|
||||
panels:
|
||||
- title: "Super Chart B"
|
||||
type: "area-chart"
|
||||
y_label: "y_label"
|
||||
weight: 1
|
||||
metrics:
|
||||
- id: metric_b
|
||||
query_range: 'query'
|
||||
unit: unit
|
||||
label: Legend Label
|
56
spec/services/metrics_dashboard_processing_service_spec.rb
Normal file
56
spec/services/metrics_dashboard_processing_service_spec.rb
Normal file
|
@ -0,0 +1,56 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe MetricsDashboardProcessingService do
|
||||
let(:project) { build(:project) }
|
||||
let(:dashboard_yml) { YAML.load_file('spec/fixtures/services/metrics_dashboard_processing_service.yml') }
|
||||
|
||||
describe 'process' do
|
||||
let(:dashboard) { JSON.parse(described_class.new(dashboard_yml, project).process, symbolize_names: true) }
|
||||
|
||||
context 'when dashboard config corresponds to common metrics' do
|
||||
let!(:common_metric) { create(:prometheus_metric, :common, identifier: 'metric_a1') }
|
||||
|
||||
it 'inserts metric ids into the config' do
|
||||
target_metric = all_metrics.find { |metric| metric[:id] == 'metric_a1' }
|
||||
|
||||
expect(target_metric).to include(:metric_id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the project has associated metrics' do
|
||||
let!(:project_metric) { create(:prometheus_metric, project: project) }
|
||||
|
||||
it 'includes project-specific metrics' do
|
||||
|
||||
project_metric_details = {
|
||||
query_range: project_metric.query,
|
||||
unit: project_metric.unit,
|
||||
label: project_metric.legend,
|
||||
metric_id: project_metric.id,
|
||||
}
|
||||
|
||||
expect(all_metrics).to include project_metric_details
|
||||
end
|
||||
|
||||
it 'includes project metrics at the end of the config' do
|
||||
expected_metrics_order = ['metric_b', 'metric_a2', 'metric_a1', nil]
|
||||
actual_metrics_order = all_metrics.map { |m| m[:id] }
|
||||
|
||||
expect(actual_metrics_order).to eq expected_metrics_order
|
||||
end
|
||||
end
|
||||
|
||||
it 'orders groups by priority and panels by weight' do
|
||||
expected_metrics_order = ['metric_b', 'metric_a2', 'metric_a1']
|
||||
actual_metrics_order = all_metrics.map { |m| m[:id] }
|
||||
|
||||
expect(actual_metrics_order).to eq expected_metrics_order
|
||||
end
|
||||
end
|
||||
|
||||
def all_metrics
|
||||
dashboard[:panel_groups].map do |group|
|
||||
group[:panels].map { |panel| panel[:metrics] }
|
||||
end.flatten
|
||||
end
|
||||
end
|
22
spec/services/metrics_dashboard_service_spec.rb
Normal file
22
spec/services/metrics_dashboard_service_spec.rb
Normal file
|
@ -0,0 +1,22 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe MetricsDashboardService, :use_clean_rails_memory_store_caching do
|
||||
let(:project) { build(:project) }
|
||||
|
||||
describe 'get_dashboard' do
|
||||
it 'returns a json representation of the environment dashboard' do
|
||||
dashboard = described_class.new(project).get_dashboard
|
||||
json = JSON.parse(dashboard, symbolize_names: true)
|
||||
|
||||
expect(json).to include(:dashboard, :order, :panel_groups)
|
||||
expect(json[:panel_groups]).to all( include(:group, :priority, :panels) )
|
||||
end
|
||||
|
||||
it 'caches the dashboard for subsequent calls' do
|
||||
expect(YAML).to receive(:load_file).once.and_call_original
|
||||
|
||||
described_class.new(project).get_dashboard
|
||||
described_class.new(project).get_dashboard
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue