Skip to content
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

Merged
merged 23 commits into from
Jan 7, 2022
Merged

Develop/condition server span django #832

merged 23 commits into from
Jan 7, 2022

Conversation

sanketmehta28
Copy link
Member

@sanketmehta28 sanketmehta28 commented Dec 14, 2021

Description

there may be other instrumented components that wrap an instrumented web framework such as WSGI. In such cases WSGI would already have generated a server span and used the remote span as parent. If Django did the same, traces would not make a lot of sense. Depending on whether a remote span is present in the incoming request's carrier, Django and WSGI spans would be completely different traces or be siblings instead of parent and child.

Fixes # #448

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)

How Has This Been Tested?

  • I have tested it locally using a sample app with django and wsgi instrumentation enabled with jaeger exporter.
  • I have sent a request to the app and observe on jaeger that there are two span created: WSGI span as SERVER span and Django span as INTERNEL span.

Does This PR Require a Core Repo Change?

  • No.

Checklist:

See contributing.md for styleguide, changelog guidelines, and more.

  • Followed the style guidelines of this project
  • Unit tests have been added

@sanketmehta28 sanketmehta28 requested a review from a team December 14, 2021 16:45
@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Dec 14, 2021

CLA Signed

The committers are authorized under a signed CLA.

@sanketmehta28
Copy link
Member Author

I need some input in the pytest I have added in this PR.
I have enabled django as well as WSGI instrumentation in TestDjangoWithOtherFramework class but I am getting only 1 span when I call self.exporter.get_finished_spans().

Strange thing is the span I am getting is of type INTERNEL and it has parent_id available. It means it does have a root span of type SERVER.

Unfortunately I could not find a way to get the root span info and test is getting failed in the last statement:
self.assertEqual(trace.SpanKind.SERVER, span_list[1].kind)

Can someone help me on this?

# print(span_list)
self.assertEqual(trace.SpanKind.INTERNAL, span_list[0].kind)

#Below line give me error "index out of the range" as there is only one span created where it should be 2.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It appears that your server span from middleware started but never ended. Please try changing the line 488 to next(application(environ, start_response)) and check.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. Done and changes are pushed. Please do review them

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only intend to suggest that hack to validate the hypothesis. You should use test client instead.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With Client() it was not creating the WSGI span. That is the reason I have to go this way

@sanketmehta28
Copy link
Member Author

changes are made according to Srikanth's comments. Unit tests are running fine now. Please do review the PR

token = context = None
span_kind = SpanKind.INTERNAL
if get_current_span() is INVALID_SPAN:
context = extract(request_meta, getter=wsgi_getter)
Copy link
Contributor

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 using wsgi_getter. is this intentional?

Copy link
Member Author

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.

@@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The 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?

Copy link
Member Author

Choose a reason for hiding this comment

The 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

Copy link
Contributor

Choose a reason for hiding this comment

The 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 None but now we won't be setting it at all in some cases. This can result in lookup error if code in other places assumes the key will always be present so we should make sure this doesn't break anything else.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a check before detaching the token

@@ -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):
Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure I will add the comment.
Also what do you mean by generic way? can you please give me an example?

Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Please do check and provide your comments.

Copy link
Member

@srikanthccv srikanthccv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please resolve the conflicts and address the nit suggestion. LGTM

CHANGELOG.md Outdated Show resolved Hide resolved
CHANGELOG.md Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants