Merge lp:~michael.nelson/ubuntu-webcatalog/render_404_rather_than_raise_exception into lp:ubuntu-webcatalog

Proposed by Michael Nelson
Status: Merged
Approved by: Michael Nelson
Approved revision: 170
Merged at revision: 167
Proposed branch: lp:~michael.nelson/ubuntu-webcatalog/render_404_rather_than_raise_exception
Merge into: lp:ubuntu-webcatalog
Diff against target: 254 lines (+148/-18)
7 files modified
django_project/config/main.cfg (+10/-3)
setup.py (+3/-0)
src/webcatalog/schema.py (+8/-3)
src/webcatalog/templates/500.html (+0/-3)
src/webcatalog/tests/__init__.py (+1/-0)
src/webcatalog/tests/test_oops_wsgi_config.py (+110/-0)
src/webcatalog/wsgi.py (+16/-9)
To merge this branch: bzr merge lp:~michael.nelson/ubuntu-webcatalog/render_404_rather_than_raise_exception
Reviewer Review Type Date Requested Status
James Westby (community) Approve
Review via email: mp+121016@code.launchpad.net

Commit message

Use oops-wsgi for errors.

Description of the change

Overview
========

Contrary to the name, this branch adds and configures oops-wsgi for use with ubuntu-webcatalog.

`fab test`

To post a comment you must log in.
Revision history for this message
James Westby (james-w) wrote :

68 + 'instance_id': 'dev',

It is preferred not to set instance_id at all.

16 +[oops_datedir_publisher]
17 +type = datedir
18 +error_dir = /tmp/uwc-oops/
19 +instance_id = dev

Why override from the default here? Having the oopses in-tree seems
preferable to me anyway.

Other than that this looks excellent.

Thanks,

James

review: Approve
169. By Michael Nelson

REFACTOR: updated oops-dictconfig version to that used on our precise production boxes.

170. By Michael Nelson

