module Tabs extend self extend Tabs::Storage class UnknownTypeError < Exception; end class DuplicateMetricError < Exception; end class UnknownMetricError < Exception; end class MetricTypeMismatchError < Exception; end METRIC_TYPES = ["counter", "value", "task"] RESOLUTIONS = [:minute, :hour, :day, :week, :month, :year] def configure yield(Config) end def redis Config.redis end def config Config end def increment_counter(key, timestamp=Time.now) create_metric(key, "counter") unless metric_exists?(key) raise MetricTypeMismatchError.new("Only counter metrics can be incremented") unless metric_type(key) == "counter" get_metric(key).increment(timestamp) end def record_value(key, value, timestamp=Time.now) create_metric(key, "value") unless metric_exists?(key) raise MetricTypeMismatchError.new("Only value metrics can record a value") unless metric_type(key) == "value" get_metric(key).record(value, timestamp) end def start_task(key, token, timestamp=Time.now) create_metric(key, "task") raise MetricTypeMismatchError.new("Only task metrics can start a task") unless metric_type(key) == "task" get_metric(key).start(token, timestamp) end def complete_task(key, token, timestamp=Time.now) raise MetricTypeMismatchError.new("Only task metrics can complete a task") unless metric_type(key) == "task" get_metric(key).complete(token, timestamp) end def create_metric(key, type) raise UnknownTypeError.new("Unknown metric type: #{type}") unless METRIC_TYPES.include?(type) raise DuplicateMetricError.new("Metric already exists: #{key}") if metric_exists?(key) hset "metrics", key, type metric_klass(type).new(key) end def get_metric(key) raise UnknownMetricError.new("Unknown metric: #{key}") unless metric_exists?(key) type = hget("metrics", key) metric_klass(type).new(key) end def counter_total(key, period=nil) raise UnknownMetricError.new("Unknown metric: #{key}") unless metric_exists?(key) raise MetricTypeMismatchError.new("Only counter metrics can be incremented") unless metric_type(key) == "counter" get_metric(key).total end def get_stats(key, period, resolution) raise UnknownMetricError.new("Unknown metric: #{key}") unless metric_exists?(key) metric = get_metric(key) metric.stats(period, resolution) end def metric_type(key) raise UnknownMetricError.new("Unknown metric: #{key}") unless metric_exists?(key) hget "metrics", key end def list_metrics hkeys "metrics" end def metric_exists?(key) list_metrics.include? key end def drop_metric(key) raise UnknownMetricError.new("Unknown metric: #{key}") unless metric_exists?(key) metric = get_metric(key) metric.drop! hdel "metrics", key end private def metric_klass(type) "Tabs::Metrics::#{type.classify}".constantize end end