-
Notifications
You must be signed in to change notification settings - Fork 599
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Develop/condition server span django #832
Changes from 8 commits
f82f1d1
73fdd4c
7dffc0a
e169ce4
b216e6b
522fff4
08d8fce
52e53a3
74681e8
3a6f77b
f316f95
c601bdc
93f41c6
764e9f0
bd2491f
0af9168
7016dbc
c63ac73
c4d503a
d689edf
f3986ab
76dfec3
0932f6e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,7 +32,13 @@ | |
from opentelemetry.instrumentation.wsgi import wsgi_getter | ||
from opentelemetry.propagate import extract | ||
from opentelemetry.semconv.trace import SpanAttributes | ||
from opentelemetry.trace import Span, SpanKind, use_span | ||
from opentelemetry.trace import ( | ||
INVALID_SPAN, | ||
Span, | ||
SpanKind, | ||
get_current_span, | ||
use_span, | ||
) | ||
from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs | ||
|
||
try: | ||
|
@@ -183,11 +189,16 @@ def process_request(self, request): | |
carrier_getter = wsgi_getter | ||
collect_request_attributes = wsgi_collect_request_attributes | ||
|
||
token = attach(extract(carrier, getter=carrier_getter)) | ||
|
||
token = context = None | ||
span_kind = SpanKind.INTERNAL | ||
if get_current_span() is INVALID_SPAN: | ||
context = extract(request_meta, getter=wsgi_getter) | ||
token = attach(context) | ||
span_kind = SpanKind.SERVER | ||
span = self._tracer.start_span( | ||
self._get_span_name(request), | ||
kind=SpanKind.SERVER, | ||
context, | ||
kind=span_kind, | ||
srikanthccv marked this conversation as resolved.
Show resolved
Hide resolved
|
||
start_time=request_meta.get( | ||
"opentelemetry-instrumentor-django.starttime_key" | ||
), | ||
|
@@ -220,7 +231,8 @@ def process_request(self, request): | |
|
||
request.META[self._environ_activation_key] = activation | ||
request.META[self._environ_span_key] = span | ||
request.META[self._environ_token] = token | ||
if token: | ||
request.META[self._environ_token] = token | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. since this is conditional now, do we need to update places where this is being read to make sure everthing continues to work? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes Without this check, It was raising an exception while detaching the token from request object There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I mean earlier we were always setting this value in the dict even if it was There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added a check before detaching the token |
||
|
||
if _DjangoMiddleware._otel_request_hook: | ||
_DjangoMiddleware._otel_request_hook( # pylint: disable=not-callable | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,9 +18,13 @@ | |
from unittest.mock import Mock, patch | ||
|
||
from django import VERSION, conf | ||
from django.core.wsgi import get_wsgi_application | ||
from django.core.servers.basehttp import get_internal_wsgi_application | ||
from django.http import HttpRequest, HttpResponse | ||
from django.test.client import Client | ||
from django.test.utils import setup_test_environment, teardown_test_environment | ||
from django.test.client import Client, RequestFactory | ||
from django.test.testcases import SimpleTestCase | ||
from django.test.utils import override_settings, setup_test_environment, teardown_test_environment | ||
from opentelemetry import trace | ||
|
||
from opentelemetry.instrumentation.django import ( | ||
DjangoInstrumentor, | ||
|
@@ -30,6 +34,7 @@ | |
TraceResponsePropagator, | ||
set_global_response_propagator, | ||
) | ||
from opentelemetry.instrumentation.wsgi import OpenTelemetryMiddleware | ||
from opentelemetry.sdk import resources | ||
from opentelemetry.sdk.trace import Span | ||
from opentelemetry.sdk.trace.id_generator import RandomIdGenerator | ||
|
@@ -409,6 +414,7 @@ def setUp(self): | |
result = self.create_tracer_provider(resource=resource) | ||
tracer_provider, exporter = result | ||
self.exporter = exporter | ||
self.tracer_provider = tracer_provider | ||
_django_instrumentor.instrument(tracer_provider=tracer_provider) | ||
|
||
def tearDown(self): | ||
|
@@ -432,3 +438,22 @@ def test_tracer_provider_traced(self): | |
self.assertEqual( | ||
span.resource.attributes["resource-key"], "resource-value" | ||
) | ||
|
||
def test_django_with_wsgi_instrumented(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is fine but it would be nicer if we could test this in a generic way without wsgi instrumentation. At least lets add a comment documenting what this test does. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure I will add the comment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was thinking of just injecting a span into the execution context so the instrumentation would find it and trigger the code path. That way the test wouldn't depend on wsgi instrumentation but it is not a big issue for me. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. Please do check and provide your comments. |
||
application = get_wsgi_application() | ||
application = OpenTelemetryMiddleware(application, tracer_provider=self.tracer_provider) | ||
environ = RequestFactory()._base_environ( | ||
PATH_INFO="/span_name/1234/", | ||
CONTENT_TYPE="text/html; charset=utf-8", | ||
REQUEST_METHOD="GET" | ||
) | ||
response_data = {} | ||
def start_response(status, headers): | ||
response_data["status"] = status | ||
response_data["headers"] = headers | ||
|
||
resp = next(application(environ, start_response)) | ||
srikanthccv marked this conversation as resolved.
Show resolved
Hide resolved
|
||
span_list = self.exporter.get_finished_spans() | ||
self.assertEqual(span_list[0].attributes[SpanAttributes.HTTP_STATUS_CODE], 200) | ||
self.assertEqual(trace.SpanKind.INTERNAL, span_list[0].kind) | ||
self.assertEqual(trace.SpanKind.SERVER, span_list[1].kind) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
earlier we were using
carrier_getter
which could be either a wsgi or asgi getter. Now we are always usingwsgi_getter
. is this intentional?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh my bad. corrected to
carrier_getter
.