REFACTOR: remove instance_id setting and update eg config to match the default.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'django_project/config/main.cfg'
--- django_project/config/main.cfg 2012-07-02 13:41:19 +0000
+++ django_project/config/main.cfg 2012-08-23 15:14:17 +0000
@@ -106,8 +106,15 @@
106canonical-losas = admin106canonical-losas = admin
107canonical-ca-hackers = developers107canonical-ca-hackers = developers
108108
109[oops]109[oops_wsgi]
110oops_dir = /srv/%(hostname)s/staging-logs/www-oops110oopses = oops_publishers
111
112[oops_publishers]
113publishers = oops_datedir_publisher
114
115[oops_datedir_publisher]
116type = datedir
117error_dir = oopses
111118
112[webcatalog]119[webcatalog]
113serve_site_media = True120serve_site_media = True
@@ -142,4 +149,4 @@
142broker_url = amqp://guest:guest@localhost:5672//149broker_url = amqp://guest:guest@localhost:5672//
143celery_imports = webcatalog.tasks150celery_imports = webcatalog.tasks
144celery_result_backend = database151celery_result_backend = database
145celerybeat_scheduler = djcelery.schedulers.DatabaseScheduler
146\ No newline at end of file152\ No newline at end of file
153celerybeat_scheduler = djcelery.schedulers.DatabaseScheduler
147154
=== modified file 'setup.py'
--- setup.py 2012-07-02 13:51:23 +0000
+++ setup.py 2012-08-23 15:14:17 +0000
@@ -52,6 +52,9 @@
52 'PIL',52 'PIL',
53 'celery',53 'celery',
54 'django-celery',54 'django-celery',
55 'oops-wsgi==0.0.10',
56 'oops-dictconfig==0.0.2',
57 'oops-datedir_repo==0.0.17',
55 ],58 ],
56 package_data = find_packages_data('src'),59 package_data = find_packages_data('src'),
57 dependency_links = [60 dependency_links = [
5861
=== modified file 'src/webcatalog/schema.py'
--- src/webcatalog/schema.py 2012-08-21 13:57:11 +0000
+++ src/webcatalog/schema.py 2012-08-23 15:14:17 +0000
@@ -21,6 +21,7 @@
21import django21import django
22from configglue import schema22from configglue import schema
23from django_configglue.schema import schemas23from django_configglue.schema import schemas
24from oops_dictconfig.configglue_options import OopsOption
2425
25DjangoSchema = schemas.get('1.3.1')26DjangoSchema = schemas.get('1.3.1')
2627
@@ -32,9 +33,13 @@
32 pgconnect_timeout = schema.IntOption(default=10)33 pgconnect_timeout = schema.IntOption(default=10)
33 should_serve_https = schema.BoolOption()34 should_serve_https = schema.BoolOption()
3435
35 class oops(schema.Section):36 class oops_wsgi(schema.Section):
36 oops_dir = schema.StringOption(help='Absolute path to the directory'37 oopses = OopsOption(default={
37 ' oops reports will be stored in')38 'publishers': [{
39 'type': 'datedir',
40 'error_dir': 'oopses',
41 }],
42 })
3843
39 class openid(schema.Section):44 class openid(schema.Section):
40 openid_sso_server_url = schema.StringOption()45 openid_sso_server_url = schema.StringOption()
4146
=== modified file 'src/webcatalog/templates/500.html'
--- src/webcatalog/templates/500.html 2012-03-08 18:13:11 +0000
+++ src/webcatalog/templates/500.html 2012-08-23 15:14:17 +0000
@@ -7,7 +7,4 @@
7<h1>{% trans 'Server Error <em>(500)</em>' %}</h1>7<h1>{% trans 'Server Error <em>(500)</em>' %}</h1>
8{% if errormsg %}<p>{{ errormsg }}</p>{% endif %}8{% if errormsg %}<p>{{ errormsg }}</p>{% endif %}
9<p>{% blocktrans %}An error occurred which prevented the page you requested from loading. If this problem continues, please consider reporting this problem by sending an e-mail to <a href="mailto:webmaster@canonical.com">webmaster@canonical.com</a>{% endblocktrans %}</p>9<p>{% blocktrans %}An error occurred which prevented the page you requested from loading. If this problem continues, please consider reporting this problem by sending an e-mail to <a href="mailto:webmaster@canonical.com">webmaster@canonical.com</a>{% endblocktrans %}</p>
10<p>
11{% blocktrans %}(Error <abbr>ID</abbr>: {{oopsid}}){% endblocktrans %}
12</p>
13{% endblock %}10{% endblock %}
1411
=== modified file 'src/webcatalog/tests/__init__.py'
--- src/webcatalog/tests/__init__.py 2012-06-28 18:26:25 +0000
+++ src/webcatalog/tests/__init__.py 2012-08-23 15:14:17 +0000
@@ -25,6 +25,7 @@
25from .test_models import *25from .test_models import *
26from .test_managers import *26from .test_managers import *
27from .test_migrations import *27from .test_migrations import *
28from .test_oops_wsgi_config import *
28from .test_pep8 import *29from .test_pep8 import *
29from .test_preflight import *30from .test_preflight import *
30from .test_tasks import *31from .test_tasks import *
3132
=== added file 'src/webcatalog/tests/test_oops_wsgi_config.py'
--- src/webcatalog/tests/test_oops_wsgi_config.py 1970-01-01 00:00:00 +0000
+++ src/webcatalog/tests/test_oops_wsgi_config.py 2012-08-23 15:14:17 +0000
@@ -0,0 +1,110 @@
1# -*- coding: utf-8 -*-
2# This file is part of the Ubuntu Web Catalog
3# Copyright (C) 2011-2012 Canonical Ltd.
4#
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU Affero General Public License as
7# published by the Free Software Foundation, either version 3 of the
8# License, or (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU Affero General Public License for more details.
14#
15# You should have received a copy of the GNU Affero General Public License
16# along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18"""Tests for the oops_wsgi setup."""
19
20from __future__ import absolute_import
21
22__metaclass__ = type
23__all__ = [
24 'OopsWsgiTestCase',
25]
26
27import bson
28import os
29from shutil import rmtree
30from tempfile import mkdtemp
31
32from django.core.cache import cache
33from django.core.urlresolvers import reverse
34from django.conf import settings
35from django.test import TestCase
36from mock import (
37 Mock,
38 patch,
39)
40from webcatalog.wsgi import make_app
41from webcatalog.tests.helpers import patch_settings
42
43
44class OopsWsgiTestCase(TestCase):
45
46 def setUp(self):
47 super(OopsWsgiTestCase, self).setUp()
48 self.oops_dir = mkdtemp()
49 self.addCleanup(rmtree, self.oops_dir)
50 self.environ = {
51 'PATH_INFO': '/',
52 'QUERY_STRING': '',
53 'REMOTE_ADDR': '127.0.0.1',
54 'REQUEST_METHOD': 'GET',
55 'SCRIPT_NAME': '',
56 'SERVER_NAME': 'testserver',
57 'SERVER_PORT': '80',
58 'SERVER_PROTOCOL': 'HTTP/1.1',
59 'wsgi.version': (1, 0),
60 'wsgi.url_scheme': 'http',
61 'wsgi.multiprocess': True,
62 'wsgi.multithread': False,
63 'wsgi.run_once': False,
64 'wsgi.input': '',
65 }
66 cache.clear()
67
68 def request_wsgi_response(self, environ):
69 start_response = Mock()
70 with patch_settings(OOPSES={
71 'publishers': [{
72 'type': 'datedir',
73 'error_dir': self.oops_dir,
74 'instance_id': 'dev',
75 }],
76 }):
77 app = make_app()
78 response = app(environ, start_response).next()
79 return response
80
81 def read_oops_from_disk(self):
82 # Helper to read in the oops written to disk.
83 # There is only one date directory in the oops directory.
84 dated_dirs = os.listdir(self.oops_dir)
85 self.assertEqual(1, len(dated_dirs))
86
87 # There is only one oops.
88 todays_oops_path = dated_dirs[0]
89 oops_list = os.listdir(self.oops_dir + '/' + todays_oops_path)
90 self.assertEqual(1, len(oops_list))
91
92 oops_path = self.oops_dir + '/' + todays_oops_path + '/' + oops_list[0]
93 with open(oops_path, "r") as oops_file:
94 oops_file_contents = oops_file.read()
95 return bson.loads(oops_file_contents)
96
97 def request_with_exception(self):
98 self.environ['PATH_INFO'] = reverse('wc-index')
99 view_fn_path = 'webcatalog.views.render_to_response'
100 with patch(view_fn_path) as mock_render:
101 mock_render.side_effect = ZeroDivisionError
102 response = self.request_wsgi_response(self.environ)
103 return response
104
105 def test_oops_on_disk_on_error(self):
106 response = self.request_with_exception()
107
108 self.assertIn('Server Error <em>(500)</em>', response)
109 oops_data = self.read_oops_from_disk()
110 self.assertEqual('ZeroDivisionError', oops_data['type'])
0111
=== modified file 'src/webcatalog/wsgi.py'
--- src/webcatalog/wsgi.py 2012-06-06 17:42:04 +0000
+++ src/webcatalog/wsgi.py 2012-08-23 15:14:17 +0000
@@ -17,13 +17,13 @@
1717
18"""wsgi stack for the Apps Directory."""18"""wsgi stack for the Apps Directory."""
1919
20import logging.config
21import oops_dictconfig
22import oops_wsgi
23import oops_wsgi.django
20import os24import os
21import logging.config
22import platform25import platform
2326
24from canonical.oops.serializer import OOPSRFC822Serializer
25from canonical.oops.wsgi import OopsWare
26from django.core.handlers.wsgi import WSGIHandler
27from django.conf import settings27from django.conf import settings
2828
2929
@@ -34,9 +34,16 @@
3434
35 default_id = ''.join(x for x in platform.node() if x.isalpha())35 default_id = ''.join(x for x in platform.node() if x.isalpha())
36 appserver_id = getattr(settings, 'APPSERVER_ID', default_id)36 appserver_id = getattr(settings, 'APPSERVER_ID', default_id)
37 logging.config.fileConfig(settings.WEBAPP_LOGGING_CONFIG)37 logging_config = settings.WEBAPP_LOGGING_CONFIG
38 oops_dir = getattr(settings, 'OOPS_DIR', '/tmp')38 if logging_config:
39 oops_app = OopsWare(WSGIHandler(), oops_dir=oops_dir,39 logging.config.fileConfig(logging_config)
40 key=appserver_id, hide_meta=True)40
41 oops_app.serial = OOPSRFC822Serializer(appserver_id, oops_dir, None)41 # This is needed to workaround a bug in Django, see the file it is
42 # implemented in for more details.
43 non_oops_app = oops_wsgi.django.OOPSWSGIHandler()
44
45 config = oops_dictconfig.config_from_dict(settings.OOPSES)
46 oops_wsgi.install_hooks(config)
47 oops_app = oops_wsgi.make_app(non_oops_app, config,
48 oops_on_status=['500'])
42 return oops_app49 return oops_app

Subscribers

People subscribed via source and target branches