mirror of
https://gitlab.com/gitlab-org/gitlab-foss.git
synced 2025-07-25 16:03:48 +00:00
143 lines
4.1 KiB
Ruby
143 lines
4.1 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# Represents the relationship between a event definition and a metric definition.
|
|
#
|
|
# Example usages:
|
|
# EventSelectionRule.new('pull_package', time_framed: true, filter: { label: 'rubygems' })
|
|
#
|
|
# The above rule represents a defines a metric that "counts weekly number of pull_package events with label rubygems"
|
|
#
|
|
# EventSelectionRule.new('pull_package', time_framed: false)
|
|
#
|
|
# The above rule represents a defines a metric that "counts the total number of pull_package events"
|
|
#
|
|
module Gitlab
|
|
module Usage
|
|
class EventSelectionRule
|
|
include Gitlab::Usage::TimeSeriesStorable
|
|
include Gitlab::Usage::TimeFrame
|
|
|
|
TOTAL_COUNTER_KEY_PREFIX = "event_counters"
|
|
SUM_KEY_PREFIX = "event_sums"
|
|
|
|
attr_reader :filter, :name, :unique_identifier_name, :operator
|
|
|
|
def initialize(name:, time_framed:, filter: {}, unique_identifier_name: nil, operator: nil)
|
|
@name = name
|
|
@time_framed = time_framed
|
|
@filter = filter || {}
|
|
@unique_identifier_name = unique_identifier_name
|
|
@operator = operator
|
|
end
|
|
|
|
def redis_key_for_date(date = Date.today)
|
|
redis_key(nil, date)
|
|
end
|
|
|
|
def redis_keys_for_time_frame(time_frame)
|
|
if time_frame == 'all'
|
|
[redis_key]
|
|
else
|
|
keys_for_aggregation(events: [path_part_of_redis_key], **time_constraint(time_frame))
|
|
end
|
|
end
|
|
|
|
def time_framed?
|
|
@time_framed
|
|
end
|
|
|
|
def total_counter?
|
|
unique_identifier_name.nil? && !sum?
|
|
end
|
|
|
|
def sum?
|
|
operator == 'sum(value)'
|
|
end
|
|
|
|
def unique_total?
|
|
unique_identifier_name && operator == 'total'
|
|
end
|
|
|
|
def matches?(additional_properties)
|
|
filter.all? do |property_name, value|
|
|
additional_properties[property_name] == value
|
|
end
|
|
end
|
|
|
|
# Implementing `==` to make sure that `a == b` is true if and only if `a` and `b` have equal properties
|
|
# Checks equality by comparing each attribute.
|
|
# @param [Object] Object to be compared
|
|
def ==(other)
|
|
other.is_a?(self.class) &&
|
|
name == other.name &&
|
|
time_framed? == other.time_framed? &&
|
|
filter == other.filter &&
|
|
unique_identifier_name == other.unique_identifier_name &&
|
|
operator == other.operator
|
|
end
|
|
|
|
alias_method :eql?, :==
|
|
|
|
# Calculates hash code according to all attributes.
|
|
# @return [Integer] Hash code
|
|
# Ensures 2 objects with the same attributes can't be keys
|
|
# in the same hash twice
|
|
def hash
|
|
[name, time_framed?, filter, unique_identifier_name, operator].hash
|
|
end
|
|
|
|
private
|
|
|
|
def redis_key(_event_name = nil, date = Date.today, _used_in_aggregate_metric = false)
|
|
return base_key unless time_framed?
|
|
|
|
apply_time_aggregation(base_key, date)
|
|
end
|
|
|
|
def base_key
|
|
@base_key ||= "{#{redis_slot}}_" + path_part_of_redis_key
|
|
end
|
|
|
|
def redis_slot
|
|
return SUM_KEY_PREFIX if sum?
|
|
|
|
total_counter? ? TOTAL_COUNTER_KEY_PREFIX : Gitlab::UsageDataCounters::HLLRedisCounter::REDIS_SLOT
|
|
end
|
|
|
|
def time_constraint(time_frame)
|
|
case time_frame
|
|
when '28d'
|
|
monthly_time_range
|
|
when '7d'
|
|
weekly_time_range
|
|
else
|
|
raise "Unknown time frame: #{time_frame}"
|
|
end
|
|
end
|
|
|
|
def path_part_of_redis_key
|
|
path = name
|
|
|
|
if operator.present?
|
|
# operator should be serialized and used in the path here
|
|
path = "#{path}-operator:#{operator}"
|
|
end
|
|
|
|
if filter.present?
|
|
sorted_filter_keys = filter.keys.sort
|
|
serialized_filter = sorted_filter_keys.map { |key| "#{key}:#{filter[key]}" }.join(',')
|
|
path = "#{path}-filter:[#{serialized_filter}]"
|
|
end
|
|
|
|
path = "#{path}-#{unique_identifier_name}" if unique_identifier_name.present?
|
|
|
|
key_overrides.fetch(path, path)
|
|
end
|
|
|
|
def key_overrides
|
|
YAML.safe_load(File.read(Gitlab::UsageDataCounters::HLLRedisCounter::KEY_OVERRIDES_PATH))
|
|
end
|
|
end
|
|
end
|
|
end
|