2021-03-11 19:13:27 +05:30
# frozen_string_literal: true
module Gitlab
module Usage
module Metrics
module Aggregates
UNION_OF_AGGREGATED_METRICS = 'OR'
INTERSECTION_OF_AGGREGATED_METRICS = 'AND'
ALLOWED_METRICS_AGGREGATIONS = [ UNION_OF_AGGREGATED_METRICS , INTERSECTION_OF_AGGREGATED_METRICS ] . freeze
2021-04-29 21:17:54 +05:30
AGGREGATED_METRICS_PATH = Rails . root . join ( 'config/metrics/aggregates/*.yml' )
2021-03-11 19:13:27 +05:30
AggregatedMetricError = Class . new ( StandardError )
UnknownAggregationOperator = Class . new ( AggregatedMetricError )
UnknownAggregationSource = Class . new ( AggregatedMetricError )
2021-04-17 20:07:23 +05:30
DisallowedAggregationTimeFrame = Class . new ( AggregatedMetricError )
2021-03-11 19:13:27 +05:30
DATABASE_SOURCE = 'database'
REDIS_SOURCE = 'redis'
SOURCES = {
DATABASE_SOURCE = > Sources :: PostgresHll ,
REDIS_SOURCE = > Sources :: RedisHll
} . freeze
class Aggregate
2021-09-04 01:27:46 +05:30
include Gitlab :: Usage :: TimeFrame
2021-03-11 19:13:27 +05:30
def initialize ( recorded_at )
@aggregated_metrics = load_metrics ( AGGREGATED_METRICS_PATH )
@recorded_at = recorded_at
end
2021-04-17 20:07:23 +05:30
def all_time_data
2021-09-04 01:27:46 +05:30
aggregated_metrics_data ( start_date : nil , end_date : nil , time_frame : Gitlab :: Usage :: TimeFrame :: ALL_TIME_TIME_FRAME_NAME )
2021-04-17 20:07:23 +05:30
end
2021-03-11 19:13:27 +05:30
def monthly_data
2021-09-04 01:27:46 +05:30
aggregated_metrics_data ( ** monthly_time_range . merge ( time_frame : Gitlab :: Usage :: TimeFrame :: TWENTY_EIGHT_DAYS_TIME_FRAME_NAME ) )
2021-03-11 19:13:27 +05:30
end
def weekly_data
2021-09-04 01:27:46 +05:30
aggregated_metrics_data ( ** weekly_time_range . merge ( time_frame : Gitlab :: Usage :: TimeFrame :: SEVEN_DAYS_TIME_FRAME_NAME ) )
2021-03-11 19:13:27 +05:30
end
private
attr_accessor :aggregated_metrics , :recorded_at
2021-04-17 20:07:23 +05:30
def aggregated_metrics_data ( start_date : , end_date : , time_frame : )
2021-03-11 19:13:27 +05:30
aggregated_metrics . each_with_object ( { } ) do | aggregation , data |
next if aggregation [ :feature_flag ] && Feature . disabled? ( aggregation [ :feature_flag ] , default_enabled : :yaml , type : :development )
2021-04-17 20:07:23 +05:30
next unless aggregation [ :time_frame ] . include? ( time_frame )
2021-03-11 19:13:27 +05:30
case aggregation [ :source ]
when REDIS_SOURCE
2021-09-04 01:27:46 +05:30
if time_frame == Gitlab :: Usage :: TimeFrame :: ALL_TIME_TIME_FRAME_NAME
2021-04-17 20:07:23 +05:30
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
2021-03-11 19:13:27 +05:30
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
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
2021-06-08 01:23:25 +05:30
source . calculate_metrics_intersections ( metric_names : aggregation [ :events ] , start_date : start_date , end_date : end_date , recorded_at : recorded_at )
2021-03-11 19:13:27 +05:30
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
end
rescue Gitlab :: UsageDataCounters :: HLLRedisCounter :: EventError , AggregatedMetricError = > 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
end
end
end
end
end
2021-04-17 20:07:23 +05:30
2021-06-08 01:23:25 +05:30
Gitlab :: Usage :: Metrics :: Aggregates :: Aggregate . prepend_mod_with ( 'Gitlab::Usage::Metrics::Aggregates::Aggregate' )