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

Return no-op when segment context isn't found instead of null. #180

Merged
merged 4 commits into from
Jul 15, 2020

Conversation

anuraaga
Copy link
Contributor

While in the strictest sense, changing behavior like this is a breaking change, it's generally acceptable to replace a null with a no-op (but not vice versa). The idea is that returning the no-op segment should work in any caller code in the non-null case no problem. On the flip side, there should be less chance of NPE in user code as a result - all the major Java tracing libraries make sure never to return null spans so it's fairly standard practice.

PS: I'm intentionally not using the name of the actual class here, it's something we'll need to rename for the next major version.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

AWSXRayRecorder recorder = AWSXRayRecorderBuilder.standard()
.withContextMissingStrategy(new LogErrorContextMissingStrategy())
.withContextMissingStrategy(new IgnoreErrorContextMissingStrategy())
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 tests don't actually test whether anything's logged so I just removed that to make them more precise.

Copy link
Contributor

@willarmiros willarmiros left a comment

Choose a reason for hiding this comment

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

Looks great, big improvement on customer expectations & safety. My question is for getCurrentSegment(), will we leave that Nullable? Or do we want to change that long term to also return a DummySegment when context is missing, and it's just outside the scope of this PR?

Comment on lines 536 to 539
SegmentContext context = segmentContextResolverChain.resolve();
if (context != null) {
return context.beginSubsegment(this, name);
if (context == null) {
// No context available, we return a no-op subsegment so user code does not have to work around this. Based on
// ContextMissingStrategy they will still know about the issue unless they explicitly opt-ed out.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not actually sure the contextMissingStrategy would get fired in this case. I think this is a bug in the old implementation, and we should be using getSegmentContext() instead of resolving the it from the ResolverChain.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice catch

@@ -352,7 +345,7 @@ public Segment preFilter(ServletRequest request, ServletResponse response) {
final Segment created;
if (SampleDecision.SAMPLED.equals(sampleDecision)) {
created = recorder.beginSegment(getSegmentName(httpServletRequest), traceId, parentId);
if (created != null && samplingResponse.getRuleName().isPresent()) {
if (samplingResponse.getRuleName().isPresent()) {
logger.debug("Sampling strategy decided to use rule named: " + samplingResponse.getRuleName().get() + ".");
created.setRuleName(samplingResponse.getRuleName().get());
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Think you can get rid of the other null check in the else block

Copy link
Contributor Author

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

Good call on getCurrentSegment - I had a mind to not change it because it corresponds with the Optional method but thinking again, I think returning null can never be better. I'll make the change in a followup PR, as I tried to make it this time I realized first I want to do some refactoring of the no-op segments to not generate IDs, it'd be a bit weird to generate a random ID in a getCurrent method.

Comment on lines 536 to 539
SegmentContext context = segmentContextResolverChain.resolve();
if (context != null) {
return context.beginSubsegment(this, name);
if (context == null) {
// No context available, we return a no-op subsegment so user code does not have to work around this. Based on
// ContextMissingStrategy they will still know about the issue unless they explicitly opt-ed out.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice catch

Copy link
Contributor

@willarmiros willarmiros left a comment

Choose a reason for hiding this comment

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

LGTM

@willarmiros willarmiros merged commit e9361db into aws:master Jul 15, 2020
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

2 participants