mirror of
https://github.com/open-telemetry/opentelemetry-python-contrib.git
synced 2025-07-28 12:43:39 +08:00
Removing support for python 2.7 (#2)
OpenTelemetry doesn't support Python 2.7. Removing it from the tests and removing contrib packages that don't support Python 3. In this change: - removing pylons contrib - removing mysqldb contrib - updating minimum versions of flask (>=1.0), gevent (>=1.1) Signed-off-by: Alex Boten <aboten@lightstep.com>
This commit is contained in:
@ -202,17 +202,6 @@ jobs:
|
||||
- *persist_to_workspace_step
|
||||
- *save_cache_step
|
||||
|
||||
pylons:
|
||||
docker:
|
||||
- *test_runner
|
||||
resource_class: *resource_class
|
||||
steps:
|
||||
- checkout
|
||||
- *restore_cache_step
|
||||
- run: scripts/run-tox-scenario '^pylons_contrib-'
|
||||
- *persist_to_workspace_step
|
||||
- *save_cache_step
|
||||
|
||||
aiohttp:
|
||||
docker:
|
||||
- *test_runner
|
||||
@ -318,7 +307,7 @@ jobs:
|
||||
steps:
|
||||
- checkout
|
||||
- *restore_cache_step
|
||||
- run: tox -e 'falcon_contrib{,_autopatch}-{py27,py34,py35,py36}-falcon{10,11,12,13,14}' --result-json /tmp/falcon.results
|
||||
- run: tox -e 'falcon_contrib{,_autopatch}-{py34,py35,py36}-falcon{10,11,12,13,14}' --result-json /tmp/falcon.results
|
||||
- *persist_to_workspace_step
|
||||
- *save_cache_step
|
||||
|
||||
@ -720,7 +709,7 @@ jobs:
|
||||
- run:
|
||||
command: |
|
||||
mkdir -p /tmp/test-reports
|
||||
tox -e 'benchmarks-{py27,py34,py35,py36,py37}' --result-json /tmp/benchmarks.results -- --benchmark-storage=file:///tmp/test-reports/ --benchmark-autosave
|
||||
tox -e 'benchmarks-{py34,py35,py36,py37}' --result-json /tmp/benchmarks.results -- --benchmark-storage=file:///tmp/test-reports/ --benchmark-autosave
|
||||
- store_test_results:
|
||||
path: /tmp/test-reports
|
||||
- store_artifacts:
|
||||
@ -985,10 +974,6 @@ workflows:
|
||||
requires:
|
||||
- flake8
|
||||
- black
|
||||
- pylons:
|
||||
requires:
|
||||
- flake8
|
||||
- black
|
||||
- pymemcache:
|
||||
requires:
|
||||
- flake8
|
||||
@ -1097,7 +1082,6 @@ workflows:
|
||||
- opentracer
|
||||
- psycopg
|
||||
- pylibmc
|
||||
- pylons
|
||||
- pymemcache
|
||||
- pymongo
|
||||
- pymysql
|
||||
|
@ -11,7 +11,7 @@ import sys
|
||||
|
||||
import pytest
|
||||
|
||||
PY_DIR_PATTERN = re.compile(r"^py[23][0-9]$")
|
||||
PY_DIR_PATTERN = re.compile(r"^py3[0-9]$")
|
||||
|
||||
|
||||
# Determine if the folder should be ignored
|
||||
@ -27,7 +27,6 @@ def pytest_ignore_collect(path, config):
|
||||
Example::
|
||||
|
||||
File: tests/contrib/vertica/py35/test.py
|
||||
Python 2.7: Skip
|
||||
Python 3.4: Skip
|
||||
Python 3.5: Collect
|
||||
Python 3.6: Collect
|
||||
|
@ -43,7 +43,6 @@ EXTRA_PATCHED_MODULES = {
|
||||
"django": True,
|
||||
"falcon": True,
|
||||
"flask": True,
|
||||
"pylons": True,
|
||||
"pyramid": True,
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ Available environment variables:
|
||||
DATADOG_TRACE_AGENT_PORT=8126: override the port that the default tracer will submit to (default: 8126)
|
||||
DATADOG_SERVICE_NAME : override the service name to be used for this program (no default)
|
||||
This value is passed through when setting up middleware for web framework integrations.
|
||||
(e.g. pylons, flask, django)
|
||||
(e.g. flask, django)
|
||||
For tracing without a web integration, prefer setting the service name in code.
|
||||
DATADOG_PRIORITY_SAMPLING=true|false : (default: false): enables Priority Sampling.
|
||||
""" # noqa: E501
|
||||
|
@ -156,13 +156,6 @@ def patch():
|
||||
for signal in signals:
|
||||
module = 'flask'
|
||||
|
||||
# v0.9 missed importing `appcontext_tearing_down` in `flask/__init__.py`
|
||||
# https://github.com/pallets/flask/blob/0.9/flask/__init__.py#L35-L37
|
||||
# https://github.com/pallets/flask/blob/0.9/flask/signals.py#L52
|
||||
# DEV: Version 0.9 doesn't have a patch version
|
||||
if flask_version <= (0, 9) and signal == 'appcontext_tearing_down':
|
||||
module = 'flask.signals'
|
||||
|
||||
# DEV: Patch `receivers_for` instead of `connect` to ensure we don't mess with `disconnect`
|
||||
_w(module, '{}.receivers_for'.format(signal), traced_signal_receivers_for(signal))
|
||||
|
||||
@ -241,13 +234,6 @@ def unpatch():
|
||||
# Handle 'flask.request_started.receivers_for'
|
||||
obj = flask
|
||||
|
||||
# v0.9.0 missed importing `appcontext_tearing_down` in `flask/__init__.py`
|
||||
# https://github.com/pallets/flask/blob/0.9/flask/__init__.py#L35-L37
|
||||
# https://github.com/pallets/flask/blob/0.9/flask/signals.py#L52
|
||||
# DEV: Version 0.9 doesn't have a patch version
|
||||
if flask_version <= (0, 9) and prop == 'appcontext_tearing_down.receivers_for':
|
||||
obj = flask.signals
|
||||
|
||||
if '.' in prop:
|
||||
attr, _, prop = prop.partition('.')
|
||||
obj = getattr(obj, attr, object())
|
||||
|
@ -1,32 +0,0 @@
|
||||
"""
|
||||
The pylons trace middleware will track request timings. To
|
||||
install the middleware, prepare your WSGI application and do
|
||||
the following::
|
||||
|
||||
from pylons.wsgiapp import PylonsApp
|
||||
|
||||
from ddtrace import tracer
|
||||
from ddtrace.contrib.pylons import PylonsTraceMiddleware
|
||||
|
||||
app = PylonsApp(...)
|
||||
|
||||
traced_app = PylonsTraceMiddleware(app, tracer, service='my-pylons-app')
|
||||
|
||||
Then you can define your routes and views as usual.
|
||||
"""
|
||||
|
||||
from ...utils.importlib import require_modules
|
||||
|
||||
|
||||
required_modules = ['pylons.wsgiapp']
|
||||
|
||||
with require_modules(required_modules) as missing_modules:
|
||||
if not missing_modules:
|
||||
from .middleware import PylonsTraceMiddleware
|
||||
from .patch import patch, unpatch
|
||||
|
||||
__all__ = [
|
||||
'patch',
|
||||
'unpatch',
|
||||
'PylonsTraceMiddleware',
|
||||
]
|
@ -1,8 +0,0 @@
|
||||
try:
|
||||
from pylons.templating import render_mako # noqa
|
||||
|
||||
# Pylons > 0.9.7
|
||||
legacy_pylons = False
|
||||
except ImportError:
|
||||
# Pylons <= 0.9.7
|
||||
legacy_pylons = True
|
@ -1 +0,0 @@
|
||||
CONFIG_MIDDLEWARE = '__datadog_middleware'
|
@ -1,110 +0,0 @@
|
||||
import sys
|
||||
|
||||
from webob import Request
|
||||
from pylons import config
|
||||
|
||||
from .renderer import trace_rendering
|
||||
from .constants import CONFIG_MIDDLEWARE
|
||||
|
||||
from ...compat import reraise
|
||||
from ...constants import ANALYTICS_SAMPLE_RATE_KEY
|
||||
from ...ext import SpanTypes, http
|
||||
from ...internal.logger import get_logger
|
||||
from ...propagation.http import HTTPPropagator
|
||||
from ...settings import config as ddconfig
|
||||
|
||||
|
||||
log = get_logger(__name__)
|
||||
|
||||
|
||||
class PylonsTraceMiddleware(object):
|
||||
|
||||
def __init__(self, app, tracer, service='pylons', distributed_tracing=True):
|
||||
self.app = app
|
||||
self._service = service
|
||||
self._distributed_tracing = distributed_tracing
|
||||
self._tracer = tracer
|
||||
|
||||
# register middleware reference
|
||||
config[CONFIG_MIDDLEWARE] = self
|
||||
|
||||
# add template tracing
|
||||
trace_rendering()
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
if self._distributed_tracing:
|
||||
# retrieve distributed tracing headers
|
||||
request = Request(environ)
|
||||
propagator = HTTPPropagator()
|
||||
context = propagator.extract(request.headers)
|
||||
# only need to active the new context if something was propagated
|
||||
if context.trace_id:
|
||||
self._tracer.context_provider.activate(context)
|
||||
|
||||
with self._tracer.trace('pylons.request', service=self._service, span_type=SpanTypes.WEB) as span:
|
||||
# Set the service in tracer.trace() as priority sampling requires it to be
|
||||
# set as early as possible when different services share one single agent.
|
||||
|
||||
# set analytics sample rate with global config enabled
|
||||
span.set_tag(
|
||||
ANALYTICS_SAMPLE_RATE_KEY,
|
||||
ddconfig.pylons.get_analytics_sample_rate(use_global_config=True)
|
||||
)
|
||||
|
||||
if not span.sampled:
|
||||
return self.app(environ, start_response)
|
||||
|
||||
# tentative on status code, otherwise will be caught by except below
|
||||
def _start_response(status, *args, **kwargs):
|
||||
""" a patched response callback which will pluck some metadata. """
|
||||
http_code = int(status.split()[0])
|
||||
span.set_tag(http.STATUS_CODE, http_code)
|
||||
if http_code >= 500:
|
||||
span.error = 1
|
||||
return start_response(status, *args, **kwargs)
|
||||
|
||||
try:
|
||||
return self.app(environ, _start_response)
|
||||
except Exception as e:
|
||||
# store current exceptions info so we can re-raise it later
|
||||
(typ, val, tb) = sys.exc_info()
|
||||
|
||||
# e.code can either be a string or an int
|
||||
code = getattr(e, 'code', 500)
|
||||
try:
|
||||
code = int(code)
|
||||
if not 100 <= code < 600:
|
||||
code = 500
|
||||
except Exception:
|
||||
code = 500
|
||||
span.set_tag(http.STATUS_CODE, code)
|
||||
span.error = 1
|
||||
|
||||
# re-raise the original exception with its original traceback
|
||||
reraise(typ, val, tb=tb)
|
||||
except SystemExit:
|
||||
span.set_tag(http.STATUS_CODE, 500)
|
||||
span.error = 1
|
||||
raise
|
||||
finally:
|
||||
controller = environ.get('pylons.routes_dict', {}).get('controller')
|
||||
action = environ.get('pylons.routes_dict', {}).get('action')
|
||||
|
||||
# There are cases where users re-route requests and manually
|
||||
# set resources. If this is so, don't do anything, otherwise
|
||||
# set the resource to the controller / action that handled it.
|
||||
if span.resource == span.name:
|
||||
span.resource = '%s.%s' % (controller, action)
|
||||
|
||||
span.set_tags({
|
||||
http.METHOD: environ.get('REQUEST_METHOD'),
|
||||
http.URL: '%s://%s:%s%s' % (environ.get('wsgi.url_scheme'),
|
||||
environ.get('SERVER_NAME'),
|
||||
environ.get('SERVER_PORT'),
|
||||
environ.get('PATH_INFO')),
|
||||
'pylons.user': environ.get('REMOTE_USER', ''),
|
||||
'pylons.route.controller': controller,
|
||||
'pylons.route.action': action,
|
||||
})
|
||||
if ddconfig.pylons.trace_query_string:
|
||||
span.set_tag(http.QUERY_STRING, environ.get('QUERY_STRING'))
|
@ -1,41 +0,0 @@
|
||||
import os
|
||||
from ddtrace.vendor import wrapt
|
||||
import pylons.wsgiapp
|
||||
|
||||
from ddtrace import tracer, Pin
|
||||
|
||||
from .middleware import PylonsTraceMiddleware
|
||||
from ...utils.formats import asbool, get_env
|
||||
from ...utils.wrappers import unwrap as _u
|
||||
|
||||
|
||||
def patch():
|
||||
"""Instrument Pylons applications"""
|
||||
if getattr(pylons.wsgiapp, '_datadog_patch', False):
|
||||
return
|
||||
|
||||
setattr(pylons.wsgiapp, '_datadog_patch', True)
|
||||
wrapt.wrap_function_wrapper('pylons.wsgiapp', 'PylonsApp.__init__', traced_init)
|
||||
|
||||
|
||||
def unpatch():
|
||||
"""Disable Pylons tracing"""
|
||||
if not getattr(pylons.wsgiapp, '__datadog_patch', False):
|
||||
return
|
||||
setattr(pylons.wsgiapp, '__datadog_patch', False)
|
||||
|
||||
_u(pylons.wsgiapp.PylonsApp, '__init__')
|
||||
|
||||
|
||||
def traced_init(wrapped, instance, args, kwargs):
|
||||
wrapped(*args, **kwargs)
|
||||
|
||||
# set tracing options and create the TraceMiddleware
|
||||
service = os.environ.get('DATADOG_SERVICE_NAME', 'pylons')
|
||||
distributed_tracing = asbool(get_env('pylons', 'distributed_tracing', True))
|
||||
Pin(service=service, tracer=tracer).onto(instance)
|
||||
traced_app = PylonsTraceMiddleware(instance, tracer, service=service, distributed_tracing=distributed_tracing)
|
||||
|
||||
# re-order the middleware stack so that the first middleware is ours
|
||||
traced_app.app = instance.app
|
||||
instance.app = traced_app
|
@ -1,36 +0,0 @@
|
||||
import pylons
|
||||
|
||||
from pylons import config
|
||||
|
||||
from ddtrace.vendor.wrapt import wrap_function_wrapper as _w
|
||||
|
||||
from .compat import legacy_pylons
|
||||
from .constants import CONFIG_MIDDLEWARE
|
||||
|
||||
|
||||
def trace_rendering():
|
||||
"""Patch all Pylons renderers. It supports multiple versions
|
||||
of Pylons and multiple renderers.
|
||||
"""
|
||||
# patch only once
|
||||
if getattr(pylons.templating, '__datadog_patch', False):
|
||||
return
|
||||
setattr(pylons.templating, '__datadog_patch', True)
|
||||
|
||||
if legacy_pylons:
|
||||
# Pylons <= 0.9.7
|
||||
_w('pylons.templating', 'render', _traced_renderer)
|
||||
else:
|
||||
# Pylons > 0.9.7
|
||||
_w('pylons.templating', 'render_mako', _traced_renderer)
|
||||
_w('pylons.templating', 'render_mako_def', _traced_renderer)
|
||||
_w('pylons.templating', 'render_genshi', _traced_renderer)
|
||||
_w('pylons.templating', 'render_jinja2', _traced_renderer)
|
||||
|
||||
|
||||
def _traced_renderer(wrapped, instance, args, kwargs):
|
||||
"""Traced renderer"""
|
||||
tracer = config[CONFIG_MIDDLEWARE]._tracer
|
||||
with tracer.trace('pylons.render') as span:
|
||||
span.set_tag('template.name', args[0])
|
||||
return wrapped(*args, **kwargs)
|
@ -57,7 +57,6 @@ PATCH_MODULES = {
|
||||
# Ignore some web framework integrations that might be configured explicitly in code
|
||||
'django': False,
|
||||
'falcon': False,
|
||||
'pylons': False,
|
||||
'pyramid': False,
|
||||
|
||||
# Standard library modules off by default
|
||||
|
@ -52,8 +52,6 @@ Supported web frameworks:
|
||||
+-------------------+---------+
|
||||
| :ref:`flask` | True |
|
||||
+-------------------+---------+
|
||||
| :ref:`pylons` | True |
|
||||
+-------------------+---------+
|
||||
| :ref:`pyramid` | True |
|
||||
+-------------------+---------+
|
||||
| :ref:`requests` | True |
|
||||
@ -197,7 +195,6 @@ Enabling APM events for all web frameworks can be accomplished by setting the en
|
||||
* :ref:`falcon`
|
||||
* :ref:`flask`
|
||||
* :ref:`molten`
|
||||
* :ref:`pylons`
|
||||
* :ref:`pyramid`
|
||||
* :ref:`requests`
|
||||
* :ref:`tornado`
|
||||
@ -238,8 +235,6 @@ For most libraries, APM events can be enabled with the environment variable ``DD
|
||||
+----------------------+----------------------------------------+
|
||||
| :ref:`pylibmc` | ``DD_PYLIBMC_ANALYTICS_ENABLED`` |
|
||||
+----------------------+----------------------------------------+
|
||||
| :ref:`pylons` | ``DD_PYLONS_ANALYTICS_ENABLED`` |
|
||||
+----------------------+----------------------------------------+
|
||||
| :ref:`pymemcache` | ``DD_PYMEMCACHE_ANALYTICS_ENABLED`` |
|
||||
+----------------------+----------------------------------------+
|
||||
| :ref:`pymongo` | ``DD_PYMONGO_ANALYTICS_ENABLED`` |
|
||||
@ -564,7 +559,7 @@ The available environment variables for ``ddtrace-run`` are:
|
||||
the tracer
|
||||
* ``DATADOG_SERVICE_NAME`` (no default): override the service name to be used
|
||||
for this program. This value is passed through when setting up middleware for
|
||||
web framework integrations (e.g. pylons, flask, django). For tracing without a
|
||||
web framework integrations (e.g. flask, django). For tracing without a
|
||||
web integration, prefer setting the service name in code.
|
||||
* ``DATADOG_PATCH_MODULES=module:patch,module:patch...`` e.g.
|
||||
``boto:true,redis:false``: override the modules patched for this execution of
|
||||
|
@ -25,7 +25,7 @@ documentation`_.
|
||||
Supported Libraries
|
||||
-------------------
|
||||
|
||||
We officially support Python 2.7, 3.4 and above.
|
||||
We officially support Python 3.4 and above.
|
||||
|
||||
The versions listed are the versions that we have tested, but ``ddtrace`` can
|
||||
still be compatible with other versions of these libraries. If a version of a
|
||||
@ -72,7 +72,7 @@ contacting support.
|
||||
+--------------------------------------------------+---------------+----------------+
|
||||
| :ref:`flask_cache` | >= 0.12 | No |
|
||||
+--------------------------------------------------+---------------+----------------+
|
||||
| :ref:`gevent` | >= 1.0 | No |
|
||||
| :ref:`gevent` | >= 1.1 | No |
|
||||
+--------------------------------------------------+---------------+----------------+
|
||||
| :ref:`grpc` | >= 1.8.0 | Yes |
|
||||
+--------------------------------------------------+---------------+----------------+
|
||||
@ -96,8 +96,6 @@ contacting support.
|
||||
+--------------------------------------------------+---------------+----------------+
|
||||
| :ref:`pylibmc` | >= 1.4 | Yes |
|
||||
+--------------------------------------------------+---------------+----------------+
|
||||
| :ref:`pylons` | >= 0.9.6 | No |
|
||||
+--------------------------------------------------+---------------+----------------+
|
||||
| :ref:`pymemcache` | >= 1.3 | Yes |
|
||||
+--------------------------------------------------+---------------+----------------+
|
||||
| :ref:`pymongo` | >= 3.0 | Yes |
|
||||
|
@ -59,14 +59,6 @@ Molten
|
||||
|
||||
.. automodule:: ddtrace.contrib.molten
|
||||
|
||||
.. _pylons:
|
||||
|
||||
Pylons
|
||||
^^^^^^
|
||||
|
||||
.. automodule:: ddtrace.contrib.pylons
|
||||
|
||||
|
||||
.. _pyramid:
|
||||
|
||||
Pyramid
|
||||
|
@ -1,6 +1,6 @@
|
||||
[tool.black]
|
||||
line-length = 120
|
||||
target_version = ['py27', 'py34', 'py35', 'py36', 'py37', 'py38']
|
||||
target_version = ['py34', 'py35', 'py36', 'py37', 'py38']
|
||||
exclude = '''
|
||||
(
|
||||
\.eggs
|
||||
@ -70,7 +70,6 @@ exclude = '''
|
||||
| mysqldb
|
||||
| psycopg
|
||||
| pylibmc
|
||||
| pylons
|
||||
| pymemcache
|
||||
| pymongo
|
||||
| pymysql
|
||||
@ -140,7 +139,6 @@ exclude = '''
|
||||
| patch.py
|
||||
| psycopg
|
||||
| pylibmc
|
||||
| pylons
|
||||
| pymemcache
|
||||
| pymongo
|
||||
| pymysql
|
||||
|
3
setup.py
3
setup.py
@ -88,7 +88,7 @@ documentation][visualization docs].
|
||||
|
||||
# enum34 is an enum backport for earlier versions of python
|
||||
# funcsigs backport required for vendored debtcollector
|
||||
install_requires = ["psutil>=5.0.0", "enum34; python_version<'3.4'", "funcsigs>=1.0.0;python_version=='2.7'"]
|
||||
install_requires = ["psutil>=5.0.0", "enum34; python_version<'3.4'"]
|
||||
|
||||
# Base `setup()` kwargs without any C-extension registering
|
||||
setup_kwargs = dict(
|
||||
@ -113,7 +113,6 @@ setup_kwargs = dict(
|
||||
entry_points={"console_scripts": ["ddtrace-run = ddtrace.commands.ddtrace_run:main"]},
|
||||
classifiers=[
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 2.7",
|
||||
"Programming Language :: Python :: 3.4",
|
||||
"Programming Language :: Python :: 3.5",
|
||||
"Programming Language :: Python :: 3.6",
|
||||
|
@ -11,12 +11,6 @@ from . import BaseFlaskTestCase
|
||||
|
||||
class FlaskSignalsTestCase(BaseFlaskTestCase):
|
||||
def get_signal(self, signal_name):
|
||||
# v0.9 missed importing `appcontext_tearing_down` in `flask/__init__.py`
|
||||
# https://github.com/pallets/flask/blob/0.9/flask/__init__.py#L35-L37
|
||||
# https://github.com/pallets/flask/blob/0.9/flask/signals.py#L52
|
||||
# DEV: Version 0.9 doesn't have a patch version
|
||||
if flask_version <= (0, 9) and signal_name == 'appcontext_tearing_down':
|
||||
return getattr(flask.signals, signal_name)
|
||||
return getattr(flask, signal_name)
|
||||
|
||||
def signal_function(self, name):
|
||||
|
@ -1,44 +0,0 @@
|
||||
from pylons.controllers import WSGIController
|
||||
|
||||
from ..lib.helpers import ExceptionWithCodeMethod, get_render_fn
|
||||
|
||||
|
||||
class BaseController(WSGIController):
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
"""Invoke the Controller"""
|
||||
# WSGIController.__call__ dispatches to the Controller method
|
||||
# the request is routed to. This routing information is
|
||||
# available in environ['pylons.routes_dict']
|
||||
return WSGIController.__call__(self, environ, start_response)
|
||||
|
||||
|
||||
class RootController(BaseController):
|
||||
"""Controller used for most tests"""
|
||||
|
||||
def index(self):
|
||||
return 'Hello World'
|
||||
|
||||
def raise_exception(self):
|
||||
raise Exception('Ouch!')
|
||||
|
||||
def raise_wrong_code(self):
|
||||
e = Exception('Ouch!')
|
||||
e.code = 'wrong formatted code'
|
||||
raise e
|
||||
|
||||
def raise_code_method(self):
|
||||
raise ExceptionWithCodeMethod('Ouch!')
|
||||
|
||||
def raise_custom_code(self):
|
||||
e = Exception('Ouch!')
|
||||
e.code = '512'
|
||||
raise e
|
||||
|
||||
def render(self):
|
||||
render = get_render_fn()
|
||||
return render('/template.mako')
|
||||
|
||||
def render_exception(self):
|
||||
render = get_render_fn()
|
||||
return render('/exception.mako')
|
@ -1 +0,0 @@
|
||||
# this file is required when Pylons calls the `legacy` module
|
@ -1,29 +0,0 @@
|
||||
from webhelpers import * # noqa
|
||||
|
||||
|
||||
class ExceptionWithCodeMethod(Exception):
|
||||
"""Use case where the status code is defined by
|
||||
the `code()` method.
|
||||
"""
|
||||
def __init__(self, message):
|
||||
super(ExceptionWithCodeMethod, self).__init__(message)
|
||||
|
||||
def code():
|
||||
pass
|
||||
|
||||
|
||||
class AppGlobals(object):
|
||||
"""Object used to store application globals."""
|
||||
pass
|
||||
|
||||
|
||||
def get_render_fn():
|
||||
"""Re-import the function everytime so that double-patching
|
||||
is correctly tested.
|
||||
"""
|
||||
try:
|
||||
from pylons.templating import render_mako as render
|
||||
except ImportError:
|
||||
from pylons.templating import render
|
||||
|
||||
return render
|
@ -1,43 +0,0 @@
|
||||
from webob import Request, Response
|
||||
|
||||
|
||||
class ExceptionMiddleware(object):
|
||||
"""A middleware which raises an exception."""
|
||||
def __init__(self, app):
|
||||
self.app = app
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
raise Exception('Middleware exception')
|
||||
|
||||
|
||||
class ExceptionToSuccessMiddleware(object):
|
||||
"""A middleware which catches any exceptions that occur in a later
|
||||
middleware and returns a successful request.
|
||||
"""
|
||||
def __init__(self, app):
|
||||
self.app = app
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
req = Request(environ)
|
||||
try:
|
||||
response = req.get_response(self.app)
|
||||
except Exception:
|
||||
response = Response()
|
||||
response.status_int = 200
|
||||
response.body = 'An error has been handled appropriately'
|
||||
return response(environ, start_response)
|
||||
|
||||
|
||||
class ExceptionToClientErrorMiddleware(object):
|
||||
def __init__(self, app):
|
||||
self.app = app
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
req = Request(environ)
|
||||
try:
|
||||
response = req.get_response(self.app)
|
||||
except Exception:
|
||||
response = Response()
|
||||
response.status_int = 404
|
||||
response.body = 'An error has occured with proper client error handling'
|
||||
return response(environ, start_response)
|
@ -1,20 +0,0 @@
|
||||
import os
|
||||
|
||||
from routes import Mapper
|
||||
|
||||
|
||||
def create_routes():
|
||||
"""Change this function if you need to add more routes
|
||||
to your Pylons test app.
|
||||
"""
|
||||
app_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
controller_dir = os.path.join(app_dir, 'controllers')
|
||||
routes = Mapper(directory=controller_dir)
|
||||
routes.connect('/', controller='root', action='index')
|
||||
routes.connect('/raise_exception', controller='root', action='raise_exception')
|
||||
routes.connect('/raise_wrong_code', controller='root', action='raise_wrong_code')
|
||||
routes.connect('/raise_custom_code', controller='root', action='raise_custom_code')
|
||||
routes.connect('/raise_code_method', controller='root', action='raise_code_method')
|
||||
routes.connect('/render', controller='root', action='render')
|
||||
routes.connect('/render_exception', controller='root', action='render_exception')
|
||||
return routes
|
@ -1 +0,0 @@
|
||||
${1/0}
|
@ -1 +0,0 @@
|
||||
Hello world!
|
@ -1,41 +0,0 @@
|
||||
import os
|
||||
|
||||
from mako.lookup import TemplateLookup
|
||||
|
||||
from pylons import config
|
||||
from pylons.wsgiapp import PylonsApp
|
||||
|
||||
from routes.middleware import RoutesMiddleware
|
||||
from beaker.middleware import SessionMiddleware, CacheMiddleware
|
||||
|
||||
from paste.registry import RegistryManager
|
||||
|
||||
from .router import create_routes
|
||||
from .lib.helpers import AppGlobals
|
||||
|
||||
|
||||
def make_app(global_conf, full_stack=True, **app_conf):
|
||||
# load Pylons environment
|
||||
root = os.path.dirname(os.path.abspath(__file__))
|
||||
paths = dict(
|
||||
templates=[os.path.join(root, 'templates')],
|
||||
)
|
||||
config.init_app(global_conf, app_conf, paths=paths)
|
||||
config['pylons.package'] = 'tests.contrib.pylons.app'
|
||||
config['pylons.app_globals'] = AppGlobals()
|
||||
|
||||
# set Pylons routes
|
||||
config['routes.map'] = create_routes()
|
||||
|
||||
# Create the Mako TemplateLookup, with the default auto-escaping
|
||||
config['pylons.app_globals'].mako_lookup = TemplateLookup(
|
||||
directories=paths['templates'],
|
||||
)
|
||||
|
||||
# define a default middleware stack
|
||||
app = PylonsApp()
|
||||
app = RoutesMiddleware(app, config['routes.map'])
|
||||
app = SessionMiddleware(app, config)
|
||||
app = CacheMiddleware(app, config)
|
||||
app = RegistryManager(app)
|
||||
return app
|
@ -1,9 +0,0 @@
|
||||
[DEFAULT]
|
||||
debug = false
|
||||
|
||||
[app:main]
|
||||
use = call:tests.contrib.pylons.app.web:make_app
|
||||
full_stack = true
|
||||
cache_dir = %(here)s/.cache
|
||||
beaker.session.key = helloworld
|
||||
beaker.session.secret = somesecret
|
@ -1,429 +0,0 @@
|
||||
import os
|
||||
|
||||
from routes import url_for
|
||||
from paste import fixture
|
||||
from paste.deploy import loadapp
|
||||
import pytest
|
||||
|
||||
from ddtrace import config
|
||||
from ddtrace.ext import http, errors
|
||||
from ddtrace.constants import SAMPLING_PRIORITY_KEY, ANALYTICS_SAMPLE_RATE_KEY
|
||||
from ddtrace.contrib.pylons import PylonsTraceMiddleware
|
||||
|
||||
from tests.opentracer.utils import init_tracer
|
||||
from ...base import BaseTracerTestCase
|
||||
from ...utils import assert_span_http_status_code
|
||||
|
||||
|
||||
class PylonsTestCase(BaseTracerTestCase):
|
||||
"""Pylons Test Controller that is used to test specific
|
||||
cases defined in the Pylons controller. To test a new behavior,
|
||||
add a new action in the `app.controllers.root` module.
|
||||
"""
|
||||
conf_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
def setUp(self):
|
||||
super(PylonsTestCase, self).setUp()
|
||||
# initialize a real traced Pylons app
|
||||
wsgiapp = loadapp('config:test.ini', relative_to=PylonsTestCase.conf_dir)
|
||||
self._wsgiapp = wsgiapp
|
||||
app = PylonsTraceMiddleware(wsgiapp, self.tracer, service='web')
|
||||
self.app = fixture.TestApp(app)
|
||||
|
||||
def test_controller_exception(self):
|
||||
"""Ensure exceptions thrown in controllers can be handled.
|
||||
|
||||
No error tags should be set in the span.
|
||||
"""
|
||||
from .app.middleware import ExceptionToSuccessMiddleware
|
||||
wsgiapp = ExceptionToSuccessMiddleware(self._wsgiapp)
|
||||
app = PylonsTraceMiddleware(wsgiapp, self.tracer, service='web')
|
||||
|
||||
app = fixture.TestApp(app)
|
||||
app.get(url_for(controller='root', action='raise_exception'))
|
||||
|
||||
spans = self.tracer.writer.pop()
|
||||
|
||||
assert spans, spans
|
||||
assert len(spans) == 1
|
||||
span = spans[0]
|
||||
|
||||
assert span.service == 'web'
|
||||
assert span.resource == 'root.raise_exception'
|
||||
assert span.error == 0
|
||||
assert span.get_tag(http.URL) == 'http://localhost:80/raise_exception'
|
||||
assert_span_http_status_code(span, 200)
|
||||
assert http.QUERY_STRING not in span.meta
|
||||
assert span.get_tag(errors.ERROR_MSG) is None
|
||||
assert span.get_tag(errors.ERROR_TYPE) is None
|
||||
assert span.get_tag(errors.ERROR_STACK) is None
|
||||
assert span.span_type == 'web'
|
||||
|
||||
def test_mw_exc_success(self):
|
||||
"""Ensure exceptions can be properly handled by other middleware.
|
||||
|
||||
No error should be reported in the span.
|
||||
"""
|
||||
from .app.middleware import ExceptionMiddleware, ExceptionToSuccessMiddleware
|
||||
wsgiapp = ExceptionMiddleware(self._wsgiapp)
|
||||
wsgiapp = ExceptionToSuccessMiddleware(wsgiapp)
|
||||
app = PylonsTraceMiddleware(wsgiapp, self.tracer, service='web')
|
||||
app = fixture.TestApp(app)
|
||||
|
||||
app.get(url_for(controller='root', action='index'))
|
||||
|
||||
spans = self.tracer.writer.pop()
|
||||
|
||||
assert spans, spans
|
||||
assert len(spans) == 1
|
||||
span = spans[0]
|
||||
|
||||
assert span.service == 'web'
|
||||
assert span.resource == 'None.None'
|
||||
assert span.error == 0
|
||||
assert span.get_tag(http.URL) == 'http://localhost:80/'
|
||||
assert_span_http_status_code(span, 200)
|
||||
assert span.get_tag(errors.ERROR_MSG) is None
|
||||
assert span.get_tag(errors.ERROR_TYPE) is None
|
||||
assert span.get_tag(errors.ERROR_STACK) is None
|
||||
|
||||
def test_middleware_exception(self):
|
||||
"""Ensure exceptions raised in middleware are properly handled.
|
||||
|
||||
Uncaught exceptions should result in error tagged spans.
|
||||
"""
|
||||
from .app.middleware import ExceptionMiddleware
|
||||
wsgiapp = ExceptionMiddleware(self._wsgiapp)
|
||||
app = PylonsTraceMiddleware(wsgiapp, self.tracer, service='web')
|
||||
app = fixture.TestApp(app)
|
||||
|
||||
with pytest.raises(Exception):
|
||||
app.get(url_for(controller='root', action='index'))
|
||||
|
||||
spans = self.tracer.writer.pop()
|
||||
|
||||
assert spans, spans
|
||||
assert len(spans) == 1
|
||||
span = spans[0]
|
||||
|
||||
assert span.service == 'web'
|
||||
assert span.resource == 'None.None'
|
||||
assert span.error == 1
|
||||
assert span.get_tag(http.URL) == 'http://localhost:80/'
|
||||
assert_span_http_status_code(span, 500)
|
||||
assert span.get_tag(errors.ERROR_MSG) == 'Middleware exception'
|
||||
assert span.get_tag(errors.ERROR_TYPE) == 'exceptions.Exception'
|
||||
assert span.get_tag(errors.ERROR_STACK)
|
||||
|
||||
def test_exc_success(self):
|
||||
from .app.middleware import ExceptionToSuccessMiddleware
|
||||
wsgiapp = ExceptionToSuccessMiddleware(self._wsgiapp)
|
||||
app = PylonsTraceMiddleware(wsgiapp, self.tracer, service='web')
|
||||
app = fixture.TestApp(app)
|
||||
|
||||
app.get(url_for(controller='root', action='raise_exception'))
|
||||
|
||||
spans = self.tracer.writer.pop()
|
||||
assert spans, spans
|
||||
assert len(spans) == 1
|
||||
span = spans[0]
|
||||
|
||||
assert span.service == 'web'
|
||||
assert span.resource == 'root.raise_exception'
|
||||
assert span.error == 0
|
||||
assert span.get_tag(http.URL) == 'http://localhost:80/raise_exception'
|
||||
assert_span_http_status_code(span, 200)
|
||||
assert span.get_tag(errors.ERROR_MSG) is None
|
||||
assert span.get_tag(errors.ERROR_TYPE) is None
|
||||
assert span.get_tag(errors.ERROR_STACK) is None
|
||||
|
||||
def test_exc_client_failure(self):
|
||||
from .app.middleware import ExceptionToClientErrorMiddleware
|
||||
wsgiapp = ExceptionToClientErrorMiddleware(self._wsgiapp)
|
||||
app = PylonsTraceMiddleware(wsgiapp, self.tracer, service='web')
|
||||
app = fixture.TestApp(app)
|
||||
|
||||
app.get(url_for(controller='root', action='raise_exception'), status=404)
|
||||
|
||||
spans = self.tracer.writer.pop()
|
||||
assert spans, spans
|
||||
assert len(spans) == 1
|
||||
span = spans[0]
|
||||
|
||||
assert span.service == 'web'
|
||||
assert span.resource == 'root.raise_exception'
|
||||
assert span.error == 0
|
||||
assert span.get_tag(http.URL) == 'http://localhost:80/raise_exception'
|
||||
assert_span_http_status_code(span, 404)
|
||||
assert span.get_tag(errors.ERROR_MSG) is None
|
||||
assert span.get_tag(errors.ERROR_TYPE) is None
|
||||
assert span.get_tag(errors.ERROR_STACK) is None
|
||||
|
||||
def test_success_200(self, query_string=''):
|
||||
if query_string:
|
||||
fqs = '?' + query_string
|
||||
else:
|
||||
fqs = ''
|
||||
res = self.app.get(url_for(controller='root', action='index') + fqs)
|
||||
assert res.status == 200
|
||||
|
||||
spans = self.tracer.writer.pop()
|
||||
assert spans, spans
|
||||
assert len(spans) == 1
|
||||
span = spans[0]
|
||||
|
||||
assert span.service == 'web'
|
||||
assert span.resource == 'root.index'
|
||||
assert_span_http_status_code(span, 200)
|
||||
if config.pylons.trace_query_string:
|
||||
assert span.meta.get(http.QUERY_STRING) == query_string
|
||||
else:
|
||||
assert http.QUERY_STRING not in span.meta
|
||||
assert span.error == 0
|
||||
|
||||
def test_query_string(self):
|
||||
return self.test_success_200('foo=bar')
|
||||
|
||||
def test_multi_query_string(self):
|
||||
return self.test_success_200('foo=bar&foo=baz&x=y')
|
||||
|
||||
def test_query_string_trace(self):
|
||||
with self.override_http_config('pylons', dict(trace_query_string=True)):
|
||||
return self.test_success_200('foo=bar')
|
||||
|
||||
def test_multi_query_string_trace(self):
|
||||
with self.override_http_config('pylons', dict(trace_query_string=True)):
|
||||
return self.test_success_200('foo=bar&foo=baz&x=y')
|
||||
|
||||
def test_analytics_global_on_integration_default(self):
|
||||
"""
|
||||
When making a request
|
||||
When an integration trace search is not event sample rate is not set and globally trace search is enabled
|
||||
We expect the root span to have the appropriate tag
|
||||
"""
|
||||
with self.override_global_config(dict(analytics_enabled=True)):
|
||||
res = self.app.get(url_for(controller='root', action='index'))
|
||||
self.assertEqual(res.status, 200)
|
||||
|
||||
self.assert_structure(
|
||||
dict(name='pylons.request', metrics={ANALYTICS_SAMPLE_RATE_KEY: 1.0})
|
||||
)
|
||||
|
||||
def test_analytics_global_on_integration_on(self):
|
||||
"""
|
||||
When making a request
|
||||
When an integration trace search is enabled and sample rate is set and globally trace search is enabled
|
||||
We expect the root span to have the appropriate tag
|
||||
"""
|
||||
with self.override_global_config(dict(analytics_enabled=True)):
|
||||
with self.override_config('pylons', dict(analytics_enabled=True, analytics_sample_rate=0.5)):
|
||||
res = self.app.get(url_for(controller='root', action='index'))
|
||||
self.assertEqual(res.status, 200)
|
||||
|
||||
self.assert_structure(
|
||||
dict(name='pylons.request', metrics={ANALYTICS_SAMPLE_RATE_KEY: 0.5})
|
||||
)
|
||||
|
||||
def test_analytics_global_off_integration_default(self):
|
||||
"""
|
||||
When making a request
|
||||
When an integration trace search is not set and sample rate is set and globally trace search is disabled
|
||||
We expect the root span to not include tag
|
||||
"""
|
||||
with self.override_global_config(dict(analytics_enabled=False)):
|
||||
res = self.app.get(url_for(controller='root', action='index'))
|
||||
self.assertEqual(res.status, 200)
|
||||
|
||||
root = self.get_root_span()
|
||||
self.assertIsNone(root.get_metric(ANALYTICS_SAMPLE_RATE_KEY))
|
||||
|
||||
def test_analytics_global_off_integration_on(self):
|
||||
"""
|
||||
When making a request
|
||||
When an integration trace search is enabled and sample rate is set and globally trace search is disabled
|
||||
We expect the root span to have the appropriate tag
|
||||
"""
|
||||
with self.override_global_config(dict(analytics_enabled=False)):
|
||||
with self.override_config('pylons', dict(analytics_enabled=True, analytics_sample_rate=0.5)):
|
||||
res = self.app.get(url_for(controller='root', action='index'))
|
||||
self.assertEqual(res.status, 200)
|
||||
|
||||
self.assert_structure(
|
||||
dict(name='pylons.request', metrics={ANALYTICS_SAMPLE_RATE_KEY: 0.5})
|
||||
)
|
||||
|
||||
def test_template_render(self):
|
||||
res = self.app.get(url_for(controller='root', action='render'))
|
||||
assert res.status == 200
|
||||
|
||||
spans = self.tracer.writer.pop()
|
||||
assert spans, spans
|
||||
assert len(spans) == 2
|
||||
request = spans[0]
|
||||
template = spans[1]
|
||||
|
||||
assert request.service == 'web'
|
||||
assert request.resource == 'root.render'
|
||||
assert_span_http_status_code(request, 200)
|
||||
assert request.error == 0
|
||||
|
||||
assert template.service == 'web'
|
||||
assert template.resource == 'pylons.render'
|
||||
assert template.meta.get('template.name') == '/template.mako'
|
||||
assert template.error == 0
|
||||
|
||||
def test_template_render_exception(self):
|
||||
with pytest.raises(Exception):
|
||||
self.app.get(url_for(controller='root', action='render_exception'))
|
||||
|
||||
spans = self.tracer.writer.pop()
|
||||
assert spans, spans
|
||||
assert len(spans) == 2
|
||||
request = spans[0]
|
||||
template = spans[1]
|
||||
|
||||
assert request.service == 'web'
|
||||
assert request.resource == 'root.render_exception'
|
||||
assert_span_http_status_code(request, 500)
|
||||
assert request.error == 1
|
||||
|
||||
assert template.service == 'web'
|
||||
assert template.resource == 'pylons.render'
|
||||
assert template.meta.get('template.name') == '/exception.mako'
|
||||
assert template.error == 1
|
||||
assert template.get_tag('error.msg') == 'integer division or modulo by zero'
|
||||
assert 'ZeroDivisionError: integer division or modulo by zero' in template.get_tag('error.stack')
|
||||
|
||||
def test_failure_500(self):
|
||||
with pytest.raises(Exception):
|
||||
self.app.get(url_for(controller='root', action='raise_exception'))
|
||||
|
||||
spans = self.tracer.writer.pop()
|
||||
assert spans, spans
|
||||
assert len(spans) == 1
|
||||
span = spans[0]
|
||||
|
||||
assert span.service == 'web'
|
||||
assert span.resource == 'root.raise_exception'
|
||||
assert span.error == 1
|
||||
assert_span_http_status_code(span, 500)
|
||||
assert span.get_tag('error.msg') == 'Ouch!'
|
||||
assert span.get_tag(http.URL) == 'http://localhost:80/raise_exception'
|
||||
assert 'Exception: Ouch!' in span.get_tag('error.stack')
|
||||
|
||||
def test_failure_500_with_wrong_code(self):
|
||||
with pytest.raises(Exception):
|
||||
self.app.get(url_for(controller='root', action='raise_wrong_code'))
|
||||
|
||||
spans = self.tracer.writer.pop()
|
||||
assert spans, spans
|
||||
assert len(spans) == 1
|
||||
span = spans[0]
|
||||
|
||||
assert span.service == 'web'
|
||||
assert span.resource == 'root.raise_wrong_code'
|
||||
assert span.error == 1
|
||||
assert_span_http_status_code(span, 500)
|
||||
assert span.meta.get(http.URL) == 'http://localhost:80/raise_wrong_code'
|
||||
assert span.get_tag('error.msg') == 'Ouch!'
|
||||
assert 'Exception: Ouch!' in span.get_tag('error.stack')
|
||||
|
||||
def test_failure_500_with_custom_code(self):
|
||||
with pytest.raises(Exception):
|
||||
self.app.get(url_for(controller='root', action='raise_custom_code'))
|
||||
|
||||
spans = self.tracer.writer.pop()
|
||||
assert spans, spans
|
||||
assert len(spans) == 1
|
||||
span = spans[0]
|
||||
|
||||
assert span.service == 'web'
|
||||
assert span.resource == 'root.raise_custom_code'
|
||||
assert span.error == 1
|
||||
assert_span_http_status_code(span, 512)
|
||||
assert span.meta.get(http.URL) == 'http://localhost:80/raise_custom_code'
|
||||
assert span.get_tag('error.msg') == 'Ouch!'
|
||||
assert 'Exception: Ouch!' in span.get_tag('error.stack')
|
||||
|
||||
def test_failure_500_with_code_method(self):
|
||||
with pytest.raises(Exception):
|
||||
self.app.get(url_for(controller='root', action='raise_code_method'))
|
||||
|
||||
spans = self.tracer.writer.pop()
|
||||
assert spans, spans
|
||||
assert len(spans) == 1
|
||||
span = spans[0]
|
||||
|
||||
assert span.service == 'web'
|
||||
assert span.resource == 'root.raise_code_method'
|
||||
assert span.error == 1
|
||||
assert_span_http_status_code(span, 500)
|
||||
assert span.meta.get(http.URL) == 'http://localhost:80/raise_code_method'
|
||||
assert span.get_tag('error.msg') == 'Ouch!'
|
||||
|
||||
def test_distributed_tracing_default(self):
|
||||
# ensure by default, distributed tracing is not enabled
|
||||
headers = {
|
||||
'x-datadog-trace-id': '100',
|
||||
'x-datadog-parent-id': '42',
|
||||
'x-datadog-sampling-priority': '2',
|
||||
}
|
||||
res = self.app.get(url_for(controller='root', action='index'), headers=headers)
|
||||
assert res.status == 200
|
||||
|
||||
spans = self.tracer.writer.pop()
|
||||
assert spans, spans
|
||||
assert len(spans) == 1
|
||||
span = spans[0]
|
||||
|
||||
assert span.trace_id == 100
|
||||
assert span.parent_id == 42
|
||||
assert span.get_metric(SAMPLING_PRIORITY_KEY) == 2
|
||||
|
||||
def test_distributed_tracing_disabled(self):
|
||||
# ensure distributed tracing propagator is working
|
||||
middleware = self.app.app
|
||||
middleware._distributed_tracing = False
|
||||
headers = {
|
||||
'x-datadog-trace-id': '100',
|
||||
'x-datadog-parent-id': '42',
|
||||
'x-datadog-sampling-priority': '2',
|
||||
}
|
||||
|
||||
res = self.app.get(url_for(controller='root', action='index'), headers=headers)
|
||||
assert res.status == 200
|
||||
|
||||
spans = self.tracer.writer.pop()
|
||||
assert spans, spans
|
||||
assert len(spans) == 1
|
||||
span = spans[0]
|
||||
|
||||
assert span.trace_id != 100
|
||||
assert span.parent_id != 42
|
||||
assert span.get_metric(SAMPLING_PRIORITY_KEY) != 2
|
||||
|
||||
def test_success_200_ot(self):
|
||||
"""OpenTracing version of test_success_200."""
|
||||
ot_tracer = init_tracer('pylons_svc', self.tracer)
|
||||
|
||||
with ot_tracer.start_active_span('pylons_get'):
|
||||
res = self.app.get(url_for(controller='root', action='index'))
|
||||
assert res.status == 200
|
||||
|
||||
spans = self.tracer.writer.pop()
|
||||
assert spans, spans
|
||||
assert len(spans) == 2
|
||||
ot_span, dd_span = spans
|
||||
|
||||
# confirm the parenting
|
||||
assert ot_span.parent_id is None
|
||||
assert dd_span.parent_id == ot_span.span_id
|
||||
|
||||
assert ot_span.name == 'pylons_get'
|
||||
assert ot_span.service == 'pylons_svc'
|
||||
|
||||
assert dd_span.service == 'web'
|
||||
assert dd_span.resource == 'root.index'
|
||||
assert_span_http_status_code(dd_span, 200)
|
||||
assert dd_span.meta.get(http.URL) == 'http://localhost:80/'
|
||||
assert dd_span.error == 0
|
204
tox.ini
204
tox.ini
@ -20,12 +20,12 @@ envlist =
|
||||
flake8
|
||||
black
|
||||
wait
|
||||
{py27,py34,py35,py36,py37}-tracer
|
||||
{py27,py34,py35,py36,py37}-internal
|
||||
{py27,py34,py35,py36,py37}-integration
|
||||
{py27,py34,py35,py36,py37}-ddtracerun
|
||||
{py27,py34,py35,py36,py37}-test_utils
|
||||
{py27,py34,py35,py36,py37}-test_logging
|
||||
{py34,py35,py36,py37}-tracer
|
||||
{py34,py35,py36,py37}-internal
|
||||
{py34,py35,py36,py37}-integration
|
||||
{py34,py35,py36,py37}-ddtracerun
|
||||
{py34,py35,py36,py37}-test_utils
|
||||
{py34,py35,py36,py37}-test_logging
|
||||
# Integrations environments
|
||||
aiobotocore_contrib-py34-aiobotocore{02,03,04}
|
||||
aiobotocore_contrib-{py35,py36}-aiobotocore{02,03,04,05,07,08,09,010}
|
||||
@ -37,70 +37,63 @@ envlist =
|
||||
aiohttp_contrib-{py35,py36,py37}-aiohttp{30,31,32,33,34,35}-aiohttp_jinja{015}-yarl10
|
||||
aiopg_contrib-{py34,py35,py36}-aiopg{012,015}
|
||||
aiopg_contrib-py37-aiopg015
|
||||
algoliasearch_contrib-{py27,py34,py35,py36,py37}-algoliasearch{1,2}
|
||||
algoliasearch_contrib-{py34,py35,py36,py37}-algoliasearch{1,2}
|
||||
asyncio_contrib-{py34,py35,py36,py37}
|
||||
# boto needs moto<1 and moto<1 does not support Python >= 3.7
|
||||
boto_contrib-{py27,py34,py35,py36}-boto
|
||||
botocore_contrib-{py27,py34,py35,py36,py37}-botocore
|
||||
bottle_contrib{,_autopatch}-{py27,py34,py35,py36,py37}-bottle{11,12}-webtest
|
||||
cassandra_contrib-{py27,py34,py35,py36,py37}-cassandra{35,36,37,38,315}
|
||||
boto_contrib-{py34,py35,py36}-boto
|
||||
botocore_contrib-{py34,py35,py36,py37}-botocore
|
||||
bottle_contrib{,_autopatch}-{py34,py35,py36,py37}-bottle{11,12}-webtest
|
||||
cassandra_contrib-{py34,py35,py36,py37}-cassandra{35,36,37,38,315}
|
||||
# Non-4.x celery should be able to use the older redis lib, since it locks to an older kombu
|
||||
celery_contrib-{py27,py34,py35,py36}-celery{31}-redis{210}
|
||||
celery_contrib-{py34,py35,py36}-celery{31}-redis{210}
|
||||
# 4.x celery bumps kombu to 4.4+, which requires redis 3.2 or later, this tests against
|
||||
# older redis with an older kombu, and newer kombu/newer redis.
|
||||
# https://github.com/celery/kombu/blob/3e60e6503a77b9b1a987cf7954659929abac9bac/Changelog#L35
|
||||
celery_contrib-{py27,py34,py35,py36}-celery{40,41}-{redis210-kombu43,redis320-kombu44}
|
||||
celery_contrib-{py34,py35,py36}-celery{40,41}-{redis210-kombu43,redis320-kombu44}
|
||||
# Celery 4.2 is now limited to Kombu 4.3
|
||||
# https://github.com/celery/celery/commit/1571d414461f01ae55be63a03e2adaa94dbcb15d
|
||||
celery_contrib-{py27,py34,py35,py36}-celery42-redis210-kombu43
|
||||
celery_contrib-{py34,py35,py36}-celery42-redis210-kombu43
|
||||
# Celery 4.3 wants Kombu >= 4.4 and Redis >= 3.2
|
||||
# Python 3.7 needs Celery 4.3
|
||||
celery_contrib-{py27,py34,py35,py36,py37}-celery43-redis320-kombu44
|
||||
consul_contrib-py{27,34,35,36,37}-consul{07,10,11}
|
||||
dbapi_contrib-{py27,py34,py35,py36}
|
||||
django_contrib{,_autopatch}-{py27,py34,py35,py36}-django{18,111}-djangopylibmc06-djangoredis45-pylibmc-redis{210}-memcached
|
||||
celery_contrib-{py34,py35,py36,py37}-celery43-redis320-kombu44
|
||||
consul_contrib-py{34,35,36,37}-consul{07,10,11}
|
||||
dbapi_contrib-{py34,py35,py36}
|
||||
django_contrib{,_autopatch}-{py34,py35,py36}-django{18,111}-djangopylibmc06-djangoredis45-pylibmc-redis{210}-memcached
|
||||
django_contrib{,_autopatch}-{py34,py35,py36}-django{200}-djangopylibmc06-djangoredis45-pylibmc-redis{210}-memcached
|
||||
django_drf_contrib-{py27,py34,py35,py36}-django{111}-djangorestframework{34,37,38}
|
||||
django_drf_contrib-{py34,py35,py36}-django{111}-djangorestframework{34,37,38}
|
||||
django_drf_contrib-{py34,py35,py36}-django{200}-djangorestframework{37,38}
|
||||
dogpile_contrib-{py27,py35,py36,py37}-dogpilecache{06,07,08,latest}
|
||||
elasticsearch_contrib-{py27,py34,py35,py36}-elasticsearch{16,17,18,23,24,51,52,53,54,63,64}
|
||||
elasticsearch_contrib-{py27,py34,py35,py36}-elasticsearch1{100}
|
||||
elasticsearch_contrib-{py27,py34,py35,py36}-elasticsearch2{50}
|
||||
elasticsearch_contrib-{py27,py34,py35,py36}-elasticsearch5{50}
|
||||
elasticsearch_contrib-{py27,py34,py35,py36}-elasticsearch6{40}
|
||||
falcon_contrib{,_autopatch}-{py27,py34,py35,py36}-falcon{10,11,12,13,14}
|
||||
flask_contrib{,_autopatch}-{py27,py34,py35,py36}-flask{010,011,012,10}-blinker
|
||||
# Flask <=0.9 does not support Python 3
|
||||
flask_contrib{,_autopatch}-{py27}-flask{09}-blinker
|
||||
flask_cache_contrib{,_autopatch}-{py27,py34,py35,py36,py37}-flask{010,011,012}-flaskcache{013}-memcached-redis{210}-blinker
|
||||
flask_cache_contrib{,_autopatch}-{py27}-flask{010,011}-flaskcache{012}-memcached-redis{210}-blinker
|
||||
futures_contrib-{py27}-futures{30,31,32}
|
||||
dogpile_contrib-{py35,py36,py37}-dogpilecache{06,07,08,latest}
|
||||
elasticsearch_contrib-{py34,py35,py36}-elasticsearch{16,17,18,23,24,51,52,53,54,63,64}
|
||||
elasticsearch_contrib-{py34,py35,py36}-elasticsearch1{100}
|
||||
elasticsearch_contrib-{py34,py35,py36}-elasticsearch2{50}
|
||||
elasticsearch_contrib-{py34,py35,py36}-elasticsearch5{50}
|
||||
elasticsearch_contrib-{py34,py35,py36}-elasticsearch6{40}
|
||||
falcon_contrib{,_autopatch}-{py34,py35,py36}-falcon{10,11,12,13,14}
|
||||
flask_contrib{,_autopatch}-{py34,py35,py36}-flask{010,011,012,10}-blinker
|
||||
flask_cache_contrib{,_autopatch}-{py34,py35,py36,py37}-flask{010,011,012}-flaskcache{013}-memcached-redis{210}-blinker
|
||||
futures_contrib-{py34,py35,py36,py37}
|
||||
gevent_contrib-{py27,py34,py35,py36}-gevent{11,12,13}
|
||||
gevent_contrib-{py34,py35,py36}-gevent{11,12,13}
|
||||
gevent_contrib-py37-gevent{13,14}
|
||||
# gevent 1.0 is not python 3 compatible
|
||||
gevent_contrib-{py27}-gevent{10}
|
||||
grpc_contrib-{py27,py34,py35,py36,py37}-grpc{112,113,114,115,116,117,118,119,120,121,122}
|
||||
httplib_contrib-{py27,py34,py35,py36,py37}
|
||||
jinja2_contrib-{py27,py34,py35,py36,py37}-jinja{27,28,29,210}
|
||||
mako_contrib-{py27,py34,py35,py36,py37}-mako{010,100}
|
||||
grpc_contrib-{py34,py35,py36,py37}-grpc{112,113,114,115,116,117,118,119,120,121,122}
|
||||
httplib_contrib-{py34,py35,py36,py37}
|
||||
jinja2_contrib-{py34,py35,py36,py37}-jinja{27,28,29,210}
|
||||
mako_contrib-{py34,py35,py36,py37}-mako{010,100}
|
||||
molten_contrib-py{36,37}-molten{070,072}
|
||||
mongoengine_contrib-{py27,py34,py35,py36,py37}-mongoengine{015,016,017,018,latest}-pymongo{latest}
|
||||
mysql_contrib-{py27,py34,py35,py36,py37}-mysqlconnector
|
||||
mongoengine_contrib-{py34,py35,py36,py37}-mongoengine{015,016,017,018,latest}-pymongo{latest}
|
||||
mysql_contrib-{py34,py35,py36,py37}-mysqlconnector
|
||||
mysqldb_contrib-{py27}-mysqldb{12}
|
||||
mysqldb_contrib-{py27,py34,py35,py36,py37}-mysqlclient{13}
|
||||
psycopg_contrib-{py27,py34,py35,py36}-psycopg2{24,25,26,27,28}
|
||||
mysqldb_contrib-{py34,py35,py36,py37}-mysqlclient{13}
|
||||
psycopg_contrib-{py34,py35,py36}-psycopg2{24,25,26,27,28}
|
||||
psycopg_contrib-py37-psycopg2{27,28}
|
||||
pylibmc_contrib-{py27,py34,py35,py36,py37}-pylibmc{140,150}
|
||||
pylons_contrib-{py27}-pylons{096,097,010,10}
|
||||
pymemcache_contrib{,_autopatch}-{py27,py34,py35,py36,py37}-pymemcache{130,140}
|
||||
pymongo_contrib-{py27,py34,py35,py36,py37}-pymongo{30,31,32,33,34,35,36,37,38,39,latest}-mongoengine{latest}
|
||||
pymysql_contrib-{py27,py34,py35,py36,py37}-pymysql{07,08,09}
|
||||
pyramid_contrib{,_autopatch}-{py27,py34,py35,py36,py37}-pyramid{17,18,19}-webtest
|
||||
redis_contrib-{py27,py34,py35,py36,py37}-redis{26,27,28,29,210,300}
|
||||
rediscluster_contrib-{py27,py34,py35,py36,py37}-rediscluster{135,136}-redis210
|
||||
requests_contrib{,_autopatch}-{py27,py34,py35,py36,py37}-requests{208,209,210,211,212,213,219}
|
||||
kombu_contrib-{py27,py34,py35,py36}-kombu{40,41,42}
|
||||
pylibmc_contrib-{py34,py35,py36,py37}-pylibmc{140,150}
|
||||
pymemcache_contrib{,_autopatch}-{py34,py35,py36,py37}-pymemcache{130,140}
|
||||
pymongo_contrib-{py34,py35,py36,py37}-pymongo{30,31,32,33,34,35,36,37,38,39,latest}-mongoengine{latest}
|
||||
pymysql_contrib-{py34,py35,py36,py37}-pymysql{07,08,09}
|
||||
pyramid_contrib{,_autopatch}-{py34,py35,py36,py37}-pyramid{17,18,19}-webtest
|
||||
redis_contrib-{py34,py35,py36,py37}-redis{26,27,28,29,210,300}
|
||||
rediscluster_contrib-{py34,py35,py36,py37}-rediscluster{135,136}-redis210
|
||||
requests_contrib{,_autopatch}-{py34,py35,py36,py37}-requests{208,209,210,211,212,213,219}
|
||||
kombu_contrib-{py34,py35,py36}-kombu{40,41,42}
|
||||
# Python 3.7 needs Kombu >= 4.2
|
||||
kombu_contrib-py37-kombu42
|
||||
# python 3.6 requests + gevent regression test
|
||||
@ -108,22 +101,20 @@ envlist =
|
||||
# https://github.com/gevent/gevent/issues/903
|
||||
requests_gevent_contrib-{py36}-requests{208,209,210,211,212,213,219}-gevent{12,13}
|
||||
requests_gevent_contrib-py37-requests{208,209,210,211,212,213,219}-gevent13
|
||||
sqlalchemy_contrib-{py27,py34,py35,py36,py37}-sqlalchemy{10,11,12}-psycopg228-mysqlconnector
|
||||
sqlite3_contrib-{py27,py34,py35,py36,py37}-sqlite3
|
||||
tornado_contrib-{py27,py34,py35,py36,py37}-tornado{40,41,42,43,44,45}
|
||||
sqlalchemy_contrib-{py34,py35,py36,py37}-sqlalchemy{10,11,12}-psycopg228-mysqlconnector
|
||||
sqlite3_contrib-{py34,py35,py36,py37}-sqlite3
|
||||
tornado_contrib-{py34,py35,py36,py37}-tornado{40,41,42,43,44,45}
|
||||
tornado_contrib-{py37}-tornado{50,51,60}
|
||||
tornado_contrib-{py27}-tornado{40,41,42,43,44,45}-futures{30,31,32}
|
||||
vertica_contrib-{py27,py34,py35,py36,py37}-vertica{060,070}
|
||||
vertica_contrib-{py34,py35,py36,py37}-vertica{060,070}
|
||||
# Opentracer
|
||||
{py27,py34,py35,py36,py37}-opentracer
|
||||
{py34,py35,py36,py37}-opentracer
|
||||
{py34,py35,py36,py37}-opentracer_asyncio
|
||||
{py34,py35,py36,py37}-opentracer_tornado-tornado{40,41,42,43,44}
|
||||
{py27}-opentracer_gevent-gevent{10}
|
||||
{py27,py34,py35,py36}-opentracer_gevent-gevent{11,12}
|
||||
{py34,py35,py36}-opentracer_gevent-gevent{11,12}
|
||||
py37-opentracer_gevent-gevent{13,14}
|
||||
# Unit tests: pytest based test suite that do not require any additional dependency
|
||||
unit_tests-{py27,py34,py35,py36,py37}
|
||||
benchmarks-{py27,py34,py35,py36,py37}
|
||||
unit_tests-{py34,py35,py36,py37}
|
||||
benchmarks-{py34,py35,py36,py37}
|
||||
|
||||
[testenv]
|
||||
# Always re-run `setup.py develop` to ensure the proper C-extension .so files are created
|
||||
@ -133,7 +124,6 @@ envlist =
|
||||
commands_pre={envpython} {toxinidir}/setup.py develop
|
||||
usedevelop = True
|
||||
basepython =
|
||||
py27: python2.7
|
||||
py34: python3.4
|
||||
py35: python3.5
|
||||
py36: python3.6
|
||||
@ -153,8 +143,6 @@ deps =
|
||||
# https://github.com/aio-libs/aiohttp/issues/2662
|
||||
yarl: yarl==0.18.0
|
||||
yarl10: yarl>=1.0,<1.1
|
||||
# backports
|
||||
py27: enum34
|
||||
# integrations
|
||||
aiobotocore010: aiobotocore>=0.10,<0.11
|
||||
aiobotocore09: aiobotocore>=0.9,<0.10
|
||||
@ -246,7 +234,6 @@ deps =
|
||||
falcon12: falcon>=1.2,<1.3
|
||||
falcon13: falcon>=1.3,<1.4
|
||||
falcon14: falcon>=1.4,<1.5
|
||||
flask09: flask>=0.9,<0.10
|
||||
flask010: flask>=0.10,<0.11
|
||||
flask011: flask>=0.11,<0.12
|
||||
flask012: flask>=0.12,<0.13
|
||||
@ -257,7 +244,6 @@ deps =
|
||||
futures30: futures>=3.0,<3.1
|
||||
futures31: futures>=3.1,<3.2
|
||||
futures32: futures>=3.2,<3.3
|
||||
gevent10: gevent>=1.0,<1.1
|
||||
gevent11: gevent>=1.1,<1.2
|
||||
gevent12: gevent>=1.2,<1.3
|
||||
gevent13: gevent>=1.3,<1.4
|
||||
@ -301,14 +287,6 @@ deps =
|
||||
mysqlconnector: mysql-connector-python!=8.0.18
|
||||
mysqldb12: mysql-python>=1.2,<1.3
|
||||
mysqlclient13: mysqlclient>=1.3,<1.4
|
||||
# webob is required for Pylons < 1.0
|
||||
pylons096: pylons>=0.9.6,<0.9.7
|
||||
pylons096: webob<1.1
|
||||
pylons097: pylons>=0.9.7,<0.9.8
|
||||
pylons097: webob<1.1
|
||||
pylons010: pylons>=0.10,<0.11
|
||||
pylons010: webob<1.1
|
||||
pylons10: pylons>=1.0,<1.1
|
||||
pylibmc: pylibmc
|
||||
pylibmc140: pylibmc>=1.4.0,<1.5.0
|
||||
pylibmc150: pylibmc>=1.5.0,<1.6.0
|
||||
@ -426,7 +404,6 @@ commands =
|
||||
mysqldb_contrib: pytest {posargs} tests/contrib/mysqldb
|
||||
psycopg_contrib: pytest {posargs} tests/contrib/psycopg
|
||||
pylibmc_contrib: pytest {posargs} tests/contrib/pylibmc
|
||||
pylons_contrib: pytest {posargs} tests/contrib/pylons
|
||||
pymemcache_contrib: pytest {posargs} --ignore="tests/contrib/pymemcache/autopatch" tests/contrib/pymemcache/
|
||||
pymemcache_contrib_autopatch: python tests/ddtrace_run.py pytest {posargs} tests/contrib/pymemcache/autopatch/
|
||||
pymongo_contrib: pytest {posargs} tests/contrib/pymongo
|
||||
@ -487,22 +464,12 @@ basepython=python3.7
|
||||
# same job will cause problem for tests that use ddtrace-run
|
||||
[celery_contrib]
|
||||
usedevelop = False
|
||||
[testenv:celery_contrib-py27-celery31-redis210]
|
||||
usedevelop = {[celery_contrib]usedevelop}
|
||||
[testenv:celery_contrib-py34-celery31-redis210]
|
||||
usedevelop = {[celery_contrib]usedevelop}
|
||||
[testenv:celery_contrib-py35-celery31-redis210]
|
||||
usedevelop = {[celery_contrib]usedevelop}
|
||||
[testenv:celery_contrib-py36-celery31-redis210]
|
||||
usedevelop = {[celery_contrib]usedevelop}
|
||||
[testenv:celery_contrib-py27-celery40-redis210-kombu43]
|
||||
usedevelop = {[celery_contrib]usedevelop}
|
||||
[testenv:celery_contrib-py27-celery40-redis320-kombu44]
|
||||
usedevelop = {[celery_contrib]usedevelop}
|
||||
[testenv:celery_contrib-py27-celery41-redis210-kombu43]
|
||||
usedevelop = {[celery_contrib]usedevelop}
|
||||
[testenv:celery_contrib-py27-celery41-redis320-kombu44]
|
||||
usedevelop = {[celery_contrib]usedevelop}
|
||||
[testenv:celery_contrib-py34-celery40-redis210-kombu43]
|
||||
usedevelop = {[celery_contrib]usedevelop}
|
||||
[testenv:celery_contrib-py34-celery40-redis320-kombu44]
|
||||
@ -527,16 +494,12 @@ usedevelop = {[celery_contrib]usedevelop}
|
||||
usedevelop = {[celery_contrib]usedevelop}
|
||||
[testenv:celery_contrib-py36-celery41-redis320-kombu44]
|
||||
usedevelop = {[celery_contrib]usedevelop}
|
||||
[testenv:celery_contrib-py27-celery42-redis210-kombu43]
|
||||
usedevelop = {[celery_contrib]usedevelop}
|
||||
[testenv:celery_contrib-py34-celery42-redis210-kombu43]
|
||||
usedevelop = {[celery_contrib]usedevelop}
|
||||
[testenv:celery_contrib-py35-celery42-redis210-kombu43]
|
||||
usedevelop = {[celery_contrib]usedevelop}
|
||||
[testenv:celery_contrib-py36-celery42-redis210-kombu43]
|
||||
usedevelop = {[celery_contrib]usedevelop}
|
||||
[testenv:celery_contrib-py27-celery43-redis320-kombu44]
|
||||
usedevelop = {[celery_contrib]usedevelop}
|
||||
[testenv:celery_contrib-py34-celery43-redis320-kombu44]
|
||||
usedevelop = {[celery_contrib]usedevelop}
|
||||
[testenv:celery_contrib-py35-celery43-redis320-kombu44]
|
||||
@ -549,21 +512,6 @@ usedevelop = {[celery_contrib]usedevelop}
|
||||
[falcon_autopatch]
|
||||
setenv =
|
||||
DATADOG_SERVICE_NAME=my-falcon
|
||||
[testenv:falcon_contrib_autopatch-py27-falcon10]
|
||||
setenv =
|
||||
{[falcon_autopatch]setenv}
|
||||
[testenv:falcon_contrib_autopatch-py27-falcon11]
|
||||
setenv =
|
||||
{[falcon_autopatch]setenv}
|
||||
[testenv:falcon_contrib_autopatch-py27-falcon12]
|
||||
setenv =
|
||||
{[falcon_autopatch]setenv}
|
||||
[testenv:falcon_contrib_autopatch-py27-falcon13]
|
||||
setenv =
|
||||
{[falcon_autopatch]setenv}
|
||||
[testenv:falcon_contrib_autopatch-py27-falcon14]
|
||||
setenv =
|
||||
{[falcon_autopatch]setenv}
|
||||
[testenv:falcon_contrib_autopatch-py34-falcon10]
|
||||
setenv =
|
||||
{[falcon_autopatch]setenv}
|
||||
@ -630,16 +578,6 @@ setenv =
|
||||
setenv =
|
||||
DATADOG_SERVICE_NAME = foobar
|
||||
DATADOG_PYRAMID_DISTRIBUTED_TRACING = True
|
||||
[testenv:pyramid_contrib_autopatch-py27-pyramid17-webtest]
|
||||
setenv =
|
||||
{[pyramid_autopatch]setenv}
|
||||
|
||||
[testenv:pyramid_contrib_autopatch-py27-pyramid18-webtest]
|
||||
setenv =
|
||||
{[pyramid_autopatch]setenv}
|
||||
[testenv:pyramid_contrib_autopatch-py27-pyramid19-webtest]
|
||||
setenv =
|
||||
{[pyramid_autopatch]setenv}
|
||||
[testenv:pyramid_contrib_autopatch-py34-pyramid17-webtest]
|
||||
setenv =
|
||||
{[pyramid_autopatch]setenv}
|
||||
@ -682,18 +620,6 @@ setenv =
|
||||
setenv =
|
||||
DATADOG_SERVICE_NAME = test.flask.service
|
||||
DATADOG_PATCH_MODULES = jinja2:false
|
||||
[testenv:flask_contrib_autopatch-py27-flask010-blinker]
|
||||
setenv =
|
||||
{[flask_autopatch]setenv}
|
||||
[testenv:flask_contrib_autopatch-py27-flask011-blinker]
|
||||
setenv =
|
||||
{[flask_autopatch]setenv}
|
||||
[testenv:flask_contrib_autopatch-py27-flask012-blinker]
|
||||
setenv =
|
||||
{[flask_autopatch]setenv}
|
||||
[testenv:flask_contrib_autopatch-py27-flask10-blinker]
|
||||
setenv =
|
||||
{[flask_autopatch]setenv}
|
||||
[testenv:flask_contrib_autopatch-py34-flask010-blinker]
|
||||
setenv =
|
||||
{[flask_autopatch]setenv}
|
||||
@ -740,15 +666,6 @@ setenv =
|
||||
setenv =
|
||||
{[flask_autopatch]setenv}
|
||||
[testenv:flask_contrib_autopatch-py37-flask10-blinker]
|
||||
setenv =
|
||||
{[flask_autopatch]setenv}
|
||||
[testenv:flask_contrib_autopatch-py27-flask010-flaskcache013-memcached-redis210-blinker]
|
||||
setenv =
|
||||
{[flask_autopatch]setenv}
|
||||
[testenv:flask_contrib_autopatch-py27-flask011-flaskcache013-memcached-redis210-blinker]
|
||||
setenv =
|
||||
{[flask_autopatch]setenv}
|
||||
[testenv:flask_contrib_autopatch-py27-flask012-flaskcache013-memcached-redis210-blinker]
|
||||
setenv =
|
||||
{[flask_autopatch]setenv}
|
||||
[testenv:flask_contrib_autopatch-py34-flask010-flaskcache013-memcached-redis210-blinker]
|
||||
@ -787,20 +704,10 @@ setenv =
|
||||
[testenv:flask_contrib_autopatch-py37-flask012-flaskcache013-memcached-redis210-blinker]
|
||||
setenv =
|
||||
{[flask_autopatch]setenv}
|
||||
[testenv:flask_contrib_autopatch-py27-flask010-flaskcache012-memcached-redis210-blinker]
|
||||
setenv =
|
||||
{[flask_autopatch]setenv}
|
||||
[testenv:flask_contrib_autopatch-py27-flask011-flaskcache012-memcached-redis210-blinker]
|
||||
setenv =
|
||||
{[flask_autopatch]setenv}
|
||||
|
||||
|
||||
[bottle_autopatch]
|
||||
setenv =
|
||||
DATADOG_SERVICE_NAME = bottle-app
|
||||
[testenv:bottle_contrib_autopatch-py27-bottle11-webtest]
|
||||
setenv =
|
||||
{[bottle_autopatch]setenv}
|
||||
[testenv:bottle_contrib_autopatch-py34-bottle11-webtest]
|
||||
setenv =
|
||||
{[bottle_autopatch]setenv}
|
||||
@ -811,9 +718,6 @@ setenv =
|
||||
setenv =
|
||||
{[bottle_autopatch]setenv}
|
||||
[testenv:bottle_contrib_autopatch-py37-bottle11-webtest]
|
||||
setenv =
|
||||
{[bottle_autopatch]setenv}
|
||||
[testenv:bottle_contrib_autopatch-py27-bottle12-webtest]
|
||||
setenv =
|
||||
{[bottle_autopatch]setenv}
|
||||
[testenv:bottle_contrib_autopatch-py34-bottle12-webtest]
|
||||
|
Reference in New Issue
Block a user