# Path: tapes/local/meter.py
# class Meter(Stat):
#     def __init__(self):
#         self.last_tick = time()
#         self.count = 0
#         self.m1 = EWMA.one()
#         self.m5 = EWMA.five()
#         self.m15 = EWMA.fifteen()
# 
#     def mark(self, n=1):
#         self._tick_if_needed()
#         self.count += n
#         self.m1.update(n)
#         self.m5.update(n)
#         self.m15.update(n)
# 
#     def _get_one_minute(self):
#         self._tick_if_needed()
#         return self.m1.get_rate()
# 
#     def _get_five_minute(self):
#         self._tick_if_needed()
#         return self.m5.get_rate()
# 
#     def _get_fifteen_minute(self):
#         self._tick_if_needed()
#         return self.m15.get_rate()
# 
#     def _tick_if_needed(self):
#         old_tick = self.last_tick
#         new_tick = time()
#         age = new_tick - old_tick
#         if age > _INTERVAL:
#             new_interval_start_tick = new_tick - age % _INTERVAL
#             self.last_tick = new_interval_start_tick
#             required_ticks = int(age // _INTERVAL)
#             for _ in range(required_ticks):
#                 self.m1.tick()
#                 self.m5.tick()
#                 self.m15.tick()
# 
#     def get_values(self):
#         return {
#             'count': self.count,
#             'm1': self._get_one_minute(),
#             'm5': self._get_five_minute(),
#             'm15': self._get_fifteen_minute(),
#         }
# 
# Path: tapes/local/counter.py
# class Counter(Stat):
#     def __init__(self):
#         self.count = 0
# 
#     def get_values(self):
#         return {
#             'value': self.count
#         }
# 
#     def increment(self, n=1):
#         self.count += n
# 
#     def decrement(self, n=1):
#         self.count -= n
# 
# Path: tapes/local/gauge.py
# class Gauge(Stat):
#     def __init__(self, producer):
#         self.producer = producer
# 
#     def get_values(self):
#         return {
#             'value': self.producer()
#         }
# 
# Path: tapes/local/histogram.py
# class Histogram(Stat):
#     def __init__(self):
#         self.count = 0
#         self.reservoir = ExponentiallyDecayingReservoir()
# 
#     def update(self, value):
#         self.count += 1
#         self.reservoir.update(value)
# 
#     def get_values(self):
#         snapshot = self.reservoir.get_snapshot()
#         return {
#             'count': self.count,
#             'min': snapshot.get_min(),
#             'max': snapshot.get_max(),
#             'mean': snapshot.get_mean(),
#             'stddev': snapshot.get_sd(),
#             'q50': snapshot.get_quantile(0.5),
#             'q75': snapshot.get_quantile(0.75),
#             'q95': snapshot.get_quantile(0.95),
#             'q98': snapshot.get_quantile(0.98),
#             'q99': snapshot.get_quantile(0.99),
#             'q999': snapshot.get_quantile(0.999),
#         }
# 
# Path: tapes/local/timer.py
# class Timer(Stat):
#     def __init__(self):
#         self.count = 0
#         self.meter = Meter()
#         self.histogram = Histogram()
#         super(Timer, self).__init__()
# 
#     @contextlib.contextmanager
#     def time(self):
#         start_time = time()
#         try:
#             yield
#         finally:
#             self.update(time() - start_time)
# 
#     def update(self, value):
#         self.meter.mark()
#         self.histogram.update(value)
# 
#     def get_values(self):
#         values = self.meter.get_values()
#         values.update(self.histogram.get_values())
#         return values


import functools
import abc
import six
from addict import Dict
from .local.meter import Meter
from .local.counter import Counter
from .local.gauge import Gauge
from .local.histogram import Histogram
from .local.timer import Timer




@six.add_metaclass(abc.ABCMeta)
class BaseRegistry(object):
    def __init__(self):
        super(BaseRegistry, self).__init__()
        self.stats = dict()

    def _get_or_add_stat(self, name, stat_factory):
        path_parts = name.split('.')
        path, stat_name = path_parts[:-1], path_parts[-1]

        stats = self.stats
        for p in path:
            try:
                stats = stats[p]

