-
Notifications
You must be signed in to change notification settings - Fork 650
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
Implement IdsGenerator interface for TracerProvider and include default RandomIdsGenerator #1153
Implement IdsGenerator interface for TracerProvider and include default RandomIdsGenerator #1153
Conversation
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.
Thanks! Just suggestions on docs
|
||
from opentelemetry import trace as trace_api | ||
|
||
class RandomIdsGenerator(trace_api.IdsGenerator): |
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.
Needs docs
class IdsGenerator(abc.ABC): | ||
@abc.abstractmethod | ||
def generate_span_id(self) -> int: | ||
"""Get a new random span ID. |
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.
Don't think random
is a feature of this interface, that's the implementation
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.
I see what you're saying, makes sense, will make the change!
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.
I elected to say "Get a new span ID." instead of "Get a new unique span ID." because I don't want to assume how random implementations will be.
|
||
from opentelemetry import trace as trace_api | ||
|
||
class RandomIdsGenerator(trace_api.IdsGenerator): |
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.
Nit: Can we have this class in the same file in ids_generator.py
.
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.
Definitely get what you're saying, but maybe we would want to keep it like this for these reasons:
- Right now we have this:
.
├── opentelemetry-api
│ └── src
│ └── opentelemetry
│ └── trace
│ └── ids_generator.py
└── opentelemetry-sdk
└── src
└── opentelemetry
└── sdk
└── trace
└── random_ids_generator.py
I was thinking that it would be good to have random_ids_generator.py
separate because subsequent generators could be found in the same directory level as the default "random" one. That way, all the generators would be in the same place:
.
├── opentelemetry-api
│ └── src
│ └── opentelemetry
│ └── trace
│ └── ids_generator.py
└── opentelemetry-sdk
└── src
└── opentelemetry
└── sdk
└── trace
├── aws_xray_ids_generator.py
├── bar_ids_generator.py
├── foo_ids_generator.py
└── random_ids_generator.py
But as a concession java actually looks like this right now:
.
├── sdk
│ └── tracing
│ └── src
│ └── main
│ └── java
│ └── io
│ └── opentelemetry
│ └── sdk
│ └── trace
│ ├── IdsGenerator.java
│ └── RandomIdsGenerator.java
└── sdk_extensions
└── aws_v1_support
└── src
└── main
└── java
└── io
└── opentelemetry
└── sdk
└── extensions
└── trace
└── aws
└── AwsXRayIdsGenerator.java
- This actually follows what we already have with
span.py
because while thespan.py
has the interface in the api, the actual implementation is in theopentelemetry.span.trace
package as below:
.
├── opentelemetry-api
│ └── src
│ └── opentelemetry
│ └── trace
│ └── span.py
└── opentelemetry-sdk
└── src
└── opentelemetry
└── sdk
└── trace
└── __init__.py
I like the separation of "interface" in API and "implementation" in SDK that this models!
Let me know what you think?
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.
It was my understanding that we would not have vendor specific generators exist in any of our packages. Ideally if users wanted to use aws_xray_ids_generator
, the would create their own and extend from ids_generator
. Notice how in java, the AwsXRayIdsGenerator
is in the aws specific extension. This also forces users to take a dependency on the sdk package if they want to use the random_ids_generator
.
Also, the design pattern of span.py
is a special case. I believe it was done because it was just getting too large. If you look at the rest of the codebase, pretty much all classes that "relate" to each other in terms of functionality are in the same file.
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.
Sounds good, I think Java did it well too, and I see what you mean about span.py
, so I'll move RandomIdsGenerator
into the ids_generator.py
file like you mentioned.
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.
This is great! Can you add an entry in the CHANGELOG?
30f5eb0
to
4a643e0
Compare
Spec issue: open-telemetry/opentelemetry-specification#896 |
4a643e0
to
f18b705
Compare
@@ -8,6 +8,7 @@ Submodules | |||
|
|||
trace.status | |||
trace.span | |||
trace.ids_generator |
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.
Adding it to the docs here for visibility. Also because both span.py
is added and they are in the same directory level and similar in that they both define an interface.
66e1fa0
to
4acc788
Compare
Just realized I need to follow up with checking on if "the randomness of the id is important for the sampler". Will do so tomorrow! |
4acc788
to
33879d4
Compare
@lzchen Thanks for the comments. w3c does not define a strong requirement for randomness. Randomly generated are preferred with a SHOULD, not MUST requirement This seems to not have been PR'd yet but already agreed on that there won't be randomness requirements /cc @dyladan So I think we don't have to worry about w3c incompliance here. Hope this helps :) |
@lzchen Thanks for your followup! Definitely a good point to bring up, I'll read up on W3C and understand it better for the future. Regardless, thanks for your help here! |
0febe93
to
e6a9701
Compare
@@ -733,7 +715,7 @@ def start_span( # pylint: disable=too-many-locals | |||
|
|||
if parent_context is None or not parent_context.is_valid: | |||
parent = parent_context = None | |||
trace_id = generate_trace_id() | |||
trace_id = self.source.ids_generator.generate_trace_id() |
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.
Since this isn't part of the tracer provider API as far as I can tell from this PR, we can't guarantee that source will have an ids_generator attribute.
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.
That's a good point, but this is just being consistent with the assumption later in this file for the sampler
, resource
, and _active_span_processor
variables.
Even so, I think we can guarantee the source
will have an ids_generator
attribute because source is typed to be of the same type as TracerProvider
which will always have an ids_generator
because of the change in this PR.
I think that the only danger that could come about would be if you were to implement your own Tracer
class that expects an ids_generator
, in which case you would also be in danger of assuming there were a sampler
or resource
as well because they're also not in the API.
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.
Even so, I think we can guarantee the source will have an ids_generator attribute because source is typed to be of the same type as TracerProvider which will always have an ids_generator because of the change in this PR.
I don't think this guarantees anything really. It's only a type hint and makes mypy or other checkers complain if they are run. There is no runtime or build/package time guarantees.
I think that the only danger that could come about would be if you were to implement your own Tracer class that expects an ids_generator, in which case you would also be in danger of assuming there were a sampler or resource as well because they're also not in the API.
Another instance would be if someone implements a custom TracerProvider to add some functionality but wanted to return instance of the stock Tracer. I think both cases should be supported without surprises. Looks like SDK Tracer has taken an implicit dependency on the SDK TracerProvider which shouldn't be the case. Users and vendors should be able to implement just one or the other without having to satisfy undocumented APIs.
I think we should either update the TracerProvider API to specify all these properties or go all in on DI and modify Tracer so that it requires all these dependencies to be explicitly specified by a tracer provider implementation. Meaning IDGenerator would be an initialization argument to the Tracer class. TracerProvider can pass it down explicitly. That way people can implement custom Tracer or custom TracerProvider without surprises.
Since there are other instances of such implicit dependencies, may be we can do this in another PR but if all maintainers agree some solution now, perhaps we can start with IDGenerator now and follow up with the rest.
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.
Looks like SDK Tracer has taken an implicit dependency on the SDK TracerProvider which shouldn't be the case.
Yeah we should probably remove source from both Meter
and Tracer
SDK implementations and then pass in some sort of "config" object upon creation. Tracer and TracerProvider shouldn't be coupled. But yeah, might be for another PR. @owais can you create an issue for this?
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.
I see what you're saying, yes it makes more sense to have Tracer
and TraceProvider
not be requirements of each other.
I would also prefer to have that as a separate PR, and minimize the new things this PR is trying to do. The PR is pretty straightforward the way it is right now, and that kind of refactor could be lost in the IDs Generator specific log messages.
I wouldn't mind helping with doing that separate PR either if we can decide on what we want to do!
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.
Sounds good to me. Tracking here: #1181
52497ab
to
38a82c7
Compare
opentelemetry-sdk/src/opentelemetry/sdk/trace/propagation/b3_format.py
Outdated
Show resolved
Hide resolved
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.
Just one question otherwise the change looks good.
27e0278
to
e8f4c2c
Compare
db3437b
to
43c64ec
Compare
43c64ec
to
56e9ac5
Compare
@codeboten Changes have been made! |
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.
LGTM thanks!
Co-authored-by: Daniel Dyla <dyladan@users.noreply.github.com>
Description
This PR moves in the direction of supporting custom forms of trace & span ID generation. The opentelemtry-java SDK and opentelemetry-js SDK do this as well.
Fixes #1152
Type of change
Please delete options that are not relevant.
How Has This Been Tested?
I was able to setup a simple small script that output the traces to the console as expected:
to get output:
However, I did not think it was necessary to include tests for the
RandomIdsGenerator.py
file since it is just doing the same thing the SDK was always doing before and the method implementations are just 2 lines overall.Checklist:
- [ ] Unit tests have been addedNo unit tests included for this change