• Stars
    star
    920
  • Rank 49,289 (Top 1.0 %)
  • Language
    Python
  • License
    Apache License 2.0
  • Created about 13 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

scales - Metrics for Python

scales - Metrics for Python

Travis build status

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.

This is a brand new release - issue reports and pull requests are very much appreciated!

Installation

You can get a release from PyPI:

pip install scales

Or you can get it from GitHub:

git clone https://github.com/Cue/scales

cd scales

python setup.py install

The HTTP statistics viewer in scales requires one of the following web frameworks:

Flask

Tornado

Twisted

If you aren't sure, go with Flask; it's compatible with most every other event loop. You can get it with pip install flask.

Scales is tested with Python 2.7 and 3.3. For some reason it does not work with PyPy; pull requests for this are welcome, if you can figure out what's up.

How to use it

Getting started and adding stats only takes a few lines of code:

from greplin import scales

STATS = scales.collection('/web',
    scales.IntStat('errors'),
    scales.IntStat('success'))

# In a request handler

STATS.success += 1

This code will collect two integer stats, which is nice, but what you really want to do is look at those stats, to get insight into what your server is doing. There are two main ways of doing this: the HTTP server and Graphite logging.

The HTTP server is the simplest way to get stats out of a running server. The easiest way, if you have Flask installed, is to do this:

import greplin.scales.flaskhandler as statserver
statserver.serveInBackground(8765, serverName='something-server-42')

This will spawn a background thread that will listen on port 8765, and serve up a very convenient view of all your stats. To see it, go to

http://localhost:8765/status/

You can also get the stats in JSON by appending ?format=json to the URL. ?format=prettyjson is the same thing, but pretty-printed.

The HTTP server is good for doing spot checks on the internals of running servers, but what about continuous monitoring? How do you generate graphs of stats over time? This is where Graphite comes in. Graphite is a server for collecting stats and graphing them, and scales has easy support for using it. Again, this is handled in a background thread:

graphitePeriodicPusher = graphite.GraphitePeriodicPusher('graphite-collector-hostname', 2003, 'my.server.prefix.')
graphitePeriodicPusher.allow("*") # Logs everything to graphite
graphitePeriodicPusher.start()

That's it! Numeric stats will now be pushed to Graphite every minute. Note that, by default, if you don't use allow, nothing is logged to graphite.

You can also exclude stats from graphite logging with the forbid(prefix) method of the GraphitePeriodicPusher class.

Timing sections of code

To better understand the performance of certain critical sections of your code, scales lets you collect timing information:

from greplin import scales

STATS = scales.collection('/web',
    scales.IntStat('errors'),
    scales.IntStat('success'),
    scales.PmfStat('latency'))

# In a request handler

with STATS.latency.time():
  do_something_expensive()

This will collect statistics on the running times of that section of code: mean time, median, standard deviation, and several percentiles to help you locate outlier times. This happens in pretty small constant memory, so don't worry about the cost; time anything you like.

You can gather this same kind of sample statistics about any quantity. Just make a PmfStat and assign new values to it:

for person in people:
  person.perturb(42)
  STATS.wistfulness = person.getFeelings('wistfulness')

Metering Rates

Scales can track 1/5/15 minute averages with MeterStat:

from greplin.scales.meter import MeterStat

STATS = scales.collection('/web', MeterStat('hits'))

def handleRequest(..):
  STATS.hits.mark() # or .mark(NUMBER), or STATS.hits = NUMBER

Class Stats

While global stats are easy to use, sometimes making stats class-based makes more sense. This is supported; just make sure to give each instance of the class a unique identifier with scales.init.

class Handler(object):

  requests = scales.IntStat('requests')
  latency = scales.PmfStat('latency')
  byPath = scales.IntDictStat('byPath')

  def __init__(self):
    scales.init(self, '/handler')


  def handleRequest(self, request):
    with self.latency.time():
      doSomething()
    self.requests += 1
    self.byPath[request.path] += 1

Gauges

Simple lambdas can be used to generate stat values.

