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:
Diffstat (limited to 'lib/gitlab/usage/metrics')
-rw-r--r--lib/gitlab/usage/metrics/aggregates/aggregate.rb93
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/aggregated_metric.rb71
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/base_metric.rb6
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/count_bulk_imports_entities_metric.rb2
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/count_imported_projects_metric.rb2
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_disabled_metric.rb20
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/generic_metric.rb5
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_direct_installations_count_metric.rb15
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_proxy_installations_count_metric.rb15
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/merge_request_widget_extension_metric.rb43
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb2
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/redis_metric.rb16
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/work_items_activity_aggregated_metric.rb13
13 files changed, 253 insertions, 50 deletions
diff --git a/lib/gitlab/usage/metrics/aggregates/aggregate.rb b/lib/gitlab/usage/metrics/aggregates/aggregate.rb
index 11e2fd22638..cd72f16d46d 100644
--- a/lib/gitlab/usage/metrics/aggregates/aggregate.rb
+++ b/lib/gitlab/usage/metrics/aggregates/aggregate.rb
@@ -13,62 +13,72 @@ module Gitlab
end
def all_time_data
- aggregated_metrics_data(start_date: nil, end_date: nil, time_frame: Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME)
+ aggregated_metrics_data(Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME)
end
def monthly_data
- aggregated_metrics_data(**monthly_time_range.merge(time_frame: Gitlab::Usage::TimeFrame::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME))
+ aggregated_metrics_data(Gitlab::Usage::TimeFrame::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME)
end
def weekly_data
- aggregated_metrics_data(**weekly_time_range.merge(time_frame: Gitlab::Usage::TimeFrame::SEVEN_DAYS_TIME_FRAME_NAME))
+ aggregated_metrics_data(Gitlab::Usage::TimeFrame::SEVEN_DAYS_TIME_FRAME_NAME)
+ end
+
+ def calculate_count_for_aggregation(aggregation:, time_frame:)
+ with_validate_configuration(aggregation, time_frame) do
+ source = SOURCES[aggregation[:source]]
+
+ if aggregation[:operator] == UNION_OF_AGGREGATED_METRICS
+ source.calculate_metrics_union(**time_constraints(time_frame).merge(metric_names: aggregation[:events], recorded_at: recorded_at))
+ else
+ source.calculate_metrics_intersections(**time_constraints(time_frame).merge(metric_names: aggregation[:events], recorded_at: recorded_at))
+ end
+ end
+ rescue Gitlab::UsageDataCounters::HLLRedisCounter::EventError, AggregatedMetricError => error
+ failure(error)
end
private
attr_accessor :aggregated_metrics, :recorded_at
- def aggregated_metrics_data(start_date:, end_date:, time_frame:)
+ def aggregated_metrics_data(time_frame)
aggregated_metrics.each_with_object({}) do |aggregation, data|
next if aggregation[:feature_flag] && Feature.disabled?(aggregation[:feature_flag], type: :development)
next unless aggregation[:time_frame].include?(time_frame)
- case aggregation[:source]
- when REDIS_SOURCE
- if time_frame == Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME
- data[aggregation[:name]] = Gitlab::Utils::UsageData::FALLBACK
- Gitlab::ErrorTracking
- .track_and_raise_for_dev_exception(
- DisallowedAggregationTimeFrame.new("Aggregation time frame: 'all' is not allowed for aggregation with source: '#{REDIS_SOURCE}'")
- )
- else
- data[aggregation[:name]] = calculate_count_for_aggregation(aggregation: aggregation, start_date: start_date, end_date: end_date)
- end
- when DATABASE_SOURCE
- data[aggregation[:name]] = calculate_count_for_aggregation(aggregation: aggregation, start_date: start_date, end_date: end_date)
- else
- Gitlab::ErrorTracking
- .track_and_raise_for_dev_exception(UnknownAggregationSource.new("Aggregation source: '#{aggregation[:source]}' must be included in #{SOURCES.keys}"))
-
- data[aggregation[:name]] = Gitlab::Utils::UsageData::FALLBACK
- end
+ data[aggregation[:name]] = calculate_count_for_aggregation(aggregation: aggregation, time_frame: time_frame)
end
end
- def calculate_count_for_aggregation(aggregation:, start_date:, end_date:)
- source = SOURCES[aggregation[:source]]
-
- case aggregation[:operator]
- when UNION_OF_AGGREGATED_METRICS
- source.calculate_metrics_union(metric_names: aggregation[:events], start_date: start_date, end_date: end_date, recorded_at: recorded_at)
- when INTERSECTION_OF_AGGREGATED_METRICS
- source.calculate_metrics_intersections(metric_names: aggregation[:events], start_date: start_date, end_date: end_date, recorded_at: recorded_at)
- else
- Gitlab::ErrorTracking
- .track_and_raise_for_dev_exception(UnknownAggregationOperator.new("Events should be aggregated with one of operators #{ALLOWED_METRICS_AGGREGATIONS}"))
- Gitlab::Utils::UsageData::FALLBACK
+ def with_validate_configuration(aggregation, time_frame)
+ source = aggregation[:source]
+
+ unless ALLOWED_METRICS_AGGREGATIONS.include?(aggregation[:operator])
+ return failure(
+ UnknownAggregationOperator
+ .new("Events should be aggregated with one of operators #{ALLOWED_METRICS_AGGREGATIONS}")
+ )
end
- rescue Gitlab::UsageDataCounters::HLLRedisCounter::EventError, AggregatedMetricError => error
+
+ unless SOURCES[source]
+ return failure(
+ UnknownAggregationSource
+ .new("Aggregation source: '#{source}' must be included in #{SOURCES.keys}")
+ )
+ end
+
+ if time_frame == Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME && source == REDIS_SOURCE
+ return failure(
+ DisallowedAggregationTimeFrame
+ .new("Aggregation time frame: 'all' is not allowed for aggregation with source: '#{REDIS_SOURCE}'")
+ )
+ end
+
+ yield
+ end
+
+ def failure(error)
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
Gitlab::Utils::UsageData::FALLBACK
end
@@ -82,6 +92,17 @@ module Gitlab
def load_yaml_from_path(path)
YAML.safe_load(File.read(path), aliases: true)&.map(&:with_indifferent_access)
end
+
+ def time_constraints(time_frame)
+ case time_frame
+ when Gitlab::Usage::TimeFrame::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME
+ monthly_time_range
+ when Gitlab::Usage::TimeFrame::SEVEN_DAYS_TIME_FRAME_NAME
+ weekly_time_range
+ when Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME
+ { start_date: nil, end_date: nil }
+ end
+ end
end
end
end
diff --git a/lib/gitlab/usage/metrics/instrumentations/aggregated_metric.rb b/lib/gitlab/usage/metrics/instrumentations/aggregated_metric.rb
new file mode 100644
index 00000000000..63ead5a8cb0
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/aggregated_metric.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ # Usage example
+ #
+ # In metric YAML definition:
+ #
+ # instrumentation_class: AggregatedMetric
+ # data_source: redis_hll
+ # options:
+ # aggregate:
+ # operator: OR
+ # attribute: user_id
+ # events:
+ # - 'incident_management_alert_status_changed'
+ # - 'incident_management_alert_assigned'
+ # - 'incident_management_alert_todo'
+ # - 'incident_management_alert_create_incident'
+
+ class AggregatedMetric < BaseMetric
+ FALLBACK = -1
+
+ def initialize(metric_definition)
+ super
+ @source = parse_data_source_to_legacy_value(metric_definition)
+ @aggregate = options.fetch(:aggregate, {})
+ end
+
+ def value
+ alt_usage_data(fallback: FALLBACK) do
+ Aggregates::Aggregate
+ .new(Time.current)
+ .calculate_count_for_aggregation(
+ aggregation: aggregate_config,
+ time_frame: time_frame
+ )
+ end
+ end
+
+ def suggested_name
+ Gitlab::Usage::Metrics::NameSuggestion.for(:alt)
+ end
+
+ private
+
+ attr_accessor :source, :aggregate
+
+ # TODO: This method is a temporary measure that
+ # handles backwards compatibility until
+ # point 5 from is resolved https://gitlab.com/gitlab-org/gitlab/-/issues/370963#implementation
+ def parse_data_source_to_legacy_value(metric_definition)
+ return 'redis' if metric_definition[:data_source] == 'redis_hll'
+
+ metric_definition[:data_source]
+ end
+
+ def aggregate_config
+ {
+ source: source,
+ events: options[:events],
+ operator: aggregate[:operator]
+ }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/instrumentations/base_metric.rb b/lib/gitlab/usage/metrics/instrumentations/base_metric.rb
index 5e20766b1b4..55da2315e45 100644
--- a/lib/gitlab/usage/metrics/instrumentations/base_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/base_metric.rb
@@ -23,9 +23,9 @@ module Gitlab
attr_reader :metric_available
end
- def initialize(time_frame:, options: {})
- @time_frame = time_frame
- @options = options
+ def initialize(metric_definition)
+ @time_frame = metric_definition.fetch(:time_frame)
+ @options = metric_definition.fetch(:options, {})
end
def instrumentation
diff --git a/lib/gitlab/usage/metrics/instrumentations/count_bulk_imports_entities_metric.rb b/lib/gitlab/usage/metrics/instrumentations/count_bulk_imports_entities_metric.rb
index 67dc1455b23..642b67a3b02 100644
--- a/lib/gitlab/usage/metrics/instrumentations/count_bulk_imports_entities_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/count_bulk_imports_entities_metric.rb
@@ -7,7 +7,7 @@ module Gitlab
class CountBulkImportsEntitiesMetric < DatabaseMetric
operation :count
- def initialize(time_frame:, options: {})
+ def initialize(metric_definition)
super
if source_type.present? && !source_type.in?(allowed_source_types)
diff --git a/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_metric.rb b/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_metric.rb
index c5498ce530f..d485e8b4f72 100644
--- a/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/count_imported_projects_metric.rb
@@ -7,7 +7,7 @@ module Gitlab
class CountImportedProjectsMetric < DatabaseMetric
operation :count
- def initialize(time_frame:, options: {})
+ def initialize(metric_definition)
super
raise ArgumentError, "import_type options attribute is required" unless import_type.present?
diff --git a/lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_disabled_metric.rb b/lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_disabled_metric.rb
new file mode 100644
index 00000000000..0c421dc3311
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/distinct_count_projects_with_expiration_policy_disabled_metric.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class DistinctCountProjectsWithExpirationPolicyDisabledMetric < DatabaseMetric
+ operation :distinct_count, column: :project_id
+
+ start { Project.minimum(:id) }
+ finish { Project.maximum(:id) }
+
+ cache_start_and_finish_as :project_id
+
+ relation { ::ContainerExpirationPolicy.where(enabled: false) }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/instrumentations/generic_metric.rb b/lib/gitlab/usage/metrics/instrumentations/generic_metric.rb
index 0f4b903b99c..7c646281598 100644
--- a/lib/gitlab/usage/metrics/instrumentations/generic_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/generic_metric.rb
@@ -28,9 +28,8 @@ module Gitlab
end
end
- def initialize(time_frame: 'none', options: {})
- @time_frame = time_frame
- @options = options
+ def initialize(metric_definition)
+ super(metric_definition.reverse_merge(time_frame: 'none'))
end
def value
diff --git a/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_direct_installations_count_metric.rb b/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_direct_installations_count_metric.rb
new file mode 100644
index 00000000000..f22ee2aa3f5
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_direct_installations_count_metric.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class GitlabForJiraAppDirectInstallationsCountMetric < DatabaseMetric
+ operation :count
+
+ relation { JiraConnectInstallation.direct_installations }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_proxy_installations_count_metric.rb b/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_proxy_installations_count_metric.rb
new file mode 100644
index 00000000000..222a69faf8b
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_proxy_installations_count_metric.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class GitlabForJiraAppProxyInstallationsCountMetric < DatabaseMetric
+ operation :count
+
+ relation { JiraConnectInstallation.proxy_installations }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/instrumentations/merge_request_widget_extension_metric.rb b/lib/gitlab/usage/metrics/instrumentations/merge_request_widget_extension_metric.rb
new file mode 100644
index 00000000000..e2fdb3462c5
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/merge_request_widget_extension_metric.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ # Usage example
+ #
+ # In metric YAML definition:
+ #
+ # instrumentation_class: MergeRequestWidgetExtensionMetric
+ # options:
+ # event: expand
+ # widget: terraform
+ #
+ class MergeRequestWidgetExtensionMetric < RedisMetric
+ extend ::Gitlab::Utils::Override
+
+ def validate_options!
+ raise ArgumentError, "'event' option is required" unless metric_event.present?
+ raise ArgumentError, "'widget' option is required" unless widget_name.present?
+ end
+
+ def widget_name
+ options[:widget]
+ end
+
+ override :prefix
+ def prefix
+ 'i_code_review_merge_request_widget'
+ end
+
+ private
+
+ override :redis_key
+ def redis_key
+ "#{USAGE_PREFIX}#{prefix}_#{widget_name}_count_#{metric_event}".upcase
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb b/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb
index bb27cca1bb9..17009f7638e 100644
--- a/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb
@@ -12,7 +12,7 @@ module Gitlab
# events:
# - g_analytics_valuestream
# end
- def initialize(time_frame:, options: {})
+ def initialize(metric_definition)
super
raise ArgumentError, "options events are required" unless metric_events.present?
diff --git a/lib/gitlab/usage/metrics/instrumentations/redis_metric.rb b/lib/gitlab/usage/metrics/instrumentations/redis_metric.rb
index 26d963e2407..ae3326fa845 100644
--- a/lib/gitlab/usage/metrics/instrumentations/redis_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/redis_metric.rb
@@ -17,12 +17,17 @@ module Gitlab
include Gitlab::UsageDataCounters::RedisCounter
USAGE_PREFIX = "USAGE_"
+ OPTIONS_PREFIX_KEY = :prefix
- def initialize(time_frame:, options: {})
+ def initialize(metric_definition)
super
+ validate_options!
+ end
+
+ def validate_options!
raise ArgumentError, "'event' option is required" unless metric_event.present?
- raise ArgumentError, "'prefix' option is required" unless prefix.present?
+ raise ArgumentError, "'prefix' option is required" unless options.has_key?(OPTIONS_PREFIX_KEY)
end
def metric_event
@@ -30,7 +35,7 @@ module Gitlab
end
def prefix
- options[:prefix]
+ options[OPTIONS_PREFIX_KEY]
end
def include_usage_prefix?
@@ -50,9 +55,10 @@ module Gitlab
private
def redis_key
- key = "#{prefix}_#{metric_event}".upcase
+ key = metric_event.dup
+ key.prepend("#{prefix}_") if prefix
key.prepend(USAGE_PREFIX) if include_usage_prefix?
- key
+ key.upcase
end
end
end
diff --git a/lib/gitlab/usage/metrics/instrumentations/work_items_activity_aggregated_metric.rb b/lib/gitlab/usage/metrics/instrumentations/work_items_activity_aggregated_metric.rb
new file mode 100644
index 00000000000..d045265495a
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/work_items_activity_aggregated_metric.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class WorkItemsActivityAggregatedMetric < AggregatedMetric
+ available? { Feature.enabled?(:track_work_items_activity) }
+ end
+ end
+ end
+ end
+end