Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into christophe-papazian/make_serverless_job_unre…
Browse files Browse the repository at this point in the history
…quired
christophe-papazian authored Jan 28, 2025
2 parents c17eb7a + 55767a7 commit 203e0d0
Showing 16 changed files with 290 additions and 243 deletions.
56 changes: 54 additions & 2 deletions ddtrace/_trace/trace_handlers.py
Original file line number Diff line number Diff line change
@@ -109,11 +109,14 @@ def _get_parameters_for_new_span_directly_from_context(ctx: core.ExecutionContex
def _start_span(ctx: core.ExecutionContext, call_trace: bool = True, **kwargs) -> "Span":
span_kwargs = _get_parameters_for_new_span_directly_from_context(ctx)
call_trace = ctx.get_item("call_trace", call_trace)
tracer = (ctx.get_item("middleware") or ctx["pin"]).tracer
tracer = ctx.get_item("tracer") or (ctx.get_item("middleware") or ctx["pin"]).tracer
distributed_headers_config = ctx.get_item("distributed_headers_config")
if distributed_headers_config:
trace_utils.activate_distributed_headers(
tracer, int_config=distributed_headers_config, request_headers=ctx["distributed_headers"]
tracer,
int_config=distributed_headers_config,
request_headers=ctx["distributed_headers"],
override=ctx.get_item("distributed_headers_config_override"),
)
distributed_context = ctx.get_item("distributed_context")
if distributed_context and not call_trace:
@@ -126,6 +129,42 @@ def _start_span(ctx: core.ExecutionContext, call_trace: bool = True, **kwargs) -
return span


def _set_web_frameworks_tags(ctx, span, int_config):
span.set_tag_str(COMPONENT, int_config.integration_name)
span.set_tag_str(SPAN_KIND, SpanKind.SERVER)
span.set_tag(_SPAN_MEASURED_KEY)

analytics_enabled = ctx.get_item("analytics_enabled")
analytics_sample_rate = ctx.get_item("analytics_sample_rate", True)

# Configure trace search sample rate
if (config._analytics_enabled and analytics_enabled is not False) or analytics_enabled is True:
span.set_tag(_ANALYTICS_SAMPLE_RATE_KEY, analytics_sample_rate)


def _on_web_framework_start_request(ctx, int_config):
request_span = ctx.get_item("req_span")
_set_web_frameworks_tags(ctx, request_span, int_config)


def _on_web_framework_finish_request(
span, int_config, method, url, status_code, query, req_headers, res_headers, route, finish
):
trace_utils.set_http_meta(
span=span,
integration_config=int_config,
method=method,
url=url,
status_code=status_code,
query=query,
request_headers=req_headers,
response_headers=res_headers,
route=route,
)
if finish:
span.finish()


def _on_traced_request_context_started_flask(ctx):
current_span = ctx["pin"].tracer.current_span()
if not ctx["pin"].enabled or not current_span:
@@ -761,6 +800,10 @@ def listen():
core.on("azure.functions.request_call_modifier", _on_azure_functions_request_span_modifier)
core.on("azure.functions.start_response", _on_azure_functions_start_response)

# web frameworks general handlers
core.on("web.request.start", _on_web_framework_start_request)
core.on("web.request.finish", _on_web_framework_finish_request)

core.on("test_visibility.enable", _on_test_visibility_enable)
core.on("test_visibility.disable", _on_test_visibility_disable)
core.on("test_visibility.is_enabled", _on_test_visibility_is_enabled, "is_enabled")
@@ -769,6 +812,14 @@ def listen():
core.on("rq.queue.enqueue_job", _propagate_context)

for context_name in (
# web frameworks
"aiohttp.request",
"bottle.request",
"cherrypy.request",
"falcon.request",
"molten.request",
"pyramid.request",
"sanic.request",
"flask.call",
"flask.jsonify",
"flask.render_template",
@@ -779,6 +830,7 @@ def listen():
"django.template.render",
"django.process_exception",
"django.func.wrapped",
# non web frameworks
"botocore.instrumented_api_call",
"botocore.instrumented_lib_function",
"botocore.patched_kinesis_api_call",
105 changes: 49 additions & 56 deletions ddtrace/contrib/internal/aiohttp/middlewares.py
Original file line number Diff line number Diff line change
@@ -2,15 +2,10 @@
from aiohttp.web_urldispatcher import SystemRoute

from ddtrace import config
from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY
from ddtrace.constants import _SPAN_MEASURED_KEY
from ddtrace.constants import SPAN_KIND
from ddtrace.contrib import trace_utils
from ddtrace.contrib.asyncio import context_provider
from ddtrace.ext import SpanKind
from ddtrace.ext import SpanTypes
from ddtrace.ext import http
from ddtrace.internal.constants import COMPONENT
from ddtrace.internal import core
from ddtrace.internal.schema import schematize_url_operation
from ddtrace.internal.schema.span_attribute_schema import SpanDirection

@@ -35,47 +30,42 @@ async def attach_context(request):
# application configs
tracer = app[CONFIG_KEY]["tracer"]
service = app[CONFIG_KEY]["service"]
distributed_tracing = app[CONFIG_KEY]["distributed_tracing_enabled"]
# Create a new context based on the propagated information.
trace_utils.activate_distributed_headers(
tracer,
int_config=config.aiohttp,
request_headers=request.headers,
override=distributed_tracing,
)

# trace the handler
request_span = tracer.trace(
schematize_url_operation("aiohttp.request", protocol="http", direction=SpanDirection.INBOUND),
service=service,
span_type=SpanTypes.WEB,
)
request_span.set_tag(_SPAN_MEASURED_KEY)

request_span.set_tag_str(COMPONENT, config.aiohttp.integration_name)

# set span.kind tag equal to type of request
request_span.set_tag_str(SPAN_KIND, SpanKind.SERVER)

# Configure trace search sample rate
# DEV: aiohttp is special case maintains separate configuration from config api
analytics_enabled = app[CONFIG_KEY]["analytics_enabled"]
if (config._analytics_enabled and analytics_enabled is not False) or analytics_enabled is True:
request_span.set_tag(_ANALYTICS_SAMPLE_RATE_KEY, app[CONFIG_KEY].get("analytics_sample_rate", True))

# attach the context and the root span to the request; the Context
# may be freely used by the application code
request[REQUEST_CONTEXT_KEY] = request_span.context
request[REQUEST_SPAN_KEY] = request_span
request[REQUEST_CONFIG_KEY] = app[CONFIG_KEY]
try:
response = await handler(request)
if isinstance(response, web.StreamResponse):
request.task.add_done_callback(lambda _: finish_request_span(request, response))
return response
except Exception:
request_span.set_traceback()
raise
# Create a new context based on the propagated information.

with core.context_with_data(
"aiohttp.request",
span_name=schematize_url_operation("aiohttp.request", protocol="http", direction=SpanDirection.INBOUND),
span_type=SpanTypes.WEB,
service=service,
tags={},
tracer=tracer,
distributed_headers=request.headers,
distributed_headers_config=config.aiohttp,
distributed_headers_config_override=app[CONFIG_KEY]["distributed_tracing_enabled"],
headers_case_sensitive=True,
analytics_enabled=analytics_enabled,
analytics_sample_rate=app[CONFIG_KEY].get("analytics_sample_rate", True),
) as ctx:
req_span = ctx.span

ctx.set_item("req_span", req_span)
core.dispatch("web.request.start", (ctx, config.aiohttp))

# attach the context and the root span to the request; the Context
# may be freely used by the application code
request[REQUEST_CONTEXT_KEY] = req_span.context
request[REQUEST_SPAN_KEY] = req_span
request[REQUEST_CONFIG_KEY] = app[CONFIG_KEY]
try:
response = await handler(request)
if isinstance(response, web.StreamResponse):
request.task.add_done_callback(lambda _: finish_request_span(request, response))
return response
except Exception:
req_span.set_traceback()
raise

return attach_context

@@ -122,19 +112,22 @@ def finish_request_span(request, response):
# SystemRoute objects exist to throw HTTP errors and have no path
route = aiohttp_route.resource.canonical

trace_utils.set_http_meta(
request_span,
config.aiohttp,
method=request.method,
url=str(request.url), # DEV: request.url is a yarl's URL object
status_code=response.status,
request_headers=request.headers,
response_headers=response.headers,
route=route,
core.dispatch(
"web.request.finish",
(
request_span,
config.aiohttp,
request.method,
str(request.url), # DEV: request.url is a yarl's URL object
response.status,
None, # query arg = None
request.headers,
response.headers,
route,
True,
),
)

request_span.finish()


async def on_prepare(request, response):
"""
61 changes: 29 additions & 32 deletions ddtrace/contrib/internal/bottle/trace.py
Original file line number Diff line number Diff line change
@@ -5,13 +5,8 @@

import ddtrace
from ddtrace import config
from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY
from ddtrace.constants import _SPAN_MEASURED_KEY
from ddtrace.constants import SPAN_KIND
from ddtrace.contrib import trace_utils
from ddtrace.ext import SpanKind
from ddtrace.ext import SpanTypes
from ddtrace.internal.constants import COMPONENT
from ddtrace.internal import core
from ddtrace.internal.schema import schematize_url_operation
from ddtrace.internal.schema.span_attribute_schema import SpanDirection
from ddtrace.internal.utils.formats import asbool
@@ -42,24 +37,21 @@ def wrapped(*args, **kwargs):

resource = "{} {}".format(request.method, route.rule)

trace_utils.activate_distributed_headers(
self.tracer, int_config=config.bottle, request_headers=request.headers
)

with self.tracer.trace(
schematize_url_operation("bottle.request", protocol="http", direction=SpanDirection.INBOUND),
with core.context_with_data(
"bottle.request",
span_name=schematize_url_operation("bottle.request", protocol="http", direction=SpanDirection.INBOUND),
span_type=SpanTypes.WEB,
service=self.service,
resource=resource,
span_type=SpanTypes.WEB,
) as s:
s.set_tag_str(COMPONENT, config.bottle.integration_name)

# set span.kind to the type of request being performed
s.set_tag_str(SPAN_KIND, SpanKind.SERVER)

s.set_tag(_SPAN_MEASURED_KEY)
# set analytics sample rate with global config enabled
s.set_tag(_ANALYTICS_SAMPLE_RATE_KEY, config.bottle.get_analytics_sample_rate(use_global_config=True))
tags={},
tracer=self.tracer,
distributed_headers=request.headers,
distributed_headers_config=config.bottle,
headers_case_sensitive=True,
analytics_sample_rate=config.bottle.get_analytics_sample_rate(use_global_config=True),
) as ctx, ctx.span as req_span:
ctx.set_item("req_span", req_span)
core.dispatch("web.request.start", (ctx, config.bottle))

code = None
result = None
@@ -91,16 +83,21 @@ def wrapped(*args, **kwargs):
method = request.method
url = request.urlparts._replace(query="").geturl()
full_route = "/".join([request.script_name.rstrip("/"), route.rule.lstrip("/")])
trace_utils.set_http_meta(
s,
config.bottle,
method=method,
url=url,
status_code=response_code,
query=request.query_string,
request_headers=request.headers,
response_headers=response.headers,
route=full_route,

core.dispatch(
"web.request.finish",
(
req_span,
config.bottle,
method,
url,
response_code,
request.query_string,
request.headers,
response.headers,
full_route,
False,
),
)

return wrapped
53 changes: 29 additions & 24 deletions ddtrace/contrib/internal/cherrypy/middleware.py
Original file line number Diff line number Diff line change
@@ -11,12 +11,10 @@
from ddtrace.constants import ERROR_MSG
from ddtrace.constants import ERROR_STACK
from ddtrace.constants import ERROR_TYPE
from ddtrace.constants import SPAN_KIND
from ddtrace.contrib import trace_utils
from ddtrace.ext import SpanKind
from ddtrace.ext import SpanTypes
from ddtrace.internal import compat
from ddtrace.internal.constants import COMPONENT
from ddtrace.internal import core
from ddtrace.internal.schema import SpanDirection
from ddtrace.internal.schema import schematize_service_name
from ddtrace.internal.schema import schematize_url_operation
@@ -77,20 +75,23 @@ def _setup(self):
cherrypy.request.hooks.attach("after_error_response", self._after_error_response, priority=5)

def _on_start_resource(self):
trace_utils.activate_distributed_headers(
self._tracer, int_config=config.cherrypy, request_headers=cherrypy.request.headers
)

cherrypy.request._datadog_span = self._tracer.trace(
SPAN_NAME,
service=trace_utils.int_service(None, config.cherrypy, default="cherrypy"),
with core.context_with_data(
"cherrypy.request",
span_name=SPAN_NAME,
span_type=SpanTypes.WEB,
)
service=trace_utils.int_service(None, config.cherrypy, default="cherrypy"),
tags={},
tracer=self._tracer,
distributed_headers=cherrypy.request.headers,
distributed_headers_config=config.cherrypy,
headers_case_sensitive=True,
) as ctx:
req_span = ctx.span

cherrypy.request._datadog_span.set_tag_str(COMPONENT, config.cherrypy.integration_name)
ctx.set_item("req_span", req_span)
core.dispatch("web.request.start", (ctx, config.cherrypy))

# set span.kind to the type of request being performed
cherrypy.request._datadog_span.set_tag_str(SPAN_KIND, SpanKind.SERVER)
cherrypy.request._datadog_span = req_span

def _after_error_response(self):
span = getattr(cherrypy.request, "_datadog_span", None)
@@ -135,18 +136,22 @@ def _close_span(self, span):
url = compat.to_unicode(cherrypy.request.base + cherrypy.request.path_info)
status_code, _, _ = valid_status(cherrypy.response.status)

trace_utils.set_http_meta(
span,
config.cherrypy,
method=cherrypy.request.method,
url=url,
status_code=status_code,
request_headers=cherrypy.request.headers,
response_headers=cherrypy.response.headers,
core.dispatch(
"web.request.finish",
(
span,
config.cherrypy,
cherrypy.request.method,
url,
status_code,
None,
cherrypy.request.headers,
cherrypy.response.headers,
None,
True,
),
)

span.finish()

# Clear our span just in case.
cherrypy.request._datadog_span = None

61 changes: 24 additions & 37 deletions ddtrace/contrib/internal/falcon/middleware.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import sys

from ddtrace import config
from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY
from ddtrace.constants import _SPAN_MEASURED_KEY
from ddtrace.constants import SPAN_KIND
from ddtrace.contrib import trace_utils
from ddtrace.ext import SpanKind
from ddtrace.ext import SpanTypes
from ddtrace.ext import http as httpx
from ddtrace.internal.constants import COMPONENT
from ddtrace.internal import core
from ddtrace.internal.schema import SpanDirection
from ddtrace.internal.schema import schematize_service_name
from ddtrace.internal.schema import schematize_url_operation
@@ -27,26 +21,27 @@ def __init__(self, tracer, service=None, distributed_tracing=None):
def process_request(self, req, resp):
# Falcon uppercases all header names.
headers = dict((k.lower(), v) for k, v in req.headers.items())
trace_utils.activate_distributed_headers(self.tracer, int_config=config.falcon, request_headers=headers)

span = self.tracer.trace(
schematize_url_operation("falcon.request", protocol="http", direction=SpanDirection.INBOUND),
service=self.service,
with core.context_with_data(
"falcon.request",
span_name=schematize_url_operation("falcon.request", protocol="http", direction=SpanDirection.INBOUND),
span_type=SpanTypes.WEB,
)
span.set_tag_str(COMPONENT, config.falcon.integration_name)

# set span.kind to the type of operation being performed
span.set_tag_str(SPAN_KIND, SpanKind.SERVER)

span.set_tag(_SPAN_MEASURED_KEY)

# set analytics sample rate with global config enabled
span.set_tag(_ANALYTICS_SAMPLE_RATE_KEY, config.falcon.get_analytics_sample_rate(use_global_config=True))

trace_utils.set_http_meta(
span, config.falcon, method=req.method, url=req.url, query=req.query_string, request_headers=req.headers
)
service=self.service,
tags={},
tracer=self.tracer,
distributed_headers=headers,
distributed_headers_config=config.falcon,
headers_case_sensitive=True,
analytics_sample_rate=config.falcon.get_analytics_sample_rate(use_global_config=True),
) as ctx:
req_span = ctx.span
ctx.set_item("req_span", req_span)
core.dispatch("web.request.start", (ctx, config.falcon))

core.dispatch(
"web.request.finish",
(req_span, config.falcon, req.method, req.url, None, req.query_string, req.headers, None, None, False),
)

def process_resource(self, req, resp, resource, params):
span = self.tracer.current_span()
@@ -69,8 +64,7 @@ def process_response(self, req, resp, resource, req_succeeded=None):
if resource is None:
status = "404"
span.resource = "%s 404" % req.method
span.set_tag(httpx.STATUS_CODE, status)
span.finish()
core.dispatch("web.request.finish", (span, config.falcon, None, None, status, None, None, None, None, True))
return

err_type = sys.exc_info()[0]
@@ -87,20 +81,13 @@ def process_response(self, req, resp, resource, req_succeeded=None):

route = req.root_path or "" + req.uri_template

trace_utils.set_http_meta(
span,
config.falcon,
status_code=status,
response_headers=resp._headers,
route=route,
)

# Emit span hook for this response
# DEV: Emit before closing so they can overwrite `span.resource` if they want
config.falcon.hooks.emit("request", span, req, resp)

# Close the span
span.finish()
core.dispatch(
"web.request.finish", (span, config.falcon, None, None, status, None, None, resp._headers, route, True)
)


def _is_404(err_type):
52 changes: 24 additions & 28 deletions ddtrace/contrib/internal/molten/patch.py
Original file line number Diff line number Diff line change
@@ -5,15 +5,11 @@
from wrapt import wrap_function_wrapper as _w

from ddtrace import config
from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY
from ddtrace.constants import _SPAN_MEASURED_KEY
from ddtrace.constants import SPAN_KIND
from ddtrace.contrib import trace_utils
from ddtrace.contrib.internal.trace_utils import unwrap as _u
from ddtrace.ext import SpanKind
from ddtrace.ext import SpanTypes
from ddtrace.internal import core
from ddtrace.internal.compat import urlencode
from ddtrace.internal.constants import COMPONENT
from ddtrace.internal.schema import schematize_service_name
from ddtrace.internal.schema import schematize_url_operation
from ddtrace.internal.schema.span_attribute_schema import SpanDirection
@@ -89,25 +85,21 @@ def patch_app_call(wrapped, instance, args, kwargs):
request = molten.http.Request.from_environ(environ)
resource = func_name(wrapped)

# request.headers is type Iterable[Tuple[str, str]]
trace_utils.activate_distributed_headers(
pin.tracer, int_config=config.molten, request_headers=dict(request.headers)
)

with pin.tracer.trace(
schematize_url_operation("molten.request", protocol="http", direction=SpanDirection.INBOUND),
with core.context_with_data(
"molten.request",
span_name=schematize_url_operation("molten.request", protocol="http", direction=SpanDirection.INBOUND),
span_type=SpanTypes.WEB,
service=trace_utils.int_service(pin, config.molten),
resource=resource,
span_type=SpanTypes.WEB,
) as span:
span.set_tag_str(COMPONENT, config.molten.integration_name)

# set span.kind tag equal to type of operation being performed
span.set_tag_str(SPAN_KIND, SpanKind.SERVER)

span.set_tag(_SPAN_MEASURED_KEY)
# set analytics sample rate with global config enabled
span.set_tag(_ANALYTICS_SAMPLE_RATE_KEY, config.molten.get_analytics_sample_rate(use_global_config=True))
tags={},
tracer=pin.tracer,
distributed_headers=dict(request.headers), # request.headers is type Iterable[Tuple[str, str]]
distributed_headers_config=config.molten,
headers_case_sensitive=True,
analytics_sample_rate=config.molten.get_analytics_sample_rate(use_global_config=True),
) as ctx, ctx.span as req_span:
ctx.set_item("req_span", req_span)
core.dispatch("web.request.start", (ctx, config.molten))

@wrapt.function_wrapper
def _w_start_response(wrapped, instance, args, kwargs):
@@ -125,11 +117,13 @@ def _w_start_response(wrapped, instance, args, kwargs):
except ValueError:
pass

if not span.get_tag(MOLTEN_ROUTE):
if not req_span.get_tag(MOLTEN_ROUTE):
# if route never resolve, update root resource
span.resource = "{} {}".format(request.method, code)
req_span.resource = "{} {}".format(request.method, code)

trace_utils.set_http_meta(span, config.molten, status_code=code)
core.dispatch(
"web.request.finish", (req_span, config.molten, None, None, code, None, None, None, None, False)
)

return wrapped(*args, **kwargs)

@@ -143,11 +137,13 @@ def _w_start_response(wrapped, instance, args, kwargs):
request.path,
)
query = urlencode(dict(request.params))
trace_utils.set_http_meta(
span, config.molten, method=request.method, url=url, query=query, request_headers=request.headers

core.dispatch(
"web.request.finish",
(req_span, config.molten, request.method, url, None, query, request.headers, None, None, False),
)

span.set_tag_str("molten.version", molten.__version__)
req_span.set_tag_str("molten.version", molten.__version__)
return wrapped(environ, start_response, **kwargs)


72 changes: 37 additions & 35 deletions ddtrace/contrib/internal/pyramid/trace.py
Original file line number Diff line number Diff line change
@@ -6,12 +6,8 @@
# project
import ddtrace
from ddtrace import config
from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY
from ddtrace.constants import _SPAN_MEASURED_KEY
from ddtrace.constants import SPAN_KIND
from ddtrace.contrib import trace_utils
from ddtrace.ext import SpanKind
from ddtrace.ext import SpanTypes
from ddtrace.internal import core
from ddtrace.internal.constants import COMPONENT
from ddtrace.internal.logger import get_logger
from ddtrace.internal.schema import schematize_service_name
@@ -67,29 +63,30 @@ def trace_tween_factory(handler, registry):
service = settings.get(SETTINGS_SERVICE) or schematize_service_name("pyramid")
tracer = settings.get(SETTINGS_TRACER) or ddtrace.tracer
enabled = asbool(settings.get(SETTINGS_TRACE_ENABLED, tracer.enabled))
distributed_tracing = asbool(settings.get(SETTINGS_DISTRIBUTED_TRACING, True))

# ensure distributed tracing within pyramid settings matches config
config.pyramid.distributed_tracing_enabled = asbool(settings.get(SETTINGS_DISTRIBUTED_TRACING, True))

if enabled:
# make a request tracing function
def trace_tween(request):
trace_utils.activate_distributed_headers(
tracer, int_config=config.pyramid, request_headers=request.headers, override=distributed_tracing
)

span_name = schematize_url_operation("pyramid.request", protocol="http", direction=SpanDirection.INBOUND)
with tracer.trace(span_name, service=service, resource="404", span_type=SpanTypes.WEB) as span:
span.set_tag_str(COMPONENT, config.pyramid.integration_name)

# set span.kind to the type of operation being performed
span.set_tag_str(SPAN_KIND, SpanKind.SERVER)

span.set_tag(_SPAN_MEASURED_KEY)
# Configure trace search sample rate
with core.context_with_data(
"pyramid.request",
span_name=schematize_url_operation("pyramid.request", protocol="http", direction=SpanDirection.INBOUND),
span_type=SpanTypes.WEB,
service=service,
resource="404",
tags={},
tracer=tracer,
distributed_headers=request.headers,
distributed_headers_config=config.pyramid,
headers_case_sensitive=True,
# DEV: pyramid is special case maintains separate configuration from config api
analytics_enabled = settings.get(SETTINGS_ANALYTICS_ENABLED)

if (config._analytics_enabled and analytics_enabled is not False) or analytics_enabled is True:
span.set_tag(_ANALYTICS_SAMPLE_RATE_KEY, settings.get(SETTINGS_ANALYTICS_SAMPLE_RATE, True))
analytics_enabled=settings.get(SETTINGS_ANALYTICS_ENABLED),
analytics_sample_rate=settings.get(SETTINGS_ANALYTICS_SAMPLE_RATE, True),
) as ctx, ctx.span as req_span:
ctx.set_item("req_span", req_span)
core.dispatch("web.request.start", (ctx, config.pyramid))

setattr(request, DD_TRACER, tracer) # used to find the tracer in templates
response = None
@@ -110,26 +107,31 @@ def trace_tween(request):
finally:
# set request tags
if request.matched_route:
span.resource = "{} {}".format(request.method, request.matched_route.name)
span.set_tag_str("pyramid.route.name", request.matched_route.name)
req_span.resource = "{} {}".format(request.method, request.matched_route.name)
req_span.set_tag_str("pyramid.route.name", request.matched_route.name)
# set response tags
if response:
status = response.status_code
response_headers = response.headers
else:
response_headers = None

trace_utils.set_http_meta(
span,
config.pyramid,
method=request.method,
url=request.path_url,
status_code=status,
query=request.query_string,
request_headers=request.headers,
response_headers=response_headers,
route=request.matched_route.pattern if request.matched_route else None,
core.dispatch(
"web.request.finish",
(
req_span,
config.pyramid,
request.method,
request.path_url,
status,
request.query_string,
request.headers,
response_headers,
request.matched_route.pattern if request.matched_route else None,
False,
),
)

return response

return trace_tween
61 changes: 32 additions & 29 deletions ddtrace/contrib/internal/sanic/patch.py
Original file line number Diff line number Diff line change
@@ -4,14 +4,10 @@
import wrapt
from wrapt import wrap_function_wrapper as _w

import ddtrace
from ddtrace import config
from ddtrace.constants import _ANALYTICS_SAMPLE_RATE_KEY
from ddtrace.constants import SPAN_KIND
from ddtrace.contrib import trace_utils
from ddtrace.ext import SpanKind
from ddtrace.ext import SpanTypes
from ddtrace.internal.constants import COMPONENT
from ddtrace.internal import core
from ddtrace.internal.logger import get_logger
from ddtrace.internal.schema import schematize_service_name
from ddtrace.internal.schema import schematize_url_operation
@@ -47,7 +43,10 @@ def update_span(span, response):
# and so use 500
status_code = getattr(response, "status", 500)
response_headers = getattr(response, "headers", None)
trace_utils.set_http_meta(span, config.sanic, status_code=status_code, response_headers=response_headers)

core.dispatch(
"web.request.finish", (span, config.sanic, None, None, status_code, None, None, response_headers, None, False)
)


def _wrap_response_callback(span, callback):
@@ -200,31 +199,35 @@ def _create_sanic_request_span(request):

headers = request.headers.copy()

trace_utils.activate_distributed_headers(ddtrace.tracer, int_config=config.sanic, request_headers=headers)

span = pin.tracer.trace(
schematize_url_operation("sanic.request", protocol="http", direction=SpanDirection.INBOUND),
with core.context_with_data(
"sanic.request",
span_name=schematize_url_operation("sanic.request", protocol="http", direction=SpanDirection.INBOUND),
span_type=SpanTypes.WEB,
service=trace_utils.int_service(None, config.sanic),
resource=resource,
span_type=SpanTypes.WEB,
)
span.set_tag_str(COMPONENT, config.sanic.integration_name)

# set span.kind to the type of operation being performed
span.set_tag_str(SPAN_KIND, SpanKind.SERVER)

sample_rate = config.sanic.get_analytics_sample_rate(use_global_config=True)
if sample_rate is not None:
span.set_tag(_ANALYTICS_SAMPLE_RATE_KEY, sample_rate)

method = request.method
url = "{scheme}://{host}{path}".format(scheme=request.scheme, host=request.host, path=request.path)
query_string = request.query_string
if isinstance(query_string, bytes):
query_string = query_string.decode()
trace_utils.set_http_meta(span, config.sanic, method=method, url=url, query=query_string, request_headers=headers)

return span
tags={},
pin=pin,
distributed_headers=headers,
distributed_headers_config=config.sanic,
headers_case_sensitive=True,
analytics_sample_rate=config.sanic.get_analytics_sample_rate(use_global_config=True),
) as ctx:
req_span = ctx.span

ctx.set_item("req_span", req_span)
core.dispatch("web.request.start", (ctx, config.sanic))

method = request.method
url = "{scheme}://{host}{path}".format(scheme=request.scheme, host=request.host, path=request.path)
query_string = request.query_string
if isinstance(query_string, bytes):
query_string = query_string.decode()

core.dispatch(
"web.request.finish", (req_span, config.sanic, method, url, None, query_string, headers, None, None, False)
)

return req_span


async def sanic_http_lifecycle_handle(request):
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
"span.kind": "server"
},
"metrics": {
"_dd.measured": 1,
"_dd.top_level": 1,
"_dd.tracer_kr": 1.0,
"_sampling_priority_v1": 1,
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@
"span.kind": "server"
},
"metrics": {
"_dd.measured": 1,
"_dd.top_level": 1,
"_dd.tracer_kr": 1.0,
"_sampling_priority_v1": 1,
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@
"span.kind": "server"
},
"metrics": {
"_dd.measured": 1,
"_dd.top_level": 1,
"_dd.tracer_kr": 1.0,
"_sampling_priority_v1": 1,
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
"span.kind": "server"
},
"metrics": {
"_dd.measured": 1,
"_dd.top_level": 1,
"_dd.tracer_kr": 1.0,
"_sampling_priority_v1": 1,
Original file line number Diff line number Diff line change
@@ -23,6 +23,7 @@
"span.kind": "server"
},
"metrics": {
"_dd.measured": 1,
"_dd.top_level": 1,
"_dd.tracer_kr": 1.0,
"_sampling_priority_v1": 1,
@@ -72,6 +73,7 @@
"span.kind": "server"
},
"metrics": {
"_dd.measured": 1,
"_dd.top_level": 1,
"_dd.tracer_kr": 1.0,
"_sampling_priority_v1": 1,
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
"span.kind": "server"
},
"metrics": {
"_dd.measured": 1,
"_dd.top_level": 1,
"_dd.tracer_kr": 1.0,
"_sampling_priority_v1": 1,
@@ -70,6 +71,7 @@
"span.kind": "server"
},
"metrics": {
"_dd.measured": 1,
"_dd.top_level": 1,
"_dd.tracer_kr": 1.0,
"_sampling_priority_v1": 1,
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
"span.kind": "server"
},
"metrics": {
"_dd.measured": 1,
"_dd.top_level": 1,
"_dd.tracer_kr": 1.0,
"_sampling_priority_v1": 1,
@@ -58,6 +59,7 @@
"span.kind": "server"
},
"metrics": {
"_dd.measured": 1,
"_dd.top_level": 1,
"_dd.tracer_kr": 1.0,
"_sampling_priority_v1": 1,
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
"span.kind": "server"
},
"metrics": {
"_dd.measured": 1,
"_dd.top_level": 1,
"_dd.tracer_kr": 1.0,
"_sampling_priority_v1": 1,
@@ -54,6 +55,7 @@
"span.kind": "server"
},
"metrics": {
"_dd.measured": 1,
"_dd.top_level": 1,
"_dd.tracer_kr": 1.0,
"_sampling_priority_v1": 1,

0 comments on commit 203e0d0

Please sign in to comment.