Skip to content

Commit b4ca38b

Browse files
author
Emanuele Palazzetti
authored
Merge pull request #458 from palazzem/sitecustomize
[core] ensure users sitecustomize.py is called
2 parents c86b122 + a238a87 commit b4ca38b

File tree

6 files changed

+90
-0
lines changed

6 files changed

+90
-0
lines changed

ddtrace/bootstrap/sitecustomize.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
"""
55

66
import os
7+
import imp
8+
import sys
79
import logging
810

911
from ddtrace.utils.formats import asbool
@@ -46,6 +48,8 @@ def update_patched_modules():
4648
patch = True
4749

4850
# Respect DATADOG_* environment variables in global tracer configuration
51+
# TODO: these variables are deprecated; use utils method and update our documentation
52+
# correct prefix should be DD_*
4953
enabled = os.environ.get("DATADOG_TRACE_ENABLED")
5054
hostname = os.environ.get("DATADOG_TRACE_AGENT_HOSTNAME")
5155
port = os.environ.get("DATADOG_TRACE_AGENT_PORT")
@@ -76,5 +80,24 @@ def update_patched_modules():
7680

7781
if 'DATADOG_ENV' in os.environ:
7882
tracer.set_tags({"env": os.environ["DATADOG_ENV"]})
83+
84+
# Ensure sitecustomize.py is properly called if available in application directories:
85+
# * exclude `bootstrap_dir` from the search
86+
# * find a user `sitecustomize.py` module
87+
# * import that module via `imp`
88+
bootstrap_dir = os.path.dirname(__file__)
89+
path = list(sys.path)
90+
path.remove(bootstrap_dir)
91+
92+
try:
93+
(f, path, description) = imp.find_module('sitecustomize', path)
94+
except ImportError:
95+
pass
96+
else:
97+
# `sitecustomize.py` found, load it
98+
log.debug('sitecustomize from user found in: %s', path)
99+
imp.load_module('sitecustomize', f, path, description)
100+
101+
79102
except Exception as e:
80103
log.warn("error configuring Datadog tracing", exc_info=True)

tests/commands/bootstrap/__init__.py

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CORRECT_IMPORT = True
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from __future__ import print_function
2+
3+
import sys
4+
from ddtrace import tracer
5+
from nose.tools import ok_
6+
7+
8+
if __name__ == '__main__':
9+
# detect if `-S` is used
10+
suppress = len(sys.argv) == 2 and sys.argv[1] is '-S'
11+
if suppress:
12+
ok_('sitecustomize' not in sys.modules)
13+
else:
14+
ok_('sitecustomize' in sys.modules)
15+
16+
# ensure the right `sitecustomize` will be imported
17+
import sitecustomize
18+
ok_(sitecustomize.CORRECT_IMPORT)
19+
print('Test success')

tests/commands/test_runner.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import subprocess
66
import unittest
77

8+
from ..util import inject_sitecustomize
9+
810

911
class DdtraceRunTest(unittest.TestCase):
1012
def tearDown(self):
@@ -147,3 +149,23 @@ def test_patch_modules_from_env(self):
147149
update_patched_modules()
148150
assert EXTRA_PATCHED_MODULES["boto"] == True
149151
assert EXTRA_PATCHED_MODULES["django"] == False
152+
153+
def test_sitecustomize_run(self):
154+
# [Regression test]: ensure users `sitecustomize.py` is properly loaded,
155+
# so that our `bootstrap/sitecustomize.py` doesn't override the one
156+
# defined in users' PYTHONPATH.
157+
env = inject_sitecustomize('tests/commands/bootstrap')
158+
out = subprocess.check_output(
159+
['ddtrace-run', 'python', 'tests/commands/ddtrace_run_sitecustomize.py'],
160+
env=env,
161+
)
162+
assert out.startswith(b"Test success")
163+
164+
def test_sitecustomize_run_suppressed(self):
165+
# ensure `sitecustomize.py` is not loaded if `-S` is used
166+
env = inject_sitecustomize('tests/commands/bootstrap')
167+
out = subprocess.check_output(
168+
['ddtrace-run', 'python', 'tests/commands/ddtrace_run_sitecustomize.py', '-S'],
169+
env=env,
170+
)
171+
assert out.startswith(b"Test success")

tests/util.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import os
2+
import sys
23
import mock
34
import ddtrace
45

6+
from ddtrace import __file__ as root_file
57
from nose.tools import ok_
68
from contextlib import contextmanager
79

@@ -75,3 +77,26 @@ def set_env(**environ):
7577
finally:
7678
os.environ.clear()
7779
os.environ.update(old_environ)
80+
81+
82+
def inject_sitecustomize(path):
83+
"""Creates a new environment, injecting a ``sitecustomize.py`` module in
84+
the current PYTHONPATH.
85+
86+
:param path: package path containing ``sitecustomize.py`` module, starting
87+
from the ddtrace root folder
88+
:returns: a cloned environment that includes an altered PYTHONPATH with
89+
the given `sitecustomize.py`
90+
"""
91+
root_folder = os.path.dirname(root_file)
92+
# Copy the current environment and replace the PYTHONPATH. This is
93+
# required otherwise `ddtrace` scripts are not found when `env` kwarg is
94+
# passed
95+
env = os.environ.copy()
96+
sitecustomize = os.path.join(root_folder, '..', path)
97+
98+
# Add `boostrap` module so that `sitecustomize.py` is at the bottom
99+
# of the PYTHONPATH
100+
python_path = list(sys.path) + [sitecustomize]
101+
env['PYTHONPATH'] = ':'.join(python_path)[1:]
102+
return env

0 commit comments

Comments
 (0)