Skip to content

Commit 973fac4

Browse files
Kyle-VerhoogEmanuele Palazzetti
authored andcommitted
[pylons] Add middleware exception/error handling tests (#529)
* [pylons] replicate #463 * [pylons] add test coverage for exception throwing middleware
1 parent 97a9675 commit 973fac4

File tree

2 files changed

+165
-1
lines changed

2 files changed

+165
-1
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from webob import Request, Response
2+
3+
class ExceptionMiddleware(object):
4+
"""A middleware which raises an exception."""
5+
def __init__(self, app):
6+
self.app = app
7+
8+
def __call__(self, environ, start_response):
9+
raise Exception('Middleware exception')
10+
11+
class ExceptionToSuccessMiddleware(object):
12+
"""A middleware which catches any exceptions that occur in a later
13+
middleware and returns a successful request.
14+
"""
15+
def __init__(self, app):
16+
self.app = app
17+
18+
def __call__(self, environ, start_response):
19+
req = Request(environ)
20+
try:
21+
response = req.get_response(self.app)
22+
except Exception:
23+
response = Response()
24+
response.status_int = 200
25+
response.body = 'An error has been handled appropriately'
26+
return response(environ, start_response)
27+
28+
29+
class ExceptionToClientErrorMiddleware(object):
30+
def __init__(self, app):
31+
self.app = app
32+
33+
def __call__(self, environ, start_response):
34+
req = Request(environ)
35+
try:
36+
response = req.get_response(self.app)
37+
except Exception:
38+
response = Response()
39+
response.status_int = 404
40+
response.body = 'An error has occured with proper client error handling'
41+
return response(environ, start_response)

tests/contrib/pylons/test_pylons.py

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from paste import fixture
88
from paste.deploy import loadapp
99

10-
from ddtrace.ext import http
10+
from ddtrace.ext import http, errors
1111
from ddtrace.constants import SAMPLING_PRIORITY_KEY
1212
from ddtrace.contrib.pylons import PylonsTraceMiddleware
1313

@@ -25,9 +25,132 @@ def setUp(self):
2525
# initialize a real traced Pylons app
2626
self.tracer = get_dummy_tracer()
2727
wsgiapp = loadapp('config:test.ini', relative_to=PylonsTestCase.conf_dir)
28+
self._wsgiapp = wsgiapp
2829
app = PylonsTraceMiddleware(wsgiapp, self.tracer, service='web')
2930
self.app = fixture.TestApp(app)
3031

32+
def test_controller_exception(self):
33+
"""Ensure exceptions thrown in controllers can be handled.
34+
35+
No error tags should be set in the span.
36+
"""
37+
from .app.middleware import ExceptionToSuccessMiddleware
38+
wsgiapp = ExceptionToSuccessMiddleware(self._wsgiapp)
39+
app = PylonsTraceMiddleware(wsgiapp, self.tracer, service='web')
40+
41+
app = fixture.TestApp(app)
42+
app.get(url_for(controller='root', action='raise_exception'))
43+
44+
spans = self.tracer.writer.pop()
45+
46+
ok_(spans, spans)
47+
eq_(len(spans), 1)
48+
span = spans[0]
49+
50+
eq_(span.service, 'web')
51+
eq_(span.resource, 'root.raise_exception')
52+
eq_(span.error, 0)
53+
eq_(span.get_tag('http.status_code'), '200')
54+
eq_(span.get_tag(errors.ERROR_MSG), None)
55+
eq_(span.get_tag(errors.ERROR_TYPE), None)
56+
eq_(span.get_tag(errors.ERROR_STACK), None)
57+
58+
def test_mw_exc_success(self):
59+
"""Ensure exceptions can be properly handled by other middleware.
60+
61+
No error should be reported in the span.
62+
"""
63+
from .app.middleware import ExceptionMiddleware, ExceptionToSuccessMiddleware
64+
wsgiapp = ExceptionMiddleware(self._wsgiapp)
65+
wsgiapp = ExceptionToSuccessMiddleware(wsgiapp)
66+
app = PylonsTraceMiddleware(wsgiapp, self.tracer, service='web')
67+
app = fixture.TestApp(app)
68+
69+
app.get(url_for(controller='root', action='index'))
70+
71+
spans = self.tracer.writer.pop()
72+
73+
ok_(spans, spans)
74+
eq_(len(spans), 1)
75+
span = spans[0]
76+
77+
eq_(span.service, 'web')
78+
eq_(span.resource, 'None.None')
79+
eq_(span.error, 0)
80+
eq_(span.get_tag('http.status_code'), '200')
81+
eq_(span.get_tag(errors.ERROR_MSG), None)
82+
eq_(span.get_tag(errors.ERROR_TYPE), None)
83+
eq_(span.get_tag(errors.ERROR_STACK), None)
84+
85+
def test_middleware_exception(self):
86+
"""Ensure exceptions raised in middleware are properly handled.
87+
88+
Uncaught exceptions should result in error tagged spans.
89+
"""
90+
from .app.middleware import ExceptionMiddleware
91+
wsgiapp = ExceptionMiddleware(self._wsgiapp)
92+
app = PylonsTraceMiddleware(wsgiapp, self.tracer, service='web')
93+
app = fixture.TestApp(app)
94+
95+
with assert_raises(Exception):
96+
app.get(url_for(controller='root', action='index'))
97+
98+
spans = self.tracer.writer.pop()
99+
100+
ok_(spans, spans)
101+
eq_(len(spans), 1)
102+
span = spans[0]
103+
104+
eq_(span.service, 'web')
105+
eq_(span.resource, 'None.None')
106+
eq_(span.error, 1)
107+
eq_(span.get_tag('http.status_code'), '500')
108+
eq_(span.get_tag(errors.ERROR_MSG), 'Middleware exception')
109+
eq_(span.get_tag(errors.ERROR_TYPE), 'exceptions.Exception')
110+
ok_(span.get_tag(errors.ERROR_STACK))
111+
112+
def test_exc_success(self):
113+
from .app.middleware import ExceptionToSuccessMiddleware
114+
wsgiapp = ExceptionToSuccessMiddleware(self._wsgiapp)
115+
app = PylonsTraceMiddleware(wsgiapp, self.tracer, service='web')
116+
app = fixture.TestApp(app)
117+
118+
app.get(url_for(controller='root', action='raise_exception'))
119+
120+
spans = self.tracer.writer.pop()
121+
ok_(spans, spans)
122+
eq_(len(spans), 1)
123+
span = spans[0]
124+
125+
eq_(span.service, 'web')
126+
eq_(span.resource, 'root.raise_exception')
127+
eq_(span.error, 0)
128+
eq_(span.get_tag('http.status_code'), '200')
129+
eq_(span.get_tag(errors.ERROR_MSG), None)
130+
eq_(span.get_tag(errors.ERROR_TYPE), None)
131+
eq_(span.get_tag(errors.ERROR_STACK), None)
132+
133+
def test_exc_client_failure(self):
134+
from .app.middleware import ExceptionToClientErrorMiddleware
135+
wsgiapp = ExceptionToClientErrorMiddleware(self._wsgiapp)
136+
app = PylonsTraceMiddleware(wsgiapp, self.tracer, service='web')
137+
app = fixture.TestApp(app)
138+
139+
app.get(url_for(controller='root', action='raise_exception'), status=404)
140+
141+
spans = self.tracer.writer.pop()
142+
ok_(spans, spans)
143+
eq_(len(spans), 1)
144+
span = spans[0]
145+
146+
eq_(span.service, 'web')
147+
eq_(span.resource, 'root.raise_exception')
148+
eq_(span.error, 0)
149+
eq_(span.get_tag('http.status_code'), '404')
150+
eq_(span.get_tag(errors.ERROR_MSG), None)
151+
eq_(span.get_tag(errors.ERROR_TYPE), None)
152+
eq_(span.get_tag(errors.ERROR_STACK), None)
153+
31154
def test_success_200(self):
32155
res = self.app.get(url_for(controller='root', action='index'))
33156
eq_(res.status, 200)

0 commit comments

Comments
 (0)