Merge lp:~james-w/python-oops-tools/recent-oopses into lp:python-oops-tools

Proposed by James Westby
Status: Merged
Approved by: James Westby
Approved revision: no longer in the source branch.
Merged at revision: 49
Proposed branch: lp:~james-w/python-oops-tools/recent-oopses
Merge into: lp:python-oops-tools
Diff against target: 232 lines (+163/-3)
6 files modified
src/oopstools/oops/static/oops.css (+7/-1)
src/oopstools/oops/templates/report.html (+36/-0)
src/oopstools/oops/test/__init__.py (+0/-2)
src/oopstools/oops/test/test_report.py (+77/-0)
src/oopstools/oops/test/testcase.py (+11/-0)
src/oopstools/oops/views.py (+32/-0)
To merge this branch: bzr merge lp:~james-w/python-oops-tools/recent-oopses
Reviewer Review Type Date Requested Status
Curtis Hovey (community) code Approve
j.c.sackett (community) Approve
Review via email: mp+137055@code.launchpad.net

Commit message

Show the (paginated) oopses for each report.

Description of the change

Hi,

Showing the day-old reports is of limited use, because you don't know
if there are issues with the site at this moment. To try and help with that
show the oopses, sorted with the most recent first, on the report page.

It uses pagination to keep the number of oopses displayed small.

Thanks,

James

To post a comment you must log in.
Revision history for this message
j.c.sackett (jcsackett) wrote :

Looks good. Thanks, James.

review: Approve
Revision history for this message
Launchpad PQM Bot (launchpad-pqm) wrote :
Download full text (4.0 KiB)

The attempt to merge lp:~james-w/python-oops-tools/recent-oopses into lp:python-oops-tools failed.Below is the output from the failed tests.

find . -type f -name '*.py[co]' -exec rm -f {} \;
rm -f bin/buildout
rm -f src/oopstools/settings.py
bzr clean-tree --unknown --force
bzr up download-cache
python bootstrap.py \
  --setup-source=download-cache/ez_setup.py \
  --download-base=download-cache/dist --eggs=eggs
Download error: [Errno 111] Connection refused -- Some packages may not be found!
Download error: [Errno 111] Connection refused -- Some packages may not be found!
Generated script '/home/pqm/pqm-workdir/oops-tools/bin/buildout'.
bin/buildout configuration:db-port=5433
Develop: '/home/pqm/pqm-workdir/oops-tools/.'
Uninstalling filetemplates.
Updating scripts.
Installing filetemplates.
Updating django.
Updating docs.
Updating tags.
bin/test
Creating test database for alias 'default'...
Destroying test database for alias 'default'...

W: line 4 [buildbot-staging]: Deprecated key 'location' used
I: This option will be removed in the future; please update your configuration
W: line 2 [pqm]: Deprecated key 'location' used
I: This option will be removed in the future; please update your configuration
W: line 3 [pqm-oops-tools]: Deprecated key 'location' used
I: This option will be removed in the future; please update your configuration
W: line 1 [precise]: Deprecated key 'location' used
I: This option will be removed in the future; please update your configuration
I: [pqm-oops-tools chroot] Running command: "cd /home/pqm/pqm-workdir/oops-tools && make check"
Nothing to delete.
+N dist/Twisted-12.2.0.tar.bz2
+N dist/lazr.jobrunner-0.11.tar.gz
+N dist/lazr.restful-0.19.7.tar.gz
+N dist/lazr.restful-0.19.8.tar.gz
+N dist/lazr.restful-0.19.9.tar.gz
+N dist/lazr.restfulclient-0.13.1.tar.gz
-D dist/lazr.restful-0.19.2.tar.gz
-D dist/lazr.restful-0.19.3.tar.gz
-D dist/lazr.restful-0.19.4.tar.gz
-D dist/lazr.restful-0.19.5.tar.gz
All changes applied successfully.
Updated to revision 531 of branch http://bazaar.launchpad.net/~launchpad/lp-source-dependencies/trunk
/home/pqm/pqm-workdir/oops-tools/eggs/Django-1.3.3-py2.6.egg/django/template/loaders/filesystem.py:58: DeprecationWarning: 'django.template.loaders.filesystem.load_template_source' is deprecated; use 'django.template.loaders.filesystem.Loader' instead.
  DeprecationWarning
/home/pqm/pqm-workdir/oops-tools/eggs/Django-1.3.3-py2.6.egg/django/template/loaders/app_directories.py:71: DeprecationWarning: 'django.template.loaders.app_directories.load_template_source' is deprecated; use 'django.template.loaders.app_directories.Loader' instead.
  DeprecationWarning
