92 lines
2.7 KiB
Ruby
92 lines
2.7 KiB
Ruby
|
require 'active_support/time'
|
||
|
require_relative '../../../lib/carto/metrics/usage_metrics_interface'
|
||
|
|
||
|
module CartoDB
|
||
|
# The purpose of this class is to encapsulate storage of usage metrics.
|
||
|
# This shall be used for billing, quota checking and metrics.
|
||
|
class ServiceUsageMetrics < Carto::Metrics::UsageMetricsInterface
|
||
|
|
||
|
def initialize(username, orgname = nil, redis=$geocoder_metrics)
|
||
|
@username = username
|
||
|
@orgname = orgname
|
||
|
@redis = redis
|
||
|
end
|
||
|
|
||
|
def incr(service, metric, amount = 1, date = DateTime.current)
|
||
|
check_valid_data(service, metric)
|
||
|
assert_valid_amount(amount)
|
||
|
return if amount == 0
|
||
|
|
||
|
# TODO We could add EXPIRE command to add TTL to the keys
|
||
|
if !@orgname.nil?
|
||
|
@redis.zincrby("#{org_key_prefix(service, metric, date)}", amount, "#{date_day(date)}")
|
||
|
end
|
||
|
|
||
|
@redis.zincrby("#{user_key_prefix(service, metric, date)}", amount, "#{date_day(date)}")
|
||
|
end
|
||
|
|
||
|
def get(service, metric, date = DateTime.current)
|
||
|
check_valid_data(service, metric)
|
||
|
|
||
|
total = 0
|
||
|
if !@orgname.nil?
|
||
|
total += @redis.zscore(org_key_prefix(service, metric, date), date_day(date)) || 0
|
||
|
else
|
||
|
total += @redis.zscore(user_key_prefix(service, metric, date), date_day(date)) || 0
|
||
|
end
|
||
|
|
||
|
total
|
||
|
end
|
||
|
|
||
|
def get_sum_by_date_range(service, metric, date_from, date_to)
|
||
|
get_date_range(service, metric, date_from, date_to).values.reduce(:+)
|
||
|
end
|
||
|
|
||
|
def get_date_range(service, metric, date_from, date_to)
|
||
|
check_valid_data(service, metric)
|
||
|
|
||
|
ret = {}
|
||
|
month_values = {}
|
||
|
(date_from..date_to).each do |date|
|
||
|
year_month_key = date_year_month(date)
|
||
|
if month_values[year_month_key].nil?
|
||
|
key_prefix = @orgname.nil? ? user_key_prefix(service, metric, date) : org_key_prefix(service, metric, date)
|
||
|
month_values[year_month_key] = @redis.zrange(key_prefix, 0, -1, with_scores: true).to_h
|
||
|
end
|
||
|
ret[date] = month_values[year_month_key][date_day(date)] || 0
|
||
|
end
|
||
|
|
||
|
ret
|
||
|
end
|
||
|
|
||
|
protected
|
||
|
|
||
|
def check_valid_data(_service, _metric)
|
||
|
raise NotImplementedError.new("You must implement check_valid_data in your metrics class.")
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
def user_key_prefix(service, metric, date)
|
||
|
"user:#{@username}:#{service}:#{metric}:#{date_year_month(date)}"
|
||
|
end
|
||
|
|
||
|
def org_key_prefix(service, metric, date)
|
||
|
"org:#{@orgname}:#{service}:#{metric}:#{date_year_month(date)}"
|
||
|
end
|
||
|
|
||
|
def date_day(date)
|
||
|
date.strftime('%d')
|
||
|
end
|
||
|
|
||
|
def date_year_month(date)
|
||
|
date.strftime('%Y%m')
|
||
|
end
|
||
|
|
||
|
def assert_valid_amount(amount)
|
||
|
raise ArgumentError.new('Invalid metric amount') if amount.nil? || amount < 0
|
||
|
end
|
||
|
|
||
|
end
|
||
|
end
|