# Path: tapes/local/meter.py
# class Meter(Stat):
#     def __init__(self):
#         self.last_tick = time()
#         self.count = 0
#         self.m1 = EWMA.one()
#         self.m5 = EWMA.five()
#         self.m15 = EWMA.fifteen()
# 
#     def mark(self, n=1):
#         self._tick_if_needed()
#         self.count += n
#         self.m1.update(n)
#         self.m5.update(n)
#         self.m15.update(n)
# 
#     def _get_one_minute(self):
#         self._tick_if_needed()
#         return self.m1.get_rate()
# 
#     def _get_five_minute(self):
#         self._tick_if_needed()
#         return self.m5.get_rate()
# 
#     def _get_fifteen_minute(self):
#         self._tick_if_needed()
#         return self.m15.get_rate()
# 
#     def _tick_if_needed(self):
#         old_tick = self.last_tick
#         new_tick = time()
#         age = new_tick - old_tick
#         if age > _INTERVAL:
#             new_interval_start_tick = new_tick - age % _INTERVAL
#             self.last_tick = new_interval_start_tick
#             required_ticks = int(age // _INTERVAL)
#             for _ in range(required_ticks):
#                 self.m1.tick()
#                 self.m5.tick()
#                 self.m15.tick()
# 
#     def get_values(self):
#         return {
#             'count': self.count,
#             'm1': self._get_one_minute(),
#             'm5': self._get_five_minute(),
#             'm15': self._get_fifteen_minute(),
#         }
# 
# Path: tapes/local/counter.py
# class Counter(Stat):
#     def __init__(self):
#         self.count = 0
# 
#     def get_values(self):
#         return {
#             'value': self.count
#         }
# 
#     def increment(self, n=1):
#         self.count += n
# 
#     def decrement(self, n=1):
#         self.count -= n
# 
# Path: tapes/local/gauge.py
# class Gauge(Stat):
#     def __init__(self, producer):
#         self.producer = producer
# 
#     def get_values(self):
#         return {
#             'value': self.producer()
#         }
# 
# Path: tapes/local/histogram.py
# class Histogram(Stat):
#     def __init__(self):
#         self.count = 0
#         self.reservoir = ExponentiallyDecayingReservoir()
# 
#     def update(self, value):
#         self.count += 1
#         self.reservoir.update(value)
# 
#     def get_values(self):
#         snapshot = self.reservoir.get_snapshot()
#         return {
#             'count': self.count,
#             'min': snapshot.get_min(),
#             'max': snapshot.get_max(),
#             'mean': snapshot.get_mean(),
#             'stddev': snapshot.get_sd(),
#             'q50': snapshot.get_quantile(0.5),
#             'q75': snapshot.get_quantile(0.75),
#             'q95': snapshot.get_quantile(0.95),
#             'q98': snapshot.get_quantile(0.98),
#             'q99': snapshot.get_quantile(0.99),
#             'q999': snapshot.get_quantile(0.999),
#         }
# 
# Path: tapes/local/timer.py
# class Timer(Stat):
#     def __init__(self):
#         self.count = 0
#         self.meter = Meter()
#         self.histogram = Histogram()
#         super(Timer, self).__init__()
# 
#     @contextlib.contextmanager
#     def time(self):
#         start_time = time()
#         try:
#             yield
#         finally:
#             self.update(time() - start_time)
# 
#     def update(self, value):
#         self.meter.mark()
#         self.histogram.update(value)
# 
#     def get_values(self):
#         values = self.meter.get_values()
#         values.update(self.histogram.get_values())
#         return values


# Path: tapes/registry.py
import functools
import abc
import six
from addict import Dict
from .local.meter import Meter
from .local.counter import Counter
from .local.gauge import Gauge
from .local.histogram import Histogram
from .local.timer import Timer





@six.add_metaclass(abc.ABCMeta)
class BaseRegistry(object):
    def __init__(self):
        super(BaseRegistry, self).__init__()
        self.stats = dict()

    def _get_or_add_stat(self, name, stat_factory):
        path_parts = name.split('.')
        path, stat_name = path_parts[:-1], path_parts[-1]

        stats = self.stats
        for p in path:
            try:
                stats = stats[p]

            except KeyError: