Commit 54dd4403 authored by syasonik's avatar syasonik

Expose prometheus endpoint per metric in dashboard

Adds a new stage to dashboard processesing step for the
EnvironmentsController::metrics_dashboard endpoint.

Allows the front end to avoid generating the endpoint
unitutive string mutations.
parent b46b38ff
...@@ -7,12 +7,13 @@ module Gitlab ...@@ -7,12 +7,13 @@ module Gitlab
module Dashboard module Dashboard
class BaseService < ::BaseService class BaseService < ::BaseService
DASHBOARD_LAYOUT_ERROR = Gitlab::Metrics::Dashboard::Stages::BaseStage::DashboardLayoutError DASHBOARD_LAYOUT_ERROR = Gitlab::Metrics::Dashboard::Stages::BaseStage::DashboardLayoutError
MISSING_QUERY_ERROR = Gitlab::Metrics::Dashboard::Stages::EndpointInserter::MissingQueryError
def get_dashboard def get_dashboard
return error("#{dashboard_path} could not be found.", :not_found) unless path_available? return error("#{dashboard_path} could not be found.", :not_found) unless path_available?
success(dashboard: process_dashboard) success(dashboard: process_dashboard)
rescue DASHBOARD_LAYOUT_ERROR => e rescue DASHBOARD_LAYOUT_ERROR, MISSING_QUERY_ERROR => e
error(e.message, :unprocessable_entity) error(e.message, :unprocessable_entity)
end end
......
...@@ -11,11 +11,13 @@ module Gitlab ...@@ -11,11 +11,13 @@ module Gitlab
SYSTEM_SEQUENCE = [ SYSTEM_SEQUENCE = [
Stages::CommonMetricsInserter, Stages::CommonMetricsInserter,
Stages::ProjectMetricsInserter, Stages::ProjectMetricsInserter,
Stages::EndpointInserter,
Stages::Sorter Stages::Sorter
].freeze ].freeze
PROJECT_SEQUENCE = [ PROJECT_SEQUENCE = [
Stages::CommonMetricsInserter, Stages::CommonMetricsInserter,
Stages::EndpointInserter,
Stages::Sorter Stages::Sorter
].freeze ].freeze
......
# frozen_string_literal: true
module Gitlab
module Metrics
module Dashboard
module Stages
class EndpointInserter < BaseStage
MissingQueryError = Class.new(StandardError)
def transform!
for_metrics do |metric|
metric[:prometheus_endpoint_path] = endpoint_for_metric(metric)
end
end
private
def endpoint_for_metric(metric)
Gitlab::Routing.url_helpers.prometheus_api_namespace_project_environment_path(
project.namespace,
project,
environment,
proxy_path: query_type(metric),
query: query_for_metric(metric)
)
end
def query_type(metric)
metric[:query] ? :query : :query_range
end
def query_for_metric(metric)
query = metric[query_type(metric)]
raise MissingQueryError.new('Missing required metric key: one of :query or :query_range') unless query
query
end
end
end
end
end
end
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
"type": "object", "type": "object",
"required": [ "required": [
"unit", "unit",
"label" "label",
"prometheus_endpoint_path"
], ],
"oneOf": [ "oneOf": [
{ "required": ["query"] }, { "required": ["query"] },
...@@ -14,7 +15,8 @@ ...@@ -14,7 +15,8 @@
"query": { "type": "string" }, "query": { "type": "string" },
"unit": { "type": "string" }, "unit": { "type": "string" },
"label": { "type": "string" }, "label": { "type": "string" },
"track": { "type": "string" } "track": { "type": "string" },
"prometheus_endpoint_path": { "type": "string" }
}, },
"additionalProperties": false "additionalProperties": false
} }
...@@ -6,7 +6,7 @@ describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store_cachi ...@@ -6,7 +6,7 @@ describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store_cachi
include MetricsDashboardHelpers include MetricsDashboardHelpers
set(:project) { build(:project) } set(:project) { build(:project) }
set(:environment) { build(:environment, project: project) } set(:environment) { create(:environment, project: project) }
let(:system_dashboard_path) { Gitlab::Metrics::Dashboard::SystemDashboardService::SYSTEM_DASHBOARD_PATH} let(:system_dashboard_path) { Gitlab::Metrics::Dashboard::SystemDashboardService::SYSTEM_DASHBOARD_PATH}
describe '.find' do describe '.find' do
...@@ -27,6 +27,17 @@ describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store_cachi ...@@ -27,6 +27,17 @@ describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store_cachi
it_behaves_like 'misconfigured dashboard service response', :unprocessable_entity it_behaves_like 'misconfigured dashboard service response', :unprocessable_entity
end end
context 'when the dashboard contains a metric without a query' do
let(:project) do
project_with_dashboard(
dashboard_path,
{ 'panel_groups' => [{ 'panels' => [{ 'metrics' => [{ 'id' => 'mock' }] }] }] }.to_yaml
)
end
it_behaves_like 'misconfigured dashboard service response', :unprocessable_entity
end
context 'when the system dashboard is specified' do context 'when the system dashboard is specified' do
let(:dashboard_path) { system_dashboard_path } let(:dashboard_path) { system_dashboard_path }
......
...@@ -4,13 +4,19 @@ require 'spec_helper' ...@@ -4,13 +4,19 @@ require 'spec_helper'
describe Gitlab::Metrics::Dashboard::Processor do describe Gitlab::Metrics::Dashboard::Processor do
let(:project) { build(:project) } let(:project) { build(:project) }
let(:environment) { build(:environment, project: project) } let(:environment) { create(:environment, project: project) }
let(:dashboard_yml) { YAML.load_file('spec/fixtures/lib/gitlab/metrics/dashboard/sample_dashboard.yml') } let(:dashboard_yml) { YAML.load_file('spec/fixtures/lib/gitlab/metrics/dashboard/sample_dashboard.yml') }
describe 'process' do describe 'process' do
let(:process_params) { [project, environment, dashboard_yml] } let(:process_params) { [project, environment, dashboard_yml] }
let(:dashboard) { described_class.new(*process_params).process(insert_project_metrics: true) } let(:dashboard) { described_class.new(*process_params).process(insert_project_metrics: true) }
it 'includes a path for the prometheus endpoint with each metric' do
all_metrics.each do |metric|
expect(metric).to include(prometheus_endpoint_path: prometheus_path(metric[:query_range]))
end
end
context 'when dashboard config corresponds to common metrics' do context 'when dashboard config corresponds to common metrics' do
let!(:common_metric) { create(:prometheus_metric, :common, identifier: 'metric_a1') } let!(:common_metric) { create(:prometheus_metric, :common, identifier: 'metric_a1') }
...@@ -99,7 +105,15 @@ describe Gitlab::Metrics::Dashboard::Processor do ...@@ -99,7 +105,15 @@ describe Gitlab::Metrics::Dashboard::Processor do
query_range: metric.query, query_range: metric.query,
unit: metric.unit, unit: metric.unit,
label: metric.legend, label: metric.legend,
metric_id: metric.id metric_id: metric.id,
prometheus_endpoint_path: prometheus_path(metric.query)
} }
end end
def prometheus_path(query)
"/#{project.namespace.path}" \
"/#{project.name}/environments/" \
"#{environment.id}/prometheus/api/v1" \
"/query_range?query=#{CGI::escape query}"
end
end end
...@@ -7,7 +7,7 @@ describe Gitlab::Metrics::Dashboard::ProjectDashboardService, :use_clean_rails_m ...@@ -7,7 +7,7 @@ describe Gitlab::Metrics::Dashboard::ProjectDashboardService, :use_clean_rails_m
set(:user) { build(:user) } set(:user) { build(:user) }
set(:project) { build(:project) } set(:project) { build(:project) }
set(:environment) { build(:environment, project: project) } set(:environment) { create(:environment, project: project) }
before do before do
project.add_maintainer(user) project.add_maintainer(user)
......
...@@ -6,7 +6,7 @@ describe Gitlab::Metrics::Dashboard::SystemDashboardService, :use_clean_rails_me ...@@ -6,7 +6,7 @@ describe Gitlab::Metrics::Dashboard::SystemDashboardService, :use_clean_rails_me
include MetricsDashboardHelpers include MetricsDashboardHelpers
set(:project) { build(:project) } set(:project) { build(:project) }
set(:environment) { build(:environment, project: project) } set(:environment) { create(:environment, project: project) }
describe 'get_dashboard' do describe 'get_dashboard' do
let(:dashboard_path) { described_class::SYSTEM_DASHBOARD_PATH } let(:dashboard_path) { described_class::SYSTEM_DASHBOARD_PATH }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment