Ordering inconistency with DDSpanBuilder.withTag
Pior to this change, DDSpanBuilder.withTag behaves different than DDSpan.setTag when decorators are triggered. Specifically builder.withTag(a, val).withTag(b, val) can behave differently than span.setTag(a, val); span.setTag(b, val) This change makes a small step towards determinism by changing the HashMap inside DDSpanBuilder into a LinkedHashMap. That guarantees the tags from withTags translated to the same sequence of setTag calls. NOTE: Even with this change, there are inconsistencies when tags are removed or set to an empty value.
This commit is contained in:
parent
cf3f04f509
commit
ec27930d26
|
@ -34,6 +34,7 @@ import java.util.Collection;
|
|||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
@ -489,7 +490,7 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace
|
|||
private final String operationName;
|
||||
|
||||
// Builder attributes
|
||||
private final Map<String, Object> tags = new HashMap<String, Object>(defaultSpanTags);
|
||||
private final Map<String, Object> tags = new LinkedHashMap<String, Object>(defaultSpanTags);
|
||||
private long timestampMicro;
|
||||
private SpanContext parent;
|
||||
private String serviceName;
|
||||
|
|
|
@ -171,6 +171,81 @@ class SpanDecoratorTest extends DDSpecification {
|
|||
mapping = [(serviceName): "new-service"]
|
||||
}
|
||||
|
||||
static createSplittingTracer(tag) {
|
||||
def tracer = new DDTracer(
|
||||
"my-service",
|
||||
new LoggingWriter(),
|
||||
new AllSampler(),
|
||||
"some-runtime-id",
|
||||
emptyMap(),
|
||||
emptyMap(),
|
||||
emptyMap(),
|
||||
emptyMap()
|
||||
)
|
||||
// equivalent to split-by-tags: tag
|
||||
tracer.addDecorator(new ServiceNameDecorator(tag, true))
|
||||
|
||||
return tracer
|
||||
}
|
||||
|
||||
def "peer.service then split-by-tags via builder"() {
|
||||
setup:
|
||||
tracer = createSplittingTracer(Tags.MESSAGE_BUS_DESTINATION.key)
|
||||
|
||||
when:
|
||||
def span = tracer.buildSpan("some span")
|
||||
.withTag(Tags.PEER_SERVICE.key, "peer-service")
|
||||
.withTag(Tags.MESSAGE_BUS_DESTINATION.key, "some-queue")
|
||||
.start()
|
||||
span.finish()
|
||||
|
||||
then:
|
||||
span.serviceName == "some-queue"
|
||||
}
|
||||
|
||||
def "peer.service then split-by-tags via setTag"() {
|
||||
setup:
|
||||
tracer = createSplittingTracer(Tags.MESSAGE_BUS_DESTINATION.key)
|
||||
|
||||
when:
|
||||
def span = tracer.buildSpan("some span").start()
|
||||
span.setTag(Tags.PEER_SERVICE.key, "peer-service")
|
||||
span.setTag(Tags.MESSAGE_BUS_DESTINATION.key, "some-queue")
|
||||
span.finish()
|
||||
|
||||
then:
|
||||
span.serviceName == "some-queue"
|
||||
}
|
||||
|
||||
def "split-by-tags then peer-service via builder"() {
|
||||
setup:
|
||||
tracer = createSplittingTracer(Tags.MESSAGE_BUS_DESTINATION.key)
|
||||
|
||||
when:
|
||||
def span = tracer.buildSpan("some span")
|
||||
.withTag(Tags.MESSAGE_BUS_DESTINATION.key, "some-queue")
|
||||
.withTag(Tags.PEER_SERVICE.key, "peer-service")
|
||||
.start()
|
||||
span.finish()
|
||||
|
||||
then:
|
||||
span.serviceName == "peer-service"
|
||||
}
|
||||
|
||||
def "split-by-tags then peer-service via setTag"() {
|
||||
setup:
|
||||
tracer = createSplittingTracer(Tags.MESSAGE_BUS_DESTINATION.key)
|
||||
|
||||
when:
|
||||
def span = tracer.buildSpan("some span").start()
|
||||
span.setTag(Tags.MESSAGE_BUS_DESTINATION.key, "some-queue")
|
||||
span.setTag(Tags.PEER_SERVICE.key, "peer-service")
|
||||
span.finish()
|
||||
|
||||
then:
|
||||
span.serviceName == "peer-service"
|
||||
}
|
||||
|
||||
def "set operation name"() {
|
||||
when:
|
||||
Tags.COMPONENT.set(span, component)
|
||||
|
|
Loading…
Reference in New Issue