diff --git a/opentracing-spring-messaging/src/main/java/io/opentracing/contrib/spring/integration/messaging/JmsTextMapExtractAdapter.java b/opentracing-spring-messaging/src/main/java/io/opentracing/contrib/spring/integration/messaging/JmsTextMapExtractAdapter.java new file mode 100644 index 0000000..6ea4ae5 --- /dev/null +++ b/opentracing-spring-messaging/src/main/java/io/opentracing/contrib/spring/integration/messaging/JmsTextMapExtractAdapter.java @@ -0,0 +1,59 @@ +/** + * Copyright 2017-2019 The OpenTracing 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.opentracing.contrib.spring.integration.messaging; + +import io.opentracing.propagation.TextMap; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * Helper class to extract span context from message properties + */ +public class JmsTextMapExtractAdapter implements TextMap { + + private final Map map = new HashMap<>(); + static final String DASH = "_$dash$_"; + + public JmsTextMapExtractAdapter(TextMap message) { + if (message == null) { + return; + } + Iterator it = message.iterator(); + while (it.hasNext()) { + Map.Entry headerPair = (Map.Entry) it.next(); + String headerKey = (String) headerPair.getKey(); + Object headerValue = headerPair.getValue(); + if (headerValue instanceof String) { + map.put(decodeDash(headerKey), (String) headerValue); + } + } + } + + @Override + public Iterator> iterator() { + return map.entrySet().iterator(); + } + + @Override + public void put(String key, String value) { + throw new UnsupportedOperationException( + "JmsTextMapExtractAdapter should only be used with Tracer.extract()"); + } + + private String decodeDash(String key) { + return key.replace(DASH, "-"); + } +} \ No newline at end of file diff --git a/opentracing-spring-messaging/src/main/java/io/opentracing/contrib/spring/integration/messaging/MessageTextMap.java b/opentracing-spring-messaging/src/main/java/io/opentracing/contrib/spring/integration/messaging/MessageTextMap.java index 5af40aa..12ff175 100644 --- a/opentracing-spring-messaging/src/main/java/io/opentracing/contrib/spring/integration/messaging/MessageTextMap.java +++ b/opentracing-spring-messaging/src/main/java/io/opentracing/contrib/spring/integration/messaging/MessageTextMap.java @@ -60,7 +60,7 @@ public Iterator> iterator() { @Override public void put(String key, String value) { - headers.put(key, byteHeaders.contains(key) ? value.getBytes() : value); + headers.put(encodeDash(key), byteHeaders.contains(key) ? value.getBytes() : value); } public Message getMessage() { @@ -68,4 +68,13 @@ public Message getMessage() { .copyHeaders(headers) .build(); } + + private String encodeDash(String key) { + if (key == null || key.isEmpty()) { + return key; + } + + return key.replace("-", JmsTextMapExtractAdapter.DASH); + } + } diff --git a/opentracing-spring-messaging/src/main/java/io/opentracing/contrib/spring/integration/messaging/OpenTracingChannelInterceptor.java b/opentracing-spring-messaging/src/main/java/io/opentracing/contrib/spring/integration/messaging/OpenTracingChannelInterceptor.java index b7fe9ff..4f34162 100644 --- a/opentracing-spring-messaging/src/main/java/io/opentracing/contrib/spring/integration/messaging/OpenTracingChannelInterceptor.java +++ b/opentracing-spring-messaging/src/main/java/io/opentracing/contrib/spring/integration/messaging/OpenTracingChannelInterceptor.java @@ -1,5 +1,5 @@ /** - * Copyright 2017-2018 The OpenTracing Authors + * Copyright 2017-2019 The OpenTracing 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 @@ -57,7 +57,7 @@ public Message preSend(Message message, MessageChannel channel) { .withTag(Tags.MESSAGE_BUS_DESTINATION.getKey(), getChannelName(channel)); MessageTextMap carrier = new MessageTextMap<>(message); - SpanContext extractedContext = tracer.extract(Format.Builtin.TEXT_MAP, carrier); + SpanContext extractedContext = tracer.extract(Format.Builtin.TEXT_MAP, new JmsTextMapExtractAdapter(carrier)); if (isConsumer) { spanBuilder.addReference(References.FOLLOWS_FROM, extractedContext); } else if (tracer.activeSpan() == null) { diff --git a/opentracing-spring-messaging/src/test/java/io/opentracing/contrib/spring/integration/messaging/JmsTextTextExtractAdapterTest.java b/opentracing-spring-messaging/src/test/java/io/opentracing/contrib/spring/integration/messaging/JmsTextTextExtractAdapterTest.java new file mode 100644 index 0000000..ff0d35f --- /dev/null +++ b/opentracing-spring-messaging/src/test/java/io/opentracing/contrib/spring/integration/messaging/JmsTextTextExtractAdapterTest.java @@ -0,0 +1,50 @@ +/** + * Copyright 2017-2019 The OpenTracing 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.opentracing.contrib.spring.integration.messaging; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; +import org.springframework.messaging.Message; +import org.springframework.messaging.support.MessageBuilder; + +public class JmsTextTextExtractAdapterTest { + + @Test + public void shouldGetIterator() { + Map headers = new HashMap<>(2); + headers.put("h1", "v1"); + headers.put("h2", "v2"); + Message message = MessageBuilder.withPayload("test").copyHeaders(headers).build(); + MessageTextMap map = new MessageTextMap<>(message); + JmsTextMapExtractAdapter adapter = new JmsTextMapExtractAdapter(map); + assertThat(adapter.iterator()).containsAll(headers.entrySet()); + } + + @Test + public void shouldDecodeDash() { + Map headers = new HashMap<>(1); + headers.put("uber_$dash$_trace_$dash$_id", "v1"); + Map chanedHeaders = new HashMap<>(1); + headers.put("uber-trace-id", "v1"); + Message message = MessageBuilder.withPayload("test").copyHeaders(headers).build(); + MessageTextMap map = new MessageTextMap<>(message); + JmsTextMapExtractAdapter adapter = new JmsTextMapExtractAdapter(map); + assertThat(adapter.iterator()).containsAll(chanedHeaders.entrySet()); + } + +} diff --git a/opentracing-spring-messaging/src/test/java/io/opentracing/contrib/spring/integration/messaging/MessageTextMapTest.java b/opentracing-spring-messaging/src/test/java/io/opentracing/contrib/spring/integration/messaging/MessageTextMapTest.java index 371ab22..29105a0 100644 --- a/opentracing-spring-messaging/src/test/java/io/opentracing/contrib/spring/integration/messaging/MessageTextMapTest.java +++ b/opentracing-spring-messaging/src/test/java/io/opentracing/contrib/spring/integration/messaging/MessageTextMapTest.java @@ -1,5 +1,5 @@ /** - * Copyright 2017-2018 The OpenTracing Authors + * Copyright 2017-2019 The OpenTracing 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 @@ -55,6 +55,16 @@ public void shouldPutEntry() { assertThat(map.iterator()).contains(new AbstractMap.SimpleEntry<>("k1", "v1")); } + @Test + public void shouldEncodeKeyWithDash() { + Message message = MessageBuilder.withPayload("test") + .build(); + MessageTextMap map = new MessageTextMap<>(message); + map.put("uber-trace-id", "1435645"); + + assertThat(map.iterator()).contains(new AbstractMap.SimpleEntry<>("uber_$dash$_trace_$dash$_id", "1435645")); + } + @Test public void shouldGetMessageWithNewHeaders() { Message message = MessageBuilder.withPayload("test") diff --git a/opentracing-spring-messaging/src/test/java/io/opentracing/contrib/spring/integration/messaging/OpenTracingChannelInterceptorTest.java b/opentracing-spring-messaging/src/test/java/io/opentracing/contrib/spring/integration/messaging/OpenTracingChannelInterceptorTest.java index 1f894d4..bc82bbd 100644 --- a/opentracing-spring-messaging/src/test/java/io/opentracing/contrib/spring/integration/messaging/OpenTracingChannelInterceptorTest.java +++ b/opentracing-spring-messaging/src/test/java/io/opentracing/contrib/spring/integration/messaging/OpenTracingChannelInterceptorTest.java @@ -1,5 +1,5 @@ /** - * Copyright 2017-2018 The OpenTracing Authors + * Copyright 2017-2019 The OpenTracing 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 @@ -122,7 +122,7 @@ public void preSendShouldStartSpanForServerReceivedMessage() { Message message = interceptor.preSend(originalMessage, mockMessageChannel); assertThat(message.getPayload()).isEqualTo(originalMessage.getPayload()); - verify(mockTracer).extract(eq(Format.Builtin.TEXT_MAP), any(MessageTextMap.class)); + verify(mockTracer).extract(eq(Format.Builtin.TEXT_MAP), any(JmsTextMapExtractAdapter.class)); verify(mockTracer).buildSpan(String.format("receive:%s", mockMessageChannel.toString())); verify(mockSpanBuilder).addReference(References.FOLLOWS_FROM, null); verify(mockSpanBuilder).startActive(true);