Skip to content

Commit 168c5b7

Browse files
author
Jason Bulicek
authored
Merge pull request #90 from ExpediaDotCom/0.2.4-SNAPSHOT
making propagation keys case insensitive
2 parents 71ebc4a + 8da6da7 commit 168c5b7

File tree

5 files changed

+156
-42
lines changed

5 files changed

+156
-42
lines changed

core/src/main/java/com/expedia/www/haystack/client/propagation/DefaultKeyConvention.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import java.util.Collection;
2121
import java.util.Collections;
2222

23-
public class DefaultKeyConvention implements KeyConvention {
23+
public final class DefaultKeyConvention implements KeyConvention {
2424

2525
private static final String BAGGAGE_PREFIX = "Baggage-";
2626

core/src/main/java/com/expedia/www/haystack/client/propagation/TextMapPropagator.java

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@
1818

1919
import com.expedia.www.haystack.client.SpanContext;
2020
import io.opentracing.propagation.TextMap;
21+
import java.util.Collection;
2122
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
2223
import org.apache.commons.lang3.builder.ToStringStyle;
2324

2425
import java.util.HashMap;
26+
import java.util.Locale;
2527
import java.util.Map;
2628
import java.util.UUID;
2729

@@ -50,17 +52,6 @@ private String prefixKey(String prefix, String key) {
5052
return String.format("%s%s", prefix, key);
5153
}
5254

53-
private String unprefixKey(String prefix, String key) {
54-
if (prefix == null || prefix.isEmpty()) {
55-
return key;
56-
} else if (!key.startsWith(prefix)) {
57-
return key;
58-
}
59-
60-
return key.substring(prefix.length());
61-
}
62-
63-
6455
private void put(TextMap carrier, String key, String value) {
6556
carrier.put(keyCodex.encode(key), valueCodex.encode(value));
6657
}
@@ -87,14 +78,17 @@ public SpanContext extract(TextMap carrier) {
8778
final Map<String, String> baggage = new HashMap<>();
8879

8980
for (Map.Entry<String, String> entry : carrier) {
90-
final String key = entry.getKey();
91-
if (keyCodex.decode(key).startsWith(convention.baggagePrefix())) {
92-
baggage.put(unprefixKey(convention.baggagePrefix(), keyCodex.decode(key)), valueCodex.decode(entry.getValue()));
93-
} else if (convention.traceIdKeyAliases().contains(keyCodex.decode(key))) {
81+
final String decodedKey = keyCodex.decode(entry.getKey());
82+
final String decodedKeyLowerCase = decodedKey.toLowerCase();
83+
84+
if (decodedKeyLowerCase.startsWith(convention.baggagePrefix().toLowerCase(Locale.ROOT))) {
85+
baggage.put(decodedKey.substring(convention.baggagePrefix().length()),
86+
valueCodex.decode(entry.getValue()));
87+
} else if (containsIgnoreCase(convention.traceIdKeyAliases(), decodedKeyLowerCase)) {
9488
traceId = valueCodex.decode(entry.getValue());
95-
} else if (convention.parentIdKeyAliases().contains(keyCodex.decode(key))) {
89+
} else if (containsIgnoreCase(convention.parentIdKeyAliases(), decodedKeyLowerCase)) {
9690
parentId = valueCodex.decode(entry.getValue());
97-
} else if (convention.spanIdKeyAliases().contains(keyCodex.decode(key))) {
91+
} else if (containsIgnoreCase(convention.spanIdKeyAliases(), decodedKeyLowerCase)) {
9892
spanId = valueCodex.decode(entry.getValue());
9993
}
10094
}
@@ -111,6 +105,10 @@ public SpanContext extract(TextMap carrier) {
111105
return context.addBaggage(baggage);
112106
}
113107

108+
private boolean containsIgnoreCase(Collection<String> strings, String string) {
109+
return strings.stream().anyMatch(s -> s.equalsIgnoreCase(string));
110+
}
111+
114112

115113
public static class Builder {
116114
private TextMapCodex keyCodex = new TextMapCodex();
@@ -129,9 +127,7 @@ public Builder withKeyConvention(KeyConvention convention) {
129127
}
130128

131129
public Builder withCodex(TextMapCodex codex) {
132-
this.keyCodex = codex;
133-
this.valueCodex = codex;
134-
return this;
130+
return this.withKeyCodex(codex).withValueCodex(codex);
135131
}
136132

137133
public Builder withKeyCodex(TextMapCodex codex) {

core/src/test/java/com/expedia/www/haystack/client/SpanBuilderTest.java

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,10 @@
1919
import com.expedia.www.haystack.client.dispatchers.Dispatcher;
2020
import com.expedia.www.haystack.client.dispatchers.NoopDispatcher;
2121
import com.expedia.www.haystack.client.metrics.NoopMetricsRegistry;
22+
import com.expedia.www.haystack.client.propagation.MapBackedTextMap;
2223
import io.opentracing.References;
2324
import io.opentracing.propagation.Format;
24-
import io.opentracing.propagation.TextMap;
2525
import io.opentracing.tag.Tags;
26-
import java.util.HashMap;
27-
import java.util.Iterator;
2826
import java.util.Map;
2927
import org.junit.Assert;
3028
import org.junit.Before;
@@ -218,22 +216,4 @@ public void testWithTags() {
218216
Assert.assertTrue(tags.containsKey("number-key"));
219217
Assert.assertEquals(1l, tags.get("number-key"));
220218
}
221-
222-
private class MapBackedTextMap implements TextMap {
223-
private final Map<String, String> map = new HashMap<>();
224-
225-
@Override
226-
public Iterator<Map.Entry<String, String>> iterator() {
227-
return map.entrySet().iterator();
228-
}
229-
230-
@Override
231-
public void put(String key, String value) {
232-
map.put(key, value);
233-
}
234-
235-
public Map<String, String> getMap() {
236-
return map;
237-
}
238-
}
239219
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.expedia.www.haystack.client.propagation;
2+
3+
import io.opentracing.propagation.TextMap;
4+
import java.util.HashMap;
5+
import java.util.Iterator;
6+
import java.util.Map;
7+
8+
public final class MapBackedTextMap implements TextMap {
9+
private final Map<String, String> map = new HashMap<>();
10+
11+
@Override
12+
public Iterator<Map.Entry<String, String>> iterator() {
13+
return map.entrySet().iterator();
14+
}
15+
16+
@Override
17+
public void put(String key, String value) {
18+
map.put(key, value);
19+
}
20+
21+
public Map<String, String> getMap() {
22+
return map;
23+
}
24+
25+
public String get(final String key) {
26+
return map.get(key);
27+
}
28+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package com.expedia.www.haystack.client.propagation;
2+
3+
import com.expedia.www.haystack.client.SpanContext;
4+
import java.util.UUID;
5+
import org.junit.Assert;
6+
import org.junit.Test;
7+
8+
public class TextMapPropagatorTest {
9+
@Test
10+
public void propagatorExtractsSpanContextIdentitiesAsExpected() {
11+
final KeyConvention keyConvention = new DefaultKeyConvention();
12+
final TextMapPropagator propagator = new TextMapPropagator.Builder().withKeyConvention(keyConvention).build();
13+
final MapBackedTextMap carrier = new MapBackedTextMap();
14+
15+
carrier.put(keyConvention.traceIdKey(), "8557731e-cce9-45c2-9485-1fd86f5116ca");
16+
carrier.put(keyConvention.spanIdKey(), "30898bb0-f836-43fb-ad69-44969f15e52d");
17+
carrier.put(keyConvention.parentIdKey(), "3a0bc1c1-504f-4f5d-907b-9b4522453bcf");
18+
19+
final SpanContext spanContext = propagator.extract(carrier);
20+
21+
Assert.assertEquals("trace-id was not extracted correctly",
22+
"8557731e-cce9-45c2-9485-1fd86f5116ca", spanContext.getTraceId().toString());
23+
Assert.assertEquals("span-id was not extracted correctly",
24+
"30898bb0-f836-43fb-ad69-44969f15e52d", spanContext.getSpanId().toString());
25+
Assert.assertEquals("parent-id was not extracted correctly",
26+
"3a0bc1c1-504f-4f5d-907b-9b4522453bcf", spanContext.getParentId().toString());
27+
}
28+
29+
@Test
30+
public void propagatorExtractsSpanContextIdentitiesAsExpectedRegardlessOfCase() {
31+
final KeyConvention keyConvention = new DefaultKeyConvention();
32+
final TextMapPropagator propagator = new TextMapPropagator.Builder().withKeyConvention(keyConvention).build();
33+
final MapBackedTextMap carrier = new MapBackedTextMap();
34+
35+
carrier.put(keyConvention.traceIdKey().toLowerCase(), "8557731e-cce9-45c2-9485-1fd86f5116ca");
36+
carrier.put(keyConvention.spanIdKey().toLowerCase(), "30898bb0-f836-43fb-ad69-44969f15e52d");
37+
carrier.put(keyConvention.parentIdKey().toLowerCase(), "3a0bc1c1-504f-4f5d-907b-9b4522453bcf");
38+
carrier.put(keyConvention.baggagePrefix().toLowerCase() + "item-1", "foo");
39+
40+
final SpanContext spanContext = propagator.extract(carrier);
41+
42+
Assert.assertEquals("trace-id was not extracted correctly",
43+
"8557731e-cce9-45c2-9485-1fd86f5116ca", spanContext.getTraceId().toString());
44+
Assert.assertEquals("span-id was not extracted correctly",
45+
"30898bb0-f836-43fb-ad69-44969f15e52d", spanContext.getSpanId().toString());
46+
Assert.assertEquals("parent-id was not extracted correctly",
47+
"3a0bc1c1-504f-4f5d-907b-9b4522453bcf", spanContext.getParentId().toString());
48+
Assert.assertEquals("baggage item was not extracted correctly",
49+
"foo", spanContext.getBaggage().get("item-1"));
50+
}
51+
52+
@Test
53+
public void propagatorInjectsSpanContextIdentitiesAsExpected() {
54+
final KeyConvention keyConvention = new DefaultKeyConvention();
55+
final TextMapPropagator propagator = new TextMapPropagator.Builder().withKeyConvention(keyConvention).build();
56+
final MapBackedTextMap carrier = new MapBackedTextMap();
57+
58+
final SpanContext spanContext = new SpanContext(UUID.fromString("8557731e-cce9-45c2-9485-1fd86f5116ca"),
59+
UUID.fromString("30898bb0-f836-43fb-ad69-44969f15e52d"),
60+
UUID.fromString("3a0bc1c1-504f-4f5d-907b-9b4522453bcf"));
61+
62+
propagator.inject(spanContext, carrier);
63+
64+
Assert.assertEquals("trace-id was not injected correctly",
65+
"8557731e-cce9-45c2-9485-1fd86f5116ca", carrier.get(keyConvention.traceIdKey()));
66+
Assert.assertEquals("span-id was not injected correctly",
67+
"30898bb0-f836-43fb-ad69-44969f15e52d", carrier.get(keyConvention.spanIdKey()));
68+
Assert.assertEquals("parent-id was not injected correctly",
69+
"3a0bc1c1-504f-4f5d-907b-9b4522453bcf", carrier.get(keyConvention.parentIdKey()));
70+
}
71+
72+
@Test
73+
public void builderUsesTheProvidedCodexForKeyAndValue() {
74+
final KeyConvention keyConvention = new DefaultKeyConvention();
75+
final TextMapCodex codex = new OneAppendingCodex();
76+
final TextMapPropagator propagator = new TextMapPropagator.Builder()
77+
.withKeyConvention(keyConvention)
78+
.withCodex(codex)
79+
.build();
80+
final MapBackedTextMap carrier = new MapBackedTextMap();
81+
82+
final SpanContext spanContext = new SpanContext(UUID.fromString("8557731e-cce9-45c2-9485-1fd86f5116ca"),
83+
UUID.fromString("30898bb0-f836-43fb-ad69-44969f15e52d"),
84+
UUID.fromString("3a0bc1c1-504f-4f5d-907b-9b4522453bcf"));
85+
86+
propagator.inject(spanContext, carrier);
87+
88+
Assert.assertEquals("trace-id was not injected correctly",
89+
"1-8557731e-cce9-45c2-9485-1fd86f5116ca",
90+
carrier.get("1-" + keyConvention.traceIdKey()));
91+
Assert.assertEquals("span-id was not injected correctly",
92+
"1-30898bb0-f836-43fb-ad69-44969f15e52d",
93+
carrier.get("1-" + keyConvention.spanIdKey()));
94+
Assert.assertEquals("parent-id was not injected correctly",
95+
"1-3a0bc1c1-504f-4f5d-907b-9b4522453bcf",
96+
carrier.get("1-" + keyConvention.parentIdKey()));
97+
}
98+
99+
private class OneAppendingCodex extends TextMapCodex {
100+
@Override
101+
public String encode(String value) {
102+
return "1-" + value;
103+
}
104+
105+
@Override
106+
public String decode(String value) {
107+
return value.substring(2);
108+
}
109+
}
110+
}

0 commit comments

Comments
 (0)