debian-mirror-gitlab/lib/gitlab/usage/metrics/aggregates/aggregate.rb
2022-11-25 23:54:43 +05:30

112 lines
4 KiB
Ruby

# frozen_string_literal: true
module Gitlab
module Usage
module Metrics
module Aggregates
class Aggregate
include Gitlab::Usage::TimeFrame
def initialize(recorded_at)
@aggregated_metrics = load_metrics(AGGREGATED_METRICS_PATH)
@recorded_at = recorded_at
end
def all_time_data
aggregated_metrics_data(Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME)
end
def monthly_data
aggregated_metrics_data(Gitlab::Usage::TimeFrame::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME)
end
def weekly_data
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(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)
data[aggregation[:name]] = calculate_count_for_aggregation(aggregation: aggregation, time_frame: time_frame)
end
end
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
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
def load_metrics(wildcard)
Dir[wildcard].each_with_object([]) do |path, metrics|
metrics.push(*load_yaml_from_path(path))
end
end
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
end
end
Gitlab::Usage::Metrics::Aggregates::Aggregate.prepend_mod_with('Gitlab::Usage::Metrics::Aggregates::Aggregate')