# 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) [ embedded?(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) Enums::PrometheusMetric .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? || ::Metrics::Dashboard::SystemDashboardService.matching_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 metrics.empty? { 'panel_groups' => [{ 'panels' => panels }] } end private # Generated dashboard panels for each metric which # matches the provided input. # # As the panel is generated # on the fly, we're using default values for info # not represented in the DB. # # @return [Array] def panels [{ type: DEFAULT_PANEL_TYPE, title: title, y_label: y_label, metrics: metrics.map(&:to_metric_hash) }] 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] def metrics strong_memoize(:metrics) do PrometheusMetricsFinder.new( project: project, group: group_key, title: title, y_label: y_label ).execute end end # Returns a symbol representing the group that # the dashboard's group title belongs to. # It will be one of the keys found under # Enums::PrometheusMetric.custom_groups. # # @return [String] def group_key strong_memoize(:group_key) do Enums::PrometheusMetric .group_details .find { |_, details| details[:group_title] == group } .first .to_s end end end end end