A Python port of Github's Scientist lib.
Project description
A Python library for carefully refactoring critical paths (and a port of GitHub’s Scientist).
Why?
See GitHub’s blog post — http://githubengineering.com/scientist/
But how?
Imagine you’ve implemented a complex caching strategy for some objects in your database and a stale cache is simply not acceptable. How could you test this and ensure parity with your previous implementation, under load, with production data? Run it in production!
Laboratory will:
Run both the new and the old code
Compare their results
Record timing information about all code
Swallow and record exceptions in the new code
Publish all of this information
Of course, you’re still unsure your candidate code works correctly, so laboratory will always return the result from the control block.
import laboratory
experiment = laboratory.Experiment()
with experiment.control() as c:
c.record(get_objects_from_database())
with experiment.candidate() as c:
c.record(get_objects_from_cache())
objects = experiment.conduct()
Note that the Experiment class can also be used as a decorator.
@Experiment(candidate=get_objects_from_cache)
def get_objects_from_database():
return True
Publishing results
This data is useless unless we can do something with it. Laboratory makes no assumptions about how to do this — it’s entirely for you to implement to suit your needs. For example, timing data can be sent to graphite, and mismatches can be placed in a capped collection in redis for debugging later.
The publish method is passed a Result instance, with control and candidate data is available in Result.control and Result.observations respectively.
class MyExperiment(laboratory.Experiment):
def publish(self, result):
statsd.timing('MyExperiment.control', result.control.duration)
for o in result.observations:
statsd.timing('MyExperiment.%s' % o.name, o.duration)
Controlling comparison
Not all data is created equal. By default laboratory compares using ==, but sometimes you may need to tweak this to suit your needs. It’s easy enough — just subclass Experiment and implement the compare(control, observation) method.
class MyExperiment(Experiment):
def compare(self, control, observation):
return control.value['id'] == observation.value['id']
Adding context
A lot of the time there’s going to be extra context around an experiment that’s useful to use in publishing or comparisons. You can set this data in a few ways.
# The first is experiment-wide context, which will be set on every observation laboratory makes.
experiment = laboratory.Experiment(name='Object Cache Experiment', context={'user': user})
# Observation-specific context can be updated before or as the experiment is running.
with experiment.control(name='Object DB Strategy', context={'using': 'db'}) as e:
e.update_context({'uuid': uuid})
e.get_context()
# {
# 'user': <User>,
# 'uuid': 'c08d46f1-92a6-46e5-9185-82d90dcb5af1',
# 'using': 'db',
# }
with experiment.candidate(name='Object Cache Strategy', context={'using': 'cache'}) as e:
e.update_context({'uuid': uuid})
e.get_context()
# {
# 'user': <User>,
# 'using': 'cache',
# }
Context can be retrieved using the get_context method on Experiment and Observation classes.
class Experiment(laboratory.Experiment):
def publish(self, result):
self.get_context()
result.control.get_context()
result.observations[0].get_context()
Installation
Installing from pypi is recommended
$ pip install laboratory
Maintenance
Laboratory is actively maintained by Joe Alcorn (Github, Twitter)
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.
Source Distribution
Built Distribution
File details
Details for the file laboratory-0.4.2.tar.gz
.
File metadata
- Download URL: laboratory-0.4.2.tar.gz
- Upload date:
- Size: 5.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 67e70ea69b480c5da5385cb6006220c120a0d06b8f8d1c641dee3a4f61102704 |
|
MD5 | 2bac49dde4934bcf3e4b6641f67e0334 |
|
BLAKE2b-256 | 88cd2210449f9b9491225af3884a27fd938dc72b93db246ef3d2963226f44ed8 |
File details
Details for the file laboratory-0.4.2-py2.py3-none-any.whl
.
File metadata
- Download URL: laboratory-0.4.2-py2.py3-none-any.whl
- Upload date:
- Size: 8.2 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | e6f2a85aadbba876af03328b011602d84fea30228ef2536d0cb9ca6d6ed2cc44 |
|
MD5 | 3f1a439b7e5b677ce445f0e0ec6ecdab |
|
BLAKE2b-256 | 25fd7855e5198129ad123ff427c95d64fe133e53db099e5b1d897c3281e39f4b |