Files
2020-04-08 10:39:44 -07:00

95 lines
3.0 KiB
Python

# 3rd party
from ddtrace.vendor import wrapt
import django
from django.db import connections
# project
from .db import patch_db
from .conf import settings
from .cache import patch_cache
from .templates import patch_template
from .middleware import insert_exception_middleware, insert_trace_middleware
from ...internal.logger import get_logger
log = get_logger(__name__)
def patch():
"""Patch the instrumented methods
"""
if getattr(django, '_datadog_patch', False):
return
setattr(django, '_datadog_patch', True)
_w = wrapt.wrap_function_wrapper
_w('django', 'setup', traced_setup)
def traced_setup(wrapped, instance, args, kwargs):
from django.conf import settings
if 'ddtrace.contrib.django' not in settings.INSTALLED_APPS:
if isinstance(settings.INSTALLED_APPS, tuple):
# INSTALLED_APPS is a tuple < 1.9
settings.INSTALLED_APPS = settings.INSTALLED_APPS + ('ddtrace.contrib.django', )
else:
settings.INSTALLED_APPS.append('ddtrace.contrib.django')
wrapped(*args, **kwargs)
def apply_django_patches(patch_rest_framework):
"""
Ready is called as soon as the registry is fully populated.
In order for all Django internals are properly configured, this
must be called after the app is finished starting
"""
tracer = settings.TRACER
if settings.TAGS:
tracer.set_tags(settings.TAGS)
# configure the tracer instance
# TODO[manu]: we may use configure() but because it creates a new
# AgentWriter, it breaks all tests. The configure() behavior must
# be changed to use it in this integration
tracer.enabled = settings.ENABLED
tracer.writer.api.hostname = settings.AGENT_HOSTNAME
tracer.writer.api.port = settings.AGENT_PORT
if settings.AUTO_INSTRUMENT:
# trace Django internals
insert_trace_middleware()
insert_exception_middleware()
if settings.INSTRUMENT_TEMPLATE:
try:
patch_template(tracer)
except Exception:
log.exception('error patching Django template rendering')
if settings.INSTRUMENT_DATABASE:
try:
patch_db(tracer)
# This is the trigger to patch individual connections.
# By patching these here, all processes including
# management commands are also traced.
connections.all()
except Exception:
log.exception('error patching Django database connections')
if settings.INSTRUMENT_CACHE:
try:
patch_cache(tracer)
except Exception:
log.exception('error patching Django cache')
# Instrument rest_framework app to trace custom exception handling.
if patch_rest_framework:
try:
from .restframework import patch_restframework
patch_restframework(tracer)
except Exception:
log.exception('error patching rest_framework app')