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

Added experimental HTTP backpropagators #1762

Merged
merged 2 commits into from
Apr 19, 2021

Conversation

owais
Copy link
Contributor

@owais owais commented Apr 12, 2021

Description

The experimental back propagators inject trace response headers into
HTTP responses. These are meant to be used by instrumentations and are
not considered stable.

Contrib PRs that need this feature: open-telemetry/opentelemetry-python-contrib#436

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration

  • Unit tests
  • Manual testing

Checklist:

  • Followed the style guidelines of this project
  • Changelogs have been updated
  • Unit tests have been added
  • Documentation has been updated

@srikanthccv
Copy link
Member

This looks clean. Does it become part api once it is moved from experimental to stable or it is something remains with instrumentation package?

@owais
Copy link
Contributor Author

owais commented Apr 13, 2021

I think it'll remain in instrumentation package until the trace response proposal is merged into W3C and proposed in Otel.

@owais
Copy link
Contributor Author

owais commented Apr 14, 2021

@aabmass @lonewolf3739 PTAL when you can. Thanks.

Copy link
Member

@aabmass aabmass left a comment

Choose a reason for hiding this comment

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

LGTM

_BACK_PROPAGATOR = None


def get_global_back_propagator():
Copy link
Contributor

Choose a reason for hiding this comment

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

I feel like instrumentation_propagator should be a better name, considering the path of this module. Also, do we really need these get and set methods? They give the exact same "protection" and namespacing as not having them at all.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can change but it's already under instrumentation package so the import path would become opentelemetry.instrumentation.instrumentation_propagator which seems redundant and causes unnecessary stutter.

Copy link
Contributor

Choose a reason for hiding this comment

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

What I mean is that using back here is confusing. This is a propagator that is associated with instrumentation, right?

Copy link
Contributor

Choose a reason for hiding this comment

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

What do you think about keeping these get and set methods, @owais?

Copy link
Member

Choose a reason for hiding this comment

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

@ocelotl not necessarily, its called back propagator because it injects context into the response headers to propagate context backward to the caller. I think Owais has added it to the instrumentation package just because its a convenient place that instrumentation packages already have access to. Eventually, we would move this to opentelemetry-api

Copy link
Member

Choose a reason for hiding this comment

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

And I believe the get/set are added here to keep a similar API to set_global_textmap(), set_tracer_provider() etc. ?

class TraceResponsePropagator:
"""Experimental propagator that injects tracecontext into HTTP responses."""

_HEADER_NAME = "traceresponse"
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: this is a class attribute, not a module-level constant, it should be lower cased.


_HEADER_NAME = "traceresponse"

def _format_header(self, span_context): # pylint: disable=no-self-use
Copy link
Contributor

Choose a reason for hiding this comment

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

I would suggest to handle this with an ABC and static and abstract methods:

from abc import ABC, abstractmethod


class Parent(ABC):

    @staticmethod
    @abstractmethod
    def method(arg):
        pass


class Child(Parent):
    @staticmethod
    def method(arg):
        print(arg)


Child().method(4)


class Child(Parent):
    @staticmethod
    def mathod(arg):
        print(arg)

Child().mathod(4)
4
Traceback (most recent call last):
  File "tato.py", line 26, in <module>
    Child().mathod(4)
TypeError: Can't instantiate abstract class Child with abstract methods method

@owais owais force-pushed the response-propagator branch 5 times, most recently from d502b0f to cb5c78b Compare April 16, 2021 07:15
@owais owais requested a review from aabmass April 16, 2021 07:16
@owais owais force-pushed the response-propagator branch 2 times, most recently from 092dcf3 to e23dec1 Compare April 16, 2021 07:22
@owais owais requested a review from ocelotl April 16, 2021 07:53
_BACK_PROPAGATOR = None


def get_global_back_propagator():
Copy link
Contributor

Choose a reason for hiding this comment

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

What I mean is that using back here is confusing. This is a propagator that is associated with instrumentation, right?

_BACK_PROPAGATOR = None


def get_global_back_propagator():
Copy link
Contributor

Choose a reason for hiding this comment

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

What do you think about keeping these get and set methods, @owais?



class ResponsePropagator(ABC):
@abstractmethod
Copy link
Contributor

Choose a reason for hiding this comment

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

This feels like a class attribute actually. If you want to still use a method to access it, it should be a property:

class Parent:

    _the_attribute = None

    @property
    def _attribute(self):
        return self._the_attribute


class Child(Parent):

    _the_attribute = "child_attribute"

print(Child()._attribute)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK. Will make the change shortly.

