Commit bdecc719 authored by Thong Kuah's avatar Thong Kuah

Merge branch 'reorganize-metrics-dashboard' into 'master'

Reorganize metrics dashboard

See merge request gitlab-org/gitlab-ce!31006
parents 95838fe4 dfe13131
# frozen_string_literal: true
# Searches a projects repository for a metrics dashboard and formats the output.
# Expects any custom dashboards will be located in `.gitlab/dashboards`
module Metrics
module Dashboard
class BaseService < ::BaseService
PROCESSING_ERROR = Gitlab::Metrics::Dashboard::Stages::BaseStage::DashboardProcessingError
NOT_FOUND_ERROR = Gitlab::Template::Finders::RepoTemplateFinder::FileNotFoundError
def get_dashboard
return error('Insufficient permissions.', :unauthorized) unless allowed?
success(dashboard: process_dashboard)
rescue NOT_FOUND_ERROR
error("#{dashboard_path} could not be found.", :not_found)
rescue PROCESSING_ERROR => e
error(e.message, :unprocessable_entity)
end
# Summary of all known dashboards for the service.
# @return [Array<Hash>] ex) [{ path: String, default: Boolean }]
def self.all_dashboard_paths(_project)
raise NotImplementedError
end
# Returns an un-processed dashboard from the cache.
def raw_dashboard
Gitlab::Metrics::Dashboard::Cache.fetch(cache_key) { get_raw_dashboard }
end
private
# Determines whether users should be able to view
# dashboards at all.
def allowed?
Ability.allowed?(current_user, :read_environment, project)
end
# Returns a new dashboard Hash, supplemented with DB info
def process_dashboard
Gitlab::Metrics::Dashboard::Processor
.new(project, params[:environment], raw_dashboard)
.process(insert_project_metrics: insert_project_metrics?)
end
# @return [String] Relative filepath of the dashboard yml
def dashboard_path
params[:dashboard_path]
end
# @return [Hash] an unmodified dashboard
def get_raw_dashboard
raise NotImplementedError
end
# @return [String]
def cache_key
raise NotImplementedError
end
# Determines whether custom metrics should be included
# in the processed output.
# @return [Boolean]
def insert_project_metrics?
false
end
end
end
end
# frozen_string_literal: true
# Responsible for returning a filtered system dashboard
# containing only the default embedded metrics. In future,
# this class may be updated to support filtering to
# alternate metrics/panels.
#
# Why isn't this filtering in a processing stage? By filtering
# here, we ensure the dynamically-determined dashboard is cached.
#
# Use Gitlab::Metrics::Dashboard::Finder to retrive dashboards.
module Metrics
module Dashboard
class DefaultEmbedService < ::Metrics::Dashboard::BaseService
# For the default filtering for embedded metrics,
# uses the 'id' key in dashboard-yml definition for
# identification.
DEFAULT_EMBEDDED_METRICS_IDENTIFIERS = %w(
system_metrics_kubernetes_container_memory_total
system_metrics_kubernetes_container_cores_total
).freeze
# Returns a new dashboard with only the matching
# metrics from the system dashboard, stripped of groups.
# @return [Hash]
def raw_dashboard
panels = panel_groups.each_with_object([]) do |group, panels|
matched_panels = group['panels'].select { |panel| matching_panel?(panel) }
panels.concat(matched_panels)
end
{ 'panel_groups' => [{ 'panels' => panels }] }
end
def cache_key
"dynamic_metrics_dashboard_#{metric_identifiers.join('_')}"
end
private
# Returns an array of the panels groups on the
# system dashboard
def panel_groups
::Metrics::Dashboard::SystemDashboardService
.new(project, nil)
.raw_dashboard['panel_groups']
end
# Identifies a panel as "matching" if any metric ids in
# the panel is in the list of identifiers to collect.
def matching_panel?(panel)
panel['metrics'].any? do |metric|
metric_identifiers.include?(metric['id'])
end
end
def metric_identifiers
DEFAULT_EMBEDDED_METRICS_IDENTIFIERS
end
end
end
end
# frozen_string_literal: true
# Searches a projects repository for a metrics dashboard and formats the output.
# Expects any custom dashboards will be located in `.gitlab/dashboards`
# Use Gitlab::Metrics::Dashboard::Finder to retrive dashboards.
module Metrics
module Dashboard
class ProjectDashboardService < ::Metrics::Dashboard::BaseService
DASHBOARD_ROOT = ".gitlab/dashboards"
class << self
def all_dashboard_paths(project)
file_finder(project)
.list_files_for(DASHBOARD_ROOT)
.map do |filepath|
{
path: filepath,
display_name: name_for_path(filepath),
default: false
}
end
end
def file_finder(project)
Gitlab::Template::Finders::RepoTemplateFinder.new(project, DASHBOARD_ROOT, '.yml')
end
# Grabs the filepath after the base directory.
def name_for_path(filepath)
filepath.delete_prefix("#{DASHBOARD_ROOT}/")
end
end
private
# Searches the project repo for a custom-defined dashboard.
def get_raw_dashboard
yml = self.class.file_finder(project).read(dashboard_path)
YAML.safe_load(yml)
end
def cache_key
"project_#{project.id}_metrics_dashboard_#{dashboard_path}"
end
end
end
end
# frozen_string_literal: true
# Fetches the system metrics dashboard and formats the output.
# Use Gitlab::Metrics::Dashboard::Finder to retrive dashboards.
module Metrics
module Dashboard
class SystemDashboardService < ::Metrics::Dashboard::BaseService
SYSTEM_DASHBOARD_PATH = 'config/prometheus/common_metrics.yml'
SYSTEM_DASHBOARD_NAME = 'Default'
class << self
def all_dashboard_paths(_project)
[{
path: SYSTEM_DASHBOARD_PATH,
display_name: SYSTEM_DASHBOARD_NAME,
default: true
}]
end
def system_dashboard?(filepath)
filepath == SYSTEM_DASHBOARD_PATH
end
end
private
def dashboard_path
SYSTEM_DASHBOARD_PATH
end
# Returns the base metrics shipped with every GitLab service.
def get_raw_dashboard
yml = File.read(Rails.root.join(dashboard_path))
YAML.safe_load(yml)
end
def cache_key
"metrics_dashboard_#{dashboard_path}"
end
def insert_project_metrics?
true
end
end
end
end
# frozen_string_literal: true
# Searches a projects repository for a metrics dashboard and formats the output.
# Expects any custom dashboards will be located in `.gitlab/dashboards`
module Gitlab
module Metrics
module Dashboard
class BaseService < ::BaseService
PROCESSING_ERROR = Gitlab::Metrics::Dashboard::Stages::BaseStage::DashboardProcessingError
NOT_FOUND_ERROR = Gitlab::Template::Finders::RepoTemplateFinder::FileNotFoundError
def get_dashboard
return error('Insufficient permissions.', :unauthorized) unless allowed?
success(dashboard: process_dashboard)
rescue NOT_FOUND_ERROR
error("#{dashboard_path} could not be found.", :not_found)
rescue PROCESSING_ERROR => e
error(e.message, :unprocessable_entity)
end
# Summary of all known dashboards for the service.
# @return [Array<Hash>] ex) [{ path: String, default: Boolean }]
def self.all_dashboard_paths(_project)
raise NotImplementedError
end
# Returns an un-processed dashboard from the cache.
def raw_dashboard
Gitlab::Metrics::Dashboard::Cache.fetch(cache_key) { get_raw_dashboard }
end
private
# Determines whether users should be able to view
# dashboards at all.
def allowed?
Ability.allowed?(current_user, :read_environment, project)
end
# Returns a new dashboard Hash, supplemented with DB info
def process_dashboard
Gitlab::Metrics::Dashboard::Processor
.new(project, params[:environment], raw_dashboard)
.process(insert_project_metrics: insert_project_metrics?)
end
# @return [String] Relative filepath of the dashboard yml
def dashboard_path
params[:dashboard_path]
end
# @return [Hash] an unmodified dashboard
def get_raw_dashboard
raise NotImplementedError
end
# @return [String]
def cache_key
raise NotImplementedError
end
# Determines whether custom metrics should be included
# in the processed output.
# @return [Boolean]
def insert_project_metrics?
false
end
end
end
end
end
# frozen_string_literal: true
# Responsible for returning a filtered system dashboard
# containing only the default embedded metrics. In future,
# this class may be updated to support filtering to
# alternate metrics/panels.
#
# Why isn't this filtering in a processing stage? By filtering
# here, we ensure the dynamically-determined dashboard is cached.
#
# Use Gitlab::Metrics::Dashboard::Finder to retrive dashboards.
module Gitlab
module Metrics
module Dashboard
class DynamicDashboardService < Gitlab::Metrics::Dashboard::BaseService
# For the default filtering for embedded metrics,
# uses the 'id' key in dashboard-yml definition for
# identification.
DEFAULT_EMBEDDED_METRICS_IDENTIFIERS = %w(
system_metrics_kubernetes_container_memory_total
system_metrics_kubernetes_container_cores_total
).freeze
# Returns a new dashboard with only the matching
# metrics from the system dashboard, stripped of groups.
# @return [Hash]
def raw_dashboard
panels = panel_groups.each_with_object([]) do |group, panels|
matched_panels = group['panels'].select { |panel| matching_panel?(panel) }
panels.concat(matched_panels)
end
{ 'panel_groups' => [{ 'panels' => panels }] }
end
def cache_key
"dynamic_metrics_dashboard_#{metric_identifiers.join('_')}"
end
private
# Returns an array of the panels groups on the
# system dashboard
def panel_groups
Gitlab::Metrics::Dashboard::SystemDashboardService
.new(project, nil)
.raw_dashboard['panel_groups']
end
# Identifies a panel as "matching" if any metric ids in
# the panel is in the list of identifiers to collect.
def matching_panel?(panel)
panel['metrics'].any? do |metric|
metric_identifiers.include?(metric['id'])
end
end
def metric_identifiers
DEFAULT_EMBEDDED_METRICS_IDENTIFIERS
end
end
end
end
end
...@@ -47,22 +47,22 @@ module Gitlab ...@@ -47,22 +47,22 @@ module Gitlab
private private
def service_for_path(dashboard_path, embedded:) def service_for_path(dashboard_path, embedded:)
return dynamic_service if embedded return embed_service if embedded
return system_service if system_dashboard?(dashboard_path) return system_service if system_dashboard?(dashboard_path)
project_service project_service
end end
def system_service def system_service
Gitlab::Metrics::Dashboard::SystemDashboardService ::Metrics::Dashboard::SystemDashboardService
end end
def project_service def project_service
Gitlab::Metrics::Dashboard::ProjectDashboardService ::Metrics::Dashboard::ProjectDashboardService
end end
def dynamic_service def embed_service
Gitlab::Metrics::Dashboard::DynamicDashboardService ::Metrics::Dashboard::DefaultEmbedService
end end
def system_dashboard?(filepath) def system_dashboard?(filepath)
......
# frozen_string_literal: true
# Searches a projects repository for a metrics dashboard and formats the output.
# Expects any custom dashboards will be located in `.gitlab/dashboards`
# Use Gitlab::Metrics::Dashboard::Finder to retrive dashboards.
module Gitlab
module Metrics
module Dashboard
class ProjectDashboardService < Gitlab::Metrics::Dashboard::BaseService
DASHBOARD_ROOT = ".gitlab/dashboards"
class << self
def all_dashboard_paths(project)
file_finder(project)
.list_files_for(DASHBOARD_ROOT)
.map do |filepath|
{
path: filepath,
display_name: name_for_path(filepath),
default: false
}
end
end
def file_finder(project)
Gitlab::Template::Finders::RepoTemplateFinder.new(project, DASHBOARD_ROOT, '.yml')
end
# Grabs the filepath after the base directory.
def name_for_path(filepath)
filepath.delete_prefix("#{DASHBOARD_ROOT}/")
end
end
private
# Searches the project repo for a custom-defined dashboard.
def get_raw_dashboard
yml = self.class.file_finder(project).read(dashboard_path)
YAML.safe_load(yml)
end
def cache_key
"project_#{project.id}_metrics_dashboard_#{dashboard_path}"
end
end
end
end
end
# frozen_string_literal: true
# Fetches the system metrics dashboard and formats the output.
# Use Gitlab::Metrics::Dashboard::Finder to retrive dashboards.
module Gitlab
module Metrics
module Dashboard
class SystemDashboardService < Gitlab::Metrics::Dashboard::BaseService
SYSTEM_DASHBOARD_PATH = 'config/prometheus/common_metrics.yml'
SYSTEM_DASHBOARD_NAME = 'Default'
class << self
def all_dashboard_paths(_project)
[{
path: SYSTEM_DASHBOARD_PATH,
display_name: SYSTEM_DASHBOARD_NAME,
default: true
}]
end
def system_dashboard?(filepath)
filepath == SYSTEM_DASHBOARD_PATH
end
end
private
def dashboard_path
SYSTEM_DASHBOARD_PATH
end
# Returns the base metrics shipped with every GitLab service.
def get_raw_dashboard
yml = File.read(Rails.root.join(dashboard_path))
YAML.safe_load(yml)
end
def cache_key
"metrics_dashboard_#{dashboard_path}"
end
def insert_project_metrics?
true
end
end
end
end
end
...@@ -551,7 +551,7 @@ describe Projects::EnvironmentsController do ...@@ -551,7 +551,7 @@ describe Projects::EnvironmentsController do
end end
context 'when the specified dashboard is the default dashboard' do context 'when the specified dashboard is the default dashboard' do
let(:dashboard_path) { Gitlab::Metrics::Dashboard::SystemDashboardService::SYSTEM_DASHBOARD_PATH } let(:dashboard_path) { ::Metrics::Dashboard::SystemDashboardService::SYSTEM_DASHBOARD_PATH }
it_behaves_like 'the default dashboard' it_behaves_like 'the default dashboard'
end end
......
...@@ -8,7 +8,7 @@ describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store_cachi ...@@ -8,7 +8,7 @@ describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store_cachi
set(:project) { build(:project) } set(:project) { build(:project) }
set(:user) { create(:user) } set(:user) { create(:user) }
set(:environment) { create(:environment, project: project) } set(:environment) { create(:environment, project: project) }
let(:system_dashboard_path) { Gitlab::Metrics::Dashboard::SystemDashboardService::SYSTEM_DASHBOARD_PATH} let(:system_dashboard_path) { ::Metrics::Dashboard::SystemDashboardService::SYSTEM_DASHBOARD_PATH}
before do before do
project.add_maintainer(user) project.add_maintainer(user)
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
describe Gitlab::Metrics::Dashboard::DynamicDashboardService, :use_clean_rails_memory_store_caching do describe Metrics::Dashboard::DefaultEmbedService, :use_clean_rails_memory_store_caching do
include MetricsDashboardHelpers include MetricsDashboardHelpers
set(:project) { build(:project) } set(:project) { build(:project) }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
describe Gitlab::Metrics::Dashboard::ProjectDashboardService, :use_clean_rails_memory_store_caching do describe Metrics::Dashboard::ProjectDashboardService, :use_clean_rails_memory_store_caching do
include MetricsDashboardHelpers include MetricsDashboardHelpers
set(:user) { create(:user) } set(:user) { create(:user) }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
describe Gitlab::Metrics::Dashboard::SystemDashboardService, :use_clean_rails_memory_store_caching do describe Metrics::Dashboard::SystemDashboardService, :use_clean_rails_memory_store_caching do
include MetricsDashboardHelpers include MetricsDashboardHelpers
set(:user) { create(:user) } set(:user) { create(:user) }
......
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