launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #22253
[Merge] lp:~cjwatson/launchpad/job-oops-timeline into lp:launchpad
Colin Watson has proposed merging lp:~cjwatson/launchpad/job-oops-timeline into lp:launchpad.
Commit message:
Use a per-job OOPS timeline.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/job-oops-timeline/+merge/341554
Job OOPSes currently tend to be rather useless since they don't have a proper timeline set up, so they end up lacking SQL timelines and with other junk in them from previous things the runner has done. This should improve that situation.
--
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/job-oops-timeline into lp:launchpad.
=== modified file 'lib/lp/services/job/runner.py'
--- lib/lp/services/job/runner.py 2017-09-27 02:12:20 +0000
+++ lib/lp/services/job/runner.py 2018-03-17 01:54:12 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2017 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Facilities for running Jobs."""
@@ -81,6 +81,10 @@
)
from lp.services.twistedsupport import run_reactor
from lp.services.webapp import errorlog
+from lp.services.webapp.adapter import (
+ clear_request_started,
+ set_request_started,
+ )
class BaseRunnableJobSource:
@@ -311,6 +315,14 @@
finally:
set_default_timeout_function(original_timeout_function)
+ def runJobHandleError(self, job, fallback=None):
+ set_request_started(enable_timeout=False)
+ try:
+ return super(BaseJobRunner, self).runJobHandleError(
+ job, fallback=fallback)
+ finally:
+ clear_request_started()
+
def userErrorTypes(self, job):
return removeSecurityProxy(job).user_error_types
=== modified file 'lib/lp/services/job/tests/test_runner.py'
--- lib/lp/services/job/tests/test_runner.py 2017-09-14 03:57:01 +0000
+++ lib/lp/services/job/tests/test_runner.py 2018-03-17 01:54:12 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2017 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Tests for job-running facilities."""
@@ -17,6 +17,7 @@
LeaseHeld,
SuspendJobException,
)
+from lazr.restful.utils import get_current_browser_request
from pytz import UTC
from testtools.matchers import (
GreaterThan,
@@ -29,6 +30,7 @@
from zope.interface import implementer
from lp.services.config import config
+from lp.services.database.sqlbase import flush_database_updates
from lp.services.features.testing import FeatureFixture
from lp.services.job.interfaces.job import (
IRunnableJob,
@@ -42,6 +44,7 @@
TwistedJobRunner,
)
from lp.services.log.logger import BufferLogger
+from lp.services.timeline.requesttimeline import get_request_timeline
from lp.services.timeout import (
get_default_timeout_function,
set_default_timeout_function,
@@ -100,6 +103,15 @@
raise RaisingJobException(self.message)
+class RaisingJobTimelineMessage(NullJob):
+ """A job that records a timeline action and then raises when it runs."""
+
+ def run(self):
+ timeline = get_request_timeline(get_current_browser_request())
+ timeline.start('job', self.message).finish()
+ raise RaisingJobException(self.message)
+
+
class RaisingJobUserError(NullJob):
"""A job that raises a user error when it runs."""
@@ -328,6 +340,19 @@
runner.runJobHandleError(job)
self.assertEqual(1, len(self.oopses))
+ def test_runJobHandleErrors_oops_timeline(self):
+ """The oops timeline only covers the job itself."""
+ timeline = get_request_timeline(get_current_browser_request())
+ timeline.start('test', 'sentinel').finish()
+ job = RaisingJobTimelineMessage('boom')
+ flush_database_updates()
+ runner = JobRunner([job])
+ runner.runJobHandleError(job)
+ self.assertEqual(1, len(self.oopses))
+ actions = [action[2:4] for action in self.oopses[0]['timeline']]
+ self.assertIn(('job', 'boom'), actions)
+ self.assertNotIn(('test', 'sentinel'), actions)
+
def test_runJobHandleErrors_user_error_no_oops(self):
"""If the job raises a user error, there is no oops."""
job = RaisingJobUserError('boom')
Follow ups