Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-11-15 15:06:12 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2019-11-15 15:06:12 +0300
commit3fc9a8e6957ddf75576dc63069c4c0249514499f (patch)
tree003e30463853843d6fb736a9396c7eb53a3dfc9a /app/finders/prometheus_metrics_finder.rb
parente24153b0cb080b1b25076f8fd358b4273848f2e2 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/finders/prometheus_metrics_finder.rb')
-rw-r--r--app/finders/prometheus_metrics_finder.rb129
1 files changed, 129 insertions, 0 deletions
diff --git a/app/finders/prometheus_metrics_finder.rb b/app/finders/prometheus_metrics_finder.rb
new file mode 100644
index 00000000000..84a071abbd5
--- /dev/null
+++ b/app/finders/prometheus_metrics_finder.rb
@@ -0,0 +1,129 @@
+# frozen_string_literal: true
+
+class PrometheusMetricsFinder
+ ACCEPTED_PARAMS = [
+ :project,
+ :group,
+ :title,
+ :y_label,
+ :identifier,
+ :id,
+ :common,
+ :ordered
+ ].freeze
+
+ # Cautiously preferring a memoized class method over a constant
+ # so that the DB connection is accessed after the class is loaded.
+ def self.indexes
+ @indexes ||= PrometheusMetric
+ .connection
+ .indexes(:prometheus_metrics)
+ .map { |index| index.columns.map(&:to_sym) }
+ end
+
+ def initialize(params = {})
+ @params = params.slice(*ACCEPTED_PARAMS)
+ end
+
+ # @return [PrometheusMetric, PrometheusMetric::ActiveRecord_Relation]
+ def execute
+ validate_params!
+
+ metrics = by_project(::PrometheusMetric.all)
+ metrics = by_group(metrics)
+ metrics = by_title(metrics)
+ metrics = by_y_label(metrics)
+ metrics = by_common(metrics)
+ metrics = by_ordered(metrics)
+ metrics = by_identifier(metrics)
+ metrics = by_id(metrics)
+
+ metrics
+ end
+
+ private
+
+ attr_reader :params
+
+ def by_project(metrics)
+ return metrics unless params[:project]
+
+ metrics.for_project(params[:project])
+ end
+
+ def by_group(metrics)
+ return metrics unless params[:group]
+
+ metrics.for_group(params[:group])
+ end
+
+ def by_title(metrics)
+ return metrics unless params[:title]
+
+ metrics.for_title(params[:title])
+ end
+
+ def by_y_label(metrics)
+ return metrics unless params[:y_label]
+
+ metrics.for_y_label(params[:y_label])
+ end
+
+ def by_common(metrics)
+ return metrics unless params[:common]
+
+ metrics.common
+ end
+
+ def by_ordered(metrics)
+ return metrics unless params[:ordered]
+
+ metrics.ordered
+ end
+
+ def by_identifier(metrics)
+ return metrics unless params[:identifier]
+
+ metrics.for_identifier(params[:identifier])
+ end
+
+ def by_id(metrics)
+ return metrics unless params[:id]
+
+ metrics.id_in(params[:id])
+ end
+
+ def validate_params!
+ validate_params_present!
+ validate_id_params!
+ validate_indexes!
+ end
+
+ # Ensure all provided params are supported
+ def validate_params_present!
+ raise ArgumentError, "Please provide one or more of: #{ACCEPTED_PARAMS}" if params.blank?
+ end
+
+ # Protect against the caller "finding" the wrong metric
+ def validate_id_params!
+ raise ArgumentError, 'Only one of :identifier, :id is permitted' if params[:identifier] && params[:id]
+ raise ArgumentError, ':identifier must be scoped to a :project or :common' if params[:identifier] && !(params[:project] || params[:common])
+ end
+
+ # Protect against unaccounted-for, complex/slow queries.
+ # This is not a hard and fast rule, but is meant to encourage
+ # mindful inclusion of new queries.
+ def validate_indexes!
+ indexable_params = params.except(:ordered, :id, :project).keys
+ indexable_params << :project_id if params[:project]
+ indexable_params.sort!
+
+ raise ArgumentError, "An index should exist for params: #{indexable_params}" unless appropriate_index?(indexable_params)
+ end
+
+ def appropriate_index?(indexable_params)
+ return true if indexable_params.blank?
+
+ self.class.indexes.any? { |index| (index - indexable_params).empty? }
+ end
+end