Merge lp:~james-w/python-oops-celery/hooks-based into lp:python-oops-celery

Proposed by James Westby
Status: Merged
Approved by: James Westby
Approved revision: 6
Merged at revision: 4
Proposed branch: lp:~james-w/python-oops-celery/hooks-based
Merge into: lp:python-oops-celery
Prerequisite: lp:~james-w/python-oops-celery/oops-reporter
Diff against target: 165 lines (+64/-25)
2 files modified
oops_celery/oops_reporter.py (+10/-8)
oops_celery/tests/test_oops_reporter.py (+54/-17)
To merge this branch: bzr merge lp:~james-w/python-oops-celery/hooks-based
Reviewer Review Type Date Requested Status
Sidnei da Silva (community) Approve
Review via email: mp+90312@code.launchpad.net

Commit message

Switch to a hooks-based approach for populating the report.

Description of the change

Hi,

I switched to be more like python-oops-wsgi and use hooks for
populating the report.

This both makes the code a bit simpler, and allows more flexibility
for people to re-use only parts of the code.

Thanks,

James

To post a comment you must log in.
6. By James Westby

Merged oops-reporter into hooks-based.

Revision history for this message
Sidnei da Silva (sidnei) wrote :

Looks great, +1!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'oops_celery/oops_reporter.py'
--- oops_celery/oops_reporter.py 2012-01-26 19:14:26 +0000
+++ oops_celery/oops_reporter.py 2012-01-26 19:14:27 +0000
@@ -1,26 +1,28 @@
1from celery import signals1from celery import signals
22
33
4def attach_celery_info(report, context):
5 for key, value in context.items():
6 if key.startswith('celery.'):
7 report[key] = value
8
9
4class TaskOopsReporter(object):10class TaskOopsReporter(object):
511
6 def __init__(self, config):12 def __init__(self, config):
7 self.config = config13 self.config = config
814
9 def on_failure(self, signal=None, sender=None, task_id=None, exception=None,15 def on_failure(self, einfo=None, **kwargs):
10 args=None, kwargs=None, einfo=None, traceback=None):
11 context = dict()16 context = dict()
12 if einfo is not None:17 if einfo is not None:
13 context['exc_info'] = einfo.exc_info18 context['exc_info'] = einfo.exc_info
19 for key, value in kwargs.items():
20 context['celery.' + key] = value
14 report = self.config.create(context)21 report = self.config.create(context)
15 report.update({
16 'celery.task_id': task_id,
17 'celery.task_args': args,
18 'celery.task_kwargs': kwargs,
19 'celery.sender': sender,
20 })
21 self.config.publish(report)22 self.config.publish(report)
2223
2324
24def setup_oops_reporter(config):25def setup_oops_reporter(config):
26 config.on_create.append(attach_celery_info)
25 reporter = TaskOopsReporter(config)27 reporter = TaskOopsReporter(config)
26 signals.task_failure.connect(reporter.on_failure, weak=False)28 signals.task_failure.connect(reporter.on_failure, weak=False)
2729
=== modified file 'oops_celery/tests/test_oops_reporter.py'
--- oops_celery/tests/test_oops_reporter.py 2012-01-26 19:14:26 +0000
+++ oops_celery/tests/test_oops_reporter.py 2012-01-26 19:14:27 +0000
@@ -6,7 +6,32 @@
6import oops6import oops
7from testtools import TestCase7from testtools import TestCase
88
9from oops_celery.oops_reporter import setup_oops_reporter, TaskOopsReporter9from oops_celery.oops_reporter import (
10 attach_celery_info,
11 setup_oops_reporter,
12 TaskOopsReporter,
13 )
14
15
16class AttachCeleryInfoTests(TestCase):
17
18 def test_adds_all_celery_keys(self):
19 context = {
20 'celery.foo': 'foo',
21 'celery.bar': 'bar',
22 }
23 report = {}
24 attach_celery_info(report, context)
25 self.assertEqual(context, report)
26
27 def test_doesnt_add_non_celery_keys(self):
28 context = {
29 'celery': 'foo',
30 'bar': 'bar',
31 }
32 report = {}
33 attach_celery_info(report, context)
34 self.assertEqual({}, report)
1035
1136
12class TaskOopsReporterTests(TestCase):37class TaskOopsReporterTests(TestCase):
@@ -27,11 +52,15 @@
27 def get_oops_config(self):52 def get_oops_config(self):
28 config = oops.Config()53 config = oops.Config()
29 config.publishers.append(self.store_oops)54 config.publishers.append(self.store_oops)
55 config.on_create.append(self.collect_context)
30 return config56 return config
3157
32 def store_oops(self, oops):58 def store_oops(self, oops):
33 self.oopses.append(oops)59 self.oopses.append(oops)
3460
61 def collect_context(self, report, context):
62 self.context = context
63
35 def test_on_failure_publishes_oops(self):64 def test_on_failure_publishes_oops(self):
36 einfo = self.get_einfo()65 einfo = self.get_einfo()
37 self.recorder.on_failure()66 self.recorder.on_failure()
@@ -41,19 +70,19 @@
41 einfo = self.get_einfo()70 einfo = self.get_einfo()
42 task_id = 'atask'71 task_id = 'atask'
43 self.recorder.on_failure(task_id=task_id)72 self.recorder.on_failure(task_id=task_id)
44 self.assertEqual(task_id, self.oopses[0]['celery.task_id'])73 self.assertEqual(task_id, self.context['celery.task_id'])
4574
46 def test_on_failure_includes_args(self):75 def test_on_failure_includes_args(self):
47 einfo = self.get_einfo()76 einfo = self.get_einfo()
48 args = [8, 9]77 args = [8, 9]
49 self.recorder.on_failure(args=args)78 self.recorder.on_failure(args=args)
50 self.assertEqual(args, self.oopses[0]['celery.task_args'])79 self.assertEqual(args, self.context['celery.args'])
5180
52 def test_on_failure_includes_kwargs(self):81 def test_on_failure_includes_kwargs(self):
53 einfo = self.get_einfo()82 einfo = self.get_einfo()
54 kwargs = dict(a=1, b=2)83 kwargs = dict(a=1, b=2)
55 self.recorder.on_failure(kwargs=kwargs)84 self.recorder.on_failure(kwargs=kwargs)
56 self.assertEqual(kwargs, self.oopses[0]['celery.task_kwargs'])85 self.assertEqual(kwargs, self.context['celery.kwargs'])
5786
58 def test_on_failure_includes_tb_text(self):87 def test_on_failure_includes_tb_text(self):
59 einfo = self.get_einfo()88 einfo = self.get_einfo()
@@ -73,19 +102,22 @@
73 def test_on_failure_includes_sender(self):102 def test_on_failure_includes_sender(self):
74 sender = object()103 sender = object()
75 self.recorder.on_failure(sender=sender)104 self.recorder.on_failure(sender=sender)
76 self.assertEqual(sender, self.oopses[0]['celery.sender'])105 self.assertEqual(sender, self.context['celery.sender'])
77106
78 def test_on_failure_accepts_signal_kwarg(self):107 def test_on_failure_includes_signal(self):
79 # Test there's no error if celery passes the signal kwarg108 signal = object()
80 self.recorder.on_failure(signal=object())109 self.recorder.on_failure(signal=signal)
81110 self.assertEqual(signal, self.context['celery.signal'])
82 def test_on_failure_accepts_exception_kwarg(self):111
83 # Test there's no error if celery passes the exception kwarg112 def test_on_failure_includes_exception(self):
84 self.recorder.on_failure(exception=object())113 exception = object()
85114 self.recorder.on_failure(exception=exception)
86 def test_on_failure_accepts_traceback_kwarg(self):115 self.assertEqual(exception, self.context['celery.exception'])
87 # Test there's no error if celery passes the traceback kwarg116
88 self.recorder.on_failure(traceback=object())117 def test_on_failure_includes_traceback(self):
118 traceback = object()
119 self.recorder.on_failure(traceback=traceback)
120 self.assertEqual(traceback, self.context['celery.traceback'])
89121
90122
91class SetupOopsReporterTests(TestCase):123class SetupOopsReporterTests(TestCase):
@@ -119,6 +151,11 @@
119 receiver = signals.task_failure.receivers[0][1]151 receiver = signals.task_failure.receivers[0][1]
120 self.assertEqual(config, receiver.im_self.config)152 self.assertEqual(config, receiver.im_self.config)
121153
154 def test_inserts_hooks(self):
155 config = oops.Config()
156 self.setup_oops_reporter(config=config)
157 self.assertIn(attach_celery_info, config.on_create)
158
122 def test_generates_oops(self):159 def test_generates_oops(self):
123 config = oops.Config()160 config = oops.Config()
124 oopses = []161 oopses = []

Subscribers

People subscribed via source and target branches