aboutsummaryrefslogtreecommitdiffstats
path: root/api/src
diff options
context:
space:
mode:
authorBogdan Drutu <bdrutu@google.com>2017-12-06 13:04:38 -0800
committerGitHub <noreply@github.com>2017-12-06 13:04:38 -0800
commit28d023af35ef516fb472092edff3de224fc79e03 (patch)
tree8cdd636b9b5be97b38b3cee2bc3299e0bcaf8b18 /api/src
parent69aa742a314f847f846de7b10c8cf464e5c41ee9 (diff)
downloadplatform_external_opencensus-java-28d023af35ef516fb472092edff3de224fc79e03.tar.gz
platform_external_opencensus-java-28d023af35ef516fb472092edff3de224fc79e03.tar.bz2
platform_external_opencensus-java-28d023af35ef516fb472092edff3de224fc79e03.zip
Adds TextFormat and usage example. (#724)
* Adds TextFormat and usage example. * Remove multiple encodings support. * Run google java formatter. * Remove getTextFormat from PropagationComponent. * Update comments. * Improve javadoc.
Diffstat (limited to 'api/src')
-rw-r--r--api/src/main/java/io/opencensus/trace/propagation/TextFormat.java189
-rw-r--r--api/src/test/java/io/opencensus/trace/propagation/PropagationComponentTest.java2
-rw-r--r--api/src/test/java/io/opencensus/trace/propagation/TextFormatTest.java75
3 files changed, 265 insertions, 1 deletions
diff --git a/api/src/main/java/io/opencensus/trace/propagation/TextFormat.java b/api/src/main/java/io/opencensus/trace/propagation/TextFormat.java
new file mode 100644
index 00000000..25880917
--- /dev/null
+++ b/api/src/main/java/io/opencensus/trace/propagation/TextFormat.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2017, OpenCensus 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.opencensus.trace.propagation;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.opencensus.common.ExperimentalApi;
+import io.opencensus.trace.SpanContext;
+import java.util.Collections;
+import java.util.List;
+import javax.annotation.Nullable;
+
+/**
+ * Injects and extracts {@link SpanContext trace identifiers} as text into carriers that travel
+ * in-band across process boundaries. Identifiers are often encoded as messaging or RPC request
+ * headers.
+ *
+ * <p>When using http, the carrier of propagated data on both the client (injector) and server
+ * (extractor) side is usually an http request. Propagation is usually implemented via library-
+ * specific request interceptors, where the client-side injects span identifiers and the server-side
+ * extracts them.
+ *
+ * <p>Example of usage on the client:
+ *
+ * <pre>{@code
+ * private static final Tracer tracer = Tracing.getTracer();
+ * private static final TextFormat textFormat = Tracing.getPropagationComponent().getTextFormat();
+ * private static final TextFormat.Setter setter = new TextFormat.Setter<HttpURLConnection>() {
+ * public void put(HttpURLConnection carrier, String key, String value) {
+ * carrier.setRequestProperty(field, value);
+ * }
+ * }
+ *
+ * void makeHttpRequest() {
+ * Span span = tracer.spanBuilder("Sent.MyRequest").startSpan();
+ * try (Scope s = tracer.withSpan(span)) {
+ * HttpURLConnection connection =
+ * (HttpURLConnection) new URL("http://myserver").openConnection();
+ * textFormat.inject(span.getContext(), connection, httpURLConnectionSetter);
+ * // Send the request, wait for response and maybe set the status if not ok.
+ * }
+ * span.end(); // Can set a status.
+ * }
+ * }</pre>
+ *
+ * <p>Example of usage on the server:
+ *
+ * <pre>{@code
+ * private static final Tracer tracer = Tracing.getTracer();
+ * private static final TextFormat textFormat = Tracing.getPropagationComponent().getTextFormat();
+ * private static final TextFormat.Getter<HttpRequest> getter = ...;
+ *
+ * void onRequestReceived(HttpRequest request) {
+ * SpanContext spanContext = textFormat.extract(request, getter);
+ * Span span = tracer.spanBuilderWithRemoteParent("Recv.MyRequest", spanContext).startSpan();
+ * try (Scope s = tracer.withSpan(span)) {
+ * // Handle request and send response back.
+ * }
+ * span.end()
+ * }
+ * }</pre>
+ */
+@ExperimentalApi
+public abstract class TextFormat {
+ private static final NoopTextFormat NOOP_TEXT_FORMAT = new NoopTextFormat();
+
+ /**
+ * The propagation fields defined. If your carrier is reused, you should delete the fields here
+ * before calling {@link #inject(SpanContext, Object, Setter)}.
+ *
+ * <p>For example, if the carrier is a single-use or immutable request object, you don't need to
+ * clear fields as they couldn't have been set before. If it is a mutable, retryable object,
+ * successive calls should clear these fields first.
+ */
+ // The use cases of this are:
+ // * allow pre-allocation of fields, especially in systems like gRPC Metadata
+ // * allow a single-pass over an iterator (ex OpenTracing has no getter in TextMap)
+ public abstract List<String> fields();
+
+ /**
+ * Injects the span context downstream. For example, as http headers.
+ *
+ * @param spanContext possibly not sampled.
+ * @param carrier holds propagation fields. For example, an outgoing message or http request.
+ * @param setter invoked for each propagation key to add or remove.
+ */
+ public abstract <C> void inject(SpanContext spanContext, C carrier, Setter<C> setter);
+
+ /**
+ * Class that allows a {@code TextFormat} to set propagated fields into a carrier.
+ *
+ * <p>{@code Setter} is stateless and allows to be saved as a constant to avoid runtime
+ * allocations.
+ *
+ * @param <C> carrier of propagation fields, such as an http request
+ */
+ public abstract static class Setter<C> {
+
+ /**
+ * Replaces a propagated field with the given value.
+ *
+ * <p>For example, a setter for an {@link java.net.HttpURLConnection} would be the method
+ * reference {@link java.net.HttpURLConnection#addRequestProperty(String, String)}
+ *
+ * @param carrier holds propagation fields. For example, an outgoing message or http request.
+ * @param key the key of the field.
+ * @param value the value of the field.
+ */
+ public abstract void put(C carrier, String key, String value);
+ }
+
+ /**
+ * Extracts the span context from upstream. For example, as http headers.
+ *
+ * @param carrier holds propagation fields. For example, an outgoing message or http request.
+ * @param getter invoked for each propagation key to get.
+ * @throws SpanContextParseException if the input is invalid
+ */
+ public abstract <C> SpanContext extract(C carrier, Getter<C> getter)
+ throws SpanContextParseException;
+
+ /**
+ * Class that allows a {@code TextFormat} to read propagated fields from a carrier.
+ *
+ * <p>{@code Getter} is stateless and allows to be saved as a constant to avoid runtime
+ * allocations.
+ *
+ * @param <C> carrier of propagation fields, such as an http request
+ */
+ public abstract static class Getter<C> {
+
+ /**
+ * Returns the first value of the given propagation {@code key} or returns {@code null}.
+ *
+ * @param carrier carrier of propagation fields, such as an http request
+ * @param key the key of the field.
+ * @return the first value of the given propagation {@code key} or returns {@code null}.
+ */
+ @Nullable
+ public abstract String get(C carrier, String key);
+ }
+
+ /**
+ * Returns the no-op implementation of the {@code TextFormat}.
+ *
+ * @return the no-op implementation of the {@code TextFormat}.
+ */
+ static TextFormat getNoopTextFormat() {
+ return NOOP_TEXT_FORMAT;
+ }
+
+ private static final class NoopTextFormat extends TextFormat {
+
+ private NoopTextFormat() {}
+
+ @Override
+ public List<String> fields() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public <C> void inject(SpanContext spanContext, C carrier, Setter<C> setter) {
+ checkNotNull(spanContext, "spanContext");
+ checkNotNull(carrier, "carrier");
+ checkNotNull(setter, "setter");
+ }
+
+ @Override
+ public <C> SpanContext extract(C carrier, Getter<C> getter) {
+ checkNotNull(carrier, "carrier");
+ checkNotNull(getter, "getter");
+ return SpanContext.INVALID;
+ }
+ }
+}
diff --git a/api/src/test/java/io/opencensus/trace/propagation/PropagationComponentTest.java b/api/src/test/java/io/opencensus/trace/propagation/PropagationComponentTest.java
index 62f04d98..ba64e98e 100644
--- a/api/src/test/java/io/opencensus/trace/propagation/PropagationComponentTest.java
+++ b/api/src/test/java/io/opencensus/trace/propagation/PropagationComponentTest.java
@@ -29,7 +29,7 @@ public class PropagationComponentTest {
PropagationComponent.getNoopPropagationComponent();
@Test
- public void implementationOfBinary() {
+ public void implementationOfBinaryFormat() {
assertThat(propagationComponent.getBinaryFormat())
.isEqualTo(BinaryFormat.getNoopBinaryFormat());
}
diff --git a/api/src/test/java/io/opencensus/trace/propagation/TextFormatTest.java b/api/src/test/java/io/opencensus/trace/propagation/TextFormatTest.java
new file mode 100644
index 00000000..c2e6e127
--- /dev/null
+++ b/api/src/test/java/io/opencensus/trace/propagation/TextFormatTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2017, OpenCensus 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.opencensus.trace.propagation;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import io.opencensus.trace.SpanContext;
+import io.opencensus.trace.propagation.TextFormat.Getter;
+import io.opencensus.trace.propagation.TextFormat.Setter;
+import javax.annotation.Nullable;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link TextFormat}. */
+@RunWith(JUnit4.class)
+public class TextFormatTest {
+ private static final TextFormat textFormat = TextFormat.getNoopTextFormat();
+
+ @Test(expected = NullPointerException.class)
+ public void inject_NullSpanContext() {
+ textFormat.inject(
+ null,
+ new Object(),
+ new Setter<Object>() {
+ @Override
+ public void put(Object carrier, String key, String value) {}
+ });
+ }
+
+ @Test
+ public void inject_NotNullSpanContext_DoesNotFail() {
+ textFormat.inject(
+ SpanContext.INVALID,
+ new Object(),
+ new Setter<Object>() {
+ @Override
+ public void put(Object carrier, String key, String value) {}
+ });
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void fromHeaders_NullGetter() throws SpanContextParseException {
+ textFormat.extract(new Object(), null);
+ }
+
+ @Test
+ public void fromHeaders_NotNullGetter() throws SpanContextParseException {
+ assertThat(
+ textFormat.extract(
+ new Object(),
+ new Getter<Object>() {
+ @Nullable
+ @Override
+ public String get(Object carrier, String key) {
+ return null;
+ }
+ }))
+ .isSameAs(SpanContext.INVALID);
+ }
+}