Skip to content

Commit

Permalink
Merge branch 'update_datadog_exporter_error_tagging' of github.com:er…
Browse files Browse the repository at this point in the history
…icmustin/opentelemetry-python-contrib into update_datadog_exporter_error_tagging

merge upstream
  • Loading branch information
ericmustin committed Apr 19, 2021
2 parents b1b6aa3 + 0435a97 commit 7757217
Show file tree
Hide file tree
Showing 14 changed files with 232 additions and 15 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
- 'release/*'
pull_request:
env:
CORE_REPO_SHA: cad261e5dae1fe986c87e6965664b45cc9ab73c3
CORE_REPO_SHA: 6bd163f6d670319eba6693b8465a068a1828f484

jobs:
build:
Expand Down Expand Up @@ -98,6 +98,6 @@ jobs:
uses: actions/cache@v2
with:
path: .tox
key: tox-cache-${{ matrix.tox-environment }}-${{ hashFiles('tox.ini', 'dev-requirements.txt', 'docs-requirements.txt') }}
key: v2-tox-cache-${{ matrix.tox-environment }}-${{ hashFiles('tox.ini', 'dev-requirements.txt', 'docs-requirements.txt') }}
- name: run tox
run: tox -e ${{ matrix.tox-environment }}
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#415](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/415))
- `opentelemetry-instrumentation-tornado` Add request/response hooks.
([#426](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/426))
- `opentelemetry-exporter-datadog` Add parsing exception events for error tags([#459](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/459))
- `opentelemetry-exporter-datadog` Add parsing exception events for error tags.
([#459](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/459))
- `opentelemetry-instrumenation-django` now supports trace response headers.
([#436](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/436))
- `opentelemetry-instrumenation-tornado` now supports trace response headers.
([#436](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/436))
- `opentelemetry-instrumenation-pyramid` now supports trace response headers.
([#436](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/436))
- `opentelemetry-instrumenation-falcon` now supports trace response headers.
([#436](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/436))
- `opentelemetry-instrumenation-flask` now supports trace response headers.
([#436](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/436))

### Removed
- Remove `http.status_text` from span attributes
Expand Down
3 changes: 1 addition & 2 deletions docs-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ sphinx-autodoc-typehints
# doesn't work for pkg_resources.
-e "git+https://github.com/open-telemetry/opentelemetry-python.git#egg=opentelemetry-api&subdirectory=opentelemetry-api"
-e "git+https://github.com/open-telemetry/opentelemetry-python.git#egg=opentelemetry-sdk&subdirectory=opentelemetry-sdk"
-e "git+https://github.com/open-telemetry/opentelemetry-python.git#egg=opentelemetry-instrumentation&subdirectory=opentelemetry-instrumentation"

# Required by opentelemetry-instrumentation
fastapi~=0.58.1
psutil~=5.7.0
pymemcache~=1.3

-e "git+https://github.com/open-telemetry/opentelemetry-python.git#egg=opentelemetry-instrumentation&subdirectory=opentelemetry-instrumentation"

# Required by conf
django>=2.2

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@

from opentelemetry.context import attach, detach
from opentelemetry.instrumentation.django.version import __version__
from opentelemetry.instrumentation.propagators import (
get_global_response_propagator,
)
from opentelemetry.instrumentation.utils import extract_attributes_from_object
from opentelemetry.instrumentation.wsgi import (
add_response_attributes,
Expand Down Expand Up @@ -179,6 +182,11 @@ def process_response(self, request, response):
response,
)

propagator = get_global_response_propagator()
if propagator:
propagator.inject(response)

# record any exceptions raised while processing the request
exception = request.META.pop(self._environ_exception_key, None)
if _DjangoMiddleware._otel_response_hook:
_DjangoMiddleware._otel_response_hook( # pylint: disable=not-callable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,19 @@
DjangoInstrumentor,
_DjangoMiddleware,
)
from opentelemetry.instrumentation.propagators import (
TraceResponsePropagator,
set_global_response_propagator,
)
from opentelemetry.sdk.trace import Span
from opentelemetry.test.test_base import TestBase
from opentelemetry.test.wsgitestutil import WsgiTestBase
from opentelemetry.trace import SpanKind, StatusCode
from opentelemetry.trace import (
SpanKind,
StatusCode,
format_span_id,
format_trace_id,
)
from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs

# pylint: disable=import-error
Expand Down Expand Up @@ -309,3 +318,27 @@ def response_hook(span, request, response):
self.assertIsInstance(response_hook_args[1], HttpRequest)
self.assertIsInstance(response_hook_args[2], HttpResponse)
self.assertEqual(response_hook_args[2], response)

def test_trace_response_headers(self):
response = Client().get("/span_name/1234/")

self.assertNotIn("Server-Timing", response.headers)
self.memory_exporter.clear()

set_global_response_propagator(TraceResponsePropagator())

response = Client().get("/span_name/1234/")
span = self.memory_exporter.get_finished_spans()[0]

self.assertIn("traceresponse", response.headers)
self.assertEqual(
response.headers["Access-Control-Expose-Headers"], "traceresponse",
)
self.assertEqual(
response.headers["traceresponse"],
"00-{0}-{1}-01".format(
format_trace_id(span.get_span_context().trace_id),
format_span_id(span.get_span_context().span_id),
),
)
self.memory_exporter.clear()
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ def response_hook(span, req, resp):
from opentelemetry import context, trace
from opentelemetry.instrumentation.falcon.version import __version__
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
from opentelemetry.instrumentation.propagators import (
FuncSetter,
get_global_response_propagator,
)
from opentelemetry.instrumentation.utils import (
extract_attributes_from_object,
http_status_to_status_code,
Expand All @@ -119,6 +123,7 @@ def response_hook(span, req, resp):

_excluded_urls = get_excluded_urls("FALCON")
_traced_request_attrs = get_traced_request_attrs("FALCON")
_response_propagation_setter = FuncSetter(falcon.api.Response.append_header)


class FalconInstrumentor(BaseInstrumentor):
Expand Down Expand Up @@ -273,5 +278,9 @@ def process_response(
)
)

propagator = get_global_response_propagator()
if propagator:
propagator.inject(resp, setter=_response_propagation_setter)

if self._response_hook:
self._response_hook(span, req, resp)
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@
from falcon import testing

from opentelemetry.instrumentation.falcon import FalconInstrumentor
from opentelemetry.instrumentation.propagators import (
TraceResponsePropagator,
get_global_response_propagator,
set_global_response_propagator,
)
from opentelemetry.test.test_base import TestBase
from opentelemetry.trace import StatusCode
from opentelemetry.trace import StatusCode, format_span_id, format_trace_id
from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs

from .app import make_app
Expand Down Expand Up @@ -197,6 +202,28 @@ def test_traced_request_attributes(self):
self.assertEqual(span.attributes["query_string"], "q=abc")
self.assertNotIn("not_available_attr", span.attributes)

def test_trace_response(self):
orig = get_global_response_propagator()
set_global_response_propagator(TraceResponsePropagator())

response = self.client().simulate_get(path="/hello?q=abc")
headers = response.headers
span = self.memory_exporter.get_finished_spans()[0]

self.assertIn("traceresponse", headers)
self.assertEqual(
headers["access-control-expose-headers"], "traceresponse",
)
self.assertEqual(
headers["traceresponse"],
"00-{0}-{1}-01".format(
format_trace_id(span.get_span_context().trace_id),
format_span_id(span.get_span_context().span_id),
),
)

set_global_response_propagator(orig)

def test_traced_not_recording(self):
mock_tracer = Mock()
mock_span = Mock()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ def hello():
from opentelemetry import context, trace
from opentelemetry.instrumentation.flask.version import __version__
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
from opentelemetry.instrumentation.propagators import (
get_global_response_propagator,
)
from opentelemetry.propagate import extract
from opentelemetry.util._time import _time_ns
from opentelemetry.util.http import get_excluded_urls
Expand Down Expand Up @@ -91,6 +94,13 @@ def _start_response(status, response_headers, *args, **kwargs):
if not _excluded_urls.url_disabled(flask.request.url):
span = flask.request.environ.get(_ENVIRON_SPAN_KEY)

propagator = get_global_response_propagator()
if propagator:
propagator.inject(
response_headers,
setter=otel_wsgi.default_response_propagation_setter,
)

if span:
otel_wsgi.add_response_attributes(
span, status, response_headers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@

from opentelemetry import trace
from opentelemetry.instrumentation.flask import FlaskInstrumentor
from opentelemetry.instrumentation.propagators import (
TraceResponsePropagator,
get_global_response_propagator,
set_global_response_propagator,
)
from opentelemetry.test.test_base import TestBase
from opentelemetry.test.wsgitestutil import WsgiTestBase
from opentelemetry.util.http import get_excluded_urls
Expand Down Expand Up @@ -119,6 +124,31 @@ def test_simple(self):
self.assertEqual(span_list[0].kind, trace.SpanKind.SERVER)
self.assertEqual(span_list[0].attributes, expected_attrs)

def test_trace_response(self):
orig = get_global_response_propagator()

set_global_response_propagator(TraceResponsePropagator())
response = self.client.get("/hello/123")
headers = response.headers

span_list = self.memory_exporter.get_finished_spans()
self.assertEqual(len(span_list), 1)
span = span_list[0]

self.assertIn("traceresponse", headers)
self.assertEqual(
headers["access-control-expose-headers"], "traceresponse",
)
self.assertEqual(
headers["traceresponse"],
"00-{0}-{1}-01".format(
trace.format_trace_id(span.get_span_context().trace_id),
trace.format_span_id(span.get_span_context().span_id),
),
)

set_global_response_propagator(orig)

def test_not_recording(self):
mock_tracer = Mock()
mock_span = Mock()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@

import opentelemetry.instrumentation.wsgi as otel_wsgi
from opentelemetry import context, trace
from opentelemetry.instrumentation.propagators import (
get_global_response_propagator,
)
from opentelemetry.instrumentation.pyramid.version import __version__
from opentelemetry.propagate import extract
from opentelemetry.util._time import _time_ns
Expand Down Expand Up @@ -157,6 +160,10 @@ def trace_tween(request):
response_or_exception.headers,
)

propagator = get_global_response_propagator()
if propagator:
propagator.inject(response.headers)

activation = request.environ.get(_ENVIRON_ACTIVATION_KEY)

if isinstance(response_or_exception, HTTPException):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
from pyramid.config import Configurator

from opentelemetry import trace
from opentelemetry.instrumentation.propagators import (
TraceResponsePropagator,
get_global_response_propagator,
set_global_response_propagator,
)
from opentelemetry.instrumentation.pyramid import PyramidInstrumentor
from opentelemetry.test.test_base import TestBase
from opentelemetry.test.wsgitestutil import WsgiTestBase
Expand Down Expand Up @@ -98,6 +103,28 @@ def test_simple(self):
self.assertEqual(span_list[0].kind, trace.SpanKind.SERVER)
self.assertEqual(span_list[0].attributes, expected_attrs)

def test_response_headers(self):
orig = get_global_response_propagator()
set_global_response_propagator(TraceResponsePropagator())

response = self.client.get("/hello/500")
headers = response.headers
span = self.memory_exporter.get_finished_spans()[0]

self.assertIn("traceresponse", headers)
self.assertEqual(
headers["access-control-expose-headers"], "traceresponse",
)
self.assertEqual(
headers["traceresponse"],
"00-{0}-{1}-01".format(
trace.format_trace_id(span.get_span_context().trace_id),
trace.format_span_id(span.get_span_context().span_id),
),
)

set_global_response_propagator(orig)

def test_not_recording(self):
mock_tracer = Mock()
mock_span = Mock()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ def client_resposne_hook(span, future):

from opentelemetry import context, trace
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
from opentelemetry.instrumentation.propagators import (
FuncSetter,
get_global_response_propagator,
)
from opentelemetry.instrumentation.tornado.version import __version__
from opentelemetry.instrumentation.utils import (
extract_attributes_from_object,
Expand All @@ -105,6 +109,8 @@ def client_resposne_hook(span, future):
_excluded_urls = get_excluded_urls("TORNADO")
_traced_request_attrs = get_traced_request_attrs("TORNADO")

response_propagation_setter = FuncSetter(tornado.web.RequestHandler.add_header)


class TornadoInstrumentor(BaseInstrumentor):
patched_handlers = []
Expand Down Expand Up @@ -256,6 +262,14 @@ def _start_span(tracer, handler, start_time) -> _TraceContext:
activation.__enter__() # pylint: disable=E1101
ctx = _TraceContext(activation, span, token)
setattr(handler, _HANDLER_CONTEXT_KEY, ctx)

# finish handler is called after the response is sent back to
# the client so it is too late to inject trace response headers
# there.
propagator = get_global_response_propagator()
if propagator:
propagator.inject(handler, setter=response_propagation_setter)

return ctx


Expand Down
Loading

0 comments on commit 7757217

Please sign in to comment.