summaryrefslogtreecommitdiff
path: root/lib/gitlab/usage/metrics
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/usage/metrics')
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/count_imported_projects_total_metric.rb40
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/count_issues_metric.rb2
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/database_metric.rb2
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/issues_created_from_alerts_metric.rb30
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/issues_with_alert_management_alerts_metric.rb24
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/issues_with_prometheus_alert_events.rb24
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/issues_with_self_managed_prometheus_alert_events.rb24
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/jira_imports_total_imported_issues_count_metric.rb15
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/numbers_metric.rb60
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/unique_active_users_metric.rb29
-rw-r--r--lib/gitlab/usage/metrics/name_suggestion.rb2
-rw-r--r--lib/gitlab/usage/metrics/query.rb36
12 files changed, 280 insertions, 8 deletions
diff --git a/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_total_metric.rb b/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_total_metric.rb
new file mode 100644
index 00000000000..109d2245635
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_total_metric.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class CountImportedProjectsTotalMetric < DatabaseMetric
+ # Relation and operation are not used, but are included to satisfy expectations
+ # of other metric generation logic.
+ relation { Project }
+ operation :count
+
+ IMPORT_TYPES = %w(gitlab_project gitlab github bitbucket bitbucket_server gitea git manifest
+ gitlab_migration).freeze
+
+ def value
+ count(project_relation) + count(entity_relation)
+ end
+
+ def to_sql
+ project_relation_sql = Gitlab::Usage::Metrics::Query.for(:count, project_relation)
+ entity_relation_sql = Gitlab::Usage::Metrics::Query.for(:count, entity_relation)
+
+ "SELECT (#{project_relation_sql}) + (#{entity_relation_sql})"
+ end
+
+ private
+
+ def project_relation
+ Project.imported_from(IMPORT_TYPES).where(time_constraints)
+ end
+
+ def entity_relation
+ BulkImports::Entity.where(source_type: :project_entity).where(time_constraints)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/instrumentations/count_issues_metric.rb b/lib/gitlab/usage/metrics/instrumentations/count_issues_metric.rb
index 34247f4f6dd..07dfba70d92 100644
--- a/lib/gitlab/usage/metrics/instrumentations/count_issues_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/count_issues_metric.rb
@@ -11,6 +11,8 @@ module Gitlab
finish { Issue.maximum(:id) }
relation { Issue }
+
+ cache_start_and_finish_as :issue
end
end
end
diff --git a/lib/gitlab/usage/metrics/instrumentations/database_metric.rb b/lib/gitlab/usage/metrics/instrumentations/database_metric.rb
index a000b4509c6..3b09100f3ff 100644
--- a/lib/gitlab/usage/metrics/instrumentations/database_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/database_metric.rb
@@ -18,7 +18,7 @@ module Gitlab
UnimplementedOperationError = Class.new(StandardError) # rubocop:disable UsageData/InstrumentationSuperclass
class << self
- IMPLEMENTED_OPERATIONS = %i(count distinct_count estimate_batch_distinct_count).freeze
+ IMPLEMENTED_OPERATIONS = %i(count distinct_count estimate_batch_distinct_count sum average).freeze
private_constant :IMPLEMENTED_OPERATIONS
diff --git a/lib/gitlab/usage/metrics/instrumentations/issues_created_from_alerts_metric.rb b/lib/gitlab/usage/metrics/instrumentations/issues_created_from_alerts_metric.rb
new file mode 100644
index 00000000000..e430bc8eb71
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/issues_created_from_alerts_metric.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class IssuesCreatedFromAlertsMetric < NumbersMetric
+ ISSUES_FROM_ALERTS_METRICS = [
+ IssuesWithAlertManagementAlertsMetric,
+ IssuesWithPrometheusAlertEvents,
+ IssuesWithSelfManagedPrometheusAlertEvents
+ ].freeze
+
+ operation :add
+
+ data do |time_frame|
+ ISSUES_FROM_ALERTS_METRICS.map { |metric| metric.new(time_frame: time_frame).value }
+ end
+
+ # overwriting instrumentation to generate the appropriate sql query
+ def instrumentation
+ 'SELECT ' + ISSUES_FROM_ALERTS_METRICS.map do |metric|
+ "(#{metric.new(time_frame: time_frame).instrumentation})"
+ end.join(' + ')
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/instrumentations/issues_with_alert_management_alerts_metric.rb b/lib/gitlab/usage/metrics/instrumentations/issues_with_alert_management_alerts_metric.rb
new file mode 100644
index 00000000000..62b91e50e07
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/issues_with_alert_management_alerts_metric.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class IssuesWithAlertManagementAlertsMetric < DatabaseMetric
+ # this metric is used in IssuesCreatedFromAlertsMetric
+ # do not report metric directly in service ping
+ available? { false }
+
+ operation :count
+
+ start { Issue.minimum(:id) }
+ finish { Issue.maximum(:id) }
+
+ relation { Issue.with_alert_management_alerts }
+
+ cache_start_and_finish_as :issue
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/instrumentations/issues_with_prometheus_alert_events.rb b/lib/gitlab/usage/metrics/instrumentations/issues_with_prometheus_alert_events.rb
new file mode 100644
index 00000000000..2befec65ac2
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/issues_with_prometheus_alert_events.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class IssuesWithPrometheusAlertEvents < DatabaseMetric
+ # this metric is used in IssuesCreatedFromAlertsMetric
+ # do not report metric directly in service ping
+ available? { false }
+
+ operation :count
+
+ start { Issue.minimum(:id) }
+ finish { Issue.maximum(:id) }
+
+ relation { Issue.with_prometheus_alert_events }
+
+ cache_start_and_finish_as :issue
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/instrumentations/issues_with_self_managed_prometheus_alert_events.rb b/lib/gitlab/usage/metrics/instrumentations/issues_with_self_managed_prometheus_alert_events.rb
new file mode 100644
index 00000000000..fdbaa65bc68
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/issues_with_self_managed_prometheus_alert_events.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class IssuesWithSelfManagedPrometheusAlertEvents < DatabaseMetric
+ # this metric is used in IssuesCreatedFromAlertsMetric
+ # do not report metric directly in service ping
+ available? { false }
+
+ operation :count
+
+ start { Issue.minimum(:id) }
+ finish { Issue.maximum(:id) }
+
+ relation { Issue.with_self_managed_prometheus_alert_events }
+
+ cache_start_and_finish_as :issue
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/instrumentations/jira_imports_total_imported_issues_count_metric.rb b/lib/gitlab/usage/metrics/instrumentations/jira_imports_total_imported_issues_count_metric.rb
new file mode 100644
index 00000000000..6ca57864b8a
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/jira_imports_total_imported_issues_count_metric.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class JiraImportsTotalImportedIssuesCountMetric < DatabaseMetric
+ operation :sum, column: :imported_issues_count
+
+ relation { JiraImportState.finished }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/instrumentations/numbers_metric.rb b/lib/gitlab/usage/metrics/instrumentations/numbers_metric.rb
new file mode 100644
index 00000000000..8504ee368fc
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/numbers_metric.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class NumbersMetric < BaseMetric
+ # Usage Example
+ #
+ # class BoardsCountMetric < NumbersMetric
+ # operation :add
+ #
+ # data do |time_frame|
+ # [
+ # CountIssuesMetric.new(time_frame: time_frame).value,
+ # CountBoardsMetric.new(time_frame: time_frame).value,
+ # ]
+ # end
+ # end
+
+ UnimplementedOperationError = Class.new(StandardError) # rubocop:disable UsageData/InstrumentationSuperclass
+
+ class << self
+ IMPLEMENTED_OPERATIONS = %i(add).freeze
+
+ private_constant :IMPLEMENTED_OPERATIONS
+
+ def data(&block)
+ return @metric_data&.call unless block_given?
+
+ @metric_data = block
+ end
+
+ def operation(symbol)
+ raise UnimplementedOperationError unless symbol.in?(IMPLEMENTED_OPERATIONS)
+
+ @metric_operation = symbol
+ end
+
+ attr_reader :metric_operation, :metric_data
+ end
+
+ def value
+ method(self.class.metric_operation).call(*data)
+ end
+
+ def suggested_name
+ Gitlab::Usage::Metrics::NameSuggestion.for(:alt)
+ end
+
+ private
+
+ def data
+ self.class.metric_data.call(time_frame)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/instrumentations/unique_active_users_metric.rb b/lib/gitlab/usage/metrics/instrumentations/unique_active_users_metric.rb
new file mode 100644
index 00000000000..9da30db05dd
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/unique_active_users_metric.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class UniqueActiveUsersMetric < DatabaseMetric
+ operation :count
+ relation { ::User.active }
+
+ metric_options do
+ {
+ batch_size: 10_000
+ }
+ end
+
+ def time_constraints
+ case time_frame
+ when '28d'
+ monthly_time_range_db_params(column: :last_activity_on)
+ else
+ super
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/name_suggestion.rb b/lib/gitlab/usage/metrics/name_suggestion.rb
index 0728af9e2ca..238a7a51a20 100644
--- a/lib/gitlab/usage/metrics/name_suggestion.rb
+++ b/lib/gitlab/usage/metrics/name_suggestion.rb
@@ -19,6 +19,8 @@ module Gitlab
name_suggestion(column: column, relation: relation, prefix: 'estimate_distinct_count')
when :sum
name_suggestion(column: column, relation: relation, prefix: 'sum')
+ when :average
+ name_suggestion(column: column, relation: relation, prefix: 'average')
when :redis
REDIS_EVENT_METRIC_NAME
when :alt
diff --git a/lib/gitlab/usage/metrics/query.rb b/lib/gitlab/usage/metrics/query.rb
index 851aa7a50e8..e071b422c16 100644
--- a/lib/gitlab/usage/metrics/query.rb
+++ b/lib/gitlab/usage/metrics/query.rb
@@ -13,6 +13,8 @@ module Gitlab
distinct_count(relation, column)
when :sum
sum(relation, column)
+ when :average
+ average(relation, column)
when :estimate_batch_distinct_count
estimate_batch_distinct_count(relation, column)
when :histogram
@@ -25,19 +27,23 @@ module Gitlab
private
def count(relation, column = nil)
- raw_sql(relation, column)
+ raw_count_sql(relation, column)
end
def distinct_count(relation, column = nil)
- raw_sql(relation, column, true)
+ raw_count_sql(relation, column, true)
end
def sum(relation, column)
- relation.select(relation.all.table[column].sum).to_sql
+ raw_sum_sql(relation, column)
+ end
+
+ def average(relation, column)
+ raw_average_sql(relation, column)
end
def estimate_batch_distinct_count(relation, column = nil)
- raw_sql(relation, column, true)
+ raw_count_sql(relation, column, true)
end
# rubocop: disable CodeReuse/ActiveRecord
@@ -62,15 +68,31 @@ module Gitlab
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
- def raw_sql(relation, column, distinct = false)
+ def raw_count_sql(relation, column, distinct = false)
column ||= relation.primary_key
- node = node_to_count(relation, column)
+ node = node_to_operate(relation, column)
relation.unscope(:order).select(node.count(distinct)).to_sql
end
# rubocop: enable CodeReuse/ActiveRecord
- def node_to_count(relation, column)
+ # rubocop: disable CodeReuse/ActiveRecord
+ def raw_sum_sql(relation, column)
+ node = node_to_operate(relation, column)
+
+ relation.unscope(:order).select(node.sum).to_sql
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def raw_average_sql(relation, column)
+ node = node_to_operate(relation, column)
+
+ relation.unscope(:order).select(node.average).to_sql
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def node_to_operate(relation, column)
if join_relation?(relation) && joined_column?(column)
table_name, column_name = column.split(".")
Arel::Table.new(table_name)[column_name]