cartodb/services/dataservices-metrics/lib/service_usage_metrics.rb
2020-06-15 10:58:47 +08:00

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