diff --git a/sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/DistributedContextHttpTextFormat.java b/sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/DistributedContextHttpTextFormat.java new file mode 100644 index 00000000000..1cb871fc904 --- /dev/null +++ b/sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/DistributedContextHttpTextFormat.java @@ -0,0 +1,69 @@ +/* + * Copyright 2019, OpenTelemetry 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.opentelemetry.sdk.distributedcontext; + +import io.opentelemetry.context.propagation.HttpTextFormat; +import io.opentelemetry.distributedcontext.DistributedContext; +import io.opentelemetry.distributedcontext.Entry; +import io.opentelemetry.distributedcontext.EntryKey; +import io.opentelemetry.distributedcontext.EntryValue; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** W3C Trace Context implementation of the HttpTextFormat for a DistributedContext. */ +class DistributedContextHttpTextFormat implements HttpTextFormat { + static final String TRACEPARENT = "traceparent"; + static final String TRACESTATE = "tracestate"; + private static final List FIELDS = + Collections.unmodifiableList(Arrays.asList(TRACEPARENT, TRACESTATE)); + + private static final DistributedContextHttpTextFormat INSTANCE = + new DistributedContextHttpTextFormat(); + + public static DistributedContextHttpTextFormat getInstance() { + return INSTANCE; + } + + @Override + public List fields() { + return FIELDS; + } + + @Override + public void inject(DistributedContext value, C carrier, Setter setter) { + for (String field : fields()) { + final EntryValue entryValue = value.getEntryValue(EntryKey.create(field)); + if (entryValue != null) { + setter.put(carrier, field, entryValue.asString()); + } + } + } + + @Override + public DistributedContext extract(C carrier, Getter getter) { + final DistributedContextSdk.Builder builder = new DistributedContextSdk.Builder(); + for (String field : fields()) { + final String value = getter.get(carrier, field); + if (value != null) { + builder.put( + EntryKey.create(field), EntryValue.create(value), Entry.METADATA_UNLIMITED_PROPAGATION); + } + } + return builder.build(); + } +} diff --git a/sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/DistributedContextManagerSdk.java b/sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/DistributedContextManagerSdk.java index cee4abe9a18..105b386227a 100644 --- a/sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/DistributedContextManagerSdk.java +++ b/sdk/src/main/java/io/opentelemetry/sdk/distributedcontext/DistributedContextManagerSdk.java @@ -50,6 +50,6 @@ public BinaryFormat getBinaryFormat() { @Override public HttpTextFormat getHttpTextFormat() { - throw new UnsupportedOperationException("to be implemented"); + return DistributedContextHttpTextFormat.getInstance(); } } diff --git a/sdk/src/test/java/io/opentelemetry/sdk/distributedcontext/DistributedContextHttpTextFormatTest.java b/sdk/src/test/java/io/opentelemetry/sdk/distributedcontext/DistributedContextHttpTextFormatTest.java new file mode 100644 index 00000000000..d25a2a2f3e8 --- /dev/null +++ b/sdk/src/test/java/io/opentelemetry/sdk/distributedcontext/DistributedContextHttpTextFormatTest.java @@ -0,0 +1,145 @@ +/* + * Copyright 2019, OpenTelemetry 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.opentelemetry.sdk.distributedcontext; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import io.opentelemetry.context.propagation.HttpTextFormat; +import io.opentelemetry.distributedcontext.DistributedContext; +import io.opentelemetry.distributedcontext.Entry; +import io.opentelemetry.distributedcontext.EntryKey; +import io.opentelemetry.distributedcontext.EntryValue; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.Nullable; +import org.junit.Test; + +public class DistributedContextHttpTextFormatTest { + + @Test + public void inject() { + DistributedContextHttpTextFormat httpTextFormat = + DistributedContextHttpTextFormat.getInstance(); + + Map dataCarrier = new HashMap<>(); + DistributedContext distributedContext = + new DistributedContextSdk.Builder() + .put( + EntryKey.create("foo"), + EntryValue.create("bar"), + Entry.METADATA_UNLIMITED_PROPAGATION) + .put( + EntryKey.create(DistributedContextHttpTextFormat.TRACEPARENT), + EntryValue.create("traceParentData"), + Entry.METADATA_UNLIMITED_PROPAGATION) + .put( + EntryKey.create(DistributedContextHttpTextFormat.TRACESTATE), + EntryValue.create("traceStateData"), + Entry.METADATA_UNLIMITED_PROPAGATION) + .build(); + + httpTextFormat.inject( + distributedContext, + dataCarrier, + new HttpTextFormat.Setter>() { + @Override + public void put(Map carrier, String key, String value) { + carrier.put(key, value); + } + }); + + assertEquals(2, dataCarrier.size()); + assertEquals("traceParentData", dataCarrier.get(DistributedContextHttpTextFormat.TRACEPARENT)); + assertEquals("traceStateData", dataCarrier.get(DistributedContextHttpTextFormat.TRACESTATE)); + } + + @Test + public void inject_nullValues() { + DistributedContextHttpTextFormat httpTextFormat = + DistributedContextHttpTextFormat.getInstance(); + + Map dataCarrier = new HashMap<>(); + DistributedContext distributedContext = + new DistributedContextSdk.Builder() + .put( + EntryKey.create("foo"), + EntryValue.create("bar"), + Entry.METADATA_UNLIMITED_PROPAGATION) + .build(); + + httpTextFormat.inject( + distributedContext, + dataCarrier, + new HttpTextFormat.Setter>() { + @Override + public void put(Map carrier, String key, String value) { + carrier.put(key, value); + } + }); + + assertTrue(dataCarrier.isEmpty()); + } + + @Test + public void extract() throws Exception { + DistributedContextHttpTextFormat httpTextFormat = + DistributedContextHttpTextFormat.getInstance(); + Map dataCarrier = new HashMap<>(); + dataCarrier.put(DistributedContextHttpTextFormat.TRACESTATE, "traceStateData"); + dataCarrier.put(DistributedContextHttpTextFormat.TRACEPARENT, "traceParentData"); + + DistributedContext context = + httpTextFormat.extract( + dataCarrier, + new HttpTextFormat.Getter>() { + @Nullable + @Override + public String get(Map carrier, String key) { + return carrier.get(key); + } + }); + + assertEquals(2, context.getEntries().size()); + assertEquals( + EntryValue.create("traceStateData"), + context.getEntryValue(EntryKey.create(DistributedContextHttpTextFormat.TRACESTATE))); + assertEquals( + EntryValue.create("traceParentData"), + context.getEntryValue(EntryKey.create(DistributedContextHttpTextFormat.TRACEPARENT))); + } + + @Test + public void extract_missingValues() throws Exception { + DistributedContextHttpTextFormat httpTextFormat = + DistributedContextHttpTextFormat.getInstance(); + Map dataCarrier = new HashMap<>(); + + DistributedContext context = + httpTextFormat.extract( + dataCarrier, + new HttpTextFormat.Getter>() { + @Nullable + @Override + public String get(Map carrier, String key) { + return carrier.get(key); + } + }); + + assertEquals(0, context.getEntries().size()); + } +}