debian-mirror-gitlab/app/services/metrics/dashboard/custom_metric_embed_service.rb
2019-10-12 21:52:04 +05:30

123 lines
3.8 KiB
Ruby

# frozen_string_literal: true
# Responsible for returning a dashboard containing specified
# custom metrics. Creates panels based on the matching metrics
# stored in the database.
#
# Use Gitlab::Metrics::Dashboard::Finder to retrive dashboards.
module Metrics
module Dashboard
class CustomMetricEmbedService < ::Metrics::Dashboard::BaseEmbedService
extend ::Gitlab::Utils::Override
include Gitlab::Utils::StrongMemoize
include Gitlab::Metrics::Dashboard::Defaults
class << self
# Determines whether the provided params are sufficient
# to uniquely identify a panel composed of user-defined
# custom metrics from the DB.
def valid_params?(params)
[
params[:embedded],
valid_dashboard?(params[:dashboard_path]),
valid_group_title?(params[:group]),
params[:title].present?,
params.has_key?(:y_label)
].all?
end
private
# A group title is valid if it is one of the limited
# options the user can select in the UI.
def valid_group_title?(group)
PrometheusMetricEnums
.custom_group_details
.map { |_, details| details[:group_title] }
.include?(group)
end
# All custom metrics are displayed on the system dashboard.
# Nil is acceptable as we'll default to the system dashboard.
def valid_dashboard?(dashboard)
dashboard.nil? || SystemDashboardService.system_dashboard?(dashboard)
end
end
# Returns a new dashboard with only the matching
# metrics from the system dashboard, stripped of
# group info.
#
# Note: This overrides the method #raw_dashboard,
# which means the result will not be cached. This
# is because we are inserting DB info into the
# dashboard before post-processing. This ensures
# we aren't acting on deleted or out-of-date metrics.
#
# @return [Hash]
override :raw_dashboard
def raw_dashboard
panels_not_found!(identifiers) if panels.empty?
{ 'panel_groups' => [{ 'panels' => panels }] }
end
private
# Generated dashboard panels for each metric which
# matches the provided input.
# @return [Array<Hash>]
def panels
strong_memoize(:panels) do
metrics.map { |metric| panel_for_metric(metric) }
end
end
# Metrics which match the provided inputs.
# There may be multiple metrics, but they should be
# displayed in a single panel/chart.
# @return [ActiveRecord::AssociationRelation<PromtheusMetric>]
# rubocop: disable CodeReuse/ActiveRecord
def metrics
project.prometheus_metrics.where(
group: group_key,
title: title,
y_label: y_label
)
end
# rubocop: enable CodeReuse/ActiveRecord
# Returns a symbol representing the group that
# the dashboard's group title belongs to.
# It will be one of the keys found under
# PrometheusMetricEnums.custom_groups.
#
# @return [String]
def group_key
strong_memoize(:group_key) do
PrometheusMetricEnums
.group_details
.find { |_, details| details[:group_title] == group }
.first
.to_s
end
end
# Returns a representation of a PromtheusMetric
# as a dashboard panel. As the panel is generated
# on the fly, we're using default values for info
# not represented in the DB.
#
# @return [Hash]
def panel_for_metric(metric)
{
type: DEFAULT_PANEL_TYPE,
weight: DEFAULT_PANEL_WEIGHT,
title: metric.title,
y_label: metric.y_label,
metrics: [metric.to_metric_hash]
}
end
end
end
end