diff options
-rw-r--r-- | doc/development/plugins.txt | 35 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugin/helpers.py | 8 | ||||
-rw-r--r-- | src/lib/Bcfg2/Statistics.py | 56 |
3 files changed, 87 insertions, 12 deletions
diff --git a/doc/development/plugins.txt b/doc/development/plugins.txt index 183126053..a680e7d04 100644 --- a/doc/development/plugins.txt +++ b/doc/development/plugins.txt @@ -156,6 +156,41 @@ For examples, see: :ref:`server-plugins-connectors-puppetenc` plugin is incompatible with aggressive caching. +Tracking Execution Time +----------------------- + +.. versionadded:: 1.3.0 + +Statistics can and should track execution time statistics using +:mod:`Bcfg2.Statistics`. This module tracks execution time for the +server core and for plugins, and exposes that data via ``bcfg2-admin +perf``. This data can be invaluable for locating bottlenecks or other +performance issues. + +The simplest way to track statistics is to use the +:func:`Bcfg2.Server.Plugin.helpers.track_statistics` decorator to +decorate functions that you would like to track execution times for: + +.. code-block:: python + + from Bcfg2.Server.Plugin import track_statistics + + @track_statistics() + def do_something(self, ...): + ... + +This will track the execution time of ``do_something``. + +More granular usage is possible by using :func:`time.time` to manually +determine the execution time of a given event and calling +:func:`Bcfg2.Statistics.Statistics.add_value` with an appropriate +statistic name. + +Bcfg2.Statistics +^^^^^^^^^^^^^^^^ + +.. automodule:: Bcfg2.Statistics + Plugin Helper Classes --------------------- diff --git a/src/lib/Bcfg2/Server/Plugin/helpers.py b/src/lib/Bcfg2/Server/Plugin/helpers.py index 5bc79a29a..131b572a4 100644 --- a/src/lib/Bcfg2/Server/Plugin/helpers.py +++ b/src/lib/Bcfg2/Server/Plugin/helpers.py @@ -81,13 +81,15 @@ def bind_info(entry, metadata, infoxml=None, default=DEFAULT_FILE_METADATA): class track_statistics(object): # pylint: disable=C0103 """ Decorator that tracks execution time for the given - :class:`Plugin` method for reporting via ``bcfg2-admin perf`` """ + :class:`Plugin` method with :mod:`Bcfg2.Statistics` for reporting + via ``bcfg2-admin perf`` """ def __init__(self, name=None): """ :param name: The name under which statistics for this function - will be tracked. By default the name of the - function will be used. + will be tracked. By default, the name will be + the name of the function concatenated with the + name of the class the function is a member of. :type name: string """ # if this is None, it will be set later during __call_ diff --git a/src/lib/Bcfg2/Statistics.py b/src/lib/Bcfg2/Statistics.py index 140c2557e..a869b03cd 100644 --- a/src/lib/Bcfg2/Statistics.py +++ b/src/lib/Bcfg2/Statistics.py @@ -1,11 +1,20 @@ -""" module for tracking execution time statistics from the bcfg2 -server core """ +""" Module for tracking execution time statistics from the Bcfg2 +server core. This data is exposed by +:func:`Bcfg2.Server.Core.BaseCore.get_statistics`.""" class Statistic(object): - """ a single named statistic, tracking minimum, maximum, and - average execution time, and number of invocations """ + """ A single named statistic, tracking minimum, maximum, and + average execution time, and number of invocations. """ + def __init__(self, name, initial_value): + """ + :param name: The name of this statistic + :type name: string + :param initial_value: The initial value to be added to this + statistic + :type initial_value: int or float + """ self.name = name self.min = float(initial_value) self.max = float(initial_value) @@ -13,32 +22,61 @@ class Statistic(object): self.count = 1 def add_value(self, value): - """ add a value to the statistic """ + """ Add a value to the statistic, recalculating the various + metrics. + + :param value: The value to add to this statistic + :type value: int or float + """ self.min = min(self.min, value) self.max = max(self.max, value) self.ave = (((self.ave * (self.count - 1)) + value) / self.count) self.count += 1 def get_value(self): - """ get a tuple of all the stats tracked on this named item """ + """ Get a tuple of all the stats tracked on this named item. + The tuple is in the format:: + + (<name>, (min, max, average, number of values)) + + This makes it very easy to cast to a dict in + :func:`Statistics.display`. + + :returns: tuple + """ return (self.name, (self.min, self.max, self.ave, self.count)) class Statistics(object): - """ A collection of named statistics """ + """ A collection of named :class:`Statistic` objects. """ + def __init__(self): self.data = dict() def add_value(self, name, value): - """ add a value to the named statistic """ + """ Add a value to the named :class:`Statistic`. This just + proxies to :func:`Statistic.add_value` or the + :class:`Statistic` constructor as appropriate. + + :param name: The name of the :class:`Statistic` to add the + value to + :type name: string + :param value: The value to add to the Statistic + :type value: int or float + """ if name not in self.data: self.data[name] = Statistic(name, value) else: self.data[name].add_value(value) def display(self): - """ return a dict of all statistics """ + """ Return a dict of all :class:`Statistic` object values. + Keys are the statistic names, and values are tuples of the + statistic metrics as returned by + :func:`Statistic.get_value`. """ return dict([value.get_value() for value in list(self.data.values())]) +#: A module-level :class:`Statistics` objects used to track all +#: execution time metrics for the server. stats = Statistics() # pylint: disable=C0103 |