Mr. Bent knows his numbers.
Project description
A fussy little man in impeccable black jacket and pinstripe trousers.
Introduction
Mr Bent is a framework for allowing profile data to be collected in a Python application and viewed at different logical levels. The three concepts involved are a plugin, a piece of code that profiles an application, a context, a logical block of code for which you want reporting data, and a filter, a way of getting fine-grained information on where the results for a context came from.
Plugins
Plugins are callables that are given to the ‘’’mkwrapper’’’ function which applies it to a function in your application.
This looks like:
mr.bent.wrapper.mkwrapper(foo.bar, plugincallable, "myplugin")
Which will cause ‘’’plugincallable’’’ to be called on every invocation of ‘’’foo.bar’’’ and add the results of the plugin to the current context as ‘’’myplugin’’’.
Plugins can return either a number or an iterable. If it returns an iterable it must contain either strings or numbers. The case of returning a number is considered equivalent to returning an iterable of length 1 of numbers.
Contexts
A context stores data generated by plugins. At any point a new context can be started which will be a “sub-context” of the currently active context. If there is no currently active context a new top-level one will be created.
Contexts are named with the dotted name of the function that they are created around, and return their data to a callback.
This looks like:
def mycallback(context, result, stats): return "%s <!-- %s -->" % (result, `stats`) mr.bent.wrapper.mkcontext(bar.foo, mycallback)
This example would cause invocations of bar.foo, a function that returns XML, to return the XML with a repr of the context dict in a following comment.
When a context ends it returns a mapping of the data it collected. As contexts are nested each time parent contexts include the data of their sub-contexts. Hence, the top level context returns the overall profiling; there is no need to manually aggregate data.
Filters
A filter is, like most things in Mr. Bent, a wrapper around a function. This will default to the dotted name of the callable, but an alternative, application specific name can be used instead. This is especially useful for a function that is used to render multiple different logical blocks of content.
This looks like:
mr.bent.wrapper.mkfilter(take.me.to.the.foo.bar)
Concrete example
In this example we have an application that renders a page of HTML including fragments that are logically different files which are then included into the main page.
Example 1:
.-------------. | Top level | `-------------' | | .--------------------. |---------| Left hand column | | `--------------------' | | | | .-------------. | |--------------| Login box | | | `-------------' | | | | | | .------------------. | `--------------| Navigation box | | `------------------' | | .-----------------. |---------| Content block | | `-----------------' | | | .---------------------. `---------| Right hand column | `---------------------' | | .----------------. `--------------| Calendar box | `----------------'
In this system we have the following notional plugins (with short names for brevity):
- t:
A timing plugin This plugin returns the number of milliseconds between it being invoked and it being stopped
- d:
A database access counting plugin This plugin returns how many times data was retrieved from a database.
The return values may look something like this:
{'t': [5, 15, 85, 25], 'd': [0, 1, 2, 8]} .-------------. | Top level | `-------------' | {'t': [5, 15], 'd': [0,1]} | .--------------------. |---------| Left hand column | | `--------------------' | | {'t': [5], 'd': [0]} | | .-------------. | |--------------| Login box | | | `-------------' | | | | {'t': [15], 'd': [1]} | | .------------------. | `--------------| Navigation box | | `------------------' | {'t': [85], 'd': [2]} | .-----------------. |---------| Content block | | `-----------------' | | {'t': [25], 'd': [8]} | .---------------------. `---------| Right hand column | `---------------------' | {'t': [25], 'd': [8]} | .----------------. `--------------| Calendar box | `----------------'
Hence, the user has data at each level he has defined which he can then process as he likes.
Lets see that again as a doctest (sorry Florian!):
>>> from mr.bent.mavolio import create, destroy, current >>> create("top") # Create the top level context >>> create("lefthand") # Create the left hand column >>> create("login") # and the login portlet >>> current() # show that it's an empty context {} >>> current()['t'] = [5] # Simulate plugin results being added to context >>> current()['d'] = [0] >>> destroy() # Leave context {'t': [5], 'd': [0]} >>> create("nav") # Create nav >>> current()['t']=[15] >>> current()['d']=[1] >>> destroy() # Leave nav {'t': [15], 'd': [1]} >>> destroy() # Leave left hand column {'t': [5, 15], 'd': [0, 1]} >>> create("content") # Enter content block >>> current()['t'] = [85] >>> current()['d'] = [2] >>> destroy() # Leave content block {'t': [85], 'd': [2]} >>> create("righthand") # Enter right hand column >>> create("cal") # Enter calendar box >>> current()['t']=[25] >>> current()['d']=[8] >>> destroy() # Leave calendar {'t': [25], 'd': [8]} >>> destroy() # Leave right hand column {'t': [25], 'd': [8]} >>> destroy() # Leave the top level context, get totals {'t': [5, 15, 85, 25], 'd': [0, 1, 2, 8]}
Method reference
Utility Methods
- mr.bent.wrapper.mkwrapper(function, plugin, name):
Wraps a function with a plugin which writes its data to the current context as name
- mr.bent.wrapper.mkcontext(function, callback):
Wraps a function to create a new context on invocation, and close it when it finishes, and give the data to callback to handle reporting.
- mr.bent.wrapper.mkfilter(function):
Wraps a function to be a key that context reporting data can be filtered on.
Low level methods
- mr.bent.mavolio.create(name):
Creates a new context called name.
- mr.bent.mavolio.destroy():
Ends the current context and returns the statistics.
- mr.bent.mavolio.current():
Returns the current, in progress, context dict.
Changelog
1.0a1 - Unreleased
Initial release [matthewwilkes, fschulze, witsch]
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.