Source code for statsd.timer

import contextlib
import time
from functools import wraps, partial

import statsd


[docs]class Timer(statsd.Client): ''' Statsd Timer Object Additional documentation is available at the parent class :class:`~statsd.client.Client` :keyword name: The name for this timer :type name: str :keyword connection: The connection to use, will be automatically created if not given :type connection: :class:`~statsd.connection.Connection` :keyword min_send_threshold: Timings smaller than this will not be sent so -1 can be used for all. :type min_send_threshold: int >>> timer = Timer('application_name').start() >>> # do something >>> timer.stop('executed_action') True ''' def __init__(self, name, connection=None, min_send_threshold=-1): super(Timer, self).__init__(name, connection=connection) self._start = None self._last = None self._stop = None self.min_send_threshold = min_send_threshold
[docs] def start(self): '''Start the timer and store the start time, this can only be executed once per instance It returns the timer instance so it can be chained when instantiating the timer instance like this: ``timer = Timer('application_name').start()``''' assert self._start is None, ( 'Unable to start, the timer is already running') self._last = self._start = time.time() return self
[docs] def send(self, subname, delta): '''Send the data to statsd via self.connection :keyword subname: The subname to report the data to (appended to the client name) :type subname: str :keyword delta: The time delta (time.time() - time.time()) to report :type delta: float ''' ms = delta * 1000 if ms > self.min_send_threshold: name = self._get_name(self.name, subname) self.logger.info('%s: %0.08fms', name, ms) return statsd.Client._send(self, {name: '%0.08f|ms' % ms}) else: return True
[docs] def intermediate(self, subname): '''Send the time that has passed since our last measurement :keyword subname: The subname to report the data to (appended to the client name) :type subname: str ''' t = time.time() response = self.send(subname, t - self._last) self._last = t return response
[docs] def stop(self, subname='total'): '''Stop the timer and send the total since `start()` was run :keyword subname: The subname to report the data to (appended to the client name) :type subname: str ''' assert self._stop is None, ( 'Unable to stop, the timer is already stopped') self._stop = time.time() return self.send(subname, self._stop - self._start)
def __enter__(self): ''' Make a context manager out of self to measure time execution in a block of code. :return: statsd.timer.Timer ''' self.start() return self def __exit__(self, exc_type, exc_val, exc_tb): ''' Stop measuring time sending total metric, while exiting block of code. :param exc_type: :param exc_val: :param exc_tb: :return: ''' self.stop() def _decorate(self, name, function, class_=None): class_ = class_ or Timer @wraps(function) def _decorator(*args, **kwargs): timer = self.get_client(name, class_) timer.start() try: return function(*args, **kwargs) finally: # Stop the timer, send the message and cleanup timer.stop('') return _decorator
[docs] def decorate(self, function_or_name): '''Decorate a function to time the execution The method can be called with or without a name. If no name is given the function defaults to the name of the function. :keyword function_or_name: The name to post to or the function to wrap >>> from statsd import Timer >>> timer = Timer('application_name') >>> >>> @timer.decorate ... def some_function(): ... # resulting timer name: application_name.some_function ... pass >>> >>> @timer.decorate('my_timer') ... def some_other_function(): ... # resulting timer name: application_name.my_timer ... pass ''' if callable(function_or_name): return self._decorate(function_or_name.__name__, function_or_name) else: return partial(self._decorate, function_or_name)
[docs] @contextlib.contextmanager def time(self, subname=None, class_=None): '''Returns a context manager to time execution of a block of code. :keyword subname: The subname to report data to :type subname: str :keyword class_: The :class:`~statsd.client.Client` subclass to use (e.g. :class:`~statsd.timer.Timer` or :class:`~statsd.counter.Counter`) :type class_: :class:`~statsd.client.Client` >>> from statsd import Timer >>> timer = Timer('application_name') >>> >>> with timer.time(): ... # resulting timer name: application_name ... pass >>> >>> >>> with timer.time('context_timer'): ... # resulting timer name: application_name.context_timer ... pass ''' if class_ is None: class_ = Timer timer = self.get_client(subname, class_) timer.start() yield timer.stop('')