STATS = scales.collection(scales.Stat('currentTime', lambda: time.time())

Of course this works with arbitrary function objects, so the example above could also be written:

STATS = scales.collection(scales.Stat('currentTime', time.time)

Hierarchical Stats + Aggregation

Stats can inherit their path from the object that creates them, and (non-gauge) stats can be aggregated up to ancestors.

class Processor(object):
  """Example processing management object."""

  threadStates = scales.HistogramAggregationStat('state')
  finished = scales.SumAggregationStat('finished')

  def __init__(self):
    scales.init(self, '/processor')
    self.threads = 0


  def createThread(self):
    threadId = self.threads
    self.threads += 1
    SomeThread(threadId).start()



class SomeThread(object):
  """Stub of a processing thread object."""

  state = scales.Stat('state')
  finished = scales.IntStat('finished')


  def __init__(self, threadId):
    scales.initChild(self, 'thread-%d' % threadId)


  def processingLoop(self):
    while True:
      self.state = 'waitingForTask'
      getTask()
      self.state = 'performingTask'
      doTask()
      self.finished += 1

This will result in a stat at the path /processor/finished which counts the total of the finished stats in each SomeThread object, as well as per-object stats with paths like /processor/thread-0/finished. There will also be stats like /processor/state/waitingForTask which aggregates the number of threads in the waitingForTask state.

Authors

Greplin, Inc.

License

Copyright 2011 The scales Authors.

Published under The Apache License, see LICENSE

More Repositories

1

hookshot

Instrumentation for Objective C for debugging and profiling
Objective-C
392
star
2

ocstyle

Objective-C style checker
Python
255
star
3

fast-python-pb

Fast Protocol Buffers in python (by using the C++ API)
Python
250
star
4

TheKitchenSync

A Tool Belt for iOS Concurrency
Objective-C
197
star
5

greplin-bloom-filter

Java implementation of a probabilistic set data structure
Java
141
star
6

hop

Script to hop to common directories and servers
Lua
112
star
7

greplin-lucene-utils

Some utilities for Lucene
Java
111
star
8

CueTableReloader

A really handy class that automatically figures out insertions, deletions, and reloads in UITableView based on unique item keys.
Objective-C
92
star
9

greplin-exception-catcher

Exception catcher that runs on Google App Engine
Python
74
star
10

greplin-tornado-ses

An asynchronous client for Amazon SES
Python
42
star
11

greplin-zookeeper-utils

Utilities for dealing with Apache Zookeeper
Java
41
star
12

greplin-nagios-utils

Utilities for monitoring with Nagios
Python
39
star
13

lucene-interval-fields

Lucene fields and queries for interval fields.
Java
37
star
14

greplin-tornado-sendgrid

A client for the Sendgrid API
Python
32
star
15

greplin-twisted-utils

Utilities for working with Twisted
Python
28
star
16

qc

QuickCheck for Python
Python
27
star
17

greplin-tornado-stripe

Tornado bindings for Stripe's API
Python
27
star
18

polarbear

OOM diagnostics for Java.
C++
21
star
19

greplin-tornado-mixpanel

A client for the Mixpanel API
Python
20
star
20

greplin-tornado-kissmetrics

A client for the Kissmetrics API
Python
17
star
21

evernote-python-api

Packaged version of latest Evernote Python API
Python
14
star
22

htmltotext

Fork of flaxcode htmltotext module
C++
13
star
23

jsnappy

Java implementation of the Snappy compression/decompression algorithm from Google.
Java
11
star
24

phpserialize

PHP style serialize and unserialize in Python
Python
6
star
25

hegemon

(java)script utilities
Java
5
star
26

skia

Fork of Google's Skia library
C++
4
star
27

pyiso8601

Forked version of pyiso8601 - http://code.google.com/p/pyiso8601
Python
3
star
28

eventlet

Fork of eventlet with patches from Greplin
Python
3
star
29

greplin-vobject

Greplin fork of vobject
Python
2
star
30

hegemon-example

Java
1
star