Another quick blog post today to show-case usage of riemann for in-app reporting. This small blurb will push out a metric for each wrap route with the metric name you provide.

When handlers raise exceptions, a metric is sent out as well with the exception’s message as description.

import socket import time import bernhard # [...] def wrap_riemann ( metric , client = bernhard . Client (), tags = [ 'python' ]): def riemann_decorator ( f ): @wraps ( f ) def decorated_function ( * args , ** kwargs ): host = socket . gethostname () started = time . time () try : response = f ( * args , ** kwargs ) except Exception as e : client . send ({ 'host' : host , 'service' : metric + "-exceptions" , 'description' : str ( e ), 'tags' : tags + [ 'exception' ], 'state' : 'critical' , 'metric' : 1 }) raise duration = ( time . time () - started ) * 1000 clientsend ({ 'host' : host , 'service' : metric + "-time" , 'tags' : tags + [ 'duration' ], 'metric' : duration }) return response return decorated_function return riemann_decorator

Provided you have a flask app for instance you could then have use the wrapper in the following way:

app = Flask ( __name__ ) riemann = bernhard . Client () @app.route ( '/users' ) @wrap_riemann ( 'list-users' , client = riemann ) def list_users (): # [...] @app.route ( '/users/<id>' , methods = [ 'DELETE' ]) @wrap_riemann ( 'delete-user' , client = riemann ) def delete_users (): # [...]

In riemann we can easily massage these events to give us points worth looking at:

A per route and overall mean request time

A per route and overall per second exception gauge

;; start-up servers ( tcp-server :host "0.0.0.0" ) ( udp-server :host "0.0.0.0" ) ( def graph ( graphite { :host "your.graphite.host" })) ( def index ( default { :state "ok" :ttl 60 } ( update-index ( index )))) ( periodically-expire 5 index ) ( streams ;; we're interested in events coming from the python web app ( tagged "python" ;; aggregate duration event for each interval of one second ;; then compute the mean before sending of to indexer and grapher ( tagged "duration" ;; We split by service to get one metric per route ( by [ :service ] ( fixed-time-window 1 ( combine folds/mean index graph ))) ;; unsplitted, we'll get an overall metric ( with { :service "overall-mean-duration" } ( fixed-time-window 1 ( combine folds/mean index graph )))) ;; sum exceptions per second ( tagged "exception" ( by [ :service ] ( rate 1 index graph )) ( with { :service "overall-exceptions" } ( rate 1 index graph )))))

Obviously this wrapper would work just as well for any python function. As a ways

I extended a bit on this idea and released a cleaned up version here: https://github.com/exoscale/python-riemann-wrapper.