Reputation: 7669
I'm looking for a performance metrics library in python.
I'm familiar with metrics by Coda Hale, which is written for the JVM and so I wonder if there's a python equivalent for that (and which does not utilize the JVM).
In short, the list of requirements from the tool would be:
So far I'd found PyCounters which does some of the job, but not all of it. It sort of satisfies my first bullet (but it doesn't have all the metric types, just three) and that's all.
Is there a better alternative to PyCounters?
Thanks
Upvotes: 12
Views: 5758
Reputation: 18649
I came across this library, which is a port of CodaHale metrics for python.
There is some stuff missing i.e. reporters but it does most other things.
https://github.com/omergertel/pyformance/
Shameless plug, here is my fork which adds a hosted graphite reporter. It should be trivial to add reporters to other systems.
https://github.com/usmanismail/pyformance
Upvotes: 6
Reputation: 2365
Haven't had the chance to try it out, but I came across this one a few days ago: https://github.com/Cue/scales
scales - Metrics for Python Tracks server state and statistics, allowing you to see what your server is doing. It can also send metrics to Graphite for graphing or to a file for crash forensics.
scales is inspired by the fantastic metrics library, though it is by no means a port.
Upvotes: 3
Reputation: 491
I'm not aware of something that does exactly that but I did write something a while back for a project that does that by simply adding decorators to the relevant functions.
I created a set of decorators for measuring runtime of functions, measuring time for DB access functions, etc.
An example of such a decorator is this:
def func_runtime(method):
@functools.wraps(method)
def wrapper(self, *args, **kwargs):
start_time = datetime.datetime.utcnow()
try:
class_name = type(self).__name__
method_name = method.__name__
return method(self, *args, **kwargs)
finally:
end_time = datetime.datetime.utcnow() - start_time
time_taken_ms = end_time.microseconds / 1000
if _statsd:
# Send the data to statsD, but you can do that for CopperEgg or anything else
self.stats.timing("func.runtime.%s.%s" % (class_name, method_name), time_taken_ms)
Later you would use it like this:
@func_runtime
def myfunc(a, b, c):
pass
I also added a decorator for functions that read from the DB and functions that write to the DB so I can get graphs on how much time the code spent on waiting to read data or write data as well as # of times I called "read" operations and "write" operations.
So, all in all I had the following decorators: - @func_runtime - to measure the runtime of a function - @func_dbread - places on functions that performs reads. Increments a database.reads counter as well as send a timing data to read_timing - @func_dbwrite - the same as @func_dbread but for writes - @func dbruntime - used to measure the runtime of DB specific functions as well as # of calls and total timing of all DB functions
You can combine decorators and they run in the order which is closest to the function, for example:
@func_dbruntime
@func_dbread
def some_db_read_function(a, b, c,d):
pass
So, @func_dbread runs before @func_dbruntime.
All in all, its easily customisable and VERY powerful and you can extend it to support 3rd party services as well as add code to dynamically turn these counters on and off whenever relevant. As far as I could tell, the performance penalty was minimal at best.
Just a notice about sending data to places like CopperEgg and other services, StatsD uses UDP and since its statistics you can lose some data and still get meaningful insights and it won't block anything. If you want to send data to 3rd party sites like CopperEgg I would consider sending the data to a local queue and then pushing it with a different process to CopperEgg just to decouple 3rd party services issues from your own.
Personally, for such data, StatsD is great and graphite gives you all the things you need including 90th percentile, average, max, graphing abilities, etc and basically have most of the counter types you require.
Upvotes: 3