/home/pqm/pqm-workdir/oops-tools/eggs/Django-1.3.3-py2.6.egg/django/contrib/auth/models.py:393: DeprecationWarning: The user messaging API is deprecated. Please update your code to use the new messages framework.
  category=DeprecationWarning)
........................................E
======================================================================
ERROR: test_recent_oopses (test_report.ReportTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/pqm/...

Read more...

Revision history for this message
Curtis Hovey (sinzui) wrote :

Thank you for addressing the upcall issue.

review: Approve (code)
Revision history for this message
Launchpad PQM Bot (launchpad-pqm) wrote :
Download full text (4.4 KiB)

The attempt to merge lp:~james-w/python-oops-tools/recent-oopses into lp:python-oops-tools failed.Below is the output from the failed tests.

find . -type f -name '*.py[co]' -exec rm -f {} \;
rm -f bin/buildout
rm -f src/oopstools/settings.py
bzr clean-tree --unknown --force
bzr up download-cache
python bootstrap.py \
  --setup-source=download-cache/ez_setup.py \
  --download-base=download-cache/dist --eggs=eggs
Download error: [Errno 111] Connection refused -- Some packages may not be found!
Download error: [Errno 111] Connection refused -- Some packages may not be found!
Generated script '/home/pqm/pqm-workdir/oops-tools/bin/buildout'.
bin/buildout configuration:db-port=5433
Develop: '/home/pqm/pqm-workdir/oops-tools/.'
Uninstalling filetemplates.
Updating scripts.
Installing filetemplates.
Updating django.
Updating docs.
Updating tags.
bin/test
Creating test database for alias 'default'...

W: line 4 [buildbot-staging]: Deprecated key 'location' used
I: This option will be removed in the future; please update your configuration
W: line 2 [pqm]: Deprecated key 'location' used
I: This option will be removed in the future; please update your configuration
W: line 3 [pqm-oops-tools]: Deprecated key 'location' used
I: This option will be removed in the future; please update your configuration
W: line 1 [precise]: Deprecated key 'location' used
I: This option will be removed in the future; please update your configuration
I: [pqm-oops-tools chroot] Running command: "cd /home/pqm/pqm-workdir/oops-tools && make check"
Nothing to delete.
Tree is up to date at revision 531 of branch http://bazaar.launchpad.net/~launchpad/lp-source-dependencies/trunk
Traceback (most recent call last):
  File "bin/test", line 58, in <module>
    djangorecipe.test.main('oopstools.settings', 'oopstools')
  File "/home/pqm/pqm-workdir/oops-tools/eggs/djangorecipe-1.3-py2.6.egg/djangorecipe/test.py", line 19, in main
    management.execute_manager(settings, argv=argv)
  File "/home/pqm/pqm-workdir/oops-tools/eggs/Django-1.3.3-py2.6.egg/django/core/management/__init__.py", line 438, in execute_manager
    utility.execute()
  File "/home/pqm/pqm-workdir/oops-tools/eggs/Django-1.3.3-py2.6.egg/django/core/management/__init__.py", line 379, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/pqm/pqm-workdir/oops-tools/eggs/Django-1.3.3-py2.6.egg/django/core/management/base.py", line 191, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/home/pqm/pqm-workdir/oops-tools/eggs/Django-1.3.3-py2.6.egg/django/core/management/base.py", line 220, in execute
    output = self.handle(*args, **options)
  File "/home/pqm/pqm-workdir/oops-tools/eggs/South-0.7.3_r929-py2.6.egg/south/management/commands/test.py", line 8, in handle
    super(Command, self).handle(*args, **kwargs)
  File "/home/pqm/pqm-workdir/oops-tools/eggs/Django-1.3.3-py2.6.egg/django/core/management/commands/test.py", line 37, in handle
    failures = test_runner.run_tests(test_labels)
  File "/home/pqm/pqm-workdir/oops-tools/eggs/Django-1.3.3-py2.6.egg/django/test/simple.py", line 359, in run_tests
    old_config = self.setup_databases()
  File "/home/pqm/pqm-workdir/oo...

Read more...

49. By James Westby

Show the (paginated) oopses for each report.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/oopstools/oops/static/oops.css'
--- src/oopstools/oops/static/oops.css 2011-10-13 20:18:51 +0000
+++ src/oopstools/oops/static/oops.css 2012-12-04 16:05:33 +0000
@@ -7,7 +7,13 @@
7 padding:0px;7 padding:0px;
8}8}
9table {9table {
10 border: 1px #000;10 border: 1px solid #000;
11}
12td {
13 padding: 4px;
14}
15tr:nth-child(2n) {
16 background-color: #eee;
11}17}
12p,h1,pre {18p,h1,pre {
13 margin:0px 10px 10px 10px;19 margin:0px 10px 10px 10px;
1420
=== modified file 'src/oopstools/oops/templates/report.html'
--- src/oopstools/oops/templates/report.html 2011-10-13 20:18:51 +0000
+++ src/oopstools/oops/templates/report.html 2012-12-04 16:05:33 +0000
@@ -13,5 +13,41 @@
13 <li><a href="{{SUMMARY_URI}}/{{report.name}}-{{date|date:"Y-m-d"}}.html">{{report.title}} {{date|date:"Y-m-d"}}</a></li>13 <li><a href="{{SUMMARY_URI}}/{{report.name}}-{{date|date:"Y-m-d"}}.html">{{report.title}} {{date|date:"Y-m-d"}}</a></li>
14 {% endfor %}14 {% endfor %}
15 <ul>15 <ul>
16 <h2>Recent Oopses</h2>
17 <table>
18 <th><tr>
19 <td>Date/Time</td>
20 <td>HTTP Method</td>
21 <td>URL</td>
22 <td>Duration (ms)</td>
23 <td>Exception Type</td>
24 <td>Oops</td>
25 </tr></th>
26 {% for oops in recent.object_list %}
27 <tr>
28 <td>{{oops.date|date:"Y-m-d H:i:s"}}</td>
29 <td>{{oops.http_method}}</td>
30 <td>{% if oops.url %}<a href="{{oops.url}}">{{oops.url}}</a>{% endif %}</td>
31 <td>{{oops.total_time}}</td>
32 <td>{{oops.exception_type}}</td>
33 <td><a href="{% url oopstools.oops.views.index %}?oopsid={{oops.oopsid}}">{{oops.oopsid}}</a></td>
34 </tr>
35 {% endfor %}
36 </table>
37 <div class="pagination">
38 <span class="step-links">
39 {% if recent.has_previous %}
40 <a href="?page={{ recent.previous_page_number }}">newer</a>
41 {% endif %}
42
43 <span class="current">
44 Page {{ recent.number }} of {{ recent.paginator.num_pages }}.
45 </span>
46
47 {% if recent.has_next %}
48 <a href="?page={{ recent.next_page_number }}">older</a>
49 {% endif %}
50 </span>
51 </div>
16 </body>52 </body>
17</html>53</html>
1854
=== modified file 'src/oopstools/oops/test/__init__.py'
--- src/oopstools/oops/test/__init__.py 2011-10-13 20:18:51 +0000
+++ src/oopstools/oops/test/__init__.py 2012-12-04 16:05:33 +0000
@@ -12,5 +12,3 @@
12#12#
13# You should have received a copy of the GNU Affero General Public License13# You should have received a copy of the GNU Affero General Public License
14# along with this program. If not, see <http://www.gnu.org/licenses/>.14# along with this program. If not, see <http://www.gnu.org/licenses/>.
15
16
1715
=== added file 'src/oopstools/oops/test/test_report.py'
--- src/oopstools/oops/test/test_report.py 1970-01-01 00:00:00 +0000
+++ src/oopstools/oops/test/test_report.py 2012-12-04 16:05:33 +0000
@@ -0,0 +1,77 @@
1# Copyright 2005-2012 Canonical Ltd. All rights reserved.
2#
3# This program is free software: you can redistribute it and/or modify
4# it under the terms of the GNU Affero General Public License as published by
5# the Free Software Foundation, either version 3 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU Affero General Public License for more details.
12#
13# You should have received a copy of the GNU Affero General Public License
14# along with this program. If not, see <http://www.gnu.org/licenses/>.
15
16from datetime import datetime
17from operator import attrgetter
18
19from oopstools.oops.models import (
20 AppInstance,
21 Classification,
22 Infestation,
23 Oops,
24 Prefix,
25 Report,
26)
27from oopstools.oops.test.testcase import TestCase
28
29
30class ReportTests(TestCase):
31
32 def test_no_report(self):
33 resp = self.client.get('/reports/some-report/')
34 self.assertEqual(404, resp.status_code)
35
36 def test_inactive_report(self):
37 report_name = 'areport'
38 Report.objects.create(name=report_name, active=False)
39 resp = self.client.get('/reports/%s/' % (report_name,))
40 self.assertEqual(404, resp.status_code)
41
42 def test_no_recent_oopses(self):
43 report_name = 'areport'
44 Report.objects.create(name=report_name, active=True)
45 resp = self.client.get('/reports/%s/' % (report_name,))
46 self.assertEqual(200, resp.status_code)
47 self.assertQuerysetEqual(resp.context['recent'].object_list, [])
48
49 def make_oops(self, prefix):
50 classification = Classification.objects.create(
51 title=self.getUniqueString(prefix="classification"))
52 infestation = Infestation.objects.create(
53 exception_type=self.getUniqueString(prefix="exc_type"),
54 exception_value=self.getUniqueString(prefix="exc_value"))
55 return Oops.objects.create(
56 prefix=prefix, classification=classification,
57 oopsinfestation=infestation, statements_count=100,
58 appinstance=prefix.appinstance, total_time=3,
59 date=datetime.now())
60
61 def make_prefix(self):
62 appinstance = AppInstance.objects.create(
63 title=self.getUniqueString(prefix="appinstance"))
64 return Prefix.objects.create(
65 value=self.getUniqueString(prefix="prefix"),
66 appinstance=appinstance)
67
68 def test_recent_oopses(self):
69 report_name = 'areport'
70 report = Report.objects.create(name=report_name, active=True)
71 prefix = self.make_prefix()
72 report.prefixes.add(prefix)
73 oops = self.make_oops(prefix)
74 resp = self.client.get('/reports/%s/' % (report_name,))
75 self.assertEqual(200, resp.status_code)
76 self.assertQuerysetEqual(
77 resp.context['recent'].object_list, [oops.pk], transform=attrgetter('pk'))
078
=== added file 'src/oopstools/oops/test/testcase.py'
--- src/oopstools/oops/test/testcase.py 1970-01-01 00:00:00 +0000
+++ src/oopstools/oops/test/testcase.py 2012-12-04 16:05:33 +0000
@@ -0,0 +1,11 @@
1from django.test import TestCase as DjangoTestCase
2from testtools import TestCase as TesttoolsTestCase
3
4
5class TestCase(DjangoTestCase, TesttoolsTestCase):
6
7 def __init__(self, *args, **kwargs):
8 # python2.6 doesn't up-call, so TesttoolsTestCase.__init__
9 # never gets called unless we do this.
10 DjangoTestCase.__init__(self, *args, **kwargs)
11 TesttoolsTestCase.__init__(self, *args, **kwargs)
012
=== modified file 'src/oopstools/oops/views.py'
--- src/oopstools/oops/views.py 2011-11-03 00:08:18 +0000
+++ src/oopstools/oops/views.py 2012-12-04 16:05:33 +0000
@@ -18,6 +18,7 @@
18from datetime import datetime, timedelta18from datetime import datetime, timedelta
1919
20from django.conf import settings20from django.conf import settings
21from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
21from django.http import Http404, HttpResponseRedirect22from django.http import Http404, HttpResponseRedirect
22from django.shortcuts import render_to_response23from django.shortcuts import render_to_response
2324
@@ -96,6 +97,32 @@
96 "prefixes": prefixes})97 "prefixes": prefixes})
9798
9899
100def get_page_from_query_args(paginator, query_args):
101 """Get the page from ``paginator`` specified in the query params.
102
103 If the request specified ``page`` in the query params, then that
104 page of the paginator will be retrieved.
105
106 This function aims to return a page regardless of the page requested,
107 e.g. requesting a page beyond the last page will just return the
108 last page.
109
110 :param paginator: a ``Paginator`` object.
111 :param query_args: a ``dict`` of query params.
112 :return: a ``Page`` from the ``Paginator``.
113 """
114 page_num = query_args.get('page', 1)
115 try:
116 page = paginator.page(page_num)
117 except PageNotAnInteger:
118 # If page is not an integer, deliver first page.
119 page = paginator.page(1)
120 except EmptyPage:
121 # If page is out of range (e.g. 9999), deliver last page of results.
122 page = paginator.page(paginator.num_pages)
123 return page
124
125
99def report(request, report_name):126def report(request, report_name):
100 try:127 try:
101 r = Report.objects.get(name=report_name, active=True)128 r = Report.objects.get(name=report_name, active=True)
@@ -108,10 +135,15 @@
108 dates = []135 dates = []
109 for day in range(1, 11):136 for day in range(1, 11):
110 dates.append(now - timedelta(day))137 dates.append(now - timedelta(day))
138 oopses = Oops.objects.filter(
139 prefix__report=r).order_by('-date')
140 paginator = Paginator(oopses, 50)
141 recent_oopses = get_page_from_query_args(paginator, request.GET)
111 data = {142 data = {
112 'report': r,143 'report': r,
113 'dates': dates,144 'dates': dates,
114 'SUMMARY_URI': settings.SUMMARY_URI,145 'SUMMARY_URI': settings.SUMMARY_URI,
146 'recent': recent_oopses,
115 }147 }
116 return render_to_response("report.html", dictionary=data)148 return render_to_response("report.html", dictionary=data)
117149

Subscribers

People subscribed via source and target branches

to all changes: