Skip to content

Commit 41c790d

Browse files
author
Emanuele Palazzetti
committed
[pylons] add distributed tracing via kwarg and environment variable
1 parent 9ffb621 commit 41c790d

File tree

4 files changed

+64
-8
lines changed

4 files changed

+64
-8
lines changed

ddtrace/contrib/pylons/__init__.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@
1010
1111
app = PylonsApp(...)
1212
13-
traced_app = PylonsTraceMiddleware(app, tracer, service="my-pylons-app")
13+
traced_app = PylonsTraceMiddleware(app, tracer, service='my-pylons-app')
1414
15-
Then you can define your routes and views as usual.
15+
Then you can define your routes and views as usual. To enable distributed tracing,
16+
set the following keyword argument::
17+
18+
traced_app = PylonsTraceMiddleware(app, tracer, service='my-pylons-app', distributed_tracing=True)
1619
"""
1720

1821
from ..util import require_modules

ddtrace/contrib/pylons/middleware.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
11
import logging
22
import sys
33

4+
from webob import Request
45
from pylons import config
56

67
from .renderer import trace_rendering
78
from .constants import CONFIG_MIDDLEWARE
89

9-
from ...ext import http
10-
from ...ext import AppTypes
10+
from ...ext import http, AppTypes
11+
from ...propagation.http import HTTPPropagator
1112

1213
log = logging.getLogger(__name__)
1314

1415

1516
class PylonsTraceMiddleware(object):
1617

17-
def __init__(self, app, tracer, service="pylons"):
18+
def __init__(self, app, tracer, service='pylons', distributed_tracing=False):
1819
self.app = app
1920
self._service = service
21+
self._distributed_tracing = distributed_tracing
2022
self._tracer = tracer
2123

2224
# register middleware reference
@@ -32,6 +34,15 @@ def __init__(self, app, tracer, service="pylons"):
3234
)
3335

3436
def __call__(self, environ, start_response):
37+
if self._distributed_tracing:
38+
# retrieve distributed tracing headers
39+
request = Request(environ)
40+
propagator = HTTPPropagator()
41+
context = propagator.extract(request.headers)
42+
# only need to active the new context if something was propagated
43+
if context.trace_id:
44+
self._tracer.context_provider.activate(context)
45+
3546
with self._tracer.trace("pylons.request", service=self._service) as span:
3647
# Set the service in tracer.trace() as priority sampling requires it to be
3748
# set as early as possible when different services share one single agent.

ddtrace/contrib/pylons/patch.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import os
22
import wrapt
3-
43
import pylons.wsgiapp
54

65
from ddtrace import tracer, Pin
@@ -31,9 +30,10 @@ def traced_init(wrapped, instance, args, kwargs):
3130
wrapped(*args, **kwargs)
3231

3332
# set tracing options and create the TraceMiddleware
34-
service = os.environ.get('DATADOG_SERVICE_NAME') or 'pylons'
33+
service = os.environ.get('DATADOG_SERVICE_NAME', 'pylons')
34+
distributed_tracing = os.environ.get('DATADOG_PYLONS_DISTRIBUTED_TRACING', False)
3535
Pin(service=service, tracer=tracer).onto(instance)
36-
traced_app = PylonsTraceMiddleware(instance, tracer, service=service)
36+
traced_app = PylonsTraceMiddleware(instance, tracer, service=service, distributed_tracing=distributed_tracing)
3737

3838
# re-order the middleware stack so that the first middleware is ours
3939
traced_app.app = instance.app

tests/contrib/pylons/test_pylons.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from paste.deploy import loadapp
99

1010
from ddtrace.ext import http
11+
from ddtrace.constants import SAMPLING_PRIORITY_KEY
1112
from ddtrace.contrib.pylons import PylonsTraceMiddleware
1213

1314
from ...test_tracer import get_dummy_tracer
@@ -145,3 +146,44 @@ def test_failure_500_with_code_method(self):
145146
eq_(span.error, 1)
146147
eq_(span.get_tag('http.status_code'), '500')
147148
eq_(span.get_tag('error.msg'), 'Ouch!')
149+
150+
def test_distributed_tracing_default(self):
151+
# ensure by default, distributed tracing is not enabled
152+
headers = {
153+
'x-datadog-trace-id': '100',
154+
'x-datadog-parent-id': '42',
155+
'x-datadog-sampling-priority': '2',
156+
}
157+
res = self.app.get(url_for(controller='root', action='index'), headers=headers)
158+
eq_(res.status, 200)
159+
160+
spans = self.tracer.writer.pop()
161+
ok_(spans, spans)
162+
eq_(len(spans), 1)
163+
span = spans[0]
164+
165+
ok_(span.trace_id != 100)
166+
ok_(span.parent_id != 42)
167+
ok_(span.get_metric(SAMPLING_PRIORITY_KEY) is None)
168+
169+
def test_distributed_tracing_enabled(self):
170+
# ensure distributed tracing propagator is working
171+
middleware = self.app.app
172+
middleware._distributed_tracing = True
173+
headers = {
174+
'x-datadog-trace-id': '100',
175+
'x-datadog-parent-id': '42',
176+
'x-datadog-sampling-priority': '2',
177+
}
178+
179+
res = self.app.get(url_for(controller='root', action='index'), headers=headers)
180+
eq_(res.status, 200)
181+
182+
spans = self.tracer.writer.pop()
183+
ok_(spans, spans)
184+
eq_(len(spans), 1)
185+
span = spans[0]
186+
187+
eq_(span.trace_id, 100)
188+
eq_(span.parent_id, 42)
189+
eq_(span.get_metric(SAMPLING_PRIORITY_KEY), 2)

0 commit comments

Comments
 (0)