def _format_header(
self, span_context
) -> str: # pylint: disable=no-self-use
return 'traceparent;desc="00-{trace_id}-{span_id}-{:02x}"'.format(
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess it comes from this?

@owais
Copy link
Contributor Author

owais commented Apr 16, 2021

What I mean is that using back here is confusing. This is a propagator that is associated with instrumentation, right?

You're right. Even this implementation is calling it either "back propagator" or "response propagator". Agree we should pick one. I don't have a strong preference. Which one do you suggest to use? @ocelotl

@owais
Copy link
Contributor Author

owais commented Apr 16, 2021

What do you think about keeping these get and set methods, @owais?

@ocelotl Sorry, I'm not following. Could you please elaborate?

(for some reason I'm not able to comment in-line on some of your comments).

@owais
Copy link
Contributor Author

owais commented Apr 16, 2021

What I mean is that using back here is confusing. This is a propagator that is associated with instrumentation, right?

They kind of are. In the sense that only instrumentation is using them today and we don't document them for users but technically it's not tried to instrumentations at all. Users can use it in their manual code just like regular propagators.

@ocelotl
Copy link
Contributor

ocelotl commented Apr 16, 2021

What I mean is that using back here is confusing. This is a propagator that is associated with instrumentation, right?

You're right. Even this implementation is calling it either "back propagator" or "response propagator". Agree we should pick one. I don't have a strong preference. Which one do you suggest to use? @ocelotl

I prefer response, it is more specific.

@ocelotl
Copy link
Contributor

ocelotl commented Apr 16, 2021

What do you think about keeping these get and set methods, @owais?

@ocelotl Sorry, I'm not following. Could you please elaborate?

(for some reason I'm not able to comment in-line on some of your comments).

I mean the get_global_back_propagator and set_global_back_propagator which don't actually provide any protection to the propagator object, so simply using a module-level variable is the same thing with two less methods.

@owais
Copy link
Contributor Author

owais commented Apr 16, 2021

I mean the get_global_back_propagator and set_global_back_propagator which don't actually provide any protection to the propagator object, so simply using a module-level variable is the same thing with two less methods.

@ocelotl Ah. I feel the functions are much more nicer to use and are consistent with how other global objects are set by API (provider, propagators). I don't think they really add any harm. I can add some type checking or safety later if you'd like.

@owais owais force-pushed the response-propagator branch 2 times, most recently from 1eb8c0d to 7fba05a Compare April 16, 2021 18:36
@owais owais requested review from lzchen and ocelotl April 16, 2021 18:37
@owais
Copy link
Contributor Author

owais commented Apr 16, 2021

@ocelotl @lzchen

  • Updated to call use "response" instead of "back".
  • Removed "ServerTiming" propagator implementation.

@owais owais force-pushed the response-propagator branch 2 times, most recently from bf0c681 to 880becc Compare April 16, 2021 18:43
Copy link
Contributor

@ocelotl ocelotl left a comment

Choose a reason for hiding this comment

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

This should work, approving. Just a question remains regarding ABCs and extract.

self._func(carrier, key, value)


class ResponsePropagator(ABC):
Copy link
Contributor

Choose a reason for hiding this comment

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

Approving, but just a question: don't we have already an ABC for propagators? I understand that these are "back" propagators (and they propagate in only one way, if I understand correctly), but may there be any situation where extract also needs to be defined?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

These are generally for web servers to respond with. May be someone uses Python compiled to JS in browser extract would be helpful. For any other type of client, the client is in full control and can start a trace before sending requests out. Only JS in browser is unable to do that as browser starts first request with JS having no control over it.

But questions like this is exactly why adding it as a propagator made more sense so we can flesh out how this should work in some time and may be provide other SIGs with a reference implementation and feedback for spec.

@lzchen
Copy link
Contributor

lzchen commented Apr 19, 2021

@ocelotl
Are your questions addressed?

_RESPONSE_PROPAGATOR = propagator


class DictHeaderSetter:
Copy link
Contributor

Choose a reason for hiding this comment

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

Similarly to normal propagators, shouldn't Setter be an ABC so others can create their own Setter s?

default_setter = DictHeaderSetter()


class FuncSetter:
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we get some guidance (maybe some comments) on when FuncSetter should be used vs Setter?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added doc string that describes intention and usage.

@owais owais force-pushed the response-propagator branch 2 times, most recently from 05973b7 to 879aba3 Compare April 19, 2021 16:44
The experimental back propagators inject trace response headers into
HTTP responses. These are meant to be used by instrumentations and are
not considered stable.
@lzchen lzchen merged commit 6bd163f into open-telemetry:main Apr 19, 2021
@owais owais deleted the response-propagator branch April 19, 2021 17:24
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.

None yet

5 participants