summaryrefslogtreecommitdiff
path: root/lib/gitlab/usage/metrics/names_suggestions/generator.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/usage/metrics/names_suggestions/generator.rb')
-rw-r--r--lib/gitlab/usage/metrics/names_suggestions/generator.rb106
1 files changed, 106 insertions, 0 deletions
diff --git a/lib/gitlab/usage/metrics/names_suggestions/generator.rb b/lib/gitlab/usage/metrics/names_suggestions/generator.rb
new file mode 100644
index 00000000000..33f025770e0
--- /dev/null
+++ b/lib/gitlab/usage/metrics/names_suggestions/generator.rb
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module NamesSuggestions
+ class Generator < ::Gitlab::UsageData
+ FREE_TEXT_METRIC_NAME = "<please fill metric name>"
+
+ class << self
+ def generate(key_path)
+ uncached_data.deep_stringify_keys.dig(*key_path.split('.'))
+ end
+
+ private
+
+ def count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)
+ name_suggestion(column: column, relation: relation, prefix: 'count')
+ end
+
+ def distinct_count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)
+ name_suggestion(column: column, relation: relation, prefix: 'count_distinct', distinct: :distinct)
+ end
+
+ def redis_usage_counter
+ FREE_TEXT_METRIC_NAME
+ end
+
+ def alt_usage_data(*)
+ FREE_TEXT_METRIC_NAME
+ end
+
+ def redis_usage_data_totals(counter)
+ counter.fallback_totals.transform_values { |_| FREE_TEXT_METRIC_NAME}
+ end
+
+ def sum(relation, column, *rest)
+ name_suggestion(column: column, relation: relation, prefix: 'sum')
+ end
+
+ def estimate_batch_distinct_count(relation, column = nil, *rest)
+ name_suggestion(column: column, relation: relation, prefix: 'estimate_distinct_count')
+ end
+
+ def add(*args)
+ "add_#{args.join('_and_')}"
+ end
+
+ def name_suggestion(relation:, column: nil, prefix: nil, distinct: nil)
+ parts = [prefix]
+
+ if column
+ parts << parse_target(column)
+ parts << 'from'
+ end
+
+ source = parse_source(relation)
+ constraints = parse_constraints(relation: relation, column: column, distinct: distinct)
+
+ if constraints.include?(source)
+ parts << "<adjective describing: '#{constraints}'>"
+ end
+
+ parts << source
+ parts.compact.join('_')
+ end
+
+ def parse_constraints(relation:, column: nil, distinct: nil)
+ connection = relation.connection
+ ::Gitlab::Usage::Metrics::NamesSuggestions::RelationParsers::Constraints
+ .new(connection)
+ .accept(arel(relation: relation, column: column, distinct: distinct), collector(connection))
+ .value
+ end
+
+ def parse_target(column)
+ if column.is_a?(Arel::Attribute)
+ "#{column.relation.name}.#{column.name}"
+ else
+ column
+ end
+ end
+
+ def parse_source(relation)
+ relation.table_name
+ end
+
+ def collector(connection)
+ Arel::Collectors::SubstituteBinds.new(connection, Arel::Collectors::SQLString.new)
+ end
+
+ def arel(relation:, column: nil, distinct: nil)
+ column ||= relation.primary_key
+
+ if column.is_a?(Arel::Attribute)
+ relation.select(column.count(distinct)).arel
+ else
+ relation.select(relation.all.table[column].count(distinct)).arel
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end