From 5c38aaad833799c158099047f5eaab33bb5f3e84 Mon Sep 17 00:00:00 2001 From: Scott Mitchell Date: Thu, 21 May 2020 09:51:51 -0700 Subject: [PATCH] AbstractInMemorySpanBuilder to respect FOLLOWS_FROM (#1063) Motivation: OpenTracing semantics defines a FOLLOWS_FROM relationship which is an alternative means of representing a parent relationship. However AbstractInMemorySpanBuilder doesn't respect this Reference type and only recognizes CHILD_OF. Modifications: - AbstractInMemorySpanBuilder#parent() should also match References against FOLLOWS_FROM Result: AbstractInMemorySpanBuilder#parent() respects the FOLLOWS_FROM relationship. --- servicetalk-opentracing-inmemory/build.gradle | 3 + .../inmemory/AbstractInMemorySpanBuilder.java | 11 ++-- .../inmemory/DefaultInMemoryTracerTest.java | 56 +++++++++++++++++++ 3 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 servicetalk-opentracing-inmemory/src/test/java/io/servicetalk/opentracing/inmemory/DefaultInMemoryTracerTest.java diff --git a/servicetalk-opentracing-inmemory/build.gradle b/servicetalk-opentracing-inmemory/build.gradle index 59fe4ab9b5..05444e810d 100644 --- a/servicetalk-opentracing-inmemory/build.gradle +++ b/servicetalk-opentracing-inmemory/build.gradle @@ -24,4 +24,7 @@ dependencies { implementation project(":servicetalk-utils-internal") implementation "com.google.code.findbugs:jsr305:$jsr305Version" implementation "org.slf4j:slf4j-api:$slf4jVersion" + + testImplementation "junit:junit:$junitVersion" + testImplementation "org.mockito:mockito-core:$mockitoCoreVersion" } diff --git a/servicetalk-opentracing-inmemory/src/main/java/io/servicetalk/opentracing/inmemory/AbstractInMemorySpanBuilder.java b/servicetalk-opentracing-inmemory/src/main/java/io/servicetalk/opentracing/inmemory/AbstractInMemorySpanBuilder.java index c8ab7bb3f9..273e4672fa 100644 --- a/servicetalk-opentracing-inmemory/src/main/java/io/servicetalk/opentracing/inmemory/AbstractInMemorySpanBuilder.java +++ b/servicetalk-opentracing-inmemory/src/main/java/io/servicetalk/opentracing/inmemory/AbstractInMemorySpanBuilder.java @@ -20,7 +20,6 @@ import io.servicetalk.opentracing.inmemory.api.InMemorySpanBuilder; import io.servicetalk.opentracing.inmemory.api.InMemorySpanContext; -import io.opentracing.References; import io.opentracing.Span; import io.opentracing.SpanContext; import io.opentracing.tag.Tags; @@ -33,6 +32,8 @@ import java.util.Map; import javax.annotation.Nullable; +import static io.opentracing.References.CHILD_OF; +import static io.opentracing.References.FOLLOWS_FROM; import static java.util.Objects.requireNonNull; abstract class AbstractInMemorySpanBuilder implements InMemorySpanBuilder { @@ -52,13 +53,13 @@ protected AbstractInMemorySpanBuilder(String operationName, int maxTagSize) { @Override public final InMemorySpanBuilder asChildOf(SpanContext parent) { - addReference(References.CHILD_OF, parent); + addReference(CHILD_OF, parent); return this; } @Override public final InMemorySpanBuilder asChildOf(Span parent) { - addReference(References.CHILD_OF, parent.context()); + addReference(CHILD_OF, parent.context()); return this; } @@ -106,8 +107,8 @@ public final InMemorySpan start() { protected final InMemorySpanContext parent() { // Use old-style for loop to save a bit of garbage creation for (int i = 0; i < references.size(); i++) { - InMemoryReference reference = references.get(i); - if (References.CHILD_OF.equals(reference.type())) { + final InMemoryReference reference = references.get(i); + if (CHILD_OF.equals(reference.type()) || FOLLOWS_FROM.equals(reference.type())) { return reference.referredTo(); } } diff --git a/servicetalk-opentracing-inmemory/src/test/java/io/servicetalk/opentracing/inmemory/DefaultInMemoryTracerTest.java b/servicetalk-opentracing-inmemory/src/test/java/io/servicetalk/opentracing/inmemory/DefaultInMemoryTracerTest.java new file mode 100644 index 0000000000..7d1d344576 --- /dev/null +++ b/servicetalk-opentracing-inmemory/src/test/java/io/servicetalk/opentracing/inmemory/DefaultInMemoryTracerTest.java @@ -0,0 +1,56 @@ +/* + * Copyright © 2020 Apple Inc. and the ServiceTalk project authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.servicetalk.opentracing.inmemory; + +import io.servicetalk.opentracing.inmemory.api.InMemoryScopeManager; +import io.servicetalk.opentracing.inmemory.api.InMemorySpan; +import io.servicetalk.opentracing.inmemory.api.InMemorySpanBuilder; +import io.servicetalk.opentracing.inmemory.api.InMemorySpanContext; +import io.servicetalk.opentracing.inmemory.api.InMemoryTraceState; +import io.servicetalk.opentracing.inmemory.api.InMemoryTracer; + +import org.junit.Test; + +import static io.opentracing.References.CHILD_OF; +import static io.opentracing.References.FOLLOWS_FROM; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class DefaultInMemoryTracerTest { + @Test + public void childOfReferenceRespected() { + verifyParentReference("childOfReferenceRespected", true); + } + + @Test + public void followsFromReferenceRespected() { + verifyParentReference("followsFromReferenceRespected", false); + } + + private static void verifyParentReference(final String parentTraceIdHex, boolean childOf) { + InMemoryScopeManager mockScopeManager = mock(InMemoryScopeManager.class); + InMemorySpanContext mockParentContext = mock(InMemorySpanContext.class); + InMemoryTraceState mockParentTraceState = mock(InMemoryTraceState.class); + when(mockParentContext.traceState()).thenReturn(mockParentTraceState); + when(mockParentTraceState.traceIdHex()).thenReturn(parentTraceIdHex); + InMemoryTracer tracer = new DefaultInMemoryTracer.Builder(mockScopeManager).build(); + InMemorySpanBuilder spanBuilder = tracer.buildSpan("foo"); + spanBuilder.addReference(childOf ? CHILD_OF : FOLLOWS_FROM, mockParentContext); + InMemorySpan span = spanBuilder.start(); + assertEquals(parentTraceIdHex, span.context().traceState().traceIdHex()); + } +}