Skip to content
This repository has been archived by the owner on Jun 11, 2018. It is now read-only.

Commit

Permalink
Merge pull request #124 from opbeat/feature/django-1.10
Browse files Browse the repository at this point in the history
Support for Django 1.10
  • Loading branch information
beniwohli authored Aug 24, 2016
2 parents cecf695 + 809e98a commit 5243bd3
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 50 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ env:
- WEBFRAMEWORK=django-1.7
- WEBFRAMEWORK=django-1.8
- WEBFRAMEWORK=django-1.9
- WEBFRAMEWORK=django-1.10
- WEBFRAMEWORK=django-master
- WEBFRAMEWORK=flask-0.10
global:
Expand All @@ -27,6 +28,8 @@ matrix:
env: WEBFRAMEWORK=django-1.4
- python: 3.3
env: WEBFRAMEWORK=django-1.9
- python: 3.3
env: WEBFRAMEWORK=django-1.10
- python: 3.3
env: WEBFRAMEWORK=django-master
- python: 3.4
Expand Down
19 changes: 13 additions & 6 deletions opbeat/contrib/django/management/commands/opbeat.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,19 +117,26 @@ class Command(BaseCommand):

# Django 1.8+
def add_arguments(self, parser):
parser.add_argument('subcommand')
for args, kwargs in self.arguments:
parser.add_argument(*args, **kwargs)

def handle(self, *args, **options):
if not args:
self.handle_command_not_found('No command specified.')
elif args[0] not in self.dispatch:
self.handle_command_not_found('No such command "%s".' % args[0])
if 'subcommand' in options:
# Django 1.8+, argparse
subcommand = options['subcommand']
elif not args:
return self.handle_command_not_found('No command specified.')
else:
# Django 1.7, optparse
subcommand = args[0]
if subcommand not in self.dispatch:
self.handle_command_not_found('No such command "%s".' % subcommand)
else:
self.dispatch.get(
args[0],
subcommand,
self.handle_command_not_found
)(self, args[0], **options)
)(self, subcommand, **options)

def handle_test(self, command, **options):
"""Send a test error to Opbeat"""
Expand Down
65 changes: 37 additions & 28 deletions opbeat/contrib/django/middleware/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@
except ImportError:
from django.utils.importlib import import_module

try:
from django.utils.deprecation import MiddlewareMixin
except ImportError:
# no-op class for Django < 1.10
class MiddlewareMixin(object):
pass


def _is_ignorable_404(uri):
"""
Expand All @@ -34,7 +41,7 @@ def _is_ignorable_404(uri):
return any(pattern.search(uri) for pattern in urls)


class Opbeat404CatchMiddleware(object):
class Opbeat404CatchMiddleware(MiddlewareMixin):
def process_response(self, request, response):
if (response.status_code != 404 or
_is_ignorable_404(request.get_full_path())):
Expand Down Expand Up @@ -98,11 +105,12 @@ def process_response_wrapper(wrapped, instance, args, kwargs):
return response


class OpbeatAPMMiddleware(object):
class OpbeatAPMMiddleware(MiddlewareMixin):
_opbeat_instrumented = False
_instrumenting_lock = threading.Lock()

def __init__(self):
def __init__(self, *args, **kwargs):
super(OpbeatAPMMiddleware, self).__init__(*args, **kwargs)
self.client = get_client()

if not self._opbeat_instrumented:
Expand All @@ -114,30 +122,31 @@ def __init__(self):
OpbeatAPMMiddleware._opbeat_instrumented = True

def instrument_middlewares(self):
for middleware_path in django_settings.MIDDLEWARE_CLASSES:
module_path, class_name = middleware_path.rsplit('.', 1)
try:
module = import_module(module_path)
middleware_class = getattr(module, class_name)
if middleware_class == type(self):
# don't instrument ourselves
continue
if hasattr(middleware_class, 'process_request'):
wrapt.wrap_function_wrapper(
middleware_class,
'process_request',
process_request_wrapper,
if getattr(django_settings, 'MIDDLEWARE_CLASSES', None):
for middleware_path in django_settings.MIDDLEWARE_CLASSES:
module_path, class_name = middleware_path.rsplit('.', 1)
try:
module = import_module(module_path)
middleware_class = getattr(module, class_name)
if middleware_class == type(self):
# don't instrument ourselves
continue
if hasattr(middleware_class, 'process_request'):
wrapt.wrap_function_wrapper(
middleware_class,
'process_request',
process_request_wrapper,
)
if hasattr(middleware_class, 'process_response'):
wrapt.wrap_function_wrapper(
middleware_class,
'process_response',
process_response_wrapper,
)
except ImportError:
client.logger.info(
"Can't instrument middleware %s", middleware_path
)
if hasattr(middleware_class, 'process_response'):
wrapt.wrap_function_wrapper(
middleware_class,
'process_response',
process_response_wrapper,
)
except ImportError:
client.logger.info(
"Can't instrument middleware %s", middleware_path
)

def process_request(self, request):
if not disabled_due_to_debug(
Expand Down Expand Up @@ -177,7 +186,7 @@ def process_response(self, request, response):
return response


class OpbeatResponseErrorIdMiddleware(object):
class OpbeatResponseErrorIdMiddleware(MiddlewareMixin):
"""
Appends the X-Opbeat-ID response header for referencing a message within
the Opbeat datastore.
Expand All @@ -189,7 +198,7 @@ def process_response(self, request, response):
return response


class OpbeatLogMiddleware(object):
class OpbeatLogMiddleware(MiddlewareMixin):
# Create a thread local variable to store the session in for logging
thread = threading.local()

Expand Down
2 changes: 2 additions & 0 deletions test_requirements/requirements-django-1.10.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Django>=1.10,<1.11
-r requirements-base.txt
Loading

0 comments on commit 5243bd3

Please sign in to comment.