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

Implement spec change to only accept Context as span parent. #1611

Merged

Conversation

Oberon00
Copy link
Member

@Oberon00 Oberon00 commented Sep 1, 2020

Partial implementation of (now merged) open-telemetry/opentelemetry-specification#875

This is a prototype for spec PR open-telemetry/opentelemetry-specification#875 (spec issue open-telemetry/opentelemetry-specification#510).

To be more minimal, it does not currently add the Context parameter to SpanProcessor.OnStart, but that would be a trivial follow-up.


OLD OUTDATED DESCRIPTION

It replaces the parentSpanId + hasRemoteParent in RecordEventsReadableSpan with a full io.grpc.Context. That was the simple part. The part that is a bit funky is that DefaultSpan now has also has a parent Context in addition to still having a SpanContext for itself.

All in all, this removes 24 lines according to git diff --stat, so as stated in the spec PR, the total complexity does not really increase here.

The most interesting changes are in SpanBuilderSdk, RecordEventsReadableSpan and DefaultSpan.

END OLD OUTDATED DESCRIPTION

@codecov
Copy link

codecov bot commented Sep 1, 2020

Codecov Report

Merging #1611 into master will increase coverage by 1.02%.
The diff coverage is 100.00%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master    #1611      +/-   ##
============================================
+ Coverage     85.36%   86.38%   +1.02%     
+ Complexity     1382     1378       -4     
============================================
  Files           164      162       -2     
  Lines          5418     5349      -69     
  Branches        556      554       -2     
============================================
- Hits           4625     4621       -4     
+ Misses          594      521      -73     
- Partials        199      207       +8     
Impacted Files Coverage Δ Complexity Δ
...ain/java/io/opentelemetry/trace/DefaultTracer.java 97.22% <ø> (-0.40%) 5.00 <0.00> (ø)
api/src/main/java/io/opentelemetry/trace/Span.java 100.00% <ø> (ø) 0.00 <0.00> (ø)
...opentelemetry/opentracingshim/SpanBuilderShim.java 54.63% <100.00%> (+0.95%) 22.00 <0.00> (ø)
...ava/io/opentelemetry/sdk/trace/SpanBuilderSdk.java 96.90% <100.00%> (+1.10%) 32.00 <10.00> (-7.00) ⬆️
...opagation/B3PropagatorInjectorMultipleHeaders.java 91.66% <0.00%> (-8.34%) 4.00% <0.00%> (ø%)
...tensions/trace/propagation/OtTracerPropagator.java 78.12% <0.00%> (-4.64%) 10.00% <0.00%> (ø%)
.../propagation/B3PropagatorInjectorSingleHeader.java 95.65% <0.00%> (-4.35%) 5.00% <0.00%> (ø%)
...io/opentelemetry/exporters/otlp/MetricAdapter.java 90.44% <0.00%> (-1.87%) 26.00% <0.00%> (+1.00%) ⬇️
...extensions/trace/propagation/JaegerPropagator.java 86.41% <0.00%> (-1.09%) 26.00% <0.00%> (ø%)
...ntelemetry/exporters/prometheus/MetricAdapter.java 89.85% <0.00%> (-0.15%) 15.00% <0.00%> (ø%)
... and 11 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 10ea529...332ce25. Read the comment docs.

@Oberon00 Oberon00 changed the title Prototype for Context as span parent. [RFC] Prototype for Context as span parent. Sep 1, 2020
@Oberon00 Oberon00 marked this pull request as ready for review September 1, 2020 18:17
Copy link
Contributor

@anuraaga anuraaga left a comment

Choose a reason for hiding this comment

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

I feel this is conflating two unrelated ideas, the parent / child relationship of spans (a logical connection of IDs) and a mechanism for propagating data within a process, often across threads (Context). The end result is contexts have spans, and spans also have contexts - it's not quite circular but it's not a logical relationship I think.

If someone needs to propagate data along with the span, there's no need to do it with as part of parent/child relationship I think, the data can be added to the Context next to the span, e.g., after creating the span, Context.withValue(valuetopropagate, Context.current()). If we really need a simpler API for adding arbitrary information to go along with the span (that is how I'm reading the rationale in #875), we could have a first-class field for extra data like Brave. But I find it confusing if we try to use the span parent for this sort of data.

@Oberon00
Copy link
Member Author

Oberon00 commented Sep 2, 2020

@anuraaga

I feel this is conflating two unrelated ideas, the parent / child relationship of spans (a logical connection of IDs) and a mechanism for propagating data within a process, often across threads (Context).

Please, can we discuss such fundamental design concerns on the spec PR open-telemetry/opentelemetry-specification#875?

@anuraaga
Copy link
Contributor

anuraaga commented Sep 2, 2020

I realized that context APIs don't allow iterating over the context, so my concern of leaking unrelated information into the exporter isn't really a concern.

So still about lifecycle, how about an example with the root span. Want to propagate some information with it.

Context context = Context.current().withValue(cat, meow);
Span span = tracer.spanBuilder().parent(context).start();

I want to add data to the span, so I have to add it to the context. And I add a parent even though it's a root span. This API seems very confusing to me. Perhaps builder has helpers to set the values, but then this would create an internal context forked from current when building the span that probably can't be mounted. I think we would have to change start to return Context instead of Span with such an approach to make clear that the old context needs to be invalidated by propagating this new one. This might make some sense and makes me more comfortable with the change, but it seems like a huge change too.

@anuraaga
Copy link
Contributor

anuraaga commented Sep 2, 2020

Doh sorry wrong PR!

…rent

Conflicts:
	api/src/main/java/io/opentelemetry/trace/DefaultTracer.java
…rent

Conflicts:
	exporters/jaeger/src/test/java/io/opentelemetry/exporters/jaeger/AdapterTest.java
	exporters/zipkin/src/test/java/io/opentelemetry/exporters/zipkin/ZipkinSpanExporterEndToEndHttpTest.java
	exporters/zipkin/src/test/java/io/opentelemetry/exporters/zipkin/ZipkinSpanExporterTest.java
	sdk/tracing/src/main/java/io/opentelemetry/sdk/trace/RecordEventsReadableSpan.java
	sdk/tracing/src/main/java/io/opentelemetry/sdk/trace/SpanBuilderSdk.java
	sdk/tracing/src/test/java/io/opentelemetry/sdk/trace/SpanBuilderSdkTest.java
	testing_internal/src/main/java/io/opentelemetry/sdk/trace/TestSpanData.java
@jkwatson
Copy link
Contributor

@Oberon00 What would you think about narrowing the scope of this PR to only update the API, rather than also change it to move the Context all the way down into the exporter layer? I think your spec issue has had the scope narrowed recently to only include the API changes.

@Oberon00
Copy link
Member Author

I think your spec issue has had the scope narrowed recently to only include the API changes.

Indeed, this was changed in today's SIG spec meeting. I will update the PR (will probably remove more than half the changes) but I didn't get around to it yet.

@Oberon00
Copy link
Member Author

I updated the PR. Currently it is even more minimal than the spec PR (no Context parameter for OnStart), but that would be trivial follow-up.

@jkwatson
Copy link
Contributor

I updated the PR. Currently it is even more minimal than the spec PR (no Context parameter for OnStart), but that would be trivial follow-up.

thanks!

@Oberon00 Oberon00 changed the title [RFC] Prototype for Context as span parent. Implement spec change to only accept Context as span parent. Sep 23, 2020
@Oberon00
Copy link
Member Author

This is now ready to merge, since the spec PR was merged. Note that a follow-up is required to add the new Context parameter for SpanProcessor.OnStart.

@@ -32,8 +33,8 @@
void doNotCrash_NoopImplementation() {
Span.Builder spanBuilder = tracer.spanBuilder("MySpanName");
spanBuilder.setSpanKind(Kind.SERVER);
spanBuilder.setParent(DefaultSpan.getInvalid());
spanBuilder.setParent(DefaultSpan.getInvalid().getContext());
spanBuilder.setParent(TracingContextUtils.withSpan(DefaultSpan.create(null), Context.ROOT));
Copy link
Contributor

Choose a reason for hiding this comment

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

youch. this API sure is ugly! Remind me again how this is going to make things easier/better for our users?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is a unit test. Normally you would just call setNoParent.

Copy link
Contributor

Choose a reason for hiding this comment

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

fair enough, but I think having to do parenting via the TCU is going to be pretty counter-intuitive to most users. :(

Copy link
Member Author

Choose a reason for hiding this comment

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

I fully agree, but at the same time, I don't think users should normally do that. Usually you would just use the implicit current parent, or sometimes you need to capture a context with Context.current() and forward that to somewhere else. If you start a span at one thread and need to continue it at another thread while not setting it as active in the current thread is the only place you would need TracingContextUtils. I also think there should be some may to make that more easy. I could imagine span.inCurrentContext() (Java 8 default methods?), or TracingContextUtils.spanInCurrent(span) to make this easier.

Remind me again how this is going to make things easier/better for our users?

As you said, using TracingContextUtils is rather unintuitive, and thus I think most users did not do it, they just passed around spans without the remaining context. However, a custom propagator should be able to set a value in the context in extract and rely on it still being available in inject.

BTW, using inject is a place where you already have to often muck around with TracingContextUtils currently.

Copy link
Member

Choose a reason for hiding this comment

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

Is it safe to assume the implicit current parent is accurate?

For instance, when dealing with asynchronous methods the thread being executed on is usually not the same thread that might have initiated/received the original request. In that situation, the implicit current parent from ThreadLocal is more than likely not the parent you want

Copy link
Member Author

@Oberon00 Oberon00 Sep 24, 2020

Choose a reason for hiding this comment

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

Maybe we can provide some convenience function (default interface implementation?), so one can do Context capturedParent = span.withCurrentContext(). But it would be interesting how common the cases where you would need this even are.

Copy link
Member

Choose a reason for hiding this comment

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

Personally, it's a lot messier, but more importantly way less obvious that that's what is needed to achieve the desired result.

With respect to a default interface implementation, that wouldn't be possible with the JDK 7 requirement, correct?

Copy link
Contributor

Choose a reason for hiding this comment

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

(FWIW, we need more convenience functions in TracingContextUtils, or in whatever new name it ends up having ;) )

Copy link
Member Author

Choose a reason for hiding this comment

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

@kenfinnigan Java 7 was dropped recently, Java 8 is now required.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks @Oberon00, don't follow things for a few weeks, and everything changes!

Copy link
Contributor

@jkwatson jkwatson left a comment

Choose a reason for hiding this comment

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

Thanks!

Copy link
Contributor

@anuraaga anuraaga left a comment

Choose a reason for hiding this comment

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

Thanks @Oberon00!

@anuraaga anuraaga merged commit 83b9ba5 into open-telemetry:master Sep 25, 2020
@arminru arminru deleted the feature/contextparent branch October 9, 2020 15:16
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