snap_stats.py :  » Development » SnapLogic » snaplogic » common » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Development » SnapLogic 
SnapLogic » snaplogic » common » snap_stats.py
# $SnapHashLicense:
# 
# SnapLogic - Open source data services
# 
# Copyright (C) 2009, SnapLogic, Inc.  All rights reserved.
# 
# See http://www.snaplogic.org for more information about
# the SnapLogic project. 
# 
# This program is free software, distributed under the terms of
# the GNU General Public License Version 2. See the LEGAL file
# at the top of the source tree.
# 
# "SnapLogic" is a trademark of SnapLogic, Inc.
# 
# $
#
# $Id: snap_stats.py 7363 2009-04-24 17:35:55Z pamor $

from snaplogic.common.snap_exceptions import *

"""
The SnapLogic stats module.

"""

import time

from snaplogic.cc.prop import SimpleProp

enforce_singleton = True

_instance = None

# The possible types for statistics
_STAT_TYPE_COUNTER = 1
_STAT_TYPE_FIELD   = 2

# The known types that we support for stats
_known_types = [ 'number', 'boolean', 'string' ]


def get_instance():
    """
    Return the single instance of the stats object in this process.

    If no instance exists yet then it returns None.

    """
    return _instance    



class SnapStatObject(object):
    """
    A class to store the definition, value and some
    additional information for an individual stat.

    Specifically, we store the SimpleProp of the stat, the current
    value, the type of stat and the permissable data types for the
    value.

    There can be more than one permissable data type. For example,
    while the SimpleProp may say only "number", the permissable types
    are 'int' and 'float'. We start out with an int, but if a float
    value is assigned or added to the counter then we will cast to
    a float. For example.

    """
    def __init__(self, prop, stat_type, permissable_types, initial_value):
        """
        Initialize stats object.

        @param prop:              The SimpleProp that defines the stat.
        @type  prop:              L{SimpleProp}

        @param stat_type:         The type of stat (counter or field) indicated
                                  by _STAT_TYPE_COUNTER or _STAT_TYPE_FIELD.
        @type  stat_type:         integer

        @param permissable_types: A list of permissable types for this stat.
        @type  permissable_types: list

        @param initial_value:     The initial value of the statistic.
        @type  initial_value:     int, float, str or bool

        """
        self._prop              = prop
        self._stat_type         = stat_type
        self._permissable_types = permissable_types
        self._value             = initial_value
        

    def set(self, value):
        """
        Set the stat to a specific value.

        @param value:   The value to which the stat should be set.
        @type  value:   int, float, string or bool

        """
        if type(value) not in self._permissable_types:
            raise SnapObjTypeError("Trying to set stat to type '%s', but only types '%s' are allowed." % (type(value), self._permissable_types))
        self._value = value


    def get(self):
        """
        Return the current value of the stat.

        @return:    The current stat value.
        @rtype:     int, float, string or bool

        """
        return self._value


    def __repr__(self):
        return str(self.get())


class SnapStatCounterObject(SnapStatObject):
    """
    Specialization of the stat object for counters.

    Counters also have functions for increasing and decreasing
    of the stat value.

    """
    def inc(self, inc_value=1):
        """
        Increase the counter value by the specified amount.

        If no increase-value is specified, the counter will be
        increased by one.

        @param inc_value: The amount by which the counter should
                          be increased. Default: 1.
        @type  inc_value: int or float

        """
        if type(inc_value) not in self._permissable_types:
            raise SnapObjTypeError("Trying to increment counter with type '%s', but only types '%s' are allowed." % (type(inc_value), self._permissable_types))
        self._value += inc_value


    def dec(self, dec_value=1):
        """
        Decrease the counter value by the specified amount.

        If no decrease-value is specified, the counter will be
        decreased by one.

        @param dec_value: The amount by which the counter should
                          be decreased. Default: 1.
        @type  dec_value: int or float

        """
        if type(dec_value) not in self._permissable_types:
            raise SnapObjTypeError("Trying to decrement counter with type '%s', but only types '%s' are allowed." % (type(dec_value), self._permissable_types))
        self._value -= dec_value


class SnapStatsGroup(object):
    """
    A module specific group of stats.

    Each module in the system can create a SnapStatsGroup object and
    add its own particular stats to it. The group object is registered
    with the SnapStats singleton. New stats may be added or old ones
    removed even after it has been registered.

    After registration, the module can forget about SnapStats. It only
    needs a handle on its SnapStatsGroup object, which it then uses
    to update the various stats, add or remove them.

    """
    def __init__(self, name):
        """
        Create a new stats-group object with the specified name.

        The name could be a module identifier. It is visible to the user
        that retrieves stats from the system. The stats in this stats
        group will be listed under the name of the stats group that is
        specified here.

        @param  name:   The name of the stats group. Most commonly, this
                        should be a module identifier. For example
                        "Repository", which will appear as 'headline' of
                        the repository-related stats when the stats are
                        retrieved and displayed.
        @type   name:   string

        """
        self.name   = name
        self._stats = {}


    def _add_stat(self, prop, stat_type, start_value=None):
        """
        Add a new statistic to the stats group.

        This is an internal utility function, which is called by more
        specific public equivalents.

        @param prop:              A SimpleProp definition of a new statistic.
        @type  prop:              L{SimpleProp}

        @param stat_type:         The type of stat, either a counter or a field.
        @type  stat_type:         Integer, either _STAT_TYPE_COUNTER or
                                  _STAT_TYPE_FIELD as value.

        @param start_value:       A data item that represent the initial value
                                  of the stat. This data item has to have an acceptable
                                  type, as implied by the simple_type field of SimpleProp.
                                  Specifically, for "number" it can be 'int' or 'float',
                                  for "boolean" it has to be 'bool' and for "string" it
                                  has to be 'str'. A "datetime" type is not currently
                                  allowed.
        @type  start_value:       int, float, str or bool

        @return:                  Reference to the newly created stats object.
        @rtype:                   L{SnapStatObject}

        """
        # A given name can only exist once in a stat group
        if prop.label_str in self._stats:
            raise SnapObjExistsError("A statistic with the name '%s' already exists in the stats-group '%s'." % (prop.label_str, self.name))

        # Determine the allowable types and possible default values, based on the
        # type definition in the SimpleProp
        if prop.simple_type == "number":
            permissable_types = [ int, float ]
            default           = 0
        elif prop.simple_type == "boolean":
            permissable_types = [ bool ]
            default           = False
        elif prop.simple_type == "string":
            permissable_types = [ str ]
            default           = ""
        else:
            raise SnapObjTypeError("Type '%s' not allowed for SimpleProps used as stats." % (prop.simple_type))

        # If a start-value for the stat was specified, check that the type
        # of the start-value and the type defined in the SimpleProp agree.
        if start_value:
            if type(start_value) not in permissable_types:
                raise SnapObjTypeError("You specified a default value with type '%s', but only types '%s' are allowed." % (type(start_value), permissable_types))
        else:
            start_value = default
                
        # Create and store the stats object
        if stat_type == _STAT_TYPE_COUNTER:
            self._stats[prop.label_str] = SnapStatCounterObject(prop, stat_type, permissable_types, start_value)
        else:
            self._stats[prop.label_str] = SnapStatObject(prop, stat_type, permissable_types, start_value)

        return self._stats[prop.label_str]


    def add_counter_stat_with_prop(self, prop, start_value=None):
        """
        Add a new counter statistic to the stats group.

        A statistic is defined via a SimpleProp, which for a counter
        statistic needs to be of type "number".

        This function needs a user-defined SimpleProp definition. If
        the calling program doesn't want to bother with the SimpleProps,
        it can use add_counter_stat() as a
        convenience function.

        Counters can be increased and decreased, and also set.

        @param prop:        The SimpleProp definition of the statistic.
        @type  prop:        L{SimpleProp}

        @param start_value: The initial value of the counter.
                            Can be left blank in which case the
                            counter is initialized to 0.
        @type  start_value  int or float

        @return:            Reference to the newly created stats object.
        @rtype:             L{SnapStatCounterObject}

        """
        if prop.simple_type != "number":
            raise SnapObjTypeError("A counter statistic requires a SimpleProp of type 'number'. Instead '%s' was specified as type." % prop.simple_type)
        return self._add_stat(prop, _STAT_TYPE_COUNTER, start_value)


    def add_counter_stat(self, name, start_value=None):
        """
        Add a new counter statistic to the stats group.

        A statistic is defined via a SimpleProp, which for a counter
        statistic needs to be of type "number".

        Counters can be increased and decreased, and also set.

        @param name:        The name of the new stat.
        @type  name:        string

        @param start_value: The initial value of the counter.
                            Can be left blank in which case the
                            counter is initialized to 0.
        @type  start_value  int or float

        @return:            Reference to the newly created stats object.
        @rtype:             L{SnapStatCounterObject}

        """
        tprop = SimpleProp(name, "number", "")
        return self._add_stat(tprop, _STAT_TYPE_COUNTER, start_value)


    def add_field_stat_with_prop(self, prop, start_value=None):
        """
        Add a new field statistic to the stats group.

        A field statistic can only be set, but not increased
        or decreased. This function needs a user-defined SimpleProp
        definition. If the calling program doesn't want to bother
        with the SimpleProps, it can use add_field_stat() as a
        convenience function.

        @param prop:        The SimpleProp definition of the statistic.
        @type  prop:        L{SimpleProp}

        @param start_value: The initial value of the stat. Can be left
                            blank in which case it will be initialized
                            to a type-appropriate 'empty' or zero value.
        @type  start_value  int, float, str or bool

        @return:            Reference to the newly created stats object.
        @rtype:             L{SnapStatObject}

        """
        return self._add_stat(prop, _STAT_TYPE_FIELD, start_value)


    def add_field_stat(self, name, type, start_value=None):
        """
        Add a new field statistic to the stats group.

        A field statistic can only be set, but not increased
        or decreased.

        @param name:        The name of the new stat.
        @type  name:        string

        @param type:        The type of the stat, which is either
                            "number", "boolean" or "string"
        @type  type:        string

        @param start_value: The initial value of the stat. Can be left
                            blank in which case it will be initialized
                            to a type-appropriate 'empty' or zero value.
        @type  start_value  int, float, str or bool

        @return:            Reference to the newly created stats object.
        @rtype:             L{SnapStatObject}

        """
        if type not in _known_types:
            raise SnapObjTypeError("Only '%s' are allowable types. You specified '%s'." % (_known_types, type))
        tprop = SimpleProp(name, type, "")
        return self.add_field_stat_with_prop(tprop, start_value)


    def delete_stat(self, name):
        """
        Delete the stat with the specified name.

        @param name:    Name of stat.
        @ptype name:    string

        """
        try:
            del self._stats[name]
        except:
            raise SnapObjNotFoundError("Cannot delete non-existing stat '%s' from stat group '%s'." % (name, self.name))


    def get_stat(self, name):
        """
        Return reference to the stat object of the given name.

        Any operations on the stat value should be done on the
        returned stats object itself.

        @param name:    Name of the stat, as originally specified in
                        the SimpleProp label field.
        @type  name:    string

        """
        try:
            return self._stats[name]
        except:
            raise SnapObjNotFoundError("A stat with name '%s' cannot be found in stats group '%s'." % (name, self.name))


    def get_stat_names(self):
        """
        Return list of the names of all stats in this group.

        @return:    List of stat names.
        @rtype:     list

        """
        return self._stats.keys()


    def get_complete_group(self):
        """
        Return a dictionary of name/value pairs for each stat in this group.

        @return:    Dictionary with stat names and values.
        @rtype      dict

        """
        d = {}
        for e in self._stats:
            d[e] = self._stats[e].get()
        return d


class SnapStats(object):
    """
    The stats object.

    One instance of this needs to be created by each process.

    """

    def __init__(self):
        """
        Initialize stats object.

        Enforces singleton.

        """
        global _instance

        if _instance and enforce_singleton:
            raise SnapObjExistsError("Attempting creation of duplicate stats singleton.")

        self._stat_groups = {}

        _instance = self


    def add_stats_group(self, group):
        """
        Add a stats group to the stats object.

        Each system module can define its own group of stats. Stats can
        be either counters (which can be set, increased and decreased) or
        they can be fields (which can only be set).

        """
        if group.name in self._stat_groups:
            raise SnapObjExistsError("A stats-group with the name '%s' has already been registered." % (group.name))

        self._stat_groups[group.name] = group


    def get_stats_group(self, name):
        """
        Return reference to the stat group with specified name.

        @return:    Reference to stats group object.
        @rtype:     L{SnapStatsGroup}

        """
        try:
            return self._stat_groups[name]
        except:
            raise SnapObjNotFoundError("A stat-group with name '%s' cannot be found." % (name))


    def get_stats_group_names(self):
        """
        Return list with all stat group names.

        @return:    List of stat group names.
        @rtype:     list

        """
        return self._stat_groups.keys()


    def get_all_groups(self):
        """
        Return dictionary with stats dictionaries from all groups.

        @return:    Dictionary with group names and stat dictionaries
                    for each group.
        @rtype      dict

        """
        d = {}
        for e in self._stat_groups:
            d[e] = self._stat_groups[e].get_complete_group()
        return d

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.