From 80ec0c120bb133b3d3747406be7e4c543b9e0446 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Tue, 6 Jun 2017 13:56:55 -0700 Subject: Move internal & common & trace to the new package io.opencensus (#339) --- api/README.md | 6 + api/build.gradle | 11 + api/src/main/java/io/opencensus/common/Clock.java | 34 ++ .../main/java/io/opencensus/common/Duration.java | 103 ++++ .../main/java/io/opencensus/common/Function.java | 25 + .../main/java/io/opencensus/common/Internal.java | 37 ++ .../io/opencensus/common/NonThrowingCloseable.java | 35 ++ .../main/java/io/opencensus/common/Timestamp.java | 146 +++++ .../main/java/io/opencensus/internal/Provider.java | 99 ++++ .../java/io/opencensus/internal/StringUtil.java | 74 +++ .../java/io/opencensus/internal/TestClock.java | 99 ++++ .../java/io/opencensus/internal/ZeroTimeClock.java | 46 ++ .../java/io/opencensus/internal/package-info.java | 21 + api/src/main/java/io/opencensus/tags/TagKey.java | 104 ++++ api/src/main/java/io/opencensus/tags/TagMap.java | 141 +++++ .../main/java/io/opencensus/trace/Annotation.java | 73 +++ .../java/io/opencensus/trace/AttributeValue.java | 91 +++ .../opencensus/trace/BinaryPropagationHandler.java | 108 ++++ .../main/java/io/opencensus/trace/BlankSpan.java | 62 +++ .../java/io/opencensus/trace/ContextUtils.java | 75 +++ .../java/io/opencensus/trace/EndSpanOptions.java | 78 +++ api/src/main/java/io/opencensus/trace/Link.java | 72 +++ .../java/io/opencensus/trace/NetworkEvent.java | 124 +++++ api/src/main/java/io/opencensus/trace/Sampler.java | 41 ++ .../main/java/io/opencensus/trace/Samplers.java | 166 ++++++ .../java/io/opencensus/trace/ScopedSpanHandle.java | 47 ++ api/src/main/java/io/opencensus/trace/Span.java | 165 ++++++ .../main/java/io/opencensus/trace/SpanBuilder.java | 282 ++++++++++ .../main/java/io/opencensus/trace/SpanContext.java | 118 ++++ .../main/java/io/opencensus/trace/SpanData.java | 308 +++++++++++ .../main/java/io/opencensus/trace/SpanFactory.java | 44 ++ api/src/main/java/io/opencensus/trace/SpanId.java | 171 ++++++ .../java/io/opencensus/trace/StartSpanOptions.java | 101 ++++ api/src/main/java/io/opencensus/trace/Status.java | 327 +++++++++++ .../java/io/opencensus/trace/TraceComponent.java | 107 ++++ .../main/java/io/opencensus/trace/TraceConfig.java | 213 +++++++ .../java/io/opencensus/trace/TraceExporter.java | 609 +++++++++++++++++++++ api/src/main/java/io/opencensus/trace/TraceId.java | 185 +++++++ .../java/io/opencensus/trace/TraceOptions.java | 210 +++++++ api/src/main/java/io/opencensus/trace/Tracer.java | 228 ++++++++ api/src/main/java/io/opencensus/trace/Tracing.java | 89 +++ .../java/io/opencensus/common/DurationTest.java | 61 +++ .../java/io/opencensus/common/TimestampTest.java | 83 +++ .../java/io/opencensus/internal/ProviderTest.java | 125 +++++ .../io/opencensus/internal/StringUtilTest.java | 45 ++ .../java/io/opencensus/internal/TestClockTest.java | 62 +++ .../test/java/io/opencensus/tags/TagKeyTest.java | 75 +++ .../test/java/io/opencensus/tags/TagMapTest.java | 114 ++++ .../java/io/opencensus/trace/AnnotationTest.java | 99 ++++ .../io/opencensus/trace/AttributeValueTest.java | 75 +++ .../trace/BinaryPropagationHandlerTest.java | 49 ++ .../java/io/opencensus/trace/BlankSpanTest.java | 60 ++ .../java/io/opencensus/trace/ContextUtilsTest.java | 90 +++ .../io/opencensus/trace/EndSpanOptionsTest.java | 68 +++ .../test/java/io/opencensus/trace/LinkTest.java | 75 +++ .../java/io/opencensus/trace/NetworkEventTest.java | 87 +++ .../java/io/opencensus/trace/SamplersTest.java | 167 ++++++ .../io/opencensus/trace/ScopedSpanHandleTest.java | 51 ++ .../java/io/opencensus/trace/SpanBuilderTest.java | 170 ++++++ .../java/io/opencensus/trace/SpanContextTest.java | 113 ++++ .../java/io/opencensus/trace/SpanDataTest.java | 241 ++++++++ .../test/java/io/opencensus/trace/SpanIdTest.java | 73 +++ .../test/java/io/opencensus/trace/SpanTest.java | 112 ++++ .../io/opencensus/trace/StartSpanOptionsTest.java | 110 ++++ .../test/java/io/opencensus/trace/StatusTest.java | 51 ++ .../io/opencensus/trace/TraceComponentTest.java | 53 ++ .../io/opencensus/trace/TraceExporterTest.java | 47 ++ .../test/java/io/opencensus/trace/TraceIdTest.java | 75 +++ .../java/io/opencensus/trace/TraceOptionsTest.java | 77 +++ .../java/io/opencensus/trace/TraceParamsTest.java | 77 +++ .../test/java/io/opencensus/trace/TracerTest.java | 210 +++++++ .../test/java/io/opencensus/trace/TracingTest.java | 78 +++ 72 files changed, 7948 insertions(+) create mode 100644 api/README.md create mode 100644 api/build.gradle create mode 100644 api/src/main/java/io/opencensus/common/Clock.java create mode 100644 api/src/main/java/io/opencensus/common/Duration.java create mode 100644 api/src/main/java/io/opencensus/common/Function.java create mode 100644 api/src/main/java/io/opencensus/common/Internal.java create mode 100644 api/src/main/java/io/opencensus/common/NonThrowingCloseable.java create mode 100644 api/src/main/java/io/opencensus/common/Timestamp.java create mode 100644 api/src/main/java/io/opencensus/internal/Provider.java create mode 100644 api/src/main/java/io/opencensus/internal/StringUtil.java create mode 100644 api/src/main/java/io/opencensus/internal/TestClock.java create mode 100644 api/src/main/java/io/opencensus/internal/ZeroTimeClock.java create mode 100644 api/src/main/java/io/opencensus/internal/package-info.java create mode 100644 api/src/main/java/io/opencensus/tags/TagKey.java create mode 100644 api/src/main/java/io/opencensus/tags/TagMap.java create mode 100644 api/src/main/java/io/opencensus/trace/Annotation.java create mode 100644 api/src/main/java/io/opencensus/trace/AttributeValue.java create mode 100644 api/src/main/java/io/opencensus/trace/BinaryPropagationHandler.java create mode 100644 api/src/main/java/io/opencensus/trace/BlankSpan.java create mode 100644 api/src/main/java/io/opencensus/trace/ContextUtils.java create mode 100644 api/src/main/java/io/opencensus/trace/EndSpanOptions.java create mode 100644 api/src/main/java/io/opencensus/trace/Link.java create mode 100644 api/src/main/java/io/opencensus/trace/NetworkEvent.java create mode 100644 api/src/main/java/io/opencensus/trace/Sampler.java create mode 100644 api/src/main/java/io/opencensus/trace/Samplers.java create mode 100644 api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java create mode 100644 api/src/main/java/io/opencensus/trace/Span.java create mode 100644 api/src/main/java/io/opencensus/trace/SpanBuilder.java create mode 100644 api/src/main/java/io/opencensus/trace/SpanContext.java create mode 100644 api/src/main/java/io/opencensus/trace/SpanData.java create mode 100644 api/src/main/java/io/opencensus/trace/SpanFactory.java create mode 100644 api/src/main/java/io/opencensus/trace/SpanId.java create mode 100644 api/src/main/java/io/opencensus/trace/StartSpanOptions.java create mode 100644 api/src/main/java/io/opencensus/trace/Status.java create mode 100644 api/src/main/java/io/opencensus/trace/TraceComponent.java create mode 100644 api/src/main/java/io/opencensus/trace/TraceConfig.java create mode 100644 api/src/main/java/io/opencensus/trace/TraceExporter.java create mode 100644 api/src/main/java/io/opencensus/trace/TraceId.java create mode 100644 api/src/main/java/io/opencensus/trace/TraceOptions.java create mode 100644 api/src/main/java/io/opencensus/trace/Tracer.java create mode 100644 api/src/main/java/io/opencensus/trace/Tracing.java create mode 100644 api/src/test/java/io/opencensus/common/DurationTest.java create mode 100644 api/src/test/java/io/opencensus/common/TimestampTest.java create mode 100644 api/src/test/java/io/opencensus/internal/ProviderTest.java create mode 100644 api/src/test/java/io/opencensus/internal/StringUtilTest.java create mode 100644 api/src/test/java/io/opencensus/internal/TestClockTest.java create mode 100644 api/src/test/java/io/opencensus/tags/TagKeyTest.java create mode 100644 api/src/test/java/io/opencensus/tags/TagMapTest.java create mode 100644 api/src/test/java/io/opencensus/trace/AnnotationTest.java create mode 100644 api/src/test/java/io/opencensus/trace/AttributeValueTest.java create mode 100644 api/src/test/java/io/opencensus/trace/BinaryPropagationHandlerTest.java create mode 100644 api/src/test/java/io/opencensus/trace/BlankSpanTest.java create mode 100644 api/src/test/java/io/opencensus/trace/ContextUtilsTest.java create mode 100644 api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java create mode 100644 api/src/test/java/io/opencensus/trace/LinkTest.java create mode 100644 api/src/test/java/io/opencensus/trace/NetworkEventTest.java create mode 100644 api/src/test/java/io/opencensus/trace/SamplersTest.java create mode 100644 api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java create mode 100644 api/src/test/java/io/opencensus/trace/SpanBuilderTest.java create mode 100644 api/src/test/java/io/opencensus/trace/SpanContextTest.java create mode 100644 api/src/test/java/io/opencensus/trace/SpanDataTest.java create mode 100644 api/src/test/java/io/opencensus/trace/SpanIdTest.java create mode 100644 api/src/test/java/io/opencensus/trace/SpanTest.java create mode 100644 api/src/test/java/io/opencensus/trace/StartSpanOptionsTest.java create mode 100644 api/src/test/java/io/opencensus/trace/StatusTest.java create mode 100644 api/src/test/java/io/opencensus/trace/TraceComponentTest.java create mode 100644 api/src/test/java/io/opencensus/trace/TraceExporterTest.java create mode 100644 api/src/test/java/io/opencensus/trace/TraceIdTest.java create mode 100644 api/src/test/java/io/opencensus/trace/TraceOptionsTest.java create mode 100644 api/src/test/java/io/opencensus/trace/TraceParamsTest.java create mode 100644 api/src/test/java/io/opencensus/trace/TracerTest.java create mode 100644 api/src/test/java/io/opencensus/trace/TracingTest.java (limited to 'api') diff --git a/api/README.md b/api/README.md new file mode 100644 index 00000000..797ebe0a --- /dev/null +++ b/api/README.md @@ -0,0 +1,6 @@ +OpenCensus API +====================================================== + +* Java 6 and Android compatible. +* The abstract classes in this directory can be subclassed to create alternative + implementations of the Instrumentation library. diff --git a/api/build.gradle b/api/build.gradle new file mode 100644 index 00000000..7cfb33b2 --- /dev/null +++ b/api/build.gradle @@ -0,0 +1,11 @@ +description = 'OpenCensus: API' + +dependencies { + compile libraries.grpc_context, + libraries.guava + compileOnly libraries.auto_value + + signature "org.codehaus.mojo.signature:java16:+@signature" +} + +javadoc.exclude 'io/opencensus/**' \ No newline at end of file diff --git a/api/src/main/java/io/opencensus/common/Clock.java b/api/src/main/java/io/opencensus/common/Clock.java new file mode 100644 index 00000000..420c5191 --- /dev/null +++ b/api/src/main/java/io/opencensus/common/Clock.java @@ -0,0 +1,34 @@ +/* + * Copyright 2017, Google Inc. + * 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.common; + +/** Interface for getting the current time. */ +public abstract class Clock { + + /** + * Obtains the current instant from this clock. + * + * @return the current instant. + */ + public abstract Timestamp now(); + + /** + * Returns a time measurement with nanosecond precision that can only be used to calculate elapsed + * time. + * + * @return a time measurement with nanosecond precision that can only be used to calculate elapsed + * time. + */ + public abstract long nowNanos(); +} diff --git a/api/src/main/java/io/opencensus/common/Duration.java b/api/src/main/java/io/opencensus/common/Duration.java new file mode 100644 index 00000000..c0e9f1bc --- /dev/null +++ b/api/src/main/java/io/opencensus/common/Duration.java @@ -0,0 +1,103 @@ +/* + * Copyright 2016, Google Inc. + * 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.common; + +/** + * Represents a signed, fixed-length span of time represented as a count of seconds and fractions of + * seconds at nanosecond resolution. It is independent of any calendar and concepts like "day" or + * "month". Range is approximately +-10,000 years. + */ +public class Duration { + /** + * Creates a new time duration from given seconds and nanoseconds. + * + * @param seconds Signed seconds of the span of time. Must be from -315,576,000,000 to + * +315,576,000,000 inclusive. + * @param nanos Signed fractions of a second at nanosecond resolution of the span of time. + * Durations less than one second are represented with a 0 `seconds` field and a positive or + * negative `nanos` field. For durations of one second or more, a non-zero value for the + * `nanos` field must be of the same sign as the `seconds` field. Must be from -999,999,999 to + * +999,999,999 inclusive. + * @return new {@link Duration} with specified fields. For invalid inputs, a {@link Duration} of + * zero is returned. + */ + public static Duration create(long seconds, int nanos) { + if (seconds < -MAX_SECONDS || seconds > MAX_SECONDS) { + return new Duration(0, 0); + } + if (nanos < -MAX_NANOS || nanos > MAX_NANOS) { + return new Duration(0, 0); + } + if ((seconds < 0 && nanos > 0) || (seconds > 0 && nanos < 0)) { + return new Duration(0, 0); + } + return new Duration(seconds, nanos); + } + + /** Creates a new {@link Duration} from given milliseconds. */ + public static Duration fromMillis(long millis) { + long seconds = millis / NUM_MILLIS_PER_SECOND; + int nanos = (int) (millis % NUM_MILLIS_PER_SECOND) * NUM_NANOS_PER_MILLI; + return new Duration(seconds, nanos); + } + + /** Returns the number of seconds in the {@link Duration}. */ + public long getSeconds() { + return seconds; + } + + /** Returns the number of nanoseconds in the {@link Duration}. */ + public int getNanos() { + return nanos; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof Duration)) { + return false; + } + + Duration that = (Duration) obj; + return seconds == that.seconds && nanos == that.nanos; + } + + @Override + public int hashCode() { + int result = 17; + result = 31 * result + (int) (seconds ^ (seconds >>> 32)); + result = 31 * result + nanos; + return result; + } + + @Override + public String toString() { + return "Duration<" + seconds + "," + nanos + ">"; + } + + private static final long MAX_SECONDS = 315576000000L; + private static final int MAX_NANOS = 999999999; + private static final long NUM_MILLIS_PER_SECOND = 1000L; + private static final int NUM_NANOS_PER_MILLI = 1000000; + private final long seconds; + private final int nanos; + + private Duration(long seconds, int nanos) { + this.seconds = seconds; + this.nanos = nanos; + } +} diff --git a/api/src/main/java/io/opencensus/common/Function.java b/api/src/main/java/io/opencensus/common/Function.java new file mode 100644 index 00000000..51bf845c --- /dev/null +++ b/api/src/main/java/io/opencensus/common/Function.java @@ -0,0 +1,25 @@ +/* + * Copyright 2016, Google Inc. + * 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.common; + +/** + * Used to specify matching functions for use encoding tagged unions (i.e. sum types) in Java. See + * {@link io.opencensus.stats.ViewDescriptor} for an example of it's use. + * + *

Note: This class is based on the java.util.Function class added in Java 1.8. We cannot use the + * Function from Java 1.8 because this library is Java 1.6 compatible. + */ +public interface Function { + B apply(A arg); +} diff --git a/api/src/main/java/io/opencensus/common/Internal.java b/api/src/main/java/io/opencensus/common/Internal.java new file mode 100644 index 00000000..9d540e21 --- /dev/null +++ b/api/src/main/java/io/opencensus/common/Internal.java @@ -0,0 +1,37 @@ +/* + * Copyright 2017, Google Inc. + * 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.common; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotates a program element (class, method, package etc) which is internal to opencensus, not + * part of the public API, and should not be used by users of the opencensus library. + */ +@Internal +@Retention(RetentionPolicy.SOURCE) +@Target({ + ElementType.ANNOTATION_TYPE, + ElementType.CONSTRUCTOR, + ElementType.FIELD, + ElementType.METHOD, + ElementType.PACKAGE, + ElementType.TYPE +}) +@Documented +public @interface Internal {} diff --git a/api/src/main/java/io/opencensus/common/NonThrowingCloseable.java b/api/src/main/java/io/opencensus/common/NonThrowingCloseable.java new file mode 100644 index 00000000..1dac89f8 --- /dev/null +++ b/api/src/main/java/io/opencensus/common/NonThrowingCloseable.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017, Google Inc. + * 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.common; + +import java.io.Closeable; + +/** + * An {@link Closeable} which cannot throw a checked exception. + * + *

This is useful because such a reversion otherwise requires the caller to catch the + * (impossible) Exception in the try-with-resources. + * + *

Example of usage: + * + *

+ *   try (NonThrowingAutoCloseable ctx = tryEnter()) {
+ *     ...
+ *   }
+ * 
+ */ +public interface NonThrowingCloseable extends Closeable { + @Override + void close(); +} diff --git a/api/src/main/java/io/opencensus/common/Timestamp.java b/api/src/main/java/io/opencensus/common/Timestamp.java new file mode 100644 index 00000000..34c4c851 --- /dev/null +++ b/api/src/main/java/io/opencensus/common/Timestamp.java @@ -0,0 +1,146 @@ +/* + * Copyright 2016, Google Inc. + * 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.common; + +import javax.annotation.concurrent.Immutable; + +/** + * A representation of an instant in time. The instant is the number of nanoseconds after the number + * of seconds since the Unix Epoch. + * + *

Use {@code Tracing.getClock().now()} to get the current timestamp since epoch + * (1970-01-01T00:00:00Z). + */ +@Immutable +public final class Timestamp { + private static final long MAX_SECONDS = 315576000000L; + private static final int MAX_NANOS = 999999999; + private static final long NUM_MILLIS_PER_SECOND = 1000L; + private static final int NUM_NANOS_PER_MILLI = 1000 * 1000; + private static final long NUM_NANOS_PER_SECOND = NUM_NANOS_PER_MILLI * NUM_MILLIS_PER_SECOND; + private final long seconds; + private final int nanos; + + private Timestamp(long seconds, int nanos) { + this.seconds = seconds; + this.nanos = nanos; + } + + // TODO(bdrutu): Make create and fromMillis package-protected. + + /** + * Creates a new timestamp from given seconds and nanoseconds. + * + * @param seconds Represents seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z. Must be + * from from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive. + * @param nanos Non-negative fractions of a second at nanosecond resolution. Negative second + * values with fractions must still have non-negative nanos values that count forward in time. + * Must be from 0 to 999,999,999 inclusive. + * @return new {@link Timestamp} with specified fields. For invalid inputs, a {@link Timestamp} of + * zero is returned. + */ + public static Timestamp create(long seconds, int nanos) { + if (seconds < -MAX_SECONDS || seconds > MAX_SECONDS) { + return new Timestamp(0, 0); + } + if (nanos < 0 || nanos > MAX_NANOS) { + return new Timestamp(0, 0); + } + return new Timestamp(seconds, nanos); + } + + /** + * Creates a new timestamp from the given milliseconds. + * + * @return a new timestamp from the given milliseconds. + */ + public static Timestamp fromMillis(long millis) { + long seconds = millis / NUM_MILLIS_PER_SECOND; + int nanos = (int) (millis % NUM_MILLIS_PER_SECOND) * NUM_NANOS_PER_MILLI; + if (nanos < 0) { + return new Timestamp(seconds - 1, (int) (nanos + NUM_NANOS_PER_SECOND)); + } else { + return new Timestamp(seconds, nanos); + } + } + + /** + * Returns the number of seconds since the Unix Epoch represented by this timestamp. + * + * @return the number of seconds since the Unix Epoch. + */ + public long getSeconds() { + return seconds; + } + + /** + * Returns the number of nanoseconds after the number of seconds since the Unix Epoch represented + * by this timestamp. + * + * @return the number of nanoseconds after the number of seconds since the Unix Epoch. + */ + public int getNanos() { + return nanos; + } + + /** + * Returns a {@code Timestamp} calculated as this {@code Timestamp} plus some number of + * nanoseconds. + * + * @param nanos the nanoseconds to be added to the current timestamp. + * @return a {@code Timestamp} calculated as this {@code Timestamp} plus some number of + * nanoseconds. + */ + public Timestamp addNanos(long nanos) { + long newSeconds = seconds + nanos / NUM_NANOS_PER_SECOND; + nanos %= NUM_NANOS_PER_SECOND; + // Cannot overflow because: abs(nanos) < NUM_NANOS_PER_SECOND AND + // this.nanos < NUM_NANOS_PER_SECOND. + long newNanos = nanos + this.nanos; + newSeconds += (newNanos / NUM_NANOS_PER_SECOND); + newNanos %= NUM_NANOS_PER_SECOND; + if (newNanos >= 0) { + return Timestamp.create(newSeconds, (int) newNanos); + } else { + return Timestamp.create(newSeconds - 1, (int) (newNanos + NUM_NANOS_PER_SECOND)); + } + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof Timestamp)) { + return false; + } + + Timestamp that = (Timestamp) obj; + return seconds == that.seconds && nanos == that.nanos; + } + + @Override + public int hashCode() { + int result = 17; + result = 31 * result + (int) (seconds ^ (seconds >>> 32)); + result = 31 * result + nanos; + return result; + } + + @Override + public String toString() { + return "Timestamp<" + seconds + "," + nanos + ">"; + } +} diff --git a/api/src/main/java/io/opencensus/internal/Provider.java b/api/src/main/java/io/opencensus/internal/Provider.java new file mode 100644 index 00000000..148b6c38 --- /dev/null +++ b/api/src/main/java/io/opencensus/internal/Provider.java @@ -0,0 +1,99 @@ +/* + * Copyright 2016, Google Inc. + * 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.internal; + +import java.util.ServiceConfigurationError; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; + +/** + * Instrumentation specific service provider mechanism. + * + *

{@code
+ * // Initialize a static variable using reflection.
+ * static final Foo foo = Provider.newInstance("Foo", new NoopFoo());
+ * }
+ */ +public final class Provider { + private static final Logger logger = Logger.getLogger(Provider.class.getName()); + + /** + * Returns a new instance of the class specified with {@code name} by invoking the empty-argument + * constructor via reflections. If the specified class is not found, the {@code defaultValue} is + * returned. + */ + @SuppressWarnings("unchecked") + @Nullable + public static T newInstance(String name, @Nullable T defaultValue) { + try { + Class provider = Class.forName(name); + T result = (T) provider.getConstructor().newInstance(); + logger.fine("Loaded: " + name); + return result; + } catch (ClassNotFoundException e) { + logger.log(Level.FINE, "Falling back to " + defaultValue, e); + return defaultValue; + } catch (Exception e) { + if (e instanceof RuntimeException) { + throw (RuntimeException) e; + } else { + throw new RuntimeException(e); + } + } + } + + /** + * Tries to create an instance of the given rawClass as a subclass of the given superclass. + * + * @param rawClass The class that is initialized. + * @param superclass The initialized class must be a subclass of this. + * @return an instance of the class given rawClass which is a subclass of the given superclass. + * @throws ServiceConfigurationError if any error happens. + */ + public static T createInstance(Class rawClass, Class superclass) { + try { + return rawClass.asSubclass(superclass).getConstructor().newInstance(); + } catch (Exception e) { + throw new ServiceConfigurationError( + "Provider " + rawClass.getName() + " could not be instantiated.", e); + } + } + + /** + * Get the correct {@link ClassLoader} that must be used when loading using reflection. + * + * @return The correct {@code ClassLoader} that must be used when loading using reflection. + */ + public static ClassLoader getCorrectClassLoader(Class superClass) { + if (isAndroid()) { + // When android:sharedUserId or android:process is used, Android will setup a dummy + // ClassLoader for the thread context (http://stackoverflow.com/questions/13407006), + // instead of letting users to manually set context class loader, we choose the + // correct class loader here. + return superClass.getClassLoader(); + } + return Thread.currentThread().getContextClassLoader(); + } + + private static boolean isAndroid() { + try { + Class.forName("android.app.Application", /*initialize=*/ false, null); + return true; + } catch (Exception e) { + // If Application isn't loaded, it might as well not be Android. + return false; + } + } +} diff --git a/api/src/main/java/io/opencensus/internal/StringUtil.java b/api/src/main/java/io/opencensus/internal/StringUtil.java new file mode 100644 index 00000000..48992ebd --- /dev/null +++ b/api/src/main/java/io/opencensus/internal/StringUtil.java @@ -0,0 +1,74 @@ +/* + * Copyright 2016, Google Inc. + * 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.internal; + +/** Internal utility methods for working with tag keys, tag values, and metric names. */ +public final class StringUtil { + + public static final int MAX_LENGTH = 255; + public static final char UNPRINTABLE_CHAR_SUBSTITUTE = '_'; + + /** + * Transforms the given {@code String} into a valid tag key, tag value, or metric name. This + * method replaces non-printable characters with underscores and truncates to {@link + * StringUtil#MAX_LENGTH}. + * + * @param str the {@code String} to be sanitized. + * @return the {@code String} with all non-printable characters replaced by underscores, truncated + * to {@code MAX_LENGTH}. + */ + public static String sanitize(String str) { + if (str.length() > MAX_LENGTH) { + str = str.substring(0, MAX_LENGTH); + } + if (isPrintableString(str)) { + return str; + } + StringBuilder builder = new StringBuilder(str.length()); + for (int i = 0; i < str.length(); i++) { + char ch = str.charAt(i); + builder.append(isPrintableChar(ch) ? ch : UNPRINTABLE_CHAR_SUBSTITUTE); + } + return builder.toString(); + } + + /** + * Determines whether the {@code String} is a valid tag key, tag value, or metric name. + * + * @param string the {@code String} to be validated. + * @return whether the {@code String} is valid. + * @see #sanitize(String) + */ + public static boolean isValid(String string) { + return string.length() <= MAX_LENGTH && isPrintableString(string); + } + + private static boolean isPrintableString(String str) { + for (int i = 0; i < str.length(); i++) { + if (!isPrintableChar(str.charAt(i))) { + return false; + } + } + return true; + } + + private static boolean isPrintableChar(char ch) { + return ch >= ' ' && ch <= '~'; + } + + // Visible for testing + StringUtil() { + throw new AssertionError(); + } +} diff --git a/api/src/main/java/io/opencensus/internal/TestClock.java b/api/src/main/java/io/opencensus/internal/TestClock.java new file mode 100644 index 00000000..d181da3a --- /dev/null +++ b/api/src/main/java/io/opencensus/internal/TestClock.java @@ -0,0 +1,99 @@ +/* + * Copyright 2017, Google Inc. + * 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.internal; + +import com.google.common.math.LongMath; +import io.opencensus.common.Clock; +import io.opencensus.common.Duration; +import io.opencensus.common.Timestamp; +import javax.annotation.concurrent.GuardedBy; +import javax.annotation.concurrent.ThreadSafe; + +/** A {@link Clock} that allows the time to be set for testing. */ +@ThreadSafe +public final class TestClock extends Clock { + private static final int NUM_NANOS_PER_SECOND = 1000 * 1000 * 1000; + + @GuardedBy("this") + private Timestamp currentTime = validateNanos(Timestamp.create(1493419949, 223123456)); + + private TestClock() {} + + /** + * Creates a clock initialized to a constant non-zero time. {@code Timestamp.create(0, 0)} is not + * a good default, because it represents an invalid time. + * + * @return a clock initialized to a constant non-zero time. + */ + public static TestClock create() { + return new TestClock(); + } + + /** + * Creates a clock with the given time. + * + * @param time the initial time. + * @return a new {@code TestClock} with the given time. + */ + public static TestClock create(Timestamp time) { + TestClock clock = new TestClock(); + clock.setTime(time); + return clock; + } + + /** + * Sets the time. + * + * @param time the new time. + */ + public synchronized void setTime(Timestamp time) { + currentTime = validateNanos(time); + } + + /** + * Advances the time by a duration. + * + * @param duration the increase in time. + */ + // TODO(sebright): Consider adding an 'addDuration' method to Timestamp. + public synchronized void advanceTime(Duration duration) { + currentTime = + validateNanos( + Timestamp.create( + LongMath.checkedAdd(currentTime.getSeconds(), duration.getSeconds()), + currentTime.getNanos()) + .addNanos(duration.getNanos())); + } + + @Override + public synchronized Timestamp now() { + return currentTime; + } + + @Override + public synchronized long nowNanos() { + return getNanos(currentTime); + } + + private static Timestamp validateNanos(Timestamp time) { + getNanos(time); + return time; + } + + // Converts Timestamp into nanoseconds since time 0 and throws an exception if it overflows. + private static long getNanos(Timestamp time) { + return LongMath.checkedAdd( + LongMath.checkedMultiply(time.getSeconds(), NUM_NANOS_PER_SECOND), time.getNanos()); + } +} diff --git a/api/src/main/java/io/opencensus/internal/ZeroTimeClock.java b/api/src/main/java/io/opencensus/internal/ZeroTimeClock.java new file mode 100644 index 00000000..022f02fe --- /dev/null +++ b/api/src/main/java/io/opencensus/internal/ZeroTimeClock.java @@ -0,0 +1,46 @@ +/* + * Copyright 2017, Google Inc. + * 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.internal; + +import io.opencensus.common.Clock; +import io.opencensus.common.Timestamp; +import javax.annotation.concurrent.Immutable; + +/** A {@link Clock} that always returns 0. */ +@Immutable +public final class ZeroTimeClock extends Clock { + private static final ZeroTimeClock INSTANCE = new ZeroTimeClock(); + private static final Timestamp ZERO_TIMESTAMP = Timestamp.create(0, 0); + + private ZeroTimeClock() {} + + /** + * Returns a {@code ZeroTimeClock}. + * + * @return a {@code ZeroTimeClock}. + */ + public static ZeroTimeClock getInstance() { + return INSTANCE; + } + + @Override + public Timestamp now() { + return ZERO_TIMESTAMP; + } + + @Override + public long nowNanos() { + return 0; + } +} diff --git a/api/src/main/java/io/opencensus/internal/package-info.java b/api/src/main/java/io/opencensus/internal/package-info.java new file mode 100644 index 00000000..5fe0010d --- /dev/null +++ b/api/src/main/java/io/opencensus/internal/package-info.java @@ -0,0 +1,21 @@ +/* + * Copyright 2017, Google Inc. + * 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. + */ + +/** + * Interfaces and implementations that are internal to opencensus. + * + *

All the content under this package and its subpackages are considered annotated with {@link + * io.opencensus.common.Internal}. + */ +@io.opencensus.common.Internal +package io.opencensus.internal; diff --git a/api/src/main/java/io/opencensus/tags/TagKey.java b/api/src/main/java/io/opencensus/tags/TagKey.java new file mode 100644 index 00000000..970ee925 --- /dev/null +++ b/api/src/main/java/io/opencensus/tags/TagKey.java @@ -0,0 +1,104 @@ +/* + * Copyright 2017, Google Inc. + * 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.tags; + +import static com.google.common.base.Preconditions.checkArgument; +import static io.opencensus.tags.TagKey.TagType.TAG_BOOLEAN; +import static io.opencensus.tags.TagKey.TagType.TAG_LONG; +import static io.opencensus.tags.TagKey.TagType.TAG_STRING; + +import com.google.auto.value.AutoValue; +import io.opencensus.internal.StringUtil; +import javax.annotation.concurrent.Immutable; + +/** + * A key to a value stored in a {@link TagMap}. + * + * @param The type of value that can be paired with this {@code TagKey}. {@code TagKey}s + * can only be instantiated with types {@code String}, {@code Long}, and {@code Boolean}. + */ +@Immutable +@AutoValue +public abstract class TagKey { + /** The maximum length for a tag key name. */ + public static final int MAX_LENGTH = StringUtil.MAX_LENGTH; + + enum TagType { + TAG_STRING, + TAG_LONG, + TAG_BOOLEAN + } + + TagKey() {} + + /** + * Constructs a {@code TagKey} with the given name. + * + *

The name must meet the following requirements: + * + *

    + *
  1. It cannot be longer than {@link #MAX_LENGTH}. + *
  2. It can only contain printable ASCII characters. + *
+ * + * @param name the name of the key. + * @throws IllegalArgumentException if the name is not valid. + */ + public static TagKey createStringKey(String name) { + checkArgument(StringUtil.isValid(name)); + return new AutoValue_TagKey(name, TAG_STRING); + } + + /** + * Constructs a {@code TagKey} with the given name. + * + *

The name must meet the following requirements: + * + *

    + *
  1. It cannot be longer than {@link #MAX_LENGTH}. + *
  2. It can only contain printable ASCII characters. + *
+ * + * @param name the name of the key. + * @throws IllegalArgumentException if the name is not valid. + */ + // TODO(sebright): Make this public once we support types other than String. + static TagKey createLongKey(String name) { + checkArgument(StringUtil.isValid(name)); + return new AutoValue_TagKey(name, TAG_LONG); + } + + /** + * Constructs a {@code TagKey} with the given name. + * + *

The name must meet the following requirements: + * + *

    + *
  1. It cannot be longer than {@link #MAX_LENGTH}. + *
  2. It can only contain printable ASCII characters. + *
+ * + * @param name the name of the key. + * @throws IllegalArgumentException if the name is not valid. + */ + // TODO(sebright): Make this public once we support types other than String. + static TagKey createBooleanKey(String name) { + checkArgument(StringUtil.isValid(name)); + return new AutoValue_TagKey(name, TAG_BOOLEAN); + } + + abstract String getName(); + + abstract TagType getTagType(); +} diff --git a/api/src/main/java/io/opencensus/tags/TagMap.java b/api/src/main/java/io/opencensus/tags/TagMap.java new file mode 100644 index 00000000..8edbda0d --- /dev/null +++ b/api/src/main/java/io/opencensus/tags/TagMap.java @@ -0,0 +1,141 @@ +/* + * Copyright 2017, Google Inc. + * 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.tags; + +import static com.google.common.base.Preconditions.checkArgument; + +import io.opencensus.internal.StringUtil; +import io.opencensus.tags.TagKey.TagType; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.concurrent.Immutable; + +/** + * A map from keys to values that can be used to label anything that is associated with a specific + * operation. + * + *

For example, {@code TagMap}s can be used to label stats, log messages, or debugging + * information. + */ +@Immutable +public final class TagMap { + /** The maximum length for a string tag value. */ + public static final int MAX_STRING_LENGTH = StringUtil.MAX_LENGTH; + + // The types of the TagKey and value must match for each entry. + private final Map, Object> tags; + + TagMap(Map, Object> tags) { + this.tags = Collections.unmodifiableMap(new HashMap, Object>(tags)); + } + + Map, Object> getTags() { + return tags; + } + + /** + * Returns a builder based on this {@code TagMap}. + * + * @return a builder based on this {@code TagMap}. + */ + public Builder toBuilder() { + return new Builder(getTags()); + } + + /** Builder for the {@link TagMap} class. */ + public static final class Builder { + private final Map, Object> tags; + + private Builder(Map, Object> tags) { + this.tags = new HashMap, Object>(tags); + } + + Builder() { + this.tags = new HashMap, Object>(); + } + + /** + * Adds the key/value pair regardless of whether the key is present. + * + * @param key the {@code TagKey} which will be set. + * @param value the value to set for the given key. + * @return this + * @throws IllegalArgumentException if either argument is null, the key is the wrong type, or + * the value contains unprintable characters or is longer than {@link + * TagMap#MAX_STRING_LENGTH}. + */ + public Builder set(TagKey key, String value) { + checkArgument(key.getTagType() == TagType.TAG_STRING); + + // TODO(sebright): Consider adding a TagValue class to avoid validating the String every time + // it is set. + checkArgument(StringUtil.isValid(value)); + return setInternal(key, value); + } + + /** + * Adds the key/value pair regardless of whether the key is present. + * + * @param key the {@code TagKey} which will be set. + * @param value the value to set for the given key. + * @return this + * @throws IllegalArgumentException if the key is null or the key is the wrong type. + */ + // TODO(sebright): Make this public once we support types other than String. + Builder set(TagKey key, long value) { + checkArgument(key.getTagType() == TagType.TAG_LONG); + return setInternal(key, value); + } + + /** + * Adds the key/value pair regardless of whether the key is present. + * + * @param key the {@code TagKey} which will be set. + * @param value the value to set for the given key. + * @return this + * @throws IllegalArgumentException if the key is null or the key is the wrong type. + */ + // TODO(sebright): Make this public once we support types other than String. + Builder set(TagKey key, boolean value) { + checkArgument(key.getTagType() == TagType.TAG_BOOLEAN); + return setInternal(key, value); + } + + private Builder setInternal(TagKey key, TagValueT value) { + tags.put(key, value); + return this; + } + + /** + * Removes the key if it exists. + * + * @param key the {@code TagKey} which will be cleared. + * @return this + */ + public Builder clear(TagKey key) { + tags.remove(key); + return this; + } + + /** + * Creates a {@code TagMap} from this builder. + * + * @return a {@code TagMap} with the same tags as this builder. + */ + public TagMap build() { + return new TagMap(new HashMap, Object>(tags)); + } + } +} diff --git a/api/src/main/java/io/opencensus/trace/Annotation.java b/api/src/main/java/io/opencensus/trace/Annotation.java new file mode 100644 index 00000000..f72070e8 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/Annotation.java @@ -0,0 +1,73 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.concurrent.Immutable; + +/** A text annotation with a set of attributes. */ +@Immutable +@AutoValue +public abstract class Annotation { + private static final Map EMPTY_ATTRIBUTES = + Collections.unmodifiableMap(Collections.emptyMap()); + + /** + * Returns a new {@code Annotation} with the given description. + * + * @param description the text description of the {@code Annotation}. + * @return a new {@code Annotation} with the given description. + * @throws NullPointerException if {@code description} is {@code null}. + */ + public static Annotation fromDescription(String description) { + return new AutoValue_Annotation(description, EMPTY_ATTRIBUTES); + } + + /** + * Returns a new {@code Annotation} with the given description and set of attributes. + * + * @param description the text description of the {@code Annotation}. + * @param attributes the attributes of the {@code Annotation}. + * @return a new {@code Annotation} with the given description and set of attributes. + * @throws NullPointerException if {@code description} or {@code attributes} are {@code null}. + */ + public static Annotation fromDescriptionAndAttributes( + String description, Map attributes) { + return new AutoValue_Annotation( + description, + Collections.unmodifiableMap( + new HashMap(checkNotNull(attributes, "attributes")))); + } + + /** + * Return the description of the {@code Annotation}. + * + * @return the description of the {@code Annotation}. + */ + public abstract String getDescription(); + + /** + * Return the attributes of the {@code Annotation}. + * + * @return the attributes of the {@code Annotation}. + */ + public abstract Map getAttributes(); + + Annotation() {} +} diff --git a/api/src/main/java/io/opencensus/trace/AttributeValue.java b/api/src/main/java/io/opencensus/trace/AttributeValue.java new file mode 100644 index 00000000..f66fd425 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/AttributeValue.java @@ -0,0 +1,91 @@ +/* + * Copyright 2016, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * A class that represents all the possible values for an attribute. An attribute can have 3 types + * of values: {@code String}, {@code Boolean} or {@code Long}. + */ +@Immutable +@AutoValue +public abstract class AttributeValue { + /** + * Returns an {@code AttributeValue} with a string value. + * + * @param stringValue The new value. + * @return an {@code AttributeValue} with a string value. + * @throws NullPointerException if {@code stringValue} is {@code null}. + */ + public static AttributeValue stringAttributeValue(String stringValue) { + return new AutoValue_AttributeValue(checkNotNull(stringValue, "stringValue"), null, null); + } + + /** + * Returns an {@code AttributeValue} with a boolean value. + * + * @param booleanValue The new value. + * @return an {@code AttributeValue} with a boolean value. + */ + public static AttributeValue booleanAttributeValue(boolean booleanValue) { + return new AutoValue_AttributeValue(null, booleanValue, null); + } + + /** + * Returns an {@code AttributeValue} with a long value. + * + * @param longValue The new value. + * @return an {@code AttributeValue} with a long value. + */ + public static AttributeValue longAttributeValue(long longValue) { + return new AutoValue_AttributeValue(null, null, longValue); + } + + AttributeValue() {} + + /** + * Returns the {@code String} value if this is a string {@code AttributeValue}, otherwise {@code + * null}. + * + * @return the {@code String} value if this is a string {@code AttributeValue}, otherwise {@code + * null}. + */ + @Nullable + public abstract String getStringValue(); + + /** + * Returns the {@code Boolean} value if this is a boolean {@code AttributeValue}, otherwise {@code + * null}. + * + * @return the {@code Boolean} value if this is a boolean {@code AttributeValue}, otherwise {@code + * null}. + */ + @Nullable + public abstract Boolean getBooleanValue(); + + /** + * Returns the {@code Long} value if this is a long {@code AttributeValue}, otherwise {@code + * null}. + * + * @return the {@code Long} value if this is a long {@code AttributeValue}, otherwise {@code + * null}. + */ + @Nullable + public abstract Long getLongValue(); +} diff --git a/api/src/main/java/io/opencensus/trace/BinaryPropagationHandler.java b/api/src/main/java/io/opencensus/trace/BinaryPropagationHandler.java new file mode 100644 index 00000000..bc86dd7f --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/BinaryPropagationHandler.java @@ -0,0 +1,108 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.text.ParseException; + +/** + * This is a helper class for {@link SpanContext} propagation on the wire using binary encoding. + * + *

Example of usage on the client: + * + *

{@code
+ * private static final Tracer tracer = Tracing.getTracer();
+ * private static final BinaryPropagationHandler binaryPropagationHandler =
+ *     Tracing.getBinaryPropagationHandler();
+ * void onSendRequest() {
+ *   try (NonThrowingCloseable ss = tracer.spanBuilder("Sent.MyRequest").startScopedSpan()) {
+ *     byte[] binaryValue = binaryPropagationHandler.toBinaryValue(
+ *         tracer.getCurrentContext().context());
+ *     // Send the request including the binaryValue and wait for the response.
+ *   }
+ * }
+ * }
+ * + *

Example of usage on the server: + * + *

{@code
+ * private static final Tracer tracer = Tracing.getTracer();
+ * private static final BinaryPropagationHandler binaryPropagationHandler =
+ *     Tracing.getBinaryPropagationHandler();
+ * void onRequestReceived() {
+ *   // Get the binaryValue from the request.
+ *   SpanContext spanContext = SpanContext.INVALID;
+ *   try {
+ *     if (binaryValue != null) {
+ *       spanContext = binaryPropagationHandler.fromBinaryValue(binaryValue);
+ *     }
+ *   } catch (ParseException e) {
+ *     // Maybe log the exception.
+ *   }
+ *   try (NonThrowingCloseable ss =
+ *            tracer.spanBuilderWithRemoteParent(spanContext, "Recv.MyRequest").startScopedSpan()) {
+ *     // Handle request and send response back.
+ *   }
+ * }
+ * }
+ */ +public abstract class BinaryPropagationHandler { + static final NoopBinaryPropagationHandler noopBinaryPropagationHandler = + new NoopBinaryPropagationHandler(); + + /** + * Serializes a {@link SpanContext} using the binary format. + * + * @param spanContext the {@code SpanContext} to serialize. + * @return the serialized binary value. + * @throws NullPointerException if the {@code spanContext} is {@code null}. + */ + public abstract byte[] toBinaryValue(SpanContext spanContext); + + /** + * Parses the {@link SpanContext} from the binary format. + * + * @param bytes a binary encoded buffer from which the {@code SpanContext} will be parsed. + * @return the parsed {@code SpanContext}. + * @throws NullPointerException if the {@code input} is {@code null}. + * @throws ParseException if the version is not supported or the input is invalid + */ + public abstract SpanContext fromBinaryValue(byte[] bytes) throws ParseException; + + /** + * Returns the no-op implementation of the {@code BinaryPropagationHandler}. + * + * @return the no-op implementation of the {@code BinaryPropagationHandler}. + */ + static BinaryPropagationHandler getNoopBinaryPropagationHandler() { + return noopBinaryPropagationHandler; + } + + private static final class NoopBinaryPropagationHandler extends BinaryPropagationHandler { + @Override + public byte[] toBinaryValue(SpanContext spanContext) { + checkNotNull(spanContext, "spanContext"); + return new byte[0]; + } + + @Override + public SpanContext fromBinaryValue(byte[] bytes) throws ParseException { + checkNotNull(bytes, "bytes"); + return SpanContext.INVALID; + } + + private NoopBinaryPropagationHandler() {} + } +} diff --git a/api/src/main/java/io/opencensus/trace/BlankSpan.java b/api/src/main/java/io/opencensus/trace/BlankSpan.java new file mode 100644 index 00000000..40e49551 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/BlankSpan.java @@ -0,0 +1,62 @@ +/* + * Copyright 2016, Google Inc. + * 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; + +import java.util.Map; +import javax.annotation.concurrent.Immutable; + +/** + * The {@code BlankSpan} is a singleton class, which is the default {@link Span} that is used when + * no {@code Span} implementation is available. All operations are no-op. + * + *

Used also to stop tracing, see {@link Tracer#withSpan}. + */ +@Immutable +public final class BlankSpan extends Span { + /** Singleton instance of this class. */ + public static final BlankSpan INSTANCE = new BlankSpan(); + + private BlankSpan() { + super(SpanContext.INVALID, null); + } + + /** No-op implementation of the {@link Span#addAttributes(Map)} method. */ + @Override + public void addAttributes(Map attributes) {} + + /** No-op implementation of the {@link Span#addAnnotation(String, Map)} method. */ + @Override + public void addAnnotation(String description, Map attributes) {} + + /** No-op implementation of the {@link Span#addAnnotation(Annotation)} method. */ + @Override + public void addAnnotation(Annotation annotation) {} + + /** No-op implementation of the {@link Span#addNetworkEvent(NetworkEvent)} method. */ + @Override + public void addNetworkEvent(NetworkEvent networkEvent) {} + + /** No-op implementation of the {@link Span#addLink(Link)} method. */ + @Override + public void addLink(Link link) {} + + /** No-op implementation of the {@link Span#end(EndSpanOptions)} method. */ + @Override + public void end(EndSpanOptions options) {} + + @Override + public String toString() { + return "BlankSpan"; + } +} diff --git a/api/src/main/java/io/opencensus/trace/ContextUtils.java b/api/src/main/java/io/opencensus/trace/ContextUtils.java new file mode 100644 index 00000000..c5331563 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/ContextUtils.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import io.grpc.Context; +import io.opencensus.common.NonThrowingCloseable; + +/** + * Util methods/functionality to interact with the {@link io.grpc.Context}. + * + *

Users must interact with the current Context via the public APIs in {@link Tracer} and avoid + * usages of the {@link #CONTEXT_SPAN_KEY} directly. + */ +public final class ContextUtils { + /** The {@link io.grpc.Context.Key} used to interact with {@link io.grpc.Context}. */ + public static final Context.Key CONTEXT_SPAN_KEY = Context.key("instrumentation-trace-key"); + + // No instance of this class. + private ContextUtils() {} + + /** + * Returns The {@link Span} from the current context. + * + * @return The {@code Span} from the current context. + */ + static Span getCurrentSpan() { + return CONTEXT_SPAN_KEY.get(Context.current()); + } + + /** + * Enters the scope of code where the given {@link Span} is in the current context, and returns an + * object that represents that scope. The scope is exited when the returned object is closed. + * + *

Supports try-with-resource idiom. + * + * @param span The {@code Span} to be set to the current context. + * @return An object that defines a scope where the given {@code Span} is set to the current + * context. + */ + static NonThrowingCloseable withSpan(Span span) { + return new WithSpan(span, CONTEXT_SPAN_KEY); + } + + // Defines an arbitrary scope of code as a traceable operation. Supports try-with-resources idiom. + private static final class WithSpan implements NonThrowingCloseable { + private final Context origContext; + + /** + * Constructs a new {@link WithSpan}. + * + * @param span is the {@code Span} to be added to the current {@code io.grpc.Context}. + * @param contextKey is the {@code Context.Key} used to set/get {@code Span} from the {@code + * Context}. + */ + WithSpan(Span span, Context.Key contextKey) { + origContext = Context.current().withValue(contextKey, span).attach(); + } + + @Override + public void close() { + Context.current().detach(origContext); + } + } +} diff --git a/api/src/main/java/io/opencensus/trace/EndSpanOptions.java b/api/src/main/java/io/opencensus/trace/EndSpanOptions.java new file mode 100644 index 00000000..e58a06c3 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/EndSpanOptions.java @@ -0,0 +1,78 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import javax.annotation.concurrent.Immutable; + +/** + * A class that enables overriding the default values used when ending a {@link Span}. Allows + * overriding the {@link Status status}. + */ +@Immutable +@AutoValue +public abstract class EndSpanOptions { + /** The default {@code EndSpanOptions}. */ + public static final EndSpanOptions DEFAULT = builder().build(); + + /** + * Returns a new {@link Builder} with default options. + * + * @return a new {@code Builder} with default options. + */ + public static Builder builder() { + return new AutoValue_EndSpanOptions.Builder().setStatus(Status.OK); + } + + /** + * Returns the status. + * + * @return the status. + */ + public abstract Status getStatus(); + + /** Builder class for {@link EndSpanOptions}. */ + @AutoValue.Builder + public abstract static class Builder { + /** + * Sets the status for the {@link Span}. + * + *

If set, this will override the default {@code Span} status. Default is {@link Status#OK}. + * + * @param status the status. + * @return this. + */ + public abstract Builder setStatus(Status status); + + abstract EndSpanOptions autoBuild(); // not public + + /** + * Builds and returns a {@code EndSpanOptions} with the desired settings. + * + * @return a {@code EndSpanOptions} with the desired settings. + * @throws NullPointerException if {@code status} is {@code null}. + */ + public EndSpanOptions build() { + EndSpanOptions endSpanOptions = autoBuild(); + checkNotNull(endSpanOptions.getStatus(), "status"); + return endSpanOptions; + } + + Builder() {} + } + + EndSpanOptions() {} +} diff --git a/api/src/main/java/io/opencensus/trace/Link.java b/api/src/main/java/io/opencensus/trace/Link.java new file mode 100644 index 00000000..d582b68b --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/Link.java @@ -0,0 +1,72 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import com.google.auto.value.AutoValue; +import javax.annotation.concurrent.Immutable; + +/** + * A link to a {@link Span} from a different trace. + * + *

It requires a {@link Type} which describes the relationship with the linked {@code Span} and + * the identifiers of the linked {@code Span}. + * + *

Used (for example) in batching operations, where a single batch handler processes multiple + * requests from different traces. + */ +@Immutable +@AutoValue +public abstract class Link { + /** The relationship with the linked {@code Span} relative to the current {@code Span}. */ + public enum Type { + /** When the linked {@code Span} is a child of the current {@code Span}. */ + CHILD, + /** When the linked {@code Span} is a parent of the current {@code Span}. */ + PARENT + } + + /** + * Returns a new {@code Link}. + * + * @param context the context of the linked {@code Span}. + * @param type the type of the relationship with the linked {@code Span}. + * @return a new {@code Link}. + */ + public static Link fromSpanContext(SpanContext context, Type type) { + return new AutoValue_Link(context.getTraceId(), context.getSpanId(), type); + } + + /** + * Returns the {@code TraceId}. + * + * @return the {@code TraceId}. + */ + public abstract TraceId getTraceId(); + + /** + * Returns the {@code SpanId}. + * + * @return the {@code SpanId} + */ + public abstract SpanId getSpanId(); + + /** + * Returns the {@code Type}. + * + * @return the {@code Type}. + */ + public abstract Type getType(); + + Link() {} +} diff --git a/api/src/main/java/io/opencensus/trace/NetworkEvent.java b/api/src/main/java/io/opencensus/trace/NetworkEvent.java new file mode 100644 index 00000000..10687074 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/NetworkEvent.java @@ -0,0 +1,124 @@ +/* + * Copyright 2016, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.Timestamp; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * A class that represents a network event. It requires a {@link Type type} and a message id that + * serves to uniquely identify each network message. It can optionally can have information about + * the kernel time and message size. + */ +@Immutable +@AutoValue +public abstract class NetworkEvent { + /** Available types for a {@code NetworkEvent}. */ + public enum Type { + /** When the message was sent. */ + SENT, + /** When the message was received. */ + RECV, + } + + /** + * Returns a new {@link Builder} with default values. + * + * @param type designates whether this is a network send or receive message. + * @param messageId serves to uniquely identify each network message. + * @return a new {@code Builder} with default values. + * @throws NullPointerException if {@code type} is {@code null}. + */ + public static Builder builder(Type type, long messageId) { + return new AutoValue_NetworkEvent.Builder() + .setType(checkNotNull(type, "type")) + .setMessageId(messageId) + // We need to set a value for the message size because the autovalue requires all + // primitives to be initialized. + // TODO(bdrutu): Consider to change the API to require message size. + .setMessageSize(0); + } + + /** + * Returns the kernel timestamp associated with the {@code NetworkEvent} or {@code null} if not + * set. + * + * @return the kernel timestamp associated with the {@code NetworkEvent} or {@code null} if not + * set. + */ + @Nullable + public abstract Timestamp getKernelTimestamp(); + + /** + * Returns the type of the {@code NetworkEvent}. + * + * @return the type of the {@code NetworkEvent}. + */ + public abstract Type getType(); + + /** + * Returns the message id argument that serves to uniquely identify each network message. + * + * @return The message id of the {@code NetworkEvent}. + */ + public abstract long getMessageId(); + + /** + * Returns The message size in bytes of the {@code NetworkEvent}. + * + * @return The message size in bytes of the {@code NetworkEvent}. + */ + public abstract long getMessageSize(); + + /** Builder class for {@link NetworkEvent}. */ + @AutoValue.Builder + public abstract static class Builder { + // Package protected methods because these values are mandatory and set only in the + // NetworkEvent#builder() function. + abstract Builder setType(Type type); + + abstract Builder setMessageId(long messageId); + + /** + * Sets the kernel timestamp. + * + * @param kernelTimestamp The kernel timestamp of the event. + * @return this. + */ + public abstract Builder setKernelTimestamp(@Nullable Timestamp kernelTimestamp); + + /** + * Sets the message size. + * + * @param messageSize represents the size in bytes of this network message. + * @return this. + */ + public abstract Builder setMessageSize(long messageSize); + + /** + * Builds and returns a {@code NetworkEvent} with the desired values. + * + * @return a {@code NetworkEvent} with the desired values. + */ + public abstract NetworkEvent build(); + + Builder() {} + } + + NetworkEvent() {} +} diff --git a/api/src/main/java/io/opencensus/trace/Sampler.java b/api/src/main/java/io/opencensus/trace/Sampler.java new file mode 100644 index 00000000..e5014fa4 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/Sampler.java @@ -0,0 +1,41 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import java.util.List; +import javax.annotation.Nullable; + +/** Sampler is used to make decisions on {@link Span} sampling. */ +public abstract class Sampler { + /** + * Called during {@link Span} creation to make a sampling decision. + * + * @param parentContext The parent {@code Span} {@link SpanContext}. May be {@code null} if this + * is a root span. + * @param remoteParent true if the parentContext is remote. + * @param traceId The {@link TraceId} for the new {@code Span}. This will be identical to that in + * the parentContext, unless this is a root span. + * @param spanId The span ID for the new {@code Span}. + * @param name The name of the new {@code Span}. + * @param parentLinks The parentLinks associated with the new {@code Span}. + * @return {@code true} if the {@code Span} is sampled. + */ + protected abstract boolean shouldSample( + @Nullable SpanContext parentContext, + boolean remoteParent, + TraceId traceId, + SpanId spanId, + String name, + List parentLinks); +} diff --git a/api/src/main/java/io/opencensus/trace/Samplers.java b/api/src/main/java/io/opencensus/trace/Samplers.java new file mode 100644 index 00000000..33c2a006 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/Samplers.java @@ -0,0 +1,166 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.auto.value.AutoValue; +import java.util.List; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** Static class to access a set of pre-defined {@link Sampler Samplers}. */ +public final class Samplers { + private static final Sampler ALWAYS_SAMPLE = new AlwaysSampleSampler(); + private static final Sampler NEVER_SAMPLE = new NeverSampleSampler(); + + // No instance of this class. + private Samplers() {} + + /** + * Returns a {@link Sampler} that always makes a "yes" decision on {@link Span} sampling. + * + * @return a {@code Sampler} that always makes a "yes" decision on {@code Span} sampling. + */ + public static Sampler alwaysSample() { + return ALWAYS_SAMPLE; + } + + /** + * Returns a {@link Sampler} that always makes a "no" decision on {@link Span} sampling. + * + * @return a {@code Sampler} that always makes a "no" decision on {@code Span} sampling. + */ + public static Sampler neverSample() { + return NEVER_SAMPLE; + } + + /** + * Returns a {@link Sampler} that makes a "yes" decision with a given probability. + * + * @param probability The desired probability of sampling. Must be within [0.0, 1.0]. + * @return a {@code Sampler} that makes a "yes" decision with a given probability. + * @throws IllegalArgumentException if {@code probability} is out of range + */ + public static Sampler probabilitySampler(double probability) { + return ProbabilitySampler.create(probability); + } + + @Immutable + private static final class AlwaysSampleSampler extends Sampler { + private AlwaysSampleSampler() {} + + // Returns always makes a "yes" decision on {@link Span} sampling. + @Override + protected boolean shouldSample( + @Nullable SpanContext parentContext, + boolean remoteParent, + TraceId traceId, + SpanId spanId, + String name, + List parentLinks) { + return true; + } + + @Override + public String toString() { + return "AlwaysSampleSampler"; + } + } + + @Immutable + private static final class NeverSampleSampler extends Sampler { + private NeverSampleSampler() {} + + // Returns always makes a "no" decision on {@link Span} sampling. + @Override + protected boolean shouldSample( + @Nullable SpanContext parentContext, + boolean remoteParent, + TraceId traceId, + SpanId spanId, + String name, + List parentLinks) { + return false; + } + + @Override + public String toString() { + return "NeverSampleSampler"; + } + } + + // We assume the lower 64 bits of the traceId's are randomly distributed around the whole (long) + // range. We convert an incoming probability into an upper bound on that value, such that we can + // just compare the absolute value of the id and the bound to see if we are within the desired + // probability range. Using the low bits of the traceId also ensures that systems that only use + // 64 bit ID's will also work with this sampler. + @AutoValue + @Immutable + abstract static class ProbabilitySampler extends Sampler { + ProbabilitySampler() {} + + abstract double getProbability(); + + abstract long getIdUpperBound(); + + /** + * Returns a new {@link ProbabilitySampler}. The probability of sampling a trace is equal to + * that of the specified probability. + * + * @param probability The desired probability of sampling. Must be within [0.0, 1.0]. + * @return a new {@link ProbabilitySampler}. + * @throws IllegalArgumentException if {@code probability} is out of range + */ + private static ProbabilitySampler create(double probability) { + checkArgument( + probability >= 0.0 && probability <= 1.0, "probability must be in range [0.0, 1.0]"); + long idUpperBound = 0; + // Special case the limits, to avoid any possible issues with lack of precision across + // double/long boundaries. For probability == 0.0, we use Long.MIN_VALUE as this guarantees + // that we will never sample a trace, even in the case where the id == Long.MIN_VALUE, since + // Math.Abs(Long.MIN_VALUE) == Long.MIN_VALUE. + if (probability == 0.0) { + idUpperBound = Long.MIN_VALUE; + } else if (probability == 1.0) { + idUpperBound = Long.MAX_VALUE; + } else { + idUpperBound = (long) (probability * Long.MAX_VALUE); + } + return new AutoValue_Samplers_ProbabilitySampler(probability, idUpperBound); + } + + @Override + protected final boolean shouldSample( + @Nullable SpanContext parentContext, + boolean remoteParent, + TraceId traceId, + SpanId spanId, + String name, + @Nullable List parentLinks) { + // Always enable sampling if parent was sampled. + if (parentContext != null && parentContext.getTraceOptions().isSampled()) { + return true; + } + // Always sample if we are within probability range. This is true even for child spans (that + // may have had a different sampling decision made) to allow for different sampling policies, + // and dynamic increases to sampling probabilities for debugging purposes. + // Note use of '<' for comparison. This ensures that we never sample for probability == 0.0, + // while allowing for a (very) small chance of *not* sampling if the id == Long.MAX_VALUE. + // This is considered a reasonable tradeoff for the simplicity/performance requirements (this + // code is executed in-line for every Span creation). + return Math.abs(traceId.getLowerLong()) < getIdUpperBound(); + } + } +} diff --git a/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java b/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java new file mode 100644 index 00000000..965c4d98 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java @@ -0,0 +1,47 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import io.opencensus.common.NonThrowingCloseable; + +/** + * Defines a scope of code where the given {@link Span} is in the current context. The scope is + * exited when the object is closed and the previous context is restored. When the scope exits the + * given {@code Span} will be ended using {@link Span#end}. + * + *

Supports try-with-resource idiom. + */ +final class ScopedSpanHandle implements NonThrowingCloseable { + private final Span span; + private final NonThrowingCloseable withSpan; + + /** + * Creates a {@code ScopedSpanHandle} + * + * @param span The span that will be installed in the current context. + */ + ScopedSpanHandle(Span span) { + this.span = span; + this.withSpan = ContextUtils.withSpan(span); + } + + /** + * Uninstalls the {@code Span} from the current context and ends it by calling {@link Span#end()}. + */ + @Override + public void close() { + withSpan.close(); + span.end(); + } +} diff --git a/api/src/main/java/io/opencensus/trace/Span.java b/api/src/main/java/io/opencensus/trace/Span.java new file mode 100644 index 00000000..76dcd9c7 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/Span.java @@ -0,0 +1,165 @@ +/* + * Copyright 2016, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Collections; +import java.util.EnumSet; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +/** + * An abstract class that represents a span. It has an associated {@link SpanContext} and a set of + * {@link Options}. + * + *

Spans are created by the {@link SpanBuilder#startSpan} method. + * + *

{@code Span} must be ended by calling {@link #end()} or {@link #end(EndSpanOptions)} + */ +public abstract class Span { + private static final Map EMPTY_ATTRIBUTES = Collections.emptyMap(); + + // Contains the identifiers associated with this Span. + private final SpanContext context; + + // Contains the options associated with this Span. This object is immutable. + private final Set options; + + /** + * {@code Span} options. These options are NOT propagated to child spans. These options determine + * features such as whether a {@code Span} should record any annotations or events. + */ + public enum Options { + /** + * This option is set if the Span is part of a sampled distributed trace OR the {@link + * StartSpanOptions#getRecordEvents()} is true. + */ + RECORD_EVENTS; + } + + private static final Set DEFAULT_OPTIONS = + Collections.unmodifiableSet(EnumSet.noneOf(Options.class)); + + /** + * Creates a new {@code Span}. + * + * @param context the context associated with this {@code Span}. + * @param options the options associated with this {@code Span}. If {@code null} then default + * options will be set. + * @throws NullPointerException if context is {@code null}. + * @throws IllegalArgumentException if the {@code SpanContext} is sampled but no RECORD_EVENTS + * options. + */ + protected Span(SpanContext context, @Nullable EnumSet options) { + this.context = checkNotNull(context, "context"); + this.options = + options == null ? DEFAULT_OPTIONS : Collections.unmodifiableSet(EnumSet.copyOf(options)); + checkArgument( + !context.getTraceOptions().isSampled() || (this.options.contains(Options.RECORD_EVENTS)), + "Span is sampled, but does not have RECORD_EVENTS set."); + } + + /** + * Adds a set of attributes to the {@code Span}. + * + * @param attributes the attributes that will be added and associated with the {@code Span}. + */ + public abstract void addAttributes(Map attributes); + + /** + * Adds an annotation to the {@code Span}. + * + * @param description the description of the annotation time event. + */ + public final void addAnnotation(String description) { + addAnnotation(description, EMPTY_ATTRIBUTES); + } + + /** + * Adds an annotation to the {@code Span}. + * + * @param description the description of the annotation time event. + * @param attributes the attributes that will be added; these are associated with this annotation, + * not the {@code Span} as for {@link #addAttributes}. + */ + public abstract void addAnnotation(String description, Map attributes); + + /** + * Adds an annotation to the {@code Span}. + * + * @param annotation the annotations to add. + */ + public abstract void addAnnotation(Annotation annotation); + + /** + * Adds a NetworkEvent to the {@code Span}. + * + *

This function is only intended to be used by RPC systems (either client or server), not by + * higher level applications. + * + * @param networkEvent the network event to add. + */ + public abstract void addNetworkEvent(NetworkEvent networkEvent); + + /** + * Adds a {@link Link} to the {@code Span}. + * + *

Used (for example) in batching operations, where a single batch handler processes multiple + * requests from different traces. + * + * @param link the link to add. + */ + public abstract void addLink(Link link); + + /** + * Marks the end of {@code Span} execution with the given options. + * + *

Only the timing of the first end call for a given {@code Span} will be recorded, and + * implementations are free to ignore all further calls. + * + * @param options the options to be used for the end of the {@code Span}. + */ + public abstract void end(EndSpanOptions options); + + /** + * Marks the end of {@code Span} execution with the default options. + * + *

Only the timing of the first end call for a given {@code Span} will be recorded, and + * implementations are free to ignore all further calls. + */ + public final void end() { + end(EndSpanOptions.DEFAULT); + } + + /** + * Returns the {@code SpanContext} associated with this {@code Span}. + * + * @return the {@code SpanContext} associated with this {@code Span}. + */ + public final SpanContext getContext() { + return context; + } + + /** + * Returns the options associated with this {@code Span}. + * + * @return the options associated with this {@code Span}. + */ + public final Set getOptions() { + return options; + } +} diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java new file mode 100644 index 00000000..4b988dfc --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -0,0 +1,282 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import io.opencensus.common.NonThrowingCloseable; +import java.util.List; +import javax.annotation.Nullable; + +/** + * {@link SpanBuilder} is used to construct {@link Span} instances which define arbitrary scopes of + * code that are sampled for distributed tracing as a single atomic unit. + * + *

This is a simple example where all the work is being done within a single scope and a single + * thread and the Context is automatically propagated: + * + *

{@code
+ * class MyClass {
+ *   private static final Tracer tracer = Tracing.getTracer();
+ *   void doWork {
+ *     // Create a Span as a child of the current Span.
+ *     try (NonThrowingCloseable ss = tracer.spanBuilder("MyChildSpan").startScopedSpan()) {
+ *       tracer.getCurrentSpan().addAnnotation("my annotation");
+ *       doSomeWork();  // Here the new span is in the current Context, so it can be used
+ *                      // implicitly anywhere down the stack.
+ *     }
+ *   }
+ * }
+ * }
+ * + *

There might be cases where you do not perform all the work inside one static scope and the + * Context is automatically propagated: + * + *

{@code
+ * class MyRpcServerInterceptorListener implements RpcServerInterceptor.Listener {
+ *   private static final Tracer tracer = Tracing.getTracer();
+ *   private Span mySpan;
+ *
+ *   public MyRpcInterceptor() {}
+ *
+ *   public void onRequest(String rpcName, Metadata metadata) {
+ *     // Create a Span as a child of the remote Span.
+ *     mySpan = tracer.spanBuilderWithRemoteParent(
+ *         getTraceContextFromMetadata(metadata), rpcName).startSpan();
+ *   }
+ *
+ *   public void onExecuteHandler(ServerCallHandler serverCallHandler) {
+ *     try (NonThrowingCloseable ws = tracer.withSpan(mySpan)) {
+ *       tracer.getCurrentSpan().addAnnotation("Start rpc execution.");
+ *       serverCallHandler.run();  // Here the new span is in the current Context, so it can be
+ *                                 // used implicitly anywhere down the stack.
+ *     }
+ *   }
+ *
+ *   // Called when the RPC is canceled and guaranteed onComplete will not be called.
+ *   public void onCancel() {
+ *     // IMPORTANT: DO NOT forget to ended the Span here as the work is done.
+ *     mySpan.end(EndSpanOptions.builder().setStatus(Status.CANCELLED));
+ *   }
+ *
+ *   // Called when the RPC is done and guaranteed onCancel will not be called.
+ *   public void onComplete(RpcStatus rpcStatus) {
+ *     // IMPORTANT: DO NOT forget to ended the Span here as the work is done.
+ *     mySpan.end(EndSpanOptions.builder().setStatus(rpcStatusToCanonicalTraceStatus(status));
+ *   }
+ * }
+ * }
+ * + *

This is a simple example where all the work is being done within a single scope and the + * Context is manually propagated: + * + *

{@code
+ * class MyClass {
+ *   private static final Tracer tracer = Tracing.getTracer();
+ *   void DoWork() {
+ *     Span span = tracer.spanBuilder(null, "MyRootSpan").startSpan();
+ *     span.addAnnotation("my annotation");
+ *     try {
+ *       doSomeWork(span); // Manually propagate the new span down the stack.
+ *     } finally {
+ *       // To make sure we end the span even in case of an exception.
+ *       span.end();  // Manually end the span.
+ *     }
+ *   }
+ * }
+ * }
+ * + *

If your Java version is less than Java SE 7, see {@link SpanBuilder#startSpan} and {@link + * SpanBuilder#startScopedSpan} for usage examples. + */ +public final class SpanBuilder { + private final SpanFactory spanFactory; + private final String name; + private final StartSpanOptions startSpanOption = new StartSpanOptions(); + private Span parentSpan; + private SpanContext parentSpanContext; + private boolean remoteParent; + + static SpanBuilder builder(SpanFactory spanFactory, Span parentSpan, String name) { + return new SpanBuilder(spanFactory, parentSpan, null, false, name); + } + + static SpanBuilder builderWithRemoteParent( + SpanFactory spanFactory, SpanContext parentSpanContext, String name) { + return new SpanBuilder(spanFactory, null, parentSpanContext, true, name); + } + + /** + * Sets the {@link Sampler} to use. If a {@code null} value is passed, the implementation will + * provide a default. + * + * @param sampler The {@code Sampler} to use when determining sampling for a {@code Span}. + * @return this. + */ + public SpanBuilder setSampler(@Nullable Sampler sampler) { + startSpanOption.setSampler(sampler); + return this; + } + + /** + * Sets the {@code List} of parent links. Links are used to link {@link Span}s in different + * traces. Used (for example) in batching operations, where a single batch handler processes + * multiple requests from different traces. + * + * @param parentLinks New links to be added. + * @return this. + */ + public SpanBuilder setParentLinks(@Nullable List parentLinks) { + startSpanOption.setParentLinks(parentLinks); + return this; + } + + /** + * Sets the option {@link Span.Options#RECORD_EVENTS} for the newly created {@code Span}. If not + * called, the implementation will provide a default. + * + * @param recordEvents New value determining if this {@code Span} should have events recorded. + * @return this. + */ + public SpanBuilder setRecordEvents(boolean recordEvents) { + startSpanOption.setRecordEvents(recordEvents); + return this; + } + + /** + * If called this will force the newly created {@code Span} to be a root span. As a consequence, + * any parent specified (or inherited from the Context) will be ignored (N.B. does not apply to + * linked parents set through {@link #setParentLinks}). + * + *

This is useful when {@link Tracer#spanBuilder(String)} is used and the newly created {@code + * Span} needs to be decoupled from the parent {@code Span}. + * + * @return this. + */ + public SpanBuilder becomeRoot() { + parentSpan = null; + parentSpanContext = null; + remoteParent = false; + return this; + } + + /** + * Starts a new {@link Span}. + * + *

Users must manually call {@link Span#end()} or {@link Span#end(EndSpanOptions)} to + * end this {@code Span}. + * + *

Does not install the newly created {@code Span} to the current Context. + * + *

Example of usage: + * + *

{@code
+   * class MyClass {
+   *   private static final Tracer tracer = Tracing.getTracer();
+   *   void DoWork() {
+   *     Span span = tracer.spanBuilder(null, "MyRootSpan").startSpan();
+   *     span.addAnnotation("my annotation");
+   *     try {
+   *       doSomeWork(span); // Manually propagate the new span down the stack.
+   *     } finally {
+   *       // To make sure we end the span even in case of an exception.
+   *       span.end();  // Manually end the span.
+   *     }
+   *   }
+   * }
+   * }
+ * + * @return the newly created {@code Span}. + */ + public Span startSpan() { + return start(); + } + + // TODO(bdrutu): Add error_prone annotation @MustBeClosed when the 2.0.16 jar is fixed. + /** + * Starts a new new span and sets it as the {@link Tracer#getCurrentSpan current span}. + * + *

Enters the scope of code where the newly created {@code Span} is in the current Context, and + * returns an object that represents that scope. The scope is exited when the returned object is + * closed then the previous Context is restored and the newly created {@code Span} is ended using + * {@link Span#end}. + * + *

Supports try-with-resource idiom. + * + *

Example of usage: + * + *

{@code
+   * class MyClass {
+   *   private static final Tracer tracer = Tracing.getTracer();
+   *   void doWork {
+   *     // Create a Span as a child of the current Span.
+   *     try (NonThrowingCloseable ss = tracer.spanBuilder("MyChildSpan").startScopedSpan()) {
+   *       tracer.getCurrentSpan().addAnnotation("my annotation");
+   *       doSomeWork();  // Here the new span is in the current Context, so it can be used
+   *                      // implicitly anywhere down the stack. Anytime in this closure the span
+   *                      // can be accessed via tracer.getCurrentSpan().
+   *     }
+   *   }
+   * }
+   * }
+ * + *

Prior to Java SE 7, you can use a finally block to ensure that a resource is closed (the + * {@code Span} is ended and removed from the Context) regardless of whether the try statement + * completes normally or abruptly. + * + *

Example of usage prior to Java SE7: + * + *

{@code
+   * class MyClass {
+   *   private static Tracer tracer = Tracing.getTracer();
+   *   void doWork {
+   *     // Create a Span as a child of the current Span.
+   *     NonThrowingCloseable ss = tracer.spanBuilder("MyChildSpan").startScopedSpan();
+   *     try {
+   *       tracer.getCurrentSpan().addAnnotation("my annotation");
+   *       doSomeWork();  // Here the new span is in the current Context, so it can be used
+   *                      // implicitly anywhere down the stack. Anytime in this closure the span
+   *                      // can be accessed via tracer.getCurrentSpan().
+   *     } finally {
+   *       ss.close();
+   *     }
+   *   }
+   * }
+   * }
+ * + * @return an object that defines a scope where the newly created {@code Span} will be set to the + * current Context. + */ + public NonThrowingCloseable startScopedSpan() { + return new ScopedSpanHandle(start()); + } + + private SpanBuilder( + SpanFactory spanFactory, + @Nullable Span parentSpan, + @Nullable SpanContext parentSpanContext, + boolean remoteParent, + String name) { + this.parentSpan = parentSpan; + this.parentSpanContext = parentSpanContext; + this.remoteParent = remoteParent; + this.name = name; + this.spanFactory = spanFactory; + } + + // Utility method to start a Span. + private Span start() { + return remoteParent + ? spanFactory.startSpanWithRemoteParent(parentSpanContext, name, startSpanOption) + : spanFactory.startSpan(parentSpan, name, startSpanOption); + } +} diff --git a/api/src/main/java/io/opencensus/trace/SpanContext.java b/api/src/main/java/io/opencensus/trace/SpanContext.java new file mode 100644 index 00000000..4902f15f --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/SpanContext.java @@ -0,0 +1,118 @@ +/* + * Copyright 2016, Google Inc. + * 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; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Objects; +import javax.annotation.concurrent.Immutable; + +/** + * A class that represents a span context. A span context contains the state that must propagate to + * child {@link Span}s and across process boundaries. It contains the identifiers (a {@link TraceId + * trace_id} and {@link SpanId span_id}) associated with the {@link Span} and a set of {@link + * TraceOptions options}. + */ +@Immutable +public final class SpanContext { + private final TraceId traceId; + private final SpanId spanId; + private final TraceOptions traceOptions; + + /** The invalid {@code SpanContext}. */ + public static final SpanContext INVALID = + new SpanContext(TraceId.INVALID, SpanId.INVALID, TraceOptions.DEFAULT); + + /** + * Creates a new {@code SpanContext} with the given identifiers and options. + * + * @param traceId the trace identifier of the span context. + * @param spanId the span identifier of the span context. + * @param traceOptions the trace options for the span context. + */ + public static SpanContext create(TraceId traceId, SpanId spanId, TraceOptions traceOptions) { + return new SpanContext(traceId, spanId, traceOptions); + } + + /** + * Returns the trace identifier associated with this {@code SpanContext}. + * + * @return the trace identifier associated with this {@code SpanContext}. + */ + public TraceId getTraceId() { + return traceId; + } + + /** + * Returns the span identifier associated with this {@code SpanContext}. + * + * @return the span identifier associated with this {@code SpanContext}. + */ + public SpanId getSpanId() { + return spanId; + } + + /** + * Returns the trace options associated with this {@code SpanContext}. + * + * @return the trace options associated with this {@code SpanContext}. + */ + public TraceOptions getTraceOptions() { + return traceOptions; + } + + /** + * Returns true if this {@code SpanContext} is valid. + * + * @return true if this {@code SpanContext} is valid. + */ + public boolean isValid() { + return traceId.isValid() && spanId.isValid(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof SpanContext)) { + return false; + } + + SpanContext that = (SpanContext) obj; + return traceId.equals(that.traceId) + && spanId.equals(that.spanId) + && traceOptions.equals(that.traceOptions); + } + + @Override + public int hashCode() { + return Objects.hashCode(traceId, spanId, traceOptions); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("traceId", traceId) + .add("spanId", spanId) + .add("traceOptions", traceOptions) + .toString(); + } + + private SpanContext(TraceId traceId, SpanId spanId, TraceOptions traceOptions) { + this.traceId = traceId; + this.spanId = spanId; + this.traceOptions = traceOptions; + } +} diff --git a/api/src/main/java/io/opencensus/trace/SpanData.java b/api/src/main/java/io/opencensus/trace/SpanData.java new file mode 100644 index 00000000..f9a8140f --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/SpanData.java @@ -0,0 +1,308 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.Timestamp; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** Immutable representation of all data collected by the {@link Span} class. */ +@Immutable +@AutoValue +public abstract class SpanData { + + /** + * Returns a new immutable {@code SpanData}. + * + * @param context the {@code SpanContext} of the {@code Span}. + * @param parentSpanId the parent {@code SpanId} of the {@code Span}. {@code null} if the {@code + * Span} is a root. + * @param hasRemoteParent {@code true} if the parent is on a different process. + * @param displayName the name of the {@code Span}. + * @param startTimestamp the start {@code Timestamp} of the {@code Span}. + * @param attributes the attributes associated with the {@code Span}. + * @param annotations the annotations associated with the {@code Span}. + * @param networkEvents the network events associated with the {@code Span}. + * @param links the links associated with the {@code Span}. + * @param status the {@code Status} of the {@code Span}. {@code null} if the {@code Span} is still + * active. + * @param endTimestamp the end {@code Timestamp} of the {@code Span}. {@code null} if the {@code + * Span} is still active. + * @return a new immutable {@code SpanData}. + */ + public static SpanData create( + SpanContext context, + @Nullable SpanId parentSpanId, + boolean hasRemoteParent, + String displayName, + Timestamp startTimestamp, + Attributes attributes, + TimedEvents annotations, + TimedEvents networkEvents, + Links links, + @Nullable Status status, + @Nullable Timestamp endTimestamp) { + return new AutoValue_SpanData( + context, + parentSpanId, + hasRemoteParent, + displayName, + startTimestamp, + attributes, + annotations, + networkEvents, + links, + status, + endTimestamp); + } + + /** + * Returns the {@code SpanContext} associated with this {@code Span}. + * + * @return the {@code SpanContext} associated with this {@code Span}. + */ + public abstract SpanContext getContext(); + + /** + * Returns the parent {@code SpanId} or {@code null} if the {@code Span} is a root {@code Span}. + * + * @return the parent {@code SpanId} or {@code null} if the {@code Span} is a root {@code Span}. + */ + @Nullable + public abstract SpanId getParentSpanId(); + + /** + * Returns {@code true} if the parent is on a different process. + * + * @return {@code true} if the parent is on a different process. + */ + public abstract boolean getHasRemoteParent(); + + /** + * Returns the display name of this {@code Span}. + * + * @return the display name of this {@code Span}. + */ + public abstract String getDisplayName(); + + /** + * Returns the start {@code Timestamp} of this {@code Span}. + * + * @return the start {@code Timestamp} of this {@code Span}. + */ + public abstract Timestamp getStartTimestamp(); + + /** + * Returns the attributes recorded for this {@code Span}. + * + * @return the attributes recorded for this {@code Span}. + */ + public abstract Attributes getAttributes(); + + /** + * Returns the annotations recorded for this {@code Span}. + * + * @return the annotations recorded for this {@code Span}. + */ + public abstract TimedEvents getAnnotations(); + + /** + * Returns network events recorded for this {@code Span}. + * + * @return network events recorded for this {@code Span}. + */ + public abstract TimedEvents getNetworkEvents(); + + /** + * Returns links recorded for this {@code Span}. + * + * @return links recorded for this {@code Span}. + */ + public abstract Links getLinks(); + + /** + * Returns the {@code Status} or {@code null} if {@code Span} is still active. + * + * @return the {@code Status} or {@code null} if {@code Span} is still active. + */ + @Nullable + public abstract Status getStatus(); + + /** + * Returns the end {@code Timestamp} or {@code null} if the {@code Span} is still active. + * + * @return the end {@code Timestamp} or {@code null} if the {@code Span} is still active. + */ + @Nullable + public abstract Timestamp getEndTimestamp(); + + SpanData() {} + + /** + * A timed event representation. + * + * @param the type of value that is timed. + */ + @Immutable + @AutoValue + public abstract static class TimedEvent { + /** + * Returns a new immutable {@code TimedEvent}. + * + * @param timestamp the {@code Timestamp} of this event. + * @param event the event. + * @param the type of value that is timed. + * @return a new immutable {@code TimedEvent} + */ + public static TimedEvent create(Timestamp timestamp, T event) { + return new AutoValue_SpanData_TimedEvent(timestamp, event); + } + + /** + * Returns the {@code Timestamp} of this event. + * + * @return the {@code Timestamp} of this event. + */ + public abstract Timestamp getTimestamp(); + + /** + * Returns the event. + * + * @return the event. + */ + public abstract T getEvent(); + + TimedEvent() {} + } + + /** + * A list of timed events and the number of dropped events representation. + * + * @param the type of value that is timed. + */ + @Immutable + @AutoValue + public abstract static class TimedEvents { + /** + * Returns a new immutable {@code TimedEvents}. + * + * @param events the list of events. + * @param droppedEventsCount the number of dropped events. + * @param the type of value that is timed. + * @return a new immutable {@code TimedEvents} + */ + public static TimedEvents create(List> events, int droppedEventsCount) { + return new AutoValue_SpanData_TimedEvents( + Collections.unmodifiableList( + new ArrayList>(checkNotNull(events, "events"))), + droppedEventsCount); + } + + /** + * Returns the list of events. + * + * @return the list of events. + */ + public abstract List> getEvents(); + + /** + * Returns the number of dropped events. + * + * @return the number of dropped events. + */ + public abstract int getDroppedEventsCount(); + + TimedEvents() {} + } + + /** A set of attributes and the number of dropped attributes representation. */ + @Immutable + @AutoValue + public abstract static class Attributes { + /** + * Returns a new immutable {@code Attributes}. + * + * @param attributeMap the set of attributes. + * @param droppedAttributesCount the number of dropped attributes. + * @return a new immutable {@code Attributes}. + */ + public static Attributes create( + Map attributeMap, int droppedAttributesCount) { + // TODO(bdrutu): Consider to use LinkedHashMap here and everywhere else, less test flakes + // for others on account of determinism. + return new AutoValue_SpanData_Attributes( + Collections.unmodifiableMap( + new HashMap(checkNotNull(attributeMap, "attributeMap"))), + droppedAttributesCount); + } + + /** + * Returns the set of attributes. + * + * @return the set of attributes. + */ + public abstract Map getAttributeMap(); + + /** + * Returns the number of dropped attributes. + * + * @return the number of dropped attributes. + */ + public abstract int getDroppedAttributesCount(); + + Attributes() {} + } + + /** A list of links and the number of dropped links representation. */ + @Immutable + @AutoValue + public abstract static class Links { + /** + * Returns a new immutable {@code Links}. + * + * @param links the list of links. + * @param droppedLinksCount the number of dropped links. + * @return a new immutable {@code Links}. + */ + public static Links create(List links, int droppedLinksCount) { + return new AutoValue_SpanData_Links( + Collections.unmodifiableList(new ArrayList(checkNotNull(links, "links"))), + droppedLinksCount); + } + + /** + * Returns the list of links. + * + * @return the list of links. + */ + public abstract List getLinks(); + + /** + * Returns the number of dropped links. + * + * @return the number of dropped links. + */ + public abstract int getDroppedLinksCount(); + + Links() {} + } +} diff --git a/api/src/main/java/io/opencensus/trace/SpanFactory.java b/api/src/main/java/io/opencensus/trace/SpanFactory.java new file mode 100644 index 00000000..aca5bd85 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/SpanFactory.java @@ -0,0 +1,44 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import javax.annotation.Nullable; + +/** Factory class to create and start a {@link Span}. */ +public abstract class SpanFactory { + /** + * Creates and starts a new child {@link Span} (or root if parent is {@code null}), with parent + * being the designated {@code Span} and the given options. + * + * @param parent The parent of the returned {@code Span}. + * @param name The name of the returned {@code Span}. + * @param options The options for the start of the {@code Span}. + * @return A child {@code Span} that will have the name provided. + */ + protected abstract Span startSpan(@Nullable Span parent, String name, StartSpanOptions options); + + /** + * Creates and starts a new child {@link Span} (or root if parent is {@code null}), with parent + * being the {@code Span} designated by the {@link SpanContext} and the given options. + * + *

This must be used to create a {@code Span} when the parent is on a different process. + * + * @param remoteParent The remote parent of the returned {@code Span}. + * @param name The name of the returned {@code Span}. + * @param options The options for the start of the {@code Span}. + * @return A child {@code Span} that will have the name provided. + */ + protected abstract Span startSpanWithRemoteParent( + @Nullable SpanContext remoteParent, String name, StartSpanOptions options); +} diff --git a/api/src/main/java/io/opencensus/trace/SpanId.java b/api/src/main/java/io/opencensus/trace/SpanId.java new file mode 100644 index 00000000..8128c9d7 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/SpanId.java @@ -0,0 +1,171 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.MoreObjects; +import com.google.common.io.BaseEncoding; +import java.util.Arrays; +import java.util.Random; +import javax.annotation.concurrent.Immutable; + +/** + * A class that represents a span identifier. A valid span identifier is an 8-byte array with at + * least one non-zero byte. + */ +@Immutable +public final class SpanId implements Comparable { + /** The size in bytes of the {@code SpanId}. */ + public static final int SIZE = 8; + + /** The invalid {@code SpanId}. All bytes are 0. */ + public static final SpanId INVALID = new SpanId(new byte[SIZE]); + + // The internal representation of the SpanId. + private final byte[] bytes; + + private SpanId(byte[] bytes) { + this.bytes = bytes; + } + + /** + * Returns a {@code SpanId} built from a byte representation. + * + *

Equivalent with: + * + *

{@code
+   * SpanId.fromBytes(buffer, 0);
+   * }
+ * + * @param buffer the representation of the {@code SpanId}. + * @return a {@code SpanId} whose representation is given by the {@code buffer} parameter. + * @throws NullPointerException if {@code buffer} is null. + * @throws IllegalArgumentException if {@code buffer.length} is not {@link SpanId#SIZE}. + */ + public static SpanId fromBytes(byte[] buffer) { + checkNotNull(buffer, "buffer"); + checkArgument(buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); + byte[] bytesCopied = Arrays.copyOf(buffer, SIZE); + return new SpanId(bytesCopied); + } + + /** + * Returns a {@code SpanId} whose representation is copied from the {@code src} beginning at the + * {@code srcOffset} offset. + * + * @param src the buffer where the representation of the {@code SpanId} is copied. + * @param srcOffset the offset in the buffer where the representation of the {@code SpanId} + * begins. + * @return a {@code SpanId} whose representation is copied from the buffer. + * @throws NullPointerException if {@code src} is null. + * @throws IndexOutOfBoundsException if {@code srcOffset+SpanId.SIZE} is greater than {@code + * src.length}. + */ + public static SpanId fromBytes(byte[] src, int srcOffset) { + byte[] bytes = new byte[SIZE]; + System.arraycopy(src, srcOffset, bytes, 0, SIZE); + return new SpanId(bytes); + } + + /** + * Generates a new random {@code SpanId}. + * + * @param random The random number generator. + * @return a valid new {@code SpanId}. + */ + public static SpanId generateRandomId(Random random) { + byte[] bytes = new byte[SIZE]; + do { + random.nextBytes(bytes); + } while (Arrays.equals(bytes, INVALID.bytes)); + return new SpanId(bytes); + } + + /** + * Returns the byte representation of the {@code SpanId}. + * + * @return the byte representation of the {@code SpanId}. + */ + public byte[] getBytes() { + return Arrays.copyOf(bytes, SIZE); + } + + /** + * Copies the byte array representations of the {@code SpanId} into the {@code dest} beginning at + * the {@code destOffset} offset. + * + *

Equivalent with (but faster because it avoids any new allocations): + * + *

{@code
+   * System.arraycopy(getBytes(), 0, dest, destOffset, SpanId.SIZE);
+   * }
+ * + * @param dest the destination buffer. + * @param destOffset the starting offset in the destination buffer. + * @throws NullPointerException if {@code dest} is null. + * @throws IndexOutOfBoundsException if {@code destOffset+SpanId.SIZE} is greater than {@code + * dest.length}. + */ + public void copyBytesTo(byte[] dest, int destOffset) { + System.arraycopy(bytes, 0, dest, destOffset, SIZE); + } + + /** + * Returns whether the span identifier is valid. A valid span identifier is an 8-byte array with + * at least one non-zero byte. + * + * @return {@code true} if the span identifier is valid. + */ + public boolean isValid() { + return !Arrays.equals(bytes, INVALID.bytes); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof SpanId)) { + return false; + } + + SpanId that = (SpanId) obj; + return Arrays.equals(bytes, that.bytes); + } + + @Override + public int hashCode() { + return Arrays.hashCode(bytes); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("spanId", BaseEncoding.base16().lowerCase().encode(bytes)) + .toString(); + } + + @Override + public int compareTo(SpanId that) { + for (int i = 0; i < SIZE; i++) { + if (bytes[i] != that.bytes[i]) { + return bytes[i] < that.bytes[i] ? -1 : 1; + } + } + return 0; + } +} diff --git a/api/src/main/java/io/opencensus/trace/StartSpanOptions.java b/api/src/main/java/io/opencensus/trace/StartSpanOptions.java new file mode 100644 index 00000000..01bc8885 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/StartSpanOptions.java @@ -0,0 +1,101 @@ +/* + * Copyright 2016, Google Inc. + * 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; + +import com.google.common.base.Objects; +import java.util.Collections; +import java.util.List; +import javax.annotation.Nullable; + +/** + * A class that enables overriding the default values used when starting a {@link Span}. Allows + * overriding the {@link Sampler sampler}, the parent links, and option to record all the events + * even if the {@code Span} is not sampled. + */ +public final class StartSpanOptions { + private Sampler sampler; + private List parentLinks; + private Boolean recordEvents; + + StartSpanOptions() { + this.sampler = null; + this.parentLinks = null; + this.recordEvents = null; + } + + /** + * Returns the {@link Sampler} to be used, or {@code null} if default. + * + * @return the {@code Sampler} to be used, or {@code null} if default. + */ + @Nullable + public Sampler getSampler() { + return sampler; + } + + /** + * Returns the parent links to be set for the {@link Span}. + * + * @return the parent links to be set for the {@code Span}. + */ + public List getParentLinks() { + // Return an unmodifiable list. + return parentLinks == null + ? Collections.emptyList() + : Collections.unmodifiableList(parentLinks); + } + + /** + * Returns the record events option setting. + * + * @return the record events option setting. + */ + @Nullable + public Boolean getRecordEvents() { + return recordEvents; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof StartSpanOptions)) { + return false; + } + + StartSpanOptions that = (StartSpanOptions) obj; + return Objects.equal(sampler, that.sampler) + && Objects.equal(parentLinks, that.parentLinks) + && Objects.equal(recordEvents, that.recordEvents); + } + + @Override + public int hashCode() { + return Objects.hashCode(sampler, parentLinks, recordEvents); + } + + void setSampler(@Nullable Sampler sampler) { + this.sampler = sampler; + } + + void setParentLinks(@Nullable List parentLinks) { + this.parentLinks = parentLinks; + } + + void setRecordEvents(@Nullable Boolean recordEvents) { + this.recordEvents = recordEvents; + } +} diff --git a/api/src/main/java/io/opencensus/trace/Status.java b/api/src/main/java/io/opencensus/trace/Status.java new file mode 100644 index 00000000..22cb5287 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/Status.java @@ -0,0 +1,327 @@ +/* + * Copyright 2016, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Objects; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.TreeMap; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * Defines the status of a {@link Span} by providing a standard {@link CanonicalCode} in conjunction + * with an optional descriptive message. Instances of {@code Status} are created by starting with + * the template for the appropriate {@link Status.CanonicalCode} and supplementing it with + * additional information: {@code Status.NOT_FOUND.withDescription("Could not find + * 'important_file.txt'");} + */ +@Immutable +public final class Status { + /** + * The set of canonical status codes. If new codes are added over time they must choose a + * numerical value that does not collide with any previously used value. + */ + public enum CanonicalCode { + /** The operation completed successfully. */ + OK(0), + + /** The operation was cancelled (typically by the caller). */ + CANCELLED(1), + + /** + * Unknown error. An example of where this error may be returned is if a Status value received + * from another address space belongs to an error-space that is not known in this address space. + * Also errors raised by APIs that do not return enough error information may be converted to + * this error. + */ + UNKNOWN(2), + + /** + * Client specified an invalid argument. Note that this differs from FAILED_PRECONDITION. + * INVALID_ARGUMENT indicates arguments that are problematic regardless of the state of the + * system (e.g., a malformed file name). + */ + INVALID_ARGUMENT(3), + + /** + * Deadline expired before operation could complete. For operations that change the state of the + * system, this error may be returned even if the operation has completed successfully. For + * example, a successful response from a server could have been delayed long enough for the + * deadline to expire. + */ + DEADLINE_EXCEEDED(4), + + /** Some requested entity (e.g., file or directory) was not found. */ + NOT_FOUND(5), + + /** Some entity that we attempted to create (e.g., file or directory) already exists. */ + ALREADY_EXISTS(6), + + /** + * The caller does not have permission to execute the specified operation. PERMISSION_DENIED + * must not be used for rejections caused by exhausting some resource (use RESOURCE_EXHAUSTED + * instead for those errors). PERMISSION_DENIED must not be used if the caller cannot be + * identified (use UNAUTHENTICATED instead for those errors). + */ + PERMISSION_DENIED(7), + + /** + * Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system + * is out of space. + */ + RESOURCE_EXHAUSTED(8), + + /** + * Operation was rejected because the system is not in a state required for the operation's + * execution. For example, directory to be deleted may be non-empty, an rmdir operation is + * applied to a non-directory, etc. + * + *

A litmus test that may help a service implementor in deciding between FAILED_PRECONDITION, + * ABORTED, and UNAVAILABLE: (a) Use UNAVAILABLE if the client can retry just the failing call. + * (b) Use ABORTED if the client should retry at a higher-level (e.g., restarting a + * read-modify-write sequence). (c) Use FAILED_PRECONDITION if the client should not retry until + * the system state has been explicitly fixed. E.g., if an "rmdir" fails because the directory + * is non-empty, FAILED_PRECONDITION should be returned since the client should not retry unless + * they have first fixed up the directory by deleting files from it. + */ + FAILED_PRECONDITION(9), + + /** + * The operation was aborted, typically due to a concurrency issue like sequencer check + * failures, transaction aborts, etc. + * + *

See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE. + */ + ABORTED(10), + + /** + * Operation was attempted past the valid range. E.g., seeking or reading past end of file. + * + *

Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed if the system + * state changes. For example, a 32-bit file system will generate INVALID_ARGUMENT if asked to + * read at an offset that is not in the range [0,2^32-1], but it will generate OUT_OF_RANGE if + * asked to read from an offset past the current file size. + * + *

There is a fair bit of overlap between FAILED_PRECONDITION and OUT_OF_RANGE. We recommend + * using OUT_OF_RANGE (the more specific error) when it applies so that callers who are + * iterating through a space can easily look for an OUT_OF_RANGE error to detect when they are + * done. + */ + OUT_OF_RANGE(11), + + /** Operation is not implemented or not supported/enabled in this service. */ + UNIMPLEMENTED(12), + + /** + * Internal errors. Means some invariants expected by underlying system has been broken. If you + * see one of these errors, something is very broken. + */ + INTERNAL(13), + + /** + * The service is currently unavailable. This is a most likely a transient condition and may be + * corrected by retrying with a backoff. + * + *

See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE. + */ + UNAVAILABLE(14), + + /** Unrecoverable data loss or corruption. */ + DATA_LOSS(15), + + /** The request does not have valid authentication credentials for the operation. */ + UNAUTHENTICATED(16); + + private final int value; + + private CanonicalCode(int value) { + this.value = value; + } + + /** + * Returns the numerical value of the code. + * + * @return the numerical value of the code. + */ + public int value() { + return value; + } + + Status toStatus() { + return STATUS_LIST.get(value); + } + } + + // Create the canonical list of Status instances indexed by their code values. + private static final List STATUS_LIST = buildStatusList(); + + private static List buildStatusList() { + TreeMap canonicalizer = new TreeMap(); + for (CanonicalCode code : CanonicalCode.values()) { + Status replaced = canonicalizer.put(code.value(), new Status(code, null)); + if (replaced != null) { + throw new IllegalStateException( + "Code value duplication between " + + replaced.getCanonicalCode().name() + + " & " + + code.name()); + } + } + return Collections.unmodifiableList(new ArrayList(canonicalizer.values())); + } + + // A pseudo-enum of Status instances mapped 1:1 with values in CanonicalCode. This simplifies + // construction patterns for derived instances of Status. + /** The operation completed successfully. */ + public static final Status OK = CanonicalCode.OK.toStatus(); + /** The operation was cancelled (typically by the caller). */ + public static final Status CANCELLED = CanonicalCode.CANCELLED.toStatus(); + /** Unknown error. See {@link CanonicalCode#UNKNOWN}. */ + public static final Status UNKNOWN = CanonicalCode.UNKNOWN.toStatus(); + /** Client specified an invalid argument. See {@link CanonicalCode#INVALID_ARGUMENT}. */ + public static final Status INVALID_ARGUMENT = CanonicalCode.INVALID_ARGUMENT.toStatus(); + /** + * Deadline expired before operation could complete. See {@link CanonicalCode#DEADLINE_EXCEEDED}. + */ + public static final Status DEADLINE_EXCEEDED = CanonicalCode.DEADLINE_EXCEEDED.toStatus(); + /** Some requested entity (e.g., file or directory) was not found. */ + public static final Status NOT_FOUND = CanonicalCode.NOT_FOUND.toStatus(); + /** Some entity that we attempted to create (e.g., file or directory) already exists. */ + public static final Status ALREADY_EXISTS = CanonicalCode.ALREADY_EXISTS.toStatus(); + /** + * The caller does not have permission to execute the specified operation. See {@link + * CanonicalCode#PERMISSION_DENIED}. + */ + public static final Status PERMISSION_DENIED = CanonicalCode.PERMISSION_DENIED.toStatus(); + /** The request does not have valid authentication credentials for the operation. */ + public static final Status UNAUTHENTICATED = CanonicalCode.UNAUTHENTICATED.toStatus(); + /** + * Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system + * is out of space. + */ + public static final Status RESOURCE_EXHAUSTED = CanonicalCode.RESOURCE_EXHAUSTED.toStatus(); + /** + * Operation was rejected because the system is not in a state required for the operation's + * execution. See {@link CanonicalCode#FAILED_PRECONDITION}. + */ + public static final Status FAILED_PRECONDITION = CanonicalCode.FAILED_PRECONDITION.toStatus(); + /** + * The operation was aborted, typically due to a concurrency issue like sequencer check failures, + * transaction aborts, etc. See {@link CanonicalCode#ABORTED}. + */ + public static final Status ABORTED = CanonicalCode.ABORTED.toStatus(); + /** Operation was attempted past the valid range. See {@link CanonicalCode#OUT_OF_RANGE}. */ + public static final Status OUT_OF_RANGE = CanonicalCode.OUT_OF_RANGE.toStatus(); + /** Operation is not implemented or not supported/enabled in this service. */ + public static final Status UNIMPLEMENTED = CanonicalCode.UNIMPLEMENTED.toStatus(); + /** Internal errors. See {@link CanonicalCode#INTERNAL}. */ + public static final Status INTERNAL = CanonicalCode.INTERNAL.toStatus(); + /** The service is currently unavailable. See {@link CanonicalCode#UNAVAILABLE}. */ + public static final Status UNAVAILABLE = CanonicalCode.UNAVAILABLE.toStatus(); + /** Unrecoverable data loss or corruption. */ + public static final Status DATA_LOSS = CanonicalCode.DATA_LOSS.toStatus(); + + // The canonical code of this message. + private final CanonicalCode canonicalCode; + // An additional error message. + private final String description; + + private Status(CanonicalCode canonicalCode, @Nullable String description) { + this.canonicalCode = checkNotNull(canonicalCode, "canonicalCode"); + this.description = description; + } + + /** + * Creates a derived instance of {@code Status} with the given description. + * + * @param description the new description of the {@code Status}. + * @return The newly created {@code Status} with the given description. + */ + public Status withDescription(String description) { + if (Objects.equal(this.description, description)) { + return this; + } + return new Status(this.canonicalCode, description); + } + + /** + * Returns the canonical status code. + * + * @return the canonical status code. + */ + public CanonicalCode getCanonicalCode() { + return canonicalCode; + } + + /** + * Returns the description of this {@code Status} for human consumption. + * + * @return the description of this {@code Status}. + */ + @Nullable + public String getDescription() { + return description; + } + + /** + * Returns {@code true} if this {@code Status} is OK, i.e., not an error. + * + * @return {@code true} if this {@code Status} is OK. + */ + public boolean isOk() { + return CanonicalCode.OK == canonicalCode; + } + + /** + * Equality on Statuses is not well defined. Instead, do comparison based on their CanonicalCode + * with {@link #getCanonicalCode}. The description of the Status is unlikely to be stable, and + * additional fields may be added to Status in the future. + */ + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof Status)) { + return false; + } + + Status that = (Status) obj; + return canonicalCode == that.canonicalCode && Objects.equal(description, that.description); + } + + /** + * Hash codes on Statuses are not well defined. + * + * @see #equals + */ + @Override + public int hashCode() { + return Objects.hashCode(canonicalCode, description); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("canonicalCode", canonicalCode) + .add("description", description) + .toString(); + } +} diff --git a/api/src/main/java/io/opencensus/trace/TraceComponent.java b/api/src/main/java/io/opencensus/trace/TraceComponent.java new file mode 100644 index 00000000..1829417f --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/TraceComponent.java @@ -0,0 +1,107 @@ +/* + * Copyright 2016, Google Inc. + * 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; + +import io.opencensus.common.Clock; +import io.opencensus.internal.ZeroTimeClock; + +/** + * Class that holds the implementation instances for {@link Tracer}, {@link + * BinaryPropagationHandler}, {@link Clock}, {@link TraceExporter} and {@link TraceConfig}. + * + *

Unless otherwise noted all methods (on component) results are cacheable. + */ +public abstract class TraceComponent { + private static final NoopTraceComponent noopTraceComponent = new NoopTraceComponent(); + + /** + * Returns the {@link Tracer} with the provided implementations. If no implementation is provided + * then no-op implementations will be used. + * + * @return the {@code Tracer} implementation. + */ + public abstract Tracer getTracer(); + + /** + * Returns the {@link BinaryPropagationHandler} with the provided implementations. If no + * implementation is provided then no-op implementation will be used. + * + * @return the {@code BinaryPropagationHandler} implementation. + */ + public abstract BinaryPropagationHandler getBinaryPropagationHandler(); + + /** + * Returns the {@link Clock} with the provided implementation. + * + * @return the {@code Clock} implementation. + */ + public abstract Clock getClock(); + + /** + * Returns the {@link TraceExporter} with the provided implementation. If no implementation is + * provided then no-op implementations will be used. + * + * @return the {@link TraceExporter} implementation. + */ + public abstract TraceExporter getTraceExporter(); + + /** + * Returns the {@link TraceConfig} with the provided implementation. If no implementation is + * provided then no-op implementations will be used. + * + * @return the {@link TraceConfig} implementation. + */ + public abstract TraceConfig getTraceConfig(); + + // Disallow external overrides until we define the final API. + TraceComponent() {} + + /** + * Returns an instance that contains no-op implementations for all the instances. + * + * @return an instance that contains no-op implementations for all the instances. + */ + static TraceComponent getNoopTraceComponent() { + return noopTraceComponent; + } + + private static final class NoopTraceComponent extends TraceComponent { + @Override + public Tracer getTracer() { + return Tracer.getNoopTracer(); + } + + @Override + public BinaryPropagationHandler getBinaryPropagationHandler() { + return BinaryPropagationHandler.getNoopBinaryPropagationHandler(); + } + + @Override + public Clock getClock() { + return ZeroTimeClock.getInstance(); + } + + @Override + public TraceExporter getTraceExporter() { + return TraceExporter.getNoopTraceExporter(); + } + + @Override + public TraceConfig getTraceConfig() { + return TraceConfig.getNoopTraceConfig(); + } + + private NoopTraceComponent() {} + } +} diff --git a/api/src/main/java/io/opencensus/trace/TraceConfig.java b/api/src/main/java/io/opencensus/trace/TraceConfig.java new file mode 100644 index 00000000..41fa75b8 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/TraceConfig.java @@ -0,0 +1,213 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import javax.annotation.concurrent.Immutable; + +/** + * Global configuration of the trace service. This allows users to change configs for the default + * sampler, maximum events to be kept, etc. (see {@link TraceParams} for details). + */ +public abstract class TraceConfig { + private static final NoopTraceConfig noopTraceConfig = new NoopTraceConfig(); + + /** + * Returns the active {@code TraceParams}. + * + * @return the active {@code TraceParams}. + */ + public abstract TraceParams getActiveTraceParams(); + + /** + * Updates the active {@link TraceParams}. + * + * @param traceParams the new active {@code TraceParams}. + */ + public abstract void updateActiveTraceParams(TraceParams traceParams); + + /** + * Temporary updates the active {@link TraceParams} for {@code durationNs} nanoseconds. + * + * @param traceParams the new active {@code TraceParams}. + * @param durationNs the duration for how long the new params will be active. + */ + public abstract void temporaryUpdateActiveTraceParams(TraceParams traceParams, long durationNs); + + /** + * Returns the no-op implementation of the {@code TraceConfig}. + * + * @return the no-op implementation of the {@code TraceConfig}. + */ + static TraceConfig getNoopTraceConfig() { + return noopTraceConfig; + } + + /** Class that holds global trace parameters. */ + @AutoValue + @Immutable + public abstract static class TraceParams { + // These values are the default values for all the global parameters. + private static final double DEFAULT_PROBABILITY = 1e-4; + private static final Sampler DEFAULT_SAMPLER = Samplers.probabilitySampler(DEFAULT_PROBABILITY); + private static final int DEFAULT_SPAN_MAX_NUM_ATTRIBUTES = 32; + private static final int DEFAULT_SPAN_MAX_NUM_ANNOTATIONS = 32; + private static final int DEFAULT_SPAN_MAX_NUM_NETWORK_EVENTS = 128; + private static final int DEFAULT_SPAN_MAX_NUM_LINKS = 128; + + public static final TraceParams DEFAULT = + TraceParams.builder() + .setSampler(DEFAULT_SAMPLER) + .setMaxNumberOfAttributes(DEFAULT_SPAN_MAX_NUM_ATTRIBUTES) + .setMaxNumberOfAnnotations(DEFAULT_SPAN_MAX_NUM_ANNOTATIONS) + .setMaxNumberOfNetworkEvents(DEFAULT_SPAN_MAX_NUM_NETWORK_EVENTS) + .setMaxNumberOfLinks(DEFAULT_SPAN_MAX_NUM_LINKS) + .build(); + + /** + * Returns the global default {@code Sampler}. Used if no {@code Sampler} is provided in {@link + * StartSpanOptions}. + * + * @return the global default {@code Sampler}. + */ + public abstract Sampler getSampler(); + + /** + * Returns the global default max number of attributes per {@link Span}. + * + * @return the global default max number of attributes per {@link Span}. + */ + public abstract int getMaxNumberOfAttributes(); + + /** + * Returns the global default max number of {@link Annotation} events per {@link Span}. + * + * @return the global default max number of {@code Annotation} events per {@code Span}. + */ + public abstract int getMaxNumberOfAnnotations(); + + /** + * Returns the global default max number of {@link NetworkEvent} events per {@link Span}. + * + * @return the global default max number of {@code NetworkEvent} events per {@code Span}. + */ + public abstract int getMaxNumberOfNetworkEvents(); + + /** + * Returns the global default max number of {@link Link} entries per {@link Span}. + * + * @return the global default max number of {@code Link} entries per {@code Span}. + */ + public abstract int getMaxNumberOfLinks(); + + private static Builder builder() { + return new AutoValue_TraceConfig_TraceParams.Builder(); + } + + /** + * Returns a {@link Builder} initialized to the same property values as the current instance. + * + * @return a {@link Builder} initialized to the same property values as the current instance. + */ + public abstract Builder toBuilder(); + + /** A {@code Builder} class for {@link TraceParams}. */ + @AutoValue.Builder + public abstract static class Builder { + + /** + * Sets the global default {@code Sampler}. It must be not {@code null} otherwise {@link + * #build()} will throw an exception. + * + * @param sampler the global default {@code Sampler}. + * @return this. + */ + public abstract Builder setSampler(Sampler sampler); + + /** + * Sets the global default max number of attributes per {@link Span}. + * + * @param maxNumberOfAttributes the global default max number of attributes per {@link Span}. + * It must be positive otherwise {@link #build()} will throw an exception. + * @return this. + */ + public abstract Builder setMaxNumberOfAttributes(int maxNumberOfAttributes); + + /** + * Sets the global default max number of {@link Annotation} events per {@link Span}. + * + * @param maxNumberOfAnnotations the global default max number of {@link Annotation} events + * per {@link Span}. It must be positive otherwise {@link #build()} will throw an + * exception. + * @return this. + */ + public abstract Builder setMaxNumberOfAnnotations(int maxNumberOfAnnotations); + + /** + * Sets the global default max number of {@link NetworkEvent} events per {@link Span}. + * + * @param maxNumberOfNetworkEvents the global default max number of {@link NetworkEvent} + * events per {@link Span}. It must be positive otherwise {@link #build()} will throw an + * exception. + * @return this. + */ + public abstract Builder setMaxNumberOfNetworkEvents(int maxNumberOfNetworkEvents); + + /** + * Sets the global default max number of {@link Link} entries per {@link Span}. + * + * @param maxNumberOfLinks the global default max number of {@link Link} entries per {@link + * Span}. It must be positive otherwise {@link #build()} will throw an exception. + * @return this. + */ + public abstract Builder setMaxNumberOfLinks(int maxNumberOfLinks); + + abstract TraceParams autoBuild(); + + /** + * Builds and returns a {@code TraceParams} with the desired values. + * + * @return a {@code TraceParams} with the desired values. + * @throws NullPointerException if the sampler is {@code null}. + * @throws IllegalArgumentException if any of the max numbers are not positive. + */ + public TraceParams build() { + TraceParams traceParams = autoBuild(); + checkNotNull(traceParams.getSampler(), "sampler"); + checkArgument(traceParams.getMaxNumberOfAttributes() > 0, "maxNumberOfAttributes"); + checkArgument(traceParams.getMaxNumberOfAnnotations() > 0, "maxNumberOfAnnotations"); + checkArgument(traceParams.getMaxNumberOfNetworkEvents() > 0, "maxNumberOfNetworkEvents"); + checkArgument(traceParams.getMaxNumberOfLinks() > 0, "maxNumberOfLinks"); + return traceParams; + } + } + } + + private static final class NoopTraceConfig extends TraceConfig { + + @Override + public TraceParams getActiveTraceParams() { + return TraceParams.DEFAULT; + } + + @Override + public void updateActiveTraceParams(TraceParams traceParams) {} + + @Override + public void temporaryUpdateActiveTraceParams(TraceParams traceParams, long durationNs) {} + } +} diff --git a/api/src/main/java/io/opencensus/trace/TraceExporter.java b/api/src/main/java/io/opencensus/trace/TraceExporter.java new file mode 100644 index 00000000..7da2d604 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/TraceExporter.java @@ -0,0 +1,609 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import io.opencensus.trace.Status.CanonicalCode; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; +import javax.annotation.concurrent.ThreadSafe; + +/** + * The main exporting API for the trace library. + * + *

Implementation MUST ensure that all functions are thread safe. + */ +@ThreadSafe +public abstract class TraceExporter { + + private static final NoopTraceExporter noopTraceExporter = new NoopTraceExporter(); + + /** + * Returns the no-op implementation of the {@code TraceExporter}. + * + * @return the no-op implementation of the {@code TraceExporter}. + */ + static TraceExporter getNoopTraceExporter() { + return noopTraceExporter; + } + + /** + * Registers a new service handler that is used by the library to export {@code SpanData} for + * sampled spans (see {@link TraceOptions#isSampled()}). + * + *

Example of usage: + * + *

{@code
+   * public static void main(String[] args) {
+   *   Tracing.getTraceExporter().registerServiceHandler(
+   *       "com.google.stackdriver.tracing", new StackdriverTracingServiceHandler());
+   *   // ...
+   * }
+   * }
+ * + * @param name the name of the service handler. Must be unique for each service. + * @param serviceHandler the service handler that is called for each ended sampled span. + */ + public abstract void registerServiceHandler(String name, ServiceHandler serviceHandler); + + /** + * Unregisters the service handler with the provided name. + * + * @param name the name of the service handler that will be unregistered. + */ + public abstract void unregisterServiceHandler(String name); + + /** + * Returns the {@code InProcessDebuggingHandler} that can be used to get useful debugging + * information such as (active spans, latency based sampled spans, error based sampled spans). + * + * @return the {@code InProcessDebuggingHandler} or {@code null} if in-process debugging is not + * supported. + */ + @Nullable + public abstract InProcessDebuggingHandler getInProcessDebuggingHandler(); + + /** + * This class allows users to access in-process debugging information such as (getting access to + * all active spans, support latency based sampled spans and error based sampled spans). + * + *

The active spans tracking is available for all the spans with the option {@link + * Span.Options#RECORD_EVENTS}. This functionality allows users to debug stuck operations or long + * living operations. + * + *

For all completed spans with the option {@link Span.Options#RECORD_EVENTS} the library can + * store samples based on latency for succeeded operations or based on error code for failed + * operations. To activate this, users MUST manually configure all the span names for which + * samples will be collected (see {@link #registerSpanNamesForCollection(Collection)}). + */ + public abstract static class InProcessDebuggingHandler { + + InProcessDebuggingHandler() {} + + /** + * Returns the summary of all available in-process debugging data such as number of active + * spans, number of sampled spans in the latency based samples or error based samples. + * + *

Latency based sampled summary buckets and error based sampled summary buckets are + * available only for span names registered using {@link + * #registerSpanNamesForCollection(Collection)}. + * + * @return the summary of all available in-process debugging data. + */ + public abstract Summary getSummary(); + + /** + * Returns a list of active spans that match the {@code filter}. + * + *

Active spans are available for all the span names. + * + * @param filter used to filter the returned spans. + * @return a list of active spans that match the {@code filter}. + */ + public abstract Collection getActiveSpans(ActiveSpansFilter filter); + + /** + * Returns a list of succeeded spans (spans with {@link Status} equal to {@link Status#OK}) that + * match the {@code filter}. + * + *

Latency based sampled spans are available only for span names registered using {@link + * #registerSpanNamesForCollection(Collection)}. + * + * @param filter used to filter the returned sampled spans. + * @return a list of succeeded spans that match the {@code filter}. + */ + public abstract Collection getLatencyBasedSampledSpans( + LatencyBasedSampledSpansFilter filter); + + /** + * Returns a list of failed spans (spans with {@link Status} other than {@link Status#OK}) that + * match the {@code filter}. + * + *

Error based sampled spans are available only for span names registered using {@link + * #registerSpanNamesForCollection(Collection)}. + * + * @param filter used to filter the returned sampled spans. + * @return a list of failed spans that match the {@code filter}. + */ + public abstract Collection getErrorBasedSampledSpans( + ErrorBasedSampledSpansFilter filter); + + /** + * Appends a list of span names for which the library will collect latency based sampled spans + * and error based sampled spans. + * + *

If called multiple times the library keeps the list of unique span names from all the + * calls. + * + * @param spanNames list of span names for which the library will collect samples. + */ + public abstract void registerSpanNamesForCollection(Collection spanNames); + + /** + * Removes a list of span names for which the library will collect latency based sampled spans + * and error based sampled spans. + * + *

The library keeps the list of unique registered span names for which samples will be + * called. This method allows users to remove span names from that list. + * + * @param spanNames list of span names for which the library will no longer collect samples. + */ + public abstract void unregisterSpanNamesForCollection(Collection spanNames); + + /** The summary of all in-process debugging information. */ + @AutoValue + @Immutable + public abstract static class Summary { + + Summary() {} + + /** + * Returns a new instance of {@code Summary}. + * + * @param perSpanNameSummary a map with summary for each different span name. + * @return a new instance of {@code Summary}. + * @throws NullPointerException if {@code perSpanNameSummary} is {@code null}. + */ + public static Summary create(Map perSpanNameSummary) { + return new AutoValue_TraceExporter_InProcessDebuggingHandler_Summary( + Collections.unmodifiableMap( + new HashMap( + checkNotNull(perSpanNameSummary, "perSpanNameSummary")))); + } + + /** + * Returns a map with summary of available data for each different span name. + * + * @return a map with all the span names and the summary. + */ + public abstract Map getPerSpanNameSummary(); + + /** Summary of all available data for a span name. */ + @AutoValue + @Immutable + public abstract static class PerSpanNameSummary { + + PerSpanNameSummary() {} + + /** + * Returns a new instance of {@code PerSpanNameSummary}. + * + * @param numActiveSpans the number of sampled spans. + * @param latencyBucketSummaries the summary for the latency buckets. + * @param errorBucketSummaries the summary for the error buckets. + * @return a new instance of {@code PerSpanNameSummary}. + * @throws NullPointerException if {@code latencyBucketSummaries} or {@code + * errorBucketSummaries} are {@code null}. + * @throws IllegalArgumentException if {@code numActiveSpans} is negative. + */ + public static PerSpanNameSummary create( + int numActiveSpans, + List latencyBucketSummaries, + List errorBucketSummaries) { + checkArgument(numActiveSpans >= 0, "Negative numActiveSpans."); + return new AutoValue_TraceExporter_InProcessDebuggingHandler_Summary_PerSpanNameSummary( + numActiveSpans, + Collections.unmodifiableList( + new ArrayList( + checkNotNull(latencyBucketSummaries, "latencyBucketSummaries"))), + Collections.unmodifiableList( + new ArrayList( + checkNotNull(errorBucketSummaries, "errorBucketSummaries")))); + } + + /** + * Returns the number of active spans. + * + * @return the number of active spans. + */ + public abstract int getNumActiveSpans(); + + /** + * Returns the list of all latency based sampled buckets summary. + * + *

The list is sorted based on the lower latency boundary, and the upper bound of one + * match the lower bound of the next. Every bucket contains samples with latency within the + * interval [lowerBoundary, upperBoundary). + * + * @return the list of all latency based sampled buckets summary. + */ + public abstract List getLatencyBucketSummaries(); + + /** + * Returns the list of all error based sampled buckets summary. + * + *

The list is sorted based on the {@link CanonicalCode#value()} and contains an entry + * for each of the values other than {@link CanonicalCode#OK}. + * + * @return the list of all error based sampled buckets summary. + */ + public abstract List getErrorBucketSummaries(); + + /** + * Summary of a latency based sampled spans bucket. Contains {@code Span} samples with + * latency between [latencyLowerNs, latencyUpperNs). + */ + @AutoValue + @Immutable + public abstract static class LatencyBucketSummary { + + LatencyBucketSummary() {} + + /** + * Returns a new instance of {@code LatencyBucketSummary}. The latency of the samples is + * in the interval [latencyLowerNs, latencyUpperNs). + * + * @param numSamples the number of sampled spans. + * @param latencyLowerNs the latency lower bound. + * @param latencyUpperNs the latency upper bound. + * @return a new instance of {@code LatencyBucketSummary}. + * @throws IllegalArgumentException if {@code numSamples} or {@code latencyLowerNs} or + * {@code latencyUpperNs} are negative. + */ + public static LatencyBucketSummary create( + int numSamples, long latencyLowerNs, long latencyUpperNs) { + checkArgument(numSamples >= 0, "Negative numSamples."); + checkArgument(latencyLowerNs >= 0, "Negative latencyLowerNs"); + checkArgument(latencyUpperNs >= 0, "Negative latencyUpperNs"); + //CHECKSTYLE:OFF: Long class name. + return new AutoValue_TraceExporter_InProcessDebuggingHandler_Summary_PerSpanNameSummary_LatencyBucketSummary( + numSamples, latencyLowerNs, latencyUpperNs); + //CHECKSTYLE:ON: Long class name. + } + + /** + * Returns the number of sampled spans in this bucket. + * + * @return the number of sampled spans in this bucket. + */ + public abstract int getNumSamples(); + + /** + * Returns the latency lower bound of this bucket (inclusive). + * + * @return the latency lower bound of this bucket. + */ + public abstract long getLatencyLowerNs(); + + /** + * Returns the latency upper bound of this bucket (exclusive). + * + * @return the latency upper bound of this bucket. + */ + public abstract long getLatencyUpperNs(); + } + + /** Summary of an error based sampled spans bucket. */ + @AutoValue + @Immutable + public abstract static class ErrorBucketSummary { + + ErrorBucketSummary() {} + + /** + * Returns a new instance of {@code ErrorBucketSummary}. + * + * @param numSamples the number of sampled spans. + * @param canonicalCode the error code of the bucket. + * @return a new instance of {@code ErrorBucketSummary}. + * @throws NullPointerException if {@code canonicalCode} is {@code null}. + * @throws IllegalArgumentException if {@code canonicalCode} is {@link CanonicalCode#OK} + * or {@code numSamples} is negative. + */ + public static ErrorBucketSummary create(int numSamples, CanonicalCode canonicalCode) { + checkArgument(numSamples >= 0, "Negative numSamples."); + checkArgument(canonicalCode != CanonicalCode.OK, "Invalid canonical code."); + //CHECKSTYLE:OFF: Long class name. + return new AutoValue_TraceExporter_InProcessDebuggingHandler_Summary_PerSpanNameSummary_ErrorBucketSummary( + numSamples, canonicalCode); + //CHECKSTYLE:ON: Long class name. + } + + /** + * Returns the number of sampled spans in this bucket. + * + * @return the number of sampled spans in this bucket. + */ + public abstract int getNumSamples(); + + /** + * Returns the {@code CanonicalCode} for this bucket. Always different than {@link + * CanonicalCode#OK}. + * + * @return the {@code CanonicalCode} for this bucket. + */ + public abstract CanonicalCode getCanonicalCode(); + } + } + } + + /** + * Filter for active spans. Used to filter results returned by the {@link + * #getActiveSpans(ActiveSpansFilter)} request. + */ + @AutoValue + @Immutable + public abstract static class ActiveSpansFilter { + + ActiveSpansFilter() {} + + /** + * Returns a new instance of {@code ActiveSpansFilter}. + * + *

Filters all the spans based on {@code spanName} and returns a maximum of {@code + * maxSpansToReturn}. + * + * @param spanName the name of the span. + * @param maxSpansToReturn the maximum number of results to be returned. {@code 0} means all. + * @return a new instance of {@code ActiveSpansFilter}. + * @throws NullPointerException if {@code spanName} is {@code null}. + * @throws IllegalArgumentException if {@code maxSpansToReturn} is negative. + */ + public static ActiveSpansFilter create(String spanName, int maxSpansToReturn) { + checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); + return new AutoValue_TraceExporter_InProcessDebuggingHandler_ActiveSpansFilter( + spanName, maxSpansToReturn); + } + + /** + * Returns the span name. + * + * @return the span name. + */ + public abstract String getSpanName(); + + /** + * Returns the maximum number of spans to be returned. {@code 0} means all. + * + * @return the maximum number of spans to be returned. + */ + public abstract int getMaxSpansToReturn(); + } + + /** + * Filter for latency based sampled spans. Used to filter results returned by the {@link + * #getLatencyBasedSampledSpans(LatencyBasedSampledSpansFilter)} request. + */ + @AutoValue + @Immutable + public abstract static class LatencyBasedSampledSpansFilter { + + LatencyBasedSampledSpansFilter() {} + + /** + * Returns a new instance of {@code LatencyBasedSampledSpansFilter}. + * + *

Filters all the spans based on {@code spanName} and latency in the interval + * [latencyLowerNs, latencyUpperNs) and returns a maximum of {@code maxSpansToReturn}. + * + * @param spanName the name of the span. + * @param latencyLowerNs the latency lower bound. + * @param latencyUpperNs the latency upper bound. + * @param maxSpansToReturn the maximum number of results to be returned. {@code 0} means all. + * @return a new instance of {@code LatencyBasedSampledSpansFilter}. + * @throws NullPointerException if {@code spanName} is {@code null}. + * @throws IllegalArgumentException if {@code maxSpansToReturn} or {@code latencyLowerNs} or + * {@code latencyUpperNs} are negative. + */ + public static LatencyBasedSampledSpansFilter create( + String spanName, long latencyLowerNs, long latencyUpperNs, int maxSpansToReturn) { + checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); + checkArgument(latencyLowerNs >= 0, "Negative latencyLowerNs"); + checkArgument(latencyUpperNs >= 0, "Negative latencyUpperNs"); + return new AutoValue_TraceExporter_InProcessDebuggingHandler_LatencyBasedSampledSpansFilter( + spanName, latencyLowerNs, latencyUpperNs, maxSpansToReturn); + } + + /** + * Returns the span name used by this filter. + * + * @return the span name used by this filter. + */ + public abstract String getSpanName(); + + /** + * Returns the latency lower bound of this bucket (inclusive). + * + * @return the latency lower bound of this bucket. + */ + public abstract long getLatencyLowerNs(); + + /** + * Returns the latency upper bound of this bucket (exclusive). + * + * @return the latency upper bound of this bucket. + */ + public abstract long getLatencyUpperNs(); + + /** + * Returns the maximum number of spans to be returned. {@code 0} means all. + * + * @return the maximum number of spans to be returned. + */ + public abstract int getMaxSpansToReturn(); + } + + /** Filter for error based sampled spans. */ + @AutoValue + @Immutable + public abstract static class ErrorBasedSampledSpansFilter { + + ErrorBasedSampledSpansFilter() {} + + /** + * Returns a new instance of {@code ErrorBasedSampledSpansFilter}. + * + *

Filters all the spans based on {@code spanName} and {@code canonicalCode} and returns a + * maximum of {@code maxSpansToReturn}. + * + * @param spanName the name of the span. + * @param canonicalCode the error code of the span. + * @param maxSpansToReturn the maximum number of results to be returned. {@code 0} means all. + * @return a new instance of {@code ErrorBasedSampledSpansFilter}. + * @throws NullPointerException if {@code spanName} or {@code canonicalCode} are {@code null}. + * @throws IllegalArgumentException if {@code canonicalCode} is {@link CanonicalCode#OK} or + * {@code maxSpansToReturn} is negative. + */ + public static ErrorBasedSampledSpansFilter create( + String spanName, CanonicalCode canonicalCode, int maxSpansToReturn) { + checkArgument(canonicalCode != CanonicalCode.OK, "Invalid canonical code."); + checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); + return new AutoValue_TraceExporter_InProcessDebuggingHandler_ErrorBasedSampledSpansFilter( + spanName, canonicalCode, maxSpansToReturn); + } + + /** + * Returns the span name used by this filter. + * + * @return the span name used by this filter. + */ + public abstract String getSpanName(); + + /** + * Returns the canonical code used by this filter. Always different than {@link + * CanonicalCode#OK}. + * + * @return the canonical code used by this filter. + */ + public abstract CanonicalCode getCanonicalCode(); + + /** + * Returns the maximum number of spans to be returned. Used to enforce the number of returned + * {@code SpanData}. {@code 0} means all. + * + * @return the maximum number of spans to be returned. + */ + public abstract int getMaxSpansToReturn(); + } + } + + /** + * An abstract class that allows different tracing services to export recorded data for sampled + * spans in their own format. + * + *

To export data this MUST be register to to the TraceExporter using {@link + * #registerServiceHandler(String, ServiceHandler)}. + */ + public abstract static class ServiceHandler { + + /** + * Exports a list of sampled (see {@link TraceOptions#isSampled()}) {@link Span}s using the + * immutable representation {@link SpanData}. + * + *

This may be called from a different thread than the one that called {@link Span#end()}. + * + *

Implementation SHOULD not block the calling thread. It should execute the export on a + * different thread if possible. + * + * @param spanDataList a list of {@code SpanData} objects to be exported. + */ + public abstract void export(Collection spanDataList); + } + + /** + * Implementation of the {@link ServiceHandler} which logs all the exported {@link SpanData}. + * + *

Example of usage: + * + *

{@code
+   * public static void main(String[] args) {
+   *   Tracing.getTraceExporter().registerServiceHandler(
+   *       "io.opencensus.LoggingServiceHandler", LoggingServiceHandler.getInstance());
+   *   // ...
+   * }
+   * }
+ */ + @ThreadSafe + public static final class LoggingServiceHandler extends ServiceHandler { + + private static final Logger logger = Logger.getLogger(LoggingServiceHandler.class.getName()); + private static final String SERVICE_NAME = "io.opencensus.trace.LoggingServiceHandler"; + private static final LoggingServiceHandler INSTANCE = new LoggingServiceHandler(); + + private LoggingServiceHandler() {} + + /** + * Registers the {@code LoggingServiceHandler} to the {@code TraceExporter}. + * + * @param traceExporter the instance of the {@code TraceExporter} where this service is + * registered. + */ + public static void registerService(TraceExporter traceExporter) { + traceExporter.registerServiceHandler(SERVICE_NAME, INSTANCE); + } + + /** + * Unregisters the {@code LoggingServiceHandler} from the {@code TraceExporter}. + * + * @param traceExporter the instance of the {@code TraceExporter} from where this service is + * unregistered. + */ + public static void unregisterService(TraceExporter traceExporter) { + traceExporter.unregisterServiceHandler(SERVICE_NAME); + } + + @Override + public void export(Collection spanDataList) { + for (SpanData spanData : spanDataList) { + logger.log(Level.INFO, spanData.toString()); + } + } + } + + private static final class NoopTraceExporter extends TraceExporter { + + @Override + public void registerServiceHandler(String name, @Nullable ServiceHandler serviceHandler) {} + + @Override + public void unregisterServiceHandler(String name) {} + + @Nullable + @Override + public InProcessDebuggingHandler getInProcessDebuggingHandler() { + return null; + } + } +} diff --git a/api/src/main/java/io/opencensus/trace/TraceId.java b/api/src/main/java/io/opencensus/trace/TraceId.java new file mode 100644 index 00000000..5684efdf --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/TraceId.java @@ -0,0 +1,185 @@ +/* + * Copyright 2016, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.MoreObjects; +import com.google.common.io.BaseEncoding; +import java.util.Arrays; +import java.util.Random; +import javax.annotation.concurrent.Immutable; + +/** + * A class that represents a trace identifier. A valid trace identifier is a 16-byte array with at + * least one non-zero byte. + */ +@Immutable +public final class TraceId implements Comparable { + /** The size in bytes of the {@code TraceId}. */ + public static final int SIZE = 16; + + /** The invalid {@code TraceId}. All bytes are '\0'. */ + public static final TraceId INVALID = new TraceId(new byte[SIZE]); + + // The internal representation of the TraceId. + private final byte[] bytes; + + private TraceId(byte[] bytes) { + this.bytes = bytes; + } + + /** + * Returns a {@code TraceId} built from a byte representation. + * + *

Equivalent with: + * + *

{@code
+   * TraceId.fromBytes(buffer, 0);
+   * }
+ * + * @param buffer the representation of the {@code TraceId}. + * @return a {@code TraceId} whose representation is given by the {@code buffer} parameter. + * @throws NullPointerException if {@code buffer} is null. + * @throws IllegalArgumentException if {@code buffer.length} is not {@link TraceId#SIZE}. + */ + public static TraceId fromBytes(byte[] buffer) { + checkNotNull(buffer, "buffer"); + checkArgument(buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); + byte[] bytesCopied = Arrays.copyOf(buffer, SIZE); + return new TraceId(bytesCopied); + } + + /** + * Returns a {@code TraceId} whose representation is copied from the {@code src} beginning at the + * {@code srcOffset} offset. + * + * @param src the buffer where the representation of the {@code TraceId} is copied. + * @param srcOffset the offset in the buffer where the representation of the {@code TraceId} + * begins. + * @return a {@code TraceId} whose representation is copied from the buffer. + * @throws NullPointerException if {@code src} is null. + * @throws IndexOutOfBoundsException if {@code srcOffset+TraceId.SIZE} is greater than {@code + * src.length}. + */ + public static TraceId fromBytes(byte[] src, int srcOffset) { + byte[] bytes = new byte[SIZE]; + System.arraycopy(src, srcOffset, bytes, 0, SIZE); + return new TraceId(bytes); + } + + /** + * Generates a new random {@code TraceId}. + * + * @param random the random number generator. + * @return a new valid {@code TraceId}. + */ + public static TraceId generateRandomId(Random random) { + byte[] bytes = new byte[SIZE]; + do { + random.nextBytes(bytes); + } while (Arrays.equals(bytes, INVALID.bytes)); + return new TraceId(bytes); + } + + /** + * Returns the 16-bytes array representation of the {@code TraceId}. + * + * @return the 16-bytes array representation of the {@code TraceId}. + */ + public byte[] getBytes() { + return Arrays.copyOf(bytes, SIZE); + } + + /** + * Copies the byte array representations of the {@code TraceId} into the {@code dest} beginning at + * the {@code destOffset} offset. + * + *

Equivalent with (but faster because it avoids any new allocations): + * + *

{@code
+   * System.arraycopy(getBytes(), 0, dest, destOffset, TraceId.SIZE);
+   * }
+ * + * @param dest the destination buffer. + * @param destOffset the starting offset in the destination buffer. + * @throws NullPointerException if {@code dest} is null. + * @throws IndexOutOfBoundsException if {@code destOffset+TraceId.SIZE} is greater than {@code + * dest.length}. + */ + public void copyBytesTo(byte[] dest, int destOffset) { + System.arraycopy(bytes, 0, dest, destOffset, SIZE); + } + + /** + * Returns whether the {@code TraceId} is valid. A valid trace identifier is a 16-byte array with + * at least one non-zero byte. + * + * @return {@code true} if the {@code TraceId} is valid. + */ + public boolean isValid() { + return !Arrays.equals(bytes, INVALID.bytes); + } + + // Return the lower 8 bytes of the trace-id as a long value, assuming little-endian order. This + // is used in ProbabilitySampler. + long getLowerLong() { + long result = 0; + for (int i = 0; i < Long.SIZE / Byte.SIZE; i++) { + result <<= Byte.SIZE; + result |= (bytes[i] & 0xff); + } + if (result < 0) { + return -result; + } + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof TraceId)) { + return false; + } + + TraceId that = (TraceId) obj; + return Arrays.equals(bytes, that.bytes); + } + + @Override + public int hashCode() { + return Arrays.hashCode(bytes); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("traceId", BaseEncoding.base16().lowerCase().encode(bytes)) + .toString(); + } + + @Override + public int compareTo(TraceId that) { + for (int i = 0; i < SIZE; i++) { + if (bytes[i] != that.bytes[i]) { + return bytes[i] < that.bytes[i] ? -1 : 1; + } + } + return 0; + } +} diff --git a/api/src/main/java/io/opencensus/trace/TraceOptions.java b/api/src/main/java/io/opencensus/trace/TraceOptions.java new file mode 100644 index 00000000..6fc04bb9 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/TraceOptions.java @@ -0,0 +1,210 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkElementIndex; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.MoreObjects; +import com.google.common.base.Objects; +import javax.annotation.concurrent.Immutable; + +/** + * A class that represents global trace options. These options are propagated to all child {@link + * Span spans}. These determine features such as whether a {@code Span} should be traced. It is + * implemented as a bitmask. + */ +@Immutable +public final class TraceOptions { + // Default options. Nothing set. + private static final byte DEFAULT_OPTIONS = 0; + // Bit to represent whether trace is sampled or not. + private static final byte IS_SAMPLED = 0x1; + + /** The size in bytes of the {@code TraceOptions}. */ + public static final int SIZE = 1; + + /** The default {@code TraceOptions}. */ + public static final TraceOptions DEFAULT = new TraceOptions(DEFAULT_OPTIONS); + + // The set of enabled features is determined by all the enabled bits. + private final byte options; + + // Creates a new {@code TraceOptions} with the given options. + private TraceOptions(byte options) { + this.options = options; + } + + /** + * Returns a {@code TraceOptions} built from a byte representation. + * + *

Equivalent with: + * + *

{@code
+   * TraceOptions.fromBytes(buffer, 0);
+   * }
+ * + * @param buffer the representation of the {@code TraceOptions}. + * @return a {@code TraceOptions} whose representation is given by the {@code buffer} parameter. + * @throws NullPointerException if {@code buffer} is null. + * @throws IllegalArgumentException if {@code buffer.length} is not {@link TraceOptions#SIZE}. + */ + public static TraceOptions fromBytes(byte[] buffer) { + checkNotNull(buffer, "buffer"); + checkArgument(buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); + return new TraceOptions(buffer[0]); + } + + /** + * Returns a {@code TraceOptions} whose representation is copied from the {@code src} beginning at + * the {@code srcOffset} offset. + * + * @param src the buffer where the representation of the {@code TraceOptions} is copied. + * @param srcOffset the offset in the buffer where the representation of the {@code TraceOptions} + * begins. + * @return a {@code TraceOptions} whose representation is copied from the buffer. + * @throws NullPointerException if {@code src} is null. + * @throws IndexOutOfBoundsException if {@code srcOffset+TraceOptions.SIZE} is greater than {@code + * src.length}. + */ + public static TraceOptions fromBytes(byte[] src, int srcOffset) { + checkElementIndex(srcOffset, src.length); + return new TraceOptions(src[srcOffset]); + } + + /** + * Returns the 1-byte array representation of the {@code TraceOptions}. + * + * @return the 1-byte array representation of the {@code TraceOptions}. + */ + public byte[] getBytes() { + byte[] bytes = new byte[SIZE]; + bytes[0] = options; + return bytes; + } + + /** + * Copies the byte representations of the {@code TraceOptions} into the {@code dest} beginning at + * the {@code destOffset} offset. + * + *

Equivalent with (but faster because it avoids any new allocations): + * + *

{@code
+   * System.arraycopy(getBytes(), 0, dest, destOffset, TraceOptions.SIZE);
+   * }
+ * + * @param dest the destination buffer. + * @param destOffset the starting offset in the destination buffer. + * @throws NullPointerException if {@code dest} is null. + * @throws IndexOutOfBoundsException if {@code destOffset+TraceOptions.SIZE} is greater than + * {@code dest.length}. + */ + public void copyBytesTo(byte[] dest, int destOffset) { + checkElementIndex(destOffset, dest.length); + dest[destOffset] = options; + } + + /** + * Returns a new {@link Builder} with default options. + * + * @return a new {@code Builder} with default options. + */ + public static Builder builder() { + return new Builder(DEFAULT_OPTIONS); + } + + /** + * Returns a new {@link Builder} with all given options set. + * + * @param traceOptions the given options set. + * @return a new {@code Builder} with all given options set. + */ + public static Builder builder(TraceOptions traceOptions) { + return new Builder(traceOptions.options); + } + + /** + * Returns a boolean indicating whether this {@code Span} is part of a sampled trace and data + * should be exported to a persistent store. + * + * @return a boolean indicating whether the trace is sampled. + */ + public boolean isSampled() { + return hasOption(IS_SAMPLED); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof TraceOptions)) { + return false; + } + + TraceOptions that = (TraceOptions) obj; + return options == that.options; + } + + @Override + public int hashCode() { + return Objects.hashCode(options); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this).add("sampled", isSampled()).toString(); + } + + /** Builder class for {@link TraceOptions}. */ + public static final class Builder { + private byte options; + + private Builder(byte options) { + this.options = options; + } + + /** + * Marks this trace as sampled. + * + * @return this. + */ + public Builder setIsSampled() { + options |= IS_SAMPLED; + return this; + } + + /** + * Builds and returns a {@code TraceOptions} with the desired options. + * + * @return a {@code TraceOptions} with the desired options. + */ + public TraceOptions build() { + return new TraceOptions(options); + } + } + + // Returns the current set of options bitmask. + @VisibleForTesting + byte getOptions() { + return options; + } + + private boolean hasOption(int mask) { + return (this.options & mask) != 0; + } +} diff --git a/api/src/main/java/io/opencensus/trace/Tracer.java b/api/src/main/java/io/opencensus/trace/Tracer.java new file mode 100644 index 00000000..56c4280d --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/Tracer.java @@ -0,0 +1,228 @@ +/* + * Copyright 2016, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkNotNull; + +import io.opencensus.common.NonThrowingCloseable; +import javax.annotation.Nullable; + +/** + * Tracer is a simple, thin class for {@link Span} creation and in-process context interaction. + * + *

Users may choose to use manual or automatic Context propagation. Because of that this class + * offers APIs to facilitate both usages. + * + *

The automatic context propagation is done using {@link io.grpc.Context} which is a gRPC + * independent implementation for in-process Context propagation mechanism which can carry + * scoped-values across API boundaries and between threads. Users of the library must propagate the + * {@link io.grpc.Context} between different threads. + * + *

Example usage with automatic context propagation: + * + *

{@code
+ * class MyClass {
+ *   private static final Tracer tracer = Tracing.getTracer();
+ *   void doWork() {
+ *     try(NonThrowingCloseable ss = tracer.spanBuilder("MyClass.DoWork").startScopedSpan) {
+ *       tracer.getCurrentSpan().addAnnotation("Starting the work.");
+ *       doWorkInternal();
+ *       tracer.getCurrentSpan().addAnnotation("Finished working.");
+ *     }
+ *   }
+ * }
+ * }
+ * + *

Example usage with manual context propagation: + * + *

{@code
+ * class MyClass {
+ *   private static final Tracer tracer = Tracing.getTracer();
+ *   void doWork() {
+ *     Span span = tracer.spanBuilder(null, "MyRootSpan").startSpan();
+ *     span.addAnnotation("Starting the work.");
+ *     try {
+ *       doSomeWork(span); // Manually propagate the new span down the stack.
+ *     } finally {
+ *       span.addAnnotation("Finished working.");
+ *       // To make sure we end the span even in case of an exception.
+ *       span.end();  // Manually end the span.
+ *     }
+ *   }
+ * }
+ * }
+ */ +public abstract class Tracer { + private static final NoopTracer noopTracer = new NoopTracer(); + private final SpanFactory spanFactory; + + /** + * Returns the no-op implementation of the {@code Tracer}. + * + * @return the no-op implementation of the {@code Tracer}. + */ + static Tracer getNoopTracer() { + return noopTracer; + } + + /** + * Gets the current Span from the current Context. + * + *

To install a {@link Span} to the current Context use {@link #withSpan(Span)} OR use {@link + * SpanBuilder#startScopedSpan} methods to start a new {@code Span}. + * + *

startSpan methods do NOT modify the current Context {@code Span}. + * + * @return a default {@code Span} that does nothing and has an invalid {@link SpanContext} if no + * {@code Span} is associated with the current Context, otherwise the current {@code Span} + * from the Context. + */ + public final Span getCurrentSpan() { + Span currentSpan = ContextUtils.getCurrentSpan(); + return currentSpan != null ? currentSpan : BlankSpan.INSTANCE; + } + + /** + * Enters the scope of code where the given {@link Span} is in the current Context, and returns an + * object that represents that scope. The scope is exited when the returned object is closed. + * + *

Supports try-with-resource idiom. + * + *

Can be called with {@link BlankSpan} to enter a scope of code where tracing is stopped. + * + *

Example of usage: + * + *

{@code
+   * private static Tracer tracer = Tracing.getTracer();
+   * void doWork() {
+   *   // Create a Span as a child of the current Span.
+   *   Span span = tracer.spanBuilder("my span").startSpan();
+   *   try (NonThrowingCloseable ws = tracer.withSpan(span)) {
+   *     tracer.getCurrentSpan().addAnnotation("my annotation");
+   *     doSomeOtherWork();  // Here "span" is the current Span.
+   *   }
+   *   span.end();
+   * }
+   * }
+ * + *

Prior to Java SE 7, you can use a finally block to ensure that a resource is closed + * regardless of whether the try statement completes normally or abruptly. + * + *

Example of usage prior to Java SE7: + * + *

{@code
+   * private static Tracer tracer = Tracing.getTracer();
+   * void doWork() {
+   *   // Create a Span as a child of the current Span.
+   *   Span span = tracer.spanBuilder("my span").startSpan();
+   *   NonThrowingCloseable ws = tracer.withSpan(span);
+   *   try {
+   *     tracer.getCurrentSpan().addAnnotation("my annotation");
+   *     doSomeOtherWork();  // Here "span" is the current Span.
+   *   } finally {
+   *     ws.close();
+   *   }
+   *   span.end();
+   * }
+   * }
+ * + * @param span The {@link Span} to be set to the current Context. + * @return an object that defines a scope where the given {@link Span} will be set to the current + * Context. + * @throws NullPointerException if span is null. + */ + public final NonThrowingCloseable withSpan(Span span) { + return ContextUtils.withSpan(checkNotNull(span, "span")); + } + + /** + * Returns a {@link SpanBuilder} to create and start a new child {@link Span} as a child of to the + * current {@code Span} if any, otherwise create a root Span with the default options. + * + *

See {@link SpanBuilder} for usage examples. + * + *

This must be used to create a {@code Span} when automatic Context propagation is + * used. + * + * @param name The name of the returned Span. + * @return a {@code SpanBuilder} to create and start a new {@code Span}. + * @throws NullPointerException if name is null. + */ + public final SpanBuilder spanBuilder(String name) { + return spanBuilder(ContextUtils.getCurrentSpan(), name); + } + + /** + * Returns a {@link SpanBuilder} to create and start a new child {@link Span} (or root if parent + * is null), with parent being the designated {@code Span}. + * + *

See {@link SpanBuilder} for usage examples. + * + *

This must be used to create a {@code Span} when manual Context propagation is used. + * + * @param parent The parent of the returned Span. If null the {@code SpanBuilder} will build a + * root {@code Span}. + * @param name The name of the returned Span. + * @return a {@code SpanBuilder} to create and start a new {@code Span}. + * @throws NullPointerException if name is null. + */ + public final SpanBuilder spanBuilder(@Nullable Span parent, String name) { + return SpanBuilder.builder(spanFactory, parent, checkNotNull(name, "name")); + } + + /** + * Returns a {@link SpanBuilder} to create and start a new child {@link Span} (or root if parent + * is null), with parent being the {@link Span} designated by the {@link SpanContext}. + * + *

See {@link SpanBuilder} for usage examples. + * + *

This must be used to create a {@code Span} when the parent is in a different process. + * This is only intended for use by RPC systems or similar. + * + * @param remoteParent The remote parent of the returned Span. + * @param name The name of the returned Span. + * @return a {@code SpanBuilder} to create and start a new {@code Span}. + * @throws NullPointerException if name is null. + */ + public final SpanBuilder spanBuilderWithRemoteParent( + @Nullable SpanContext remoteParent, String name) { + return SpanBuilder.builderWithRemoteParent( + spanFactory, remoteParent, checkNotNull(name, "name")); + } + + // No-Op implementation of the Tracer. + private static final class NoopTracer extends Tracer { + private NoopTracer() { + super(new NoopSpanFactory()); + } + + // No-op implementation of the SpanFactory + private static final class NoopSpanFactory extends SpanFactory { + @Override + protected Span startSpan(@Nullable Span parent, String name, StartSpanOptions options) { + return BlankSpan.INSTANCE; + } + + @Override + protected Span startSpanWithRemoteParent( + @Nullable SpanContext remoteParent, String name, StartSpanOptions options) { + return BlankSpan.INSTANCE; + } + } + } + + protected Tracer(SpanFactory spanFactory) { + this.spanFactory = checkNotNull(spanFactory, "spanFactory"); + } +} diff --git a/api/src/main/java/io/opencensus/trace/Tracing.java b/api/src/main/java/io/opencensus/trace/Tracing.java new file mode 100644 index 00000000..e6d34a45 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/Tracing.java @@ -0,0 +1,89 @@ +/* + * Copyright 2016, Google Inc. + * 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; + +import com.google.common.annotations.VisibleForTesting; +import io.opencensus.common.Clock; +import io.opencensus.internal.Provider; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** Class that manages a global instance of the {@link TraceComponent}. */ +public final class Tracing { + private static final Logger logger = Logger.getLogger(Tracer.class.getName()); + private static final TraceComponent traceComponent = + loadTraceComponent(Provider.getCorrectClassLoader(TraceComponent.class)); + + /** + * Returns the global {@link Tracer}. + * + * @return the global {@code Tracer}. + */ + public static Tracer getTracer() { + return traceComponent.getTracer(); + } + + /** + * Returns the global {@link BinaryPropagationHandler}. + * + * @return the global {@code BinaryPropagationHandler}. + */ + public static BinaryPropagationHandler getBinaryPropagationHandler() { + return traceComponent.getBinaryPropagationHandler(); + } + + /** + * Returns the global {@link Clock}. + * + * @return the global {@code Clock}. + */ + public static Clock getClock() { + return traceComponent.getClock(); + } + + /** + * Returns the global {@link TraceExporter}. + * + * @return the global {@code TraceExporter}. + */ + public static TraceExporter getTraceExporter() { + return traceComponent.getTraceExporter(); + } + + /** + * Returns the global {@link TraceConfig}. + * + * @return the global {@code TraceConfig}. + */ + public static TraceConfig getTraceConfig() { + return traceComponent.getTraceConfig(); + } + + // Any provider that may be used for TraceComponent can be added here. + @VisibleForTesting + static TraceComponent loadTraceComponent(ClassLoader classLoader) { + try { + // Call Class.forName with literal string name of the class to help shading tools. + return Provider.createInstance( + Class.forName("io.opencensus.trace.TraceComponentImpl", true, classLoader), + TraceComponent.class); + } catch (ClassNotFoundException e) { + logger.log(Level.FINE, "Using default implementation for TraceComponent.", e); + } + return TraceComponent.getNoopTraceComponent(); + } + + // No instance of this class. + private Tracing() {} +} diff --git a/api/src/test/java/io/opencensus/common/DurationTest.java b/api/src/test/java/io/opencensus/common/DurationTest.java new file mode 100644 index 00000000..b9861eea --- /dev/null +++ b/api/src/test/java/io/opencensus/common/DurationTest.java @@ -0,0 +1,61 @@ +package io.opencensus.common; + +import static com.google.common.truth.Truth.assertThat; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Duration}. */ +@RunWith(JUnit4.class) +public class DurationTest { + @Test + public void testDurationCreate() { + assertThat(Duration.create(24, 42).getSeconds()).isEqualTo(24); + assertThat(Duration.create(24, 42).getNanos()).isEqualTo(42); + assertThat(Duration.create(-24, -42).getSeconds()).isEqualTo(-24); + assertThat(Duration.create(-24, -42).getNanos()).isEqualTo(-42); + assertThat(Duration.create(315576000000L, 999999999).getSeconds()).isEqualTo(315576000000L); + assertThat(Duration.create(315576000000L, 999999999).getNanos()).isEqualTo(999999999); + assertThat(Duration.create(-315576000000L, -999999999).getSeconds()).isEqualTo(-315576000000L); + assertThat(Duration.create(-315576000000L, -999999999).getNanos()).isEqualTo(-999999999); + } + + @Test + public void testDurationCreateInvalidInput() { + assertThat(Duration.create(-315576000001L, 0)).isEqualTo(Duration.create(0, 0)); + assertThat(Duration.create(315576000001L, 0)).isEqualTo(Duration.create(0, 0)); + assertThat(Duration.create(0, 1000000000)).isEqualTo(Duration.create(0, 0)); + assertThat(Duration.create(0, -1000000000)).isEqualTo(Duration.create(0, 0)); + assertThat(Duration.create(-1, 1)).isEqualTo(Duration.create(0, 0)); + assertThat(Duration.create(1, -1)).isEqualTo(Duration.create(0, 0)); + } + + @Test + public void testDurationFromMillis() { + assertThat(Duration.fromMillis(0)).isEqualTo(Duration.create(0, 0)); + assertThat(Duration.fromMillis(987)).isEqualTo(Duration.create(0, 987000000)); + assertThat(Duration.fromMillis(3456)).isEqualTo(Duration.create(3, 456000000)); + } + + @Test + public void testDurationFromMillisNegative() { + assertThat(Duration.fromMillis(-1)).isEqualTo(Duration.create(0, -1000000)); + assertThat(Duration.fromMillis(-999)).isEqualTo(Duration.create(0, -999000000)); + assertThat(Duration.fromMillis(-1000)).isEqualTo(Duration.create(-1, 0)); + assertThat(Duration.fromMillis(-3456)).isEqualTo(Duration.create(-3, -456000000)); + } + + @Test + public void testDurationEqual() { + // Positive tests. + assertThat(Duration.create(0, 0)).isEqualTo(Duration.create(0, 0)); + assertThat(Duration.create(24, 42)).isEqualTo(Duration.create(24, 42)); + assertThat(Duration.create(-24, -42)).isEqualTo(Duration.create(-24, -42)); + // Negative tests. + assertThat(Duration.create(25, 42)).isNotEqualTo(Duration.create(24, 42)); + assertThat(Duration.create(24, 43)).isNotEqualTo(Duration.create(24, 42)); + assertThat(Duration.create(-25, -42)).isNotEqualTo(Duration.create(-24, -42)); + assertThat(Duration.create(-24, -43)).isNotEqualTo(Duration.create(-24, -42)); + } +} diff --git a/api/src/test/java/io/opencensus/common/TimestampTest.java b/api/src/test/java/io/opencensus/common/TimestampTest.java new file mode 100644 index 00000000..5a02264b --- /dev/null +++ b/api/src/test/java/io/opencensus/common/TimestampTest.java @@ -0,0 +1,83 @@ +package io.opencensus.common; + +import static com.google.common.truth.Truth.assertThat; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Timestamp}. */ +@RunWith(JUnit4.class) +public class TimestampTest { + @Test + public void timestampCreate() { + assertThat(Timestamp.create(24, 42).getSeconds()).isEqualTo(24); + assertThat(Timestamp.create(24, 42).getNanos()).isEqualTo(42); + assertThat(Timestamp.create(-24, 42).getSeconds()).isEqualTo(-24); + assertThat(Timestamp.create(-24, 42).getNanos()).isEqualTo(42); + assertThat(Timestamp.create(315576000000L, 999999999).getSeconds()).isEqualTo(315576000000L); + assertThat(Timestamp.create(315576000000L, 999999999).getNanos()).isEqualTo(999999999); + assertThat(Timestamp.create(-315576000000L, 999999999).getSeconds()).isEqualTo(-315576000000L); + assertThat(Timestamp.create(-315576000000L, 999999999).getNanos()).isEqualTo(999999999); + } + + @Test + public void timestampCreate_InvalidInput() { + assertThat(Timestamp.create(-315576000001L, 0)).isEqualTo(Timestamp.create(0, 0)); + assertThat(Timestamp.create(315576000001L, 0)).isEqualTo(Timestamp.create(0, 0)); + assertThat(Timestamp.create(1, 1000000000)).isEqualTo(Timestamp.create(0, 0)); + assertThat(Timestamp.create(1, -1)).isEqualTo(Timestamp.create(0, 0)); + assertThat(Timestamp.create(-1, 1000000000)).isEqualTo(Timestamp.create(0, 0)); + assertThat(Timestamp.create(-1, -1)).isEqualTo(Timestamp.create(0, 0)); + } + + @Test + public void timestampFromMillis() { + assertThat(Timestamp.fromMillis(0)).isEqualTo(Timestamp.create(0, 0)); + assertThat(Timestamp.fromMillis(987)).isEqualTo(Timestamp.create(0, 987000000)); + assertThat(Timestamp.fromMillis(3456)).isEqualTo(Timestamp.create(3, 456000000)); + } + + @Test + public void timestampFromMillis_Negative() { + assertThat(Timestamp.fromMillis(-1)).isEqualTo(Timestamp.create(-1, 999000000)); + assertThat(Timestamp.fromMillis(-999)).isEqualTo(Timestamp.create(-1, 1000000)); + assertThat(Timestamp.fromMillis(-3456)).isEqualTo(Timestamp.create(-4, 544000000)); + } + + @Test + public void timestampAddNanos() { + Timestamp timestamp = Timestamp.create(1234, 223); + assertThat(timestamp.addNanos(0)).isEqualTo(timestamp); + assertThat(timestamp.addNanos(999999777)).isEqualTo(Timestamp.create(1235, 0)); + assertThat(timestamp.addNanos(1300200500)).isEqualTo(Timestamp.create(1235, 300200723)); + assertThat(timestamp.addNanos(1999999777)).isEqualTo(Timestamp.create(1236, 0)); + assertThat(timestamp.addNanos(9876543789L)).isEqualTo(Timestamp.create(1243, 876544012)); + assertThat(timestamp.addNanos(Long.MAX_VALUE)) + .isEqualTo(Timestamp.create(1234L + 9223372036L, 223 + 854775807)); + } + + @Test + public void timestampAddNanos_Negative() { + Timestamp timestamp = Timestamp.create(1234, 223); + assertThat(timestamp.addNanos(-223)).isEqualTo(Timestamp.create(1234, 0)); + assertThat(timestamp.addNanos(-1000000223)).isEqualTo(Timestamp.create(1233, 0)); + assertThat(timestamp.addNanos(-1300200500)).isEqualTo(Timestamp.create(1232, 699799723)); + assertThat(timestamp.addNanos(-4123456213L)).isEqualTo(Timestamp.create(1229, 876544010)); + assertThat(timestamp.addNanos(Long.MIN_VALUE)) + .isEqualTo(Timestamp.create(1234L - 9223372036L - 1, 223 + 145224192)); + } + + @Test + public void testTimestampEqual() { + // Positive tests. + assertThat(Timestamp.create(0, 0)).isEqualTo(Timestamp.create(0, 0)); + assertThat(Timestamp.create(24, 42)).isEqualTo(Timestamp.create(24, 42)); + assertThat(Timestamp.create(-24, 42)).isEqualTo(Timestamp.create(-24, 42)); + // Negative tests. + assertThat(Timestamp.create(25, 42)).isNotEqualTo(Timestamp.create(24, 42)); + assertThat(Timestamp.create(24, 43)).isNotEqualTo(Timestamp.create(24, 42)); + assertThat(Timestamp.create(-25, 42)).isNotEqualTo(Timestamp.create(-24, 42)); + assertThat(Timestamp.create(-24, 43)).isNotEqualTo(Timestamp.create(-24, 42)); + } +} diff --git a/api/src/test/java/io/opencensus/internal/ProviderTest.java b/api/src/test/java/io/opencensus/internal/ProviderTest.java new file mode 100644 index 00000000..f6aba5ec --- /dev/null +++ b/api/src/test/java/io/opencensus/internal/ProviderTest.java @@ -0,0 +1,125 @@ +/* + * Copyright 2016, Google Inc. + * 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.internal; + +import static com.google.common.truth.Truth.assertThat; + +import java.util.ServiceConfigurationError; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link Provider} */ +@RunWith(JUnit4.class) +public class ProviderTest { + static class GoodClass { + public GoodClass() {} + } + + static class PrivateConstructorClass { + private PrivateConstructorClass() {} + } + + static class NoDefaultConstructorClass { + public NoDefaultConstructorClass(int arg) {} + } + + private static class PrivateClass {} + + static interface MyInterface {} + + static class MyInterfaceImpl implements MyInterface { + public MyInterfaceImpl() {} + } + + @Test + public void testGoodClass() { + assertThat( + Provider.newInstance("io.opencensus.internal.ProviderTest$GoodClass", null)) + .isNotNull(); + } + + @Test + public void testBadClass() { + assertThat( + Provider.newInstance("io.opencensus.internal.ProviderTest$BadClass", null)) + .isNull(); + } + + @Test(expected = ServiceConfigurationError.class) + public void createInstance_ThrowsErrorWhenClassIsPrivate() throws ClassNotFoundException { + Provider.createInstance( + Class.forName( + "io.opencensus.internal.ProviderTest$PrivateClass", + true, + Provider.getCorrectClassLoader(ProviderTest.class)), + PrivateClass.class); + } + + @Test(expected = ServiceConfigurationError.class) + public void createInstance_ThrowsErrorWhenClassHasPrivateConstructor() + throws ClassNotFoundException { + Provider.createInstance( + Class.forName( + "io.opencensus.internal.ProviderTest$PrivateConstructorClass", + true, + Provider.getCorrectClassLoader(ProviderTest.class)), + PrivateConstructorClass.class); + } + + @Test(expected = ServiceConfigurationError.class) + public void createInstance_ThrowsErrorWhenClassDoesNotHaveDefaultConstructor() + throws ClassNotFoundException { + Provider.createInstance( + Class.forName( + "io.opencensus.internal.ProviderTest$NoDefaultConstructorClass", + true, + Provider.getCorrectClassLoader(ProviderTest.class)), + NoDefaultConstructorClass.class); + } + + @Test(expected = ServiceConfigurationError.class) + public void createInstance_ThrowsErrorWhenClassIsNotASubclass() throws ClassNotFoundException { + Provider.createInstance( + Class.forName( + "io.opencensus.internal.ProviderTest$GoodClass", + true, + Provider.getCorrectClassLoader(ProviderTest.class)), + MyInterface.class); + } + + @Test + public void createInstance_GoodClass() throws ClassNotFoundException { + assertThat( + Provider.createInstance( + Class.forName( + "io.opencensus.internal.ProviderTest$GoodClass", + true, + Provider.getCorrectClassLoader(ProviderTest.class)), + GoodClass.class)) + .isNotNull(); + } + + @Test + public void createInstance_GoodSubclass() throws ClassNotFoundException { + assertThat( + Provider.createInstance( + Class.forName( + "io.opencensus.internal.ProviderTest$MyInterfaceImpl", + true, + Provider.getCorrectClassLoader(ProviderTest.class)), + MyInterface.class)) + .isNotNull(); + } +} diff --git a/api/src/test/java/io/opencensus/internal/StringUtilTest.java b/api/src/test/java/io/opencensus/internal/StringUtilTest.java new file mode 100644 index 00000000..14144391 --- /dev/null +++ b/api/src/test/java/io/opencensus/internal/StringUtilTest.java @@ -0,0 +1,45 @@ +/* + * Copyright 2016, Google Inc. + * 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.internal; + +import static com.google.common.truth.Truth.assertThat; + +import java.util.Arrays; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link StringUtil}. */ +@RunWith(JUnit4.class) +public final class StringUtilTest { + @Test + public void testMaxLength() { + char[] string = new char[StringUtil.MAX_LENGTH]; + char[] truncString = new char[StringUtil.MAX_LENGTH + 10]; + Arrays.fill(string, 'v'); + Arrays.fill(truncString, 'v'); + assertThat(StringUtil.sanitize(new String(truncString))).isEqualTo(new String(string)); + } + + @Test + public void testBadChar() { + String string = "\2ab\3cd"; + assertThat(StringUtil.sanitize(string)).isEqualTo("_ab_cd"); + } + + @Test(expected = AssertionError.class) + public void testConstructor() { + new StringUtil(); + } +} diff --git a/api/src/test/java/io/opencensus/internal/TestClockTest.java b/api/src/test/java/io/opencensus/internal/TestClockTest.java new file mode 100644 index 00000000..fe3f80cb --- /dev/null +++ b/api/src/test/java/io/opencensus/internal/TestClockTest.java @@ -0,0 +1,62 @@ +/* + * Copyright 2017, Google Inc. + * 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.internal; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.common.Duration; +import io.opencensus.common.Timestamp; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link TestClock}. */ +@RunWith(JUnit4.class) +public final class TestClockTest { + private static final int NUM_NANOS_PER_SECOND = 1000 * 1000 * 1000; + + @Test + public void setAndGetTime() { + TestClock clock = TestClock.create(Timestamp.create(1, 2)); + assertThat(clock.now()).isEqualTo(Timestamp.create(1, 2)); + clock.setTime(Timestamp.create(3, 4)); + assertThat(clock.now()).isEqualTo(Timestamp.create(3, 4)); + } + + @Test + public void advanceTime() { + TestClock clock = TestClock.create(Timestamp.create(1, 500 * 1000 * 1000)); + clock.advanceTime(Duration.create(2, 600 * 1000 * 1000)); + assertThat(clock.now()).isEqualTo(Timestamp.create(4, 100 * 1000 * 1000)); + } + + @Test + public void measureElapsedTime() { + TestClock clock = TestClock.create(Timestamp.create(10, 1)); + long nanos1 = clock.nowNanos(); + clock.setTime(Timestamp.create(11, 5)); + long nanos2 = clock.nowNanos(); + assertThat(nanos2 - nanos1).isEqualTo(1000 * 1000 * 1000 + 4); + } + + @Test(expected = ArithmeticException.class) + public void catchOverflow() { + TestClock.create(Timestamp.create(Long.MAX_VALUE / NUM_NANOS_PER_SECOND + 1, 0)); + } + + @Test(expected = ArithmeticException.class) + public void catchNegativeOverflow() { + TestClock.create(Timestamp.create(Long.MIN_VALUE / NUM_NANOS_PER_SECOND - 1, 0)); + } +} diff --git a/api/src/test/java/io/opencensus/tags/TagKeyTest.java b/api/src/test/java/io/opencensus/tags/TagKeyTest.java new file mode 100644 index 00000000..aed02d3f --- /dev/null +++ b/api/src/test/java/io/opencensus/tags/TagKeyTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017, Google Inc. + * 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.tags; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.tags.TagKey.TagType; +import java.util.Arrays; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link TagKey} */ +@RunWith(JUnit4.class) +public final class TagKeyTest { + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void testGetName() { + assertThat(TagKey.createStringKey("foo").getName()).isEqualTo("foo"); + } + + @Test + public void testGetTagType() { + assertThat(TagKey.createStringKey("key").getTagType()).isEqualTo(TagType.TAG_STRING); + assertThat(TagKey.createLongKey("key").getTagType()).isEqualTo(TagType.TAG_LONG); + assertThat(TagKey.createBooleanKey("key").getTagType()).isEqualTo(TagType.TAG_BOOLEAN); + } + + @Test + public void createString_AllowTagKeyNameWithMaxLength() { + char[] key = new char[TagKey.MAX_LENGTH]; + Arrays.fill(key, 'k'); + TagKey.createStringKey(new String(key)); + } + + @Test + public void createString_DisallowTagKeyNameOverMaxLength() { + char[] key = new char[TagKey.MAX_LENGTH + 1]; + Arrays.fill(key, 'k'); + thrown.expect(IllegalArgumentException.class); + TagKey.createStringKey(new String(key)); + } + + @Test + public void createString_DisallowUnprintableChars() { + thrown.expect(IllegalArgumentException.class); + TagKey.createStringKey("\2ab\3cd"); + } + + @Test + public void testTagKeyEquals() { + new EqualsTester() + .addEqualityGroup(TagKey.createStringKey("foo"), TagKey.createStringKey("foo")) + .addEqualityGroup(TagKey.createLongKey("foo")) + .addEqualityGroup(TagKey.createBooleanKey("foo")) + .addEqualityGroup(TagKey.createStringKey("bar")) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/tags/TagMapTest.java b/api/src/test/java/io/opencensus/tags/TagMapTest.java new file mode 100644 index 00000000..41b3b247 --- /dev/null +++ b/api/src/test/java/io/opencensus/tags/TagMapTest.java @@ -0,0 +1,114 @@ +/* + * Copyright 2017, Google Inc. + * 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.tags; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.collect.ImmutableMap; +import java.util.Arrays; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link TagMap}. */ +// TODO(sebright): Add more tests once the API is finalized. +@RunWith(JUnit4.class) +public class TagMapTest { + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + private static final TagKey KS1 = TagKey.createStringKey("k1"); + private static final TagKey KS2 = TagKey.createStringKey("k2"); + + @Test + public void applyBuilderOperationsInOrder() { + assertThat(newBuilder().set(KS1, "v1").set(KS1, "v2").build().getTags()) + .containsExactly(KS1, "v2"); + } + + @Test + public void allowMutlipleKeysWithSameNameButDifferentTypes() { + TagKey stringKey = TagKey.createStringKey("key"); + TagKey longKey = TagKey.createLongKey("key"); + TagKey booleanKey = TagKey.createBooleanKey("key"); + assertThat( + newBuilder() + .set(stringKey, "value") + .set(longKey, 123) + .set(booleanKey, true) + .build() + .getTags()) + .containsExactly(stringKey, "value", longKey, 123L, booleanKey, true); + } + + @Test + public void testSet() { + TagMap tags = singletonTagMap(KS1, "v1"); + assertThat(tags.toBuilder().set(KS1, "v2").build().getTags()).containsExactly(KS1, "v2"); + assertThat(tags.toBuilder().set(KS2, "v2").build().getTags()) + .containsExactly(KS1, "v1", KS2, "v2"); + } + + @Test + public void testClear() { + TagMap tags = singletonTagMap(KS1, "v1"); + assertThat(tags.toBuilder().clear(KS1).build().getTags()).isEmpty(); + assertThat(tags.toBuilder().clear(KS2).build().getTags()).containsExactly(KS1, "v1"); + } + + @Test + public void allowStringTagValueWithMaxLength() { + char[] chars = new char[TagMap.MAX_STRING_LENGTH]; + Arrays.fill(chars, 'v'); + String value = new String(chars); + TagKey key = TagKey.createStringKey("K"); + newBuilder().set(key, value); + } + + @Test + public void disallowStringTagValueOverMaxLength() { + char[] chars = new char[TagMap.MAX_STRING_LENGTH + 1]; + Arrays.fill(chars, 'v'); + String value = new String(chars); + TagKey key = TagKey.createStringKey("K"); + thrown.expect(IllegalArgumentException.class); + newBuilder().set(key, value); + } + + @Test + public void disallowStringTagValueWithUnprintableChars() { + String value = "\2ab\3cd"; + TagKey key = TagKey.createStringKey("K"); + thrown.expect(IllegalArgumentException.class); + newBuilder().set(key, value); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private final TagKey badLongKey = (TagKey) TagKey.createStringKey("Key"); + + @Test(expected = IllegalArgumentException.class) + public void disallowSettingWrongTypeOfKey() { + newBuilder().set(badLongKey, 123); + } + + private static TagMap.Builder newBuilder() { + return new TagMap.Builder(); + } + + private static TagMap singletonTagMap(TagKey key, TagValueT value) { + return new TagMap(ImmutableMap., Object>of(key, value)); + } +} diff --git a/api/src/test/java/io/opencensus/trace/AnnotationTest.java b/api/src/test/java/io/opencensus/trace/AnnotationTest.java new file mode 100644 index 00000000..fbfe5fd3 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/AnnotationTest.java @@ -0,0 +1,99 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Link}. */ +@RunWith(JUnit4.class) +public class AnnotationTest { + @Test(expected = NullPointerException.class) + public void fromDescription_NullDescription() { + Annotation.fromDescription(null); + } + + @Test + public void fromDescription() { + Annotation annotation = Annotation.fromDescription("MyAnnotationText"); + assertThat(annotation.getDescription()).isEqualTo("MyAnnotationText"); + assertThat(annotation.getAttributes().size()).isEqualTo(0); + } + + @Test(expected = NullPointerException.class) + public void fromDescriptionAndAttributes_NullDescription() { + Annotation.fromDescriptionAndAttributes(null, Collections.emptyMap()); + } + + @Test(expected = NullPointerException.class) + public void fromDescriptionAndAttributes_NullAttributes() { + Annotation.fromDescriptionAndAttributes("", null); + } + + @Test + public void fromDescriptionAndAttributes() { + Map attributes = new HashMap(); + attributes.put( + "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); + Annotation annotation = Annotation.fromDescriptionAndAttributes("MyAnnotationText", attributes); + assertThat(annotation.getDescription()).isEqualTo("MyAnnotationText"); + assertThat(annotation.getAttributes()).isEqualTo(attributes); + } + + @Test + public void fromDescriptionAndAttributes_EmptyAttributes() { + Annotation annotation = + Annotation.fromDescriptionAndAttributes( + "MyAnnotationText", Collections.emptyMap()); + assertThat(annotation.getDescription()).isEqualTo("MyAnnotationText"); + assertThat(annotation.getAttributes().size()).isEqualTo(0); + } + + @Test + public void annotation_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + Map attributes = new HashMap(); + attributes.put( + "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); + tester + .addEqualityGroup( + Annotation.fromDescription("MyAnnotationText"), + Annotation.fromDescriptionAndAttributes( + "MyAnnotationText", Collections.emptyMap())) + .addEqualityGroup( + Annotation.fromDescriptionAndAttributes("MyAnnotationText", attributes), + Annotation.fromDescriptionAndAttributes("MyAnnotationText", attributes)) + .addEqualityGroup(Annotation.fromDescription("MyAnnotationText2")); + tester.testEquals(); + } + + @Test + public void annotation_ToString() { + Annotation annotation = Annotation.fromDescription("MyAnnotationText"); + assertThat(annotation.toString()).contains("MyAnnotationText"); + Map attributes = new HashMap(); + attributes.put( + "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); + annotation = Annotation.fromDescriptionAndAttributes("MyAnnotationText2", attributes); + assertThat(annotation.toString()).contains("MyAnnotationText2"); + assertThat(annotation.toString()).contains(attributes.toString()); + } +} diff --git a/api/src/test/java/io/opencensus/trace/AttributeValueTest.java b/api/src/test/java/io/opencensus/trace/AttributeValueTest.java new file mode 100644 index 00000000..7a999604 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/AttributeValueTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link AttributeValue}. */ +@RunWith(JUnit4.class) +public class AttributeValueTest { + @Test + public void stringAttributeValue() { + AttributeValue attribute = AttributeValue.stringAttributeValue("MyStringAttributeValue"); + assertThat(attribute.getStringValue()).isEqualTo("MyStringAttributeValue"); + assertThat(attribute.getBooleanValue()).isNull(); + assertThat(attribute.getLongValue()).isNull(); + } + + @Test + public void booleanAttributeValue() { + AttributeValue attribute = AttributeValue.booleanAttributeValue(true); + assertThat(attribute.getStringValue()).isNull(); + assertThat(attribute.getBooleanValue()).isTrue(); + assertThat(attribute.getLongValue()).isNull(); + } + + @Test + public void longAttributeValue() { + AttributeValue attribute = AttributeValue.longAttributeValue(123456L); + assertThat(attribute.getStringValue()).isNull(); + assertThat(attribute.getBooleanValue()).isNull(); + assertThat(attribute.getLongValue()).isEqualTo(123456L); + } + + @Test + public void attributeValue_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup( + AttributeValue.stringAttributeValue("MyStringAttributeValue"), + AttributeValue.stringAttributeValue("MyStringAttributeValue")); + tester.addEqualityGroup(AttributeValue.stringAttributeValue("MyStringAttributeDiffValue")); + tester.addEqualityGroup( + AttributeValue.booleanAttributeValue(true), AttributeValue.booleanAttributeValue(true)); + tester.addEqualityGroup(AttributeValue.booleanAttributeValue(false)); + tester.addEqualityGroup( + AttributeValue.longAttributeValue(123456L), AttributeValue.longAttributeValue(123456L)); + tester.addEqualityGroup(AttributeValue.longAttributeValue(1234567L)); + tester.testEquals(); + } + + @Test + public void attributeValue_ToString() { + AttributeValue attribute = AttributeValue.stringAttributeValue("MyStringAttributeValue"); + assertThat(attribute.toString()).contains("MyStringAttributeValue"); + attribute = AttributeValue.booleanAttributeValue(true); + assertThat(attribute.toString()).contains("true"); + attribute = AttributeValue.longAttributeValue(123456L); + assertThat(attribute.toString()).contains("123456"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/BinaryPropagationHandlerTest.java b/api/src/test/java/io/opencensus/trace/BinaryPropagationHandlerTest.java new file mode 100644 index 00000000..d75effb6 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/BinaryPropagationHandlerTest.java @@ -0,0 +1,49 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import java.text.ParseException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link BinaryPropagationHandler}. */ +@RunWith(JUnit4.class) +public class BinaryPropagationHandlerTest { + private static final BinaryPropagationHandler binaryPropagationHandler = + BinaryPropagationHandler.getNoopBinaryPropagationHandler(); + + @Test(expected = NullPointerException.class) + public void toBinaryValue_NullSpanContext() { + binaryPropagationHandler.toBinaryValue(null); + } + + @Test + public void toBinaryValue_NotNullSpanContext() { + assertThat(binaryPropagationHandler.toBinaryValue(SpanContext.INVALID)).isEqualTo(new byte[0]); + } + + @Test(expected = NullPointerException.class) + public void fromBinaryValue_NullInput() throws ParseException { + binaryPropagationHandler.fromBinaryValue(null); + } + + @Test + public void fromBinaryValue_NotNullInput() throws ParseException { + assertThat(binaryPropagationHandler.fromBinaryValue(new byte[0])) + .isEqualTo(SpanContext.INVALID); + } +} diff --git a/api/src/test/java/io/opencensus/trace/BlankSpanTest.java b/api/src/test/java/io/opencensus/trace/BlankSpanTest.java new file mode 100644 index 00000000..252d02ff --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/BlankSpanTest.java @@ -0,0 +1,60 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link BlankSpan}. */ +@RunWith(JUnit4.class) +public class BlankSpanTest { + @Test + public void hasInvalidContextAndDefaultSpanOptions() { + assertThat(BlankSpan.INSTANCE.getContext()).isEqualTo(SpanContext.INVALID); + assertThat(BlankSpan.INSTANCE.getOptions().isEmpty()).isTrue(); + } + + @Test + public void doNotCrash() { + Map attributes = new HashMap(); + attributes.put( + "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); + Map multipleAttributes = new HashMap(); + multipleAttributes.put( + "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); + multipleAttributes.put("MyBooleanAttributeKey", AttributeValue.booleanAttributeValue(true)); + multipleAttributes.put("MyLongAttributeKey", AttributeValue.longAttributeValue(123)); + // Tests only that all the methods are not crashing/throwing errors. + BlankSpan.INSTANCE.addAttributes(attributes); + BlankSpan.INSTANCE.addAttributes(multipleAttributes); + BlankSpan.INSTANCE.addAnnotation("MyAnnotation"); + BlankSpan.INSTANCE.addAnnotation("MyAnnotation", attributes); + BlankSpan.INSTANCE.addAnnotation("MyAnnotation", multipleAttributes); + BlankSpan.INSTANCE.addAnnotation(Annotation.fromDescription("MyAnnotation")); + BlankSpan.INSTANCE.addNetworkEvent(NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).build()); + BlankSpan.INSTANCE.addLink(Link.fromSpanContext(SpanContext.INVALID, Link.Type.CHILD)); + BlankSpan.INSTANCE.end(EndSpanOptions.DEFAULT); + BlankSpan.INSTANCE.end(); + } + + @Test + public void blankSpan_ToString() { + assertThat(BlankSpan.INSTANCE.toString()).isEqualTo("BlankSpan"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/ContextUtilsTest.java b/api/src/test/java/io/opencensus/trace/ContextUtilsTest.java new file mode 100644 index 00000000..e4513d74 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/ContextUtilsTest.java @@ -0,0 +1,90 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import io.grpc.Context; +import io.opencensus.common.NonThrowingCloseable; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** Unit tests for {@link ContextUtils}. */ +@RunWith(JUnit4.class) +public class ContextUtilsTest { + @Mock private Span span; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void getCurrentSpan_WhenNoContext() { + assertThat(ContextUtils.getCurrentSpan()).isNull(); + } + + @Test + public void getCurrentSpan() { + assertThat(ContextUtils.getCurrentSpan()).isNull(); + Context origContext = Context.current().withValue(ContextUtils.CONTEXT_SPAN_KEY, span).attach(); + // Make sure context is detached even if test fails. + try { + assertThat(ContextUtils.getCurrentSpan()).isSameAs(span); + } finally { + Context.current().detach(origContext); + } + assertThat(ContextUtils.getCurrentSpan()).isNull(); + } + + @Test + public void withSpan() { + assertThat(ContextUtils.getCurrentSpan()).isNull(); + NonThrowingCloseable ws = ContextUtils.withSpan(span); + try { + assertThat(ContextUtils.getCurrentSpan()).isSameAs(span); + } finally { + ws.close(); + } + assertThat(ContextUtils.getCurrentSpan()).isNull(); + ; + } + + @Test + public void propagationViaRunnable() { + Runnable runnable = null; + NonThrowingCloseable ws = ContextUtils.withSpan(span); + try { + assertThat(ContextUtils.getCurrentSpan()).isSameAs(span); + runnable = + Context.current() + .wrap( + new Runnable() { + @Override + public void run() { + assertThat(ContextUtils.getCurrentSpan()).isSameAs(span); + } + }); + } finally { + ws.close(); + } + assertThat(ContextUtils.getCurrentSpan()).isNotSameAs(span); + // When we run the runnable we will have the span in the current Context. + runnable.run(); + } +} diff --git a/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java b/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java new file mode 100644 index 00000000..d531fba5 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link EndSpanOptions}. */ +@RunWith(JUnit4.class) +public class EndSpanOptionsTest { + @Test(expected = NullPointerException.class) + public void setNullStatus() { + EndSpanOptions.builder().setStatus(null).build(); + } + + @Test + public void endSpanOptions_DefaultOptions() { + assertThat(EndSpanOptions.DEFAULT.getStatus()).isEqualTo(Status.OK); + } + + @Test + public void setStatus() { + EndSpanOptions endSpanOptions = + EndSpanOptions.builder() + .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) + .build(); + assertThat(endSpanOptions.getStatus()) + .isEqualTo(Status.CANCELLED.withDescription("ThisIsAnError")); + } + + @Test + public void endSpanOptions_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup( + EndSpanOptions.builder() + .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) + .build(), + EndSpanOptions.builder() + .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) + .build()); + tester.addEqualityGroup(EndSpanOptions.builder().build(), EndSpanOptions.DEFAULT); + tester.testEquals(); + } + + @Test + public void endSpanOptions_ToString() { + EndSpanOptions endSpanOptions = + EndSpanOptions.builder() + .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) + .build(); + assertThat(endSpanOptions.toString()).contains("ThisIsAnError"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/LinkTest.java b/api/src/test/java/io/opencensus/trace/LinkTest.java new file mode 100644 index 00000000..e1289f33 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/LinkTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.trace.Link.Type; +import java.util.Random; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Link}. */ +@RunWith(JUnit4.class) +public class LinkTest { + private final Random random = new Random(1234); + private final SpanContext spanContext = + SpanContext.create( + TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); + + @Test + public void fromSpanContext_ChildLink() { + Link link = Link.fromSpanContext(spanContext, Type.CHILD); + assertThat(link.getTraceId()).isEqualTo(spanContext.getTraceId()); + assertThat(link.getSpanId()).isEqualTo(spanContext.getSpanId()); + assertThat(link.getType()).isEqualTo(Type.CHILD); + } + + @Test + public void fromSpanContext_ParentLink() { + Link link = Link.fromSpanContext(spanContext, Type.PARENT); + assertThat(link.getTraceId()).isEqualTo(spanContext.getTraceId()); + assertThat(link.getSpanId()).isEqualTo(spanContext.getSpanId()); + assertThat(link.getType()).isEqualTo(Type.PARENT); + } + + @Test + public void link_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester + .addEqualityGroup( + Link.fromSpanContext(spanContext, Type.PARENT), + Link.fromSpanContext(spanContext, Type.PARENT)) + .addEqualityGroup( + Link.fromSpanContext(spanContext, Type.CHILD), + Link.fromSpanContext(spanContext, Type.CHILD)) + .addEqualityGroup(Link.fromSpanContext(SpanContext.INVALID, Type.CHILD)) + .addEqualityGroup(Link.fromSpanContext(SpanContext.INVALID, Type.PARENT)); + tester.testEquals(); + } + + @Test + public void link_ToString() { + Link link = Link.fromSpanContext(spanContext, Type.CHILD); + assertThat(link.toString()).contains(spanContext.getTraceId().toString()); + assertThat(link.toString()).contains(spanContext.getSpanId().toString()); + assertThat(link.toString()).contains("CHILD"); + link = Link.fromSpanContext(spanContext, Type.PARENT); + assertThat(link.toString()).contains(spanContext.getTraceId().toString()); + assertThat(link.toString()).contains(spanContext.getSpanId().toString()); + assertThat(link.toString()).contains("PARENT"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/NetworkEventTest.java b/api/src/test/java/io/opencensus/trace/NetworkEventTest.java new file mode 100644 index 00000000..946e8ce1 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/NetworkEventTest.java @@ -0,0 +1,87 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.common.Timestamp; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link NetworkEvent}. */ +@RunWith(JUnit4.class) +public class NetworkEventTest { + @Test(expected = NullPointerException.class) + public void buildNetworkEvent_NullType() { + NetworkEvent.builder(null, 1L).build(); + } + + @Test + public void buildNetworkEvent_WithRequiredFields() { + NetworkEvent networkEvent = NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).build(); + assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); + assertThat(networkEvent.getMessageId()).isEqualTo(1L); + assertThat(networkEvent.getKernelTimestamp()).isNull(); + assertThat(networkEvent.getMessageSize()).isEqualTo(0L); + } + + @Test + public void buildNetworkEvent_WithTimestamp() { + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.SENT, 1L) + .setKernelTimestamp(Timestamp.fromMillis(123456L)) + .build(); + assertThat(networkEvent.getKernelTimestamp()).isEqualTo(Timestamp.fromMillis(123456L)); + assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); + assertThat(networkEvent.getMessageId()).isEqualTo(1L); + assertThat(networkEvent.getMessageSize()).isEqualTo(0L); + } + + @Test + public void buildNetworkEvent_WithMessageSize() { + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).setMessageSize(123L).build(); + assertThat(networkEvent.getKernelTimestamp()).isNull(); + assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); + assertThat(networkEvent.getMessageId()).isEqualTo(1L); + assertThat(networkEvent.getMessageSize()).isEqualTo(123L); + } + + @Test + public void buildNetworkEvent_WithAllValues() { + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.RECV, 1L) + .setKernelTimestamp(Timestamp.fromMillis(123456L)) + .setMessageSize(123L) + .build(); + assertThat(networkEvent.getKernelTimestamp()).isEqualTo(Timestamp.fromMillis(123456L)); + assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.RECV); + assertThat(networkEvent.getMessageId()).isEqualTo(1L); + assertThat(networkEvent.getMessageSize()).isEqualTo(123L); + } + + @Test + public void networkEvent_ToString() { + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.SENT, 1L) + .setKernelTimestamp(Timestamp.fromMillis(123456L)) + .setMessageSize(123L) + .build(); + assertThat(networkEvent.toString()).contains(Timestamp.fromMillis(123456L).toString()); + assertThat(networkEvent.toString()).contains("type=SENT"); + assertThat(networkEvent.toString()).contains("messageId=1"); + assertThat(networkEvent.toString()).contains("messageSize=123"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/SamplersTest.java b/api/src/test/java/io/opencensus/trace/SamplersTest.java new file mode 100644 index 00000000..af7fcaf5 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/SamplersTest.java @@ -0,0 +1,167 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import java.util.Collections; +import java.util.Random; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Samplers}. */ +@RunWith(JUnit4.class) +public class SamplersTest { + private final Random random = new Random(1234); + private final TraceId traceId = TraceId.generateRandomId(random); + private final SpanId parentSpanId = SpanId.generateRandomId(random); + private final SpanId spanId = SpanId.generateRandomId(random); + private final SpanContext sampledSpanContext = + SpanContext.create(traceId, parentSpanId, TraceOptions.builder().setIsSampled().build()); + private final SpanContext notSampledSpanContext = + SpanContext.create(traceId, parentSpanId, TraceOptions.DEFAULT); + + @Test + public void alwaysSampleSampler_AlwaysReturnTrue() { + // Sampled parent. + assertThat( + Samplers.alwaysSample() + .shouldSample( + sampledSpanContext, + false, + traceId, + spanId, + "Another name", + Collections.emptyList())) + .isTrue(); + // Not sampled parent. + assertThat( + Samplers.alwaysSample() + .shouldSample( + notSampledSpanContext, + false, + traceId, + spanId, + "Yet another name", + Collections.emptyList())) + .isTrue(); + } + + @Test + public void alwaysSampleSampler_ToString() { + assertThat(Samplers.alwaysSample().toString()).isEqualTo("AlwaysSampleSampler"); + } + + @Test + public void neverSampleSampler_AlwaysReturnFalse() { + // Sampled parent. + assertThat( + Samplers.neverSample() + .shouldSample( + sampledSpanContext, + false, + traceId, + spanId, + "bar", + Collections.emptyList())) + .isFalse(); + // Not sampled parent. + assertThat( + Samplers.neverSample() + .shouldSample( + notSampledSpanContext, + false, + traceId, + spanId, + "quux", + Collections.emptyList())) + .isFalse(); + } + + @Test + public void neverSampleSampler_ToString() { + assertThat(Samplers.neverSample().toString()).isEqualTo("NeverSampleSampler"); + } + + @Test(expected = IllegalArgumentException.class) + public void probabilitySampler_outOfRangeHighProbability() { + Samplers.probabilitySampler(1.01); + } + + @Test(expected = IllegalArgumentException.class) + public void probabilitySampler_outOfRangeLowProbability() { + Samplers.probabilitySampler(-0.00001); + } + + private final void probabilitySampler_AlwaysReturnTrueForSampled(Sampler sampler) { + final int numSamples = 100; // Number of traces for which to generate sampling decisions. + for (int i = 0; i < numSamples; i++) { + assertThat( + sampler.shouldSample( + sampledSpanContext, + false, + TraceId.generateRandomId(random), + spanId, + "bar", + Collections.emptyList())) + .isTrue(); + } + } + + private final void probabilitySampler_SamplesWithProbabilityForUnsampled( + Sampler sampler, double probability) { + final int numSamples = 1000; // Number of traces for which to generate sampling decisions. + int count = 0; // Count of spans with sampling enabled + for (int i = 0; i < numSamples; i++) { + if (sampler.shouldSample( + notSampledSpanContext, + false, + TraceId.generateRandomId(random), + spanId, + "bar", + Collections.emptyList())) { + count++; + } + } + double proportionSampled = (double) count / numSamples; + // Allow for a large amount of slop (+/- 10%) in number of sampled traces, to avoid flakiness. + assertThat(proportionSampled < probability + 0.1 && proportionSampled > probability - 0.1) + .isTrue(); + } + + @Test + public void probabilitySamper_SamplesWithProbability() { + final Sampler neverSample = Samplers.probabilitySampler(0.0); + probabilitySampler_AlwaysReturnTrueForSampled(neverSample); + probabilitySampler_SamplesWithProbabilityForUnsampled(neverSample, 0.0); + final Sampler alwaysSample = Samplers.probabilitySampler(1.0); + probabilitySampler_AlwaysReturnTrueForSampled(alwaysSample); + probabilitySampler_SamplesWithProbabilityForUnsampled(alwaysSample, 1.0); + final Sampler fiftyPercentSample = Samplers.probabilitySampler(0.5); + probabilitySampler_AlwaysReturnTrueForSampled(fiftyPercentSample); + probabilitySampler_SamplesWithProbabilityForUnsampled(fiftyPercentSample, 0.5); + final Sampler twentyPercentSample = Samplers.probabilitySampler(0.2); + probabilitySampler_AlwaysReturnTrueForSampled(twentyPercentSample); + probabilitySampler_SamplesWithProbabilityForUnsampled(twentyPercentSample, 0.2); + final Sampler twoThirdsSample = Samplers.probabilitySampler(2.0 / 3.0); + probabilitySampler_AlwaysReturnTrueForSampled(twoThirdsSample); + probabilitySampler_SamplesWithProbabilityForUnsampled(twoThirdsSample, 2.0 / 3.0); + } + + @Test + public void probabilitySampler_ToString() { + assertThat((Samplers.probabilitySampler(0.5)).toString()).contains("0.5"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java b/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java new file mode 100644 index 00000000..8922f4c2 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java @@ -0,0 +1,51 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.same; +import static org.mockito.Mockito.verify; + +import io.opencensus.common.NonThrowingCloseable; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** Unit tests for {@link ScopedSpanHandle}. */ +@RunWith(JUnit4.class) +public class ScopedSpanHandleTest { + private static final Tracer tracer = Tracer.getNoopTracer(); + @Mock private Span span; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void initAttachesSpan_CloseDetachesAndEndsSpan() { + assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + NonThrowingCloseable ss = new ScopedSpanHandle(span); + try { + assertThat(tracer.getCurrentSpan()).isSameAs(span); + } finally { + ss.close(); + } + assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + verify(span).end(same(EndSpanOptions.DEFAULT)); + } +} diff --git a/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java b/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java new file mode 100644 index 00000000..ccd3d806 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java @@ -0,0 +1,170 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.isNull; +import static org.mockito.Matchers.same; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.opencensus.common.NonThrowingCloseable; +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** Unit tests for {@link Tracer}. */ +@RunWith(JUnit4.class) +public class SpanBuilderTest { + private static final String SPAN_NAME = "MySpanName"; + private static final Tracer tracer = Tracing.getTracer(); + private final Random random = new Random(1234); + private final SpanContext spanContext = + SpanContext.create( + TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); + @Mock private Span span; + @Mock private SpanFactory spanFactory; + private SpanBuilder spanBuilder; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + spanBuilder = SpanBuilder.builder(spanFactory, BlankSpan.INSTANCE, SPAN_NAME); + } + + @Test + public void startScopedSpanRoot() { + when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(new StartSpanOptions()))) + .thenReturn(span); + NonThrowingCloseable ss = spanBuilder.becomeRoot().startScopedSpan(); + try { + assertThat(tracer.getCurrentSpan()).isSameAs(span); + } finally { + ss.close(); + } + verify(span).end(same(EndSpanOptions.DEFAULT)); + } + + @Test + public void startScopedSpanRootWithOptions() { + StartSpanOptions startSpanOptions = new StartSpanOptions(); + startSpanOptions.setSampler(Samplers.neverSample()); + when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(startSpanOptions))) + .thenReturn(span); + NonThrowingCloseable ss = + spanBuilder.becomeRoot().setSampler(Samplers.neverSample()).startScopedSpan(); + try { + assertThat(tracer.getCurrentSpan()).isSameAs(span); + } finally { + ss.close(); + } + verify(span).end(same(EndSpanOptions.DEFAULT)); + } + + @Test + public void startRootSpan() { + when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(new StartSpanOptions()))) + .thenReturn(span); + Span rootSpan = spanBuilder.becomeRoot().startSpan(); + assertThat(rootSpan).isEqualTo(span); + rootSpan.end(); + verify(span).end(same(EndSpanOptions.DEFAULT)); + } + + @Test + public void startSpan_WithNullParent() { + spanBuilder = SpanBuilder.builder(spanFactory, null, SPAN_NAME); + when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(new StartSpanOptions()))) + .thenReturn(span); + Span rootSpan = spanBuilder.startSpan(); + assertThat(rootSpan).isEqualTo(span); + rootSpan.end(); + verify(span).end(same(EndSpanOptions.DEFAULT)); + } + + @Test + public void startRootSpanWithOptions() { + List parentList = Arrays.asList(BlankSpan.INSTANCE); + StartSpanOptions startSpanOptions = new StartSpanOptions(); + startSpanOptions.setParentLinks(parentList); + startSpanOptions.setSampler(Samplers.neverSample()); + when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(startSpanOptions))) + .thenReturn(span); + Span rootSpan = + spanBuilder + .becomeRoot() + .setSampler(Samplers.neverSample()) + .setParentLinks(parentList) + .startSpan(); + assertThat(rootSpan).isEqualTo(span); + rootSpan.end(); + verify(span).end(same(EndSpanOptions.DEFAULT)); + } + + @Test + public void startChildSpan() { + when(spanFactory.startSpan( + same(BlankSpan.INSTANCE), same(SPAN_NAME), eq(new StartSpanOptions()))) + .thenReturn(span); + Span childSpan = spanBuilder.startSpan(); + assertThat(childSpan).isEqualTo(span); + childSpan.end(); + verify(span).end(same(EndSpanOptions.DEFAULT)); + } + + @Test + public void startChildSpanWithOptions() { + StartSpanOptions startSpanOptions = new StartSpanOptions(); + startSpanOptions.setSampler(Samplers.neverSample()); + startSpanOptions.setRecordEvents(true); + when(spanFactory.startSpan(same(BlankSpan.INSTANCE), same(SPAN_NAME), eq(startSpanOptions))) + .thenReturn(span); + Span childSpan = + spanBuilder.setSampler(Samplers.neverSample()).setRecordEvents(true).startSpan(); + assertThat(childSpan).isEqualTo(span); + childSpan.end(); + verify(span).end(same(EndSpanOptions.DEFAULT)); + } + + @Test + public void startSpanWitRemoteParent() { + spanBuilder = SpanBuilder.builderWithRemoteParent(spanFactory, spanContext, SPAN_NAME); + when(spanFactory.startSpanWithRemoteParent( + same(spanContext), same(SPAN_NAME), eq(new StartSpanOptions()))) + .thenReturn(span); + Span remoteChildSpan = spanBuilder.startSpan(); + assertThat(remoteChildSpan).isEqualTo(span); + remoteChildSpan.end(); + verify(span).end(same(EndSpanOptions.DEFAULT)); + } + + @Test + public void startSpanWitRemoteParent_WithNullParent() { + spanBuilder = SpanBuilder.builderWithRemoteParent(spanFactory, null, SPAN_NAME); + when(spanFactory.startSpanWithRemoteParent( + isNull(SpanContext.class), same(SPAN_NAME), eq(new StartSpanOptions()))) + .thenReturn(span); + Span remoteChildSpan = spanBuilder.startSpan(); + assertThat(remoteChildSpan).isEqualTo(span); + remoteChildSpan.end(); + verify(span).end(same(EndSpanOptions.DEFAULT)); + } +} diff --git a/api/src/test/java/io/opencensus/trace/SpanContextTest.java b/api/src/test/java/io/opencensus/trace/SpanContextTest.java new file mode 100644 index 00000000..c0eb5d40 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/SpanContextTest.java @@ -0,0 +1,113 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link SpanContext}. */ +@RunWith(JUnit4.class) +public class SpanContextTest { + private static final byte[] firstTraceIdBytes = + new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'a'}; + private static final byte[] secondTraceIdBytes = + new byte[] {0, 0, 0, 0, 0, 0, 0, '0', 0, 0, 0, 0, 0, 0, 0, 0}; + private static final byte[] firstSpanIdBytes = new byte[] {0, 0, 0, 0, 0, 0, 0, 'a'}; + private static final byte[] secondSpanIdBytes = new byte[] {'0', 0, 0, 0, 0, 0, 0, 0}; + private static final SpanContext first = + SpanContext.create( + TraceId.fromBytes(firstTraceIdBytes), + SpanId.fromBytes(firstSpanIdBytes), + TraceOptions.DEFAULT); + private static final SpanContext second = + SpanContext.create( + TraceId.fromBytes(secondTraceIdBytes), + SpanId.fromBytes(secondSpanIdBytes), + TraceOptions.builder().setIsSampled().build()); + + @Test + public void invalidSpanContext() { + assertThat(SpanContext.INVALID.getTraceId()).isEqualTo(TraceId.INVALID); + assertThat(SpanContext.INVALID.getSpanId()).isEqualTo(SpanId.INVALID); + assertThat(SpanContext.INVALID.getTraceOptions()).isEqualTo(TraceOptions.DEFAULT); + } + + @Test + public void isValid() { + assertThat(SpanContext.INVALID.isValid()).isFalse(); + assertThat( + SpanContext.create( + TraceId.fromBytes(firstTraceIdBytes), SpanId.INVALID, TraceOptions.DEFAULT) + .isValid()) + .isFalse(); + assertThat( + SpanContext.create( + TraceId.INVALID, SpanId.fromBytes(firstSpanIdBytes), TraceOptions.DEFAULT) + .isValid()) + .isFalse(); + assertThat(first.isValid()).isTrue(); + assertThat(second.isValid()).isTrue(); + } + + @Test + public void getTraceId() { + assertThat(first.getTraceId()).isEqualTo(TraceId.fromBytes(firstTraceIdBytes)); + assertThat(second.getTraceId()).isEqualTo(TraceId.fromBytes(secondTraceIdBytes)); + } + + @Test + public void getSpanId() { + assertThat(first.getSpanId()).isEqualTo(SpanId.fromBytes(firstSpanIdBytes)); + assertThat(second.getSpanId()).isEqualTo(SpanId.fromBytes(secondSpanIdBytes)); + } + + @Test + public void getTraceOptions() { + assertThat(first.getTraceOptions()).isEqualTo(TraceOptions.DEFAULT); + assertThat(second.getTraceOptions()).isEqualTo(TraceOptions.builder().setIsSampled().build()); + } + + @Test + public void spanContext_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup( + first, + SpanContext.create( + TraceId.fromBytes(firstTraceIdBytes), + SpanId.fromBytes(firstSpanIdBytes), + TraceOptions.DEFAULT)); + tester.addEqualityGroup( + second, + SpanContext.create( + TraceId.fromBytes(secondTraceIdBytes), + SpanId.fromBytes(secondSpanIdBytes), + TraceOptions.builder().setIsSampled().build())); + tester.testEquals(); + } + + @Test + public void spanContext_ToString() { + assertThat(first.toString()).contains(TraceId.fromBytes(firstTraceIdBytes).toString()); + assertThat(first.toString()).contains(SpanId.fromBytes(firstSpanIdBytes).toString()); + assertThat(first.toString()).contains(TraceOptions.DEFAULT.toString()); + assertThat(second.toString()).contains(TraceId.fromBytes(secondTraceIdBytes).toString()); + assertThat(second.toString()).contains(SpanId.fromBytes(secondSpanIdBytes).toString()); + assertThat(second.toString()) + .contains(TraceOptions.builder().setIsSampled().build().toString()); + } +} diff --git a/api/src/test/java/io/opencensus/trace/SpanDataTest.java b/api/src/test/java/io/opencensus/trace/SpanDataTest.java new file mode 100644 index 00000000..7a7f7899 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/SpanDataTest.java @@ -0,0 +1,241 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Timestamp; +import io.opencensus.trace.Link.Type; +import io.opencensus.trace.SpanData.Attributes; +import io.opencensus.trace.SpanData.Links; +import io.opencensus.trace.SpanData.TimedEvent; +import io.opencensus.trace.SpanData.TimedEvents; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Random; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link SpanData}. */ +@RunWith(JUnit4.class) +public class SpanDataTest { + private static final Timestamp startTimestamp = Timestamp.create(123, 456); + private static final Timestamp eventTimestamp1 = Timestamp.create(123, 457); + private static final Timestamp eventTimestamp2 = Timestamp.create(123, 458); + private static final Timestamp eventTimestamp3 = Timestamp.create(123, 459); + private static final Timestamp endTimestamp = Timestamp.create(123, 460); + private static final String DISPLAY_NAME = "MySpanDisplayName"; + private static final String ANNOTATION_TEXT = "MyAnnotationText"; + private static final Annotation annotation = Annotation.fromDescription(ANNOTATION_TEXT); + private static final NetworkEvent recvNetworkEvent = + NetworkEvent.builder(NetworkEvent.Type.RECV, 1).build(); + private static final NetworkEvent sentNetworkEvent = + NetworkEvent.builder(NetworkEvent.Type.SENT, 1).build(); + private static final Status status = Status.DEADLINE_EXCEEDED.withDescription("TooSlow"); + private final Random random = new Random(1234); + private final SpanContext spanContext = + SpanContext.create( + TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); + private final SpanId parentSpanId = SpanId.generateRandomId(random); + private final Map attributesMap = new HashMap(); + private final List> annotationsList = + new LinkedList>(); + private final List> networkEventsList = + new LinkedList>(); + private final List linksList = new LinkedList(); + private Attributes attributes; + private TimedEvents annotations; + private TimedEvents networkEvents; + private Links links; + + @Before + public void setUp() { + attributesMap.put("MyAttributeKey1", AttributeValue.longAttributeValue(10)); + attributesMap.put("MyAttributeKey2", AttributeValue.booleanAttributeValue(true)); + attributes = Attributes.create(attributesMap, 1); + annotationsList.add(SpanData.TimedEvent.create(eventTimestamp1, annotation)); + annotationsList.add(SpanData.TimedEvent.create(eventTimestamp3, annotation)); + annotations = TimedEvents.create(annotationsList, 2); + networkEventsList.add(SpanData.TimedEvent.create(eventTimestamp1, recvNetworkEvent)); + networkEventsList.add(SpanData.TimedEvent.create(eventTimestamp2, sentNetworkEvent)); + networkEvents = TimedEvents.create(networkEventsList, 3); + linksList.add(Link.fromSpanContext(spanContext, Type.CHILD)); + links = Links.create(linksList, 0); + } + + @Test + public void spanData_AllValues() { + SpanData spanData = + SpanData.create( + spanContext, + parentSpanId, + true, + DISPLAY_NAME, + startTimestamp, + attributes, + annotations, + networkEvents, + links, + status, + endTimestamp); + assertThat(spanData.getContext()).isEqualTo(spanContext); + assertThat(spanData.getParentSpanId()).isEqualTo(parentSpanId); + assertThat(spanData.getHasRemoteParent()).isTrue(); + assertThat(spanData.getDisplayName()).isEqualTo(DISPLAY_NAME); + assertThat(spanData.getStartTimestamp()).isEqualTo(startTimestamp); + assertThat(spanData.getAttributes()).isEqualTo(attributes); + assertThat(spanData.getAnnotations()).isEqualTo(annotations); + assertThat(spanData.getNetworkEvents()).isEqualTo(networkEvents); + assertThat(spanData.getLinks()).isEqualTo(links); + assertThat(spanData.getStatus()).isEqualTo(status); + assertThat(spanData.getEndTimestamp()).isEqualTo(endTimestamp); + } + + @Test + public void spanData_RootActiveSpan() { + SpanData spanData = + SpanData.create( + spanContext, + null, + false, + DISPLAY_NAME, + startTimestamp, + attributes, + annotations, + networkEvents, + links, + null, + null); + assertThat(spanData.getContext()).isEqualTo(spanContext); + assertThat(spanData.getParentSpanId()).isNull(); + assertThat(spanData.getHasRemoteParent()).isFalse(); + assertThat(spanData.getDisplayName()).isEqualTo(DISPLAY_NAME); + assertThat(spanData.getStartTimestamp()).isEqualTo(startTimestamp); + assertThat(spanData.getAttributes()).isEqualTo(attributes); + assertThat(spanData.getAnnotations()).isEqualTo(annotations); + assertThat(spanData.getNetworkEvents()).isEqualTo(networkEvents); + assertThat(spanData.getLinks()).isEqualTo(links); + assertThat(spanData.getStatus()).isNull(); + assertThat(spanData.getEndTimestamp()).isNull(); + } + + @Test + public void spanData_AllDataEmpty() { + SpanData spanData = + SpanData.create( + spanContext, + parentSpanId, + false, + DISPLAY_NAME, + startTimestamp, + Attributes.create(Collections.emptyMap(), 0), + TimedEvents.create(Collections.>emptyList(), 0), + TimedEvents.create(Collections.>emptyList(), 0), + Links.create(Collections.emptyList(), 0), + status, + endTimestamp); + assertThat(spanData.getContext()).isEqualTo(spanContext); + assertThat(spanData.getParentSpanId()).isEqualTo(parentSpanId); + assertThat(spanData.getHasRemoteParent()).isFalse(); + assertThat(spanData.getDisplayName()).isEqualTo(DISPLAY_NAME); + assertThat(spanData.getStartTimestamp()).isEqualTo(startTimestamp); + assertThat(spanData.getAttributes().getAttributeMap().isEmpty()).isTrue(); + assertThat(spanData.getAnnotations().getEvents().isEmpty()).isTrue(); + assertThat(spanData.getNetworkEvents().getEvents().isEmpty()).isTrue(); + assertThat(spanData.getLinks().getLinks().isEmpty()).isTrue(); + assertThat(spanData.getStatus()).isEqualTo(status); + assertThat(spanData.getEndTimestamp()).isEqualTo(endTimestamp); + } + + @Test + public void spanDataEquals() { + SpanData allSpanData1 = + SpanData.create( + spanContext, + parentSpanId, + false, + DISPLAY_NAME, + startTimestamp, + attributes, + annotations, + networkEvents, + links, + status, + endTimestamp); + SpanData allSpanData2 = + SpanData.create( + spanContext, + parentSpanId, + false, + DISPLAY_NAME, + startTimestamp, + attributes, + annotations, + networkEvents, + links, + status, + endTimestamp); + SpanData emptySpanData = + SpanData.create( + spanContext, + parentSpanId, + false, + DISPLAY_NAME, + startTimestamp, + Attributes.create(Collections.emptyMap(), 0), + TimedEvents.create(Collections.>emptyList(), 0), + TimedEvents.create(Collections.>emptyList(), 0), + Links.create(Collections.emptyList(), 0), + status, + endTimestamp); + new EqualsTester() + .addEqualityGroup(allSpanData1, allSpanData2) + .addEqualityGroup(emptySpanData) + .testEquals(); + } + + @Test + public void spanData_ToString() { + String spanDataString = + SpanData.create( + spanContext, + parentSpanId, + false, + DISPLAY_NAME, + startTimestamp, + attributes, + annotations, + networkEvents, + links, + status, + endTimestamp) + .toString(); + assertThat(spanDataString).contains(spanContext.toString()); + assertThat(spanDataString).contains(parentSpanId.toString()); + assertThat(spanDataString).contains(DISPLAY_NAME); + assertThat(spanDataString).contains(startTimestamp.toString()); + assertThat(spanDataString).contains(attributes.toString()); + assertThat(spanDataString).contains(annotations.toString()); + assertThat(spanDataString).contains(networkEvents.toString()); + assertThat(spanDataString).contains(links.toString()); + assertThat(spanDataString).contains(status.toString()); + assertThat(spanDataString).contains(endTimestamp.toString()); + } +} diff --git a/api/src/test/java/io/opencensus/trace/SpanIdTest.java b/api/src/test/java/io/opencensus/trace/SpanIdTest.java new file mode 100644 index 00000000..a35fddce --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/SpanIdTest.java @@ -0,0 +1,73 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import java.util.Arrays; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link SpanId}. */ +@RunWith(JUnit4.class) +public class SpanIdTest { + private static final byte[] firstBytes = new byte[] {0, 0, 0, 0, 0, 0, 0, 'a'}; + private static final byte[] secondBytes = new byte[] {(byte) 0xFF, 0, 0, 0, 0, 0, 0, 0}; + private static final SpanId first = SpanId.fromBytes(firstBytes); + private static final SpanId second = SpanId.fromBytes(secondBytes); + + @Test + public void invalidSpanId() { + assertThat(SpanId.INVALID.getBytes()).isEqualTo(new byte[8]); + } + + @Test + public void isValid() { + assertThat(SpanId.INVALID.isValid()).isFalse(); + assertThat(first.isValid()).isTrue(); + assertThat(second.isValid()).isTrue(); + } + + @Test + public void getBytes() { + assertThat(first.getBytes()).isEqualTo(firstBytes); + assertThat(second.getBytes()).isEqualTo(secondBytes); + } + + @Test + public void traceId_CompareTo() { + assertThat(first.compareTo(second)).isGreaterThan(0); + assertThat(second.compareTo(first)).isLessThan(0); + assertThat(first.compareTo(SpanId.fromBytes(firstBytes))).isEqualTo(0); + } + + @Test + public void traceId_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup(SpanId.INVALID, SpanId.INVALID); + tester.addEqualityGroup(first, SpanId.fromBytes(Arrays.copyOf(firstBytes, firstBytes.length))); + tester.addEqualityGroup( + second, SpanId.fromBytes(Arrays.copyOf(secondBytes, secondBytes.length))); + tester.testEquals(); + } + + @Test + public void traceId_ToString() { + assertThat(SpanId.INVALID.toString()).contains("0000000000000000"); + assertThat(first.toString()).contains("0000000000000061"); + assertThat(second.toString()).contains("ff00000000000000"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/SpanTest.java b/api/src/test/java/io/opencensus/trace/SpanTest.java new file mode 100644 index 00000000..c8f7cb50 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/SpanTest.java @@ -0,0 +1,112 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.same; +import static org.mockito.Mockito.verify; + +import java.util.EnumSet; +import java.util.Map; +import java.util.Random; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mockito; + +/** Unit tests for {@link Span}. */ +@RunWith(JUnit4.class) +public class SpanTest { + private Random random; + private SpanContext spanContext; + private SpanContext notSampledSpanContext; + private EnumSet spanOptions; + + @Before + public void setUp() { + random = new Random(1234); + spanContext = + SpanContext.create( + TraceId.generateRandomId(random), + SpanId.generateRandomId(random), + TraceOptions.builder().setIsSampled().build()); + notSampledSpanContext = + SpanContext.create( + TraceId.generateRandomId(random), + SpanId.generateRandomId(random), + TraceOptions.DEFAULT); + spanOptions = EnumSet.of(Span.Options.RECORD_EVENTS); + } + + @Test(expected = NullPointerException.class) + public void newSpan_WithNullContext() { + new NoopSpan(null, null); + } + + @Test(expected = IllegalArgumentException.class) + public void newSpan_SampledContextAndNullOptions() { + new NoopSpan(spanContext, null); + } + + @Test(expected = IllegalArgumentException.class) + public void newSpan_SampledContextAndEmptyOptions() { + new NoopSpan(spanContext, EnumSet.noneOf(Span.Options.class)); + } + + @Test + public void getOptions_WhenNullOptions() { + Span span = new NoopSpan(notSampledSpanContext, null); + assertThat(span.getOptions()).isEmpty(); + } + + @Test + public void getContextAndOptions() { + Span span = new NoopSpan(spanContext, spanOptions); + assertThat(span.getContext()).isEqualTo(spanContext); + assertThat(span.getOptions()).isEqualTo(spanOptions); + } + + @Test + public void endCallsEndWithDefaultOptions() { + Span span = Mockito.spy(new NoopSpan(spanContext, spanOptions)); + span.end(); + verify(span).end(same(EndSpanOptions.DEFAULT)); + } + + // No-op implementation of the Span for testing only. + private static class NoopSpan extends Span { + private NoopSpan(SpanContext context, EnumSet options) { + super(context, options); + } + + @Override + public void addAttributes(Map attributes) {} + + @Override + public void addAnnotation(String description, Map attributes) {} + + @Override + public void addAnnotation(Annotation annotation) {} + + @Override + public void addNetworkEvent(NetworkEvent networkEvent) {} + + @Override + public void addLink(Link link) {} + + @Override + public void end(EndSpanOptions options) {} + } +} diff --git a/api/src/test/java/io/opencensus/trace/StartSpanOptionsTest.java b/api/src/test/java/io/opencensus/trace/StartSpanOptionsTest.java new file mode 100644 index 00000000..b91e78ee --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/StartSpanOptionsTest.java @@ -0,0 +1,110 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link StartSpanOptions}. */ +@RunWith(JUnit4.class) +public class StartSpanOptionsTest { + private final List singleParentList = Arrays.asList(BlankSpan.INSTANCE); + + @Test + public void defaultOptions() { + StartSpanOptions defaultOptions = new StartSpanOptions(); + assertThat(defaultOptions.getSampler()).isNull(); + assertThat(defaultOptions.getParentLinks().isEmpty()).isTrue(); + assertThat(defaultOptions.getRecordEvents()).isNull(); + } + + @Test + public void setSampler() { + StartSpanOptions options = new StartSpanOptions(); + options.setSampler(Samplers.neverSample()); + assertThat(options.getSampler()).isEqualTo(Samplers.neverSample()); + assertThat(options.getParentLinks().isEmpty()).isTrue(); + assertThat(options.getRecordEvents()).isNull(); + } + + @Test + public void setParentLinks() { + StartSpanOptions options = new StartSpanOptions(); + options.setParentLinks(singleParentList); + assertThat(options.getSampler()).isNull(); + assertThat(options.getParentLinks()).isEqualTo(singleParentList); + assertThat(options.getRecordEvents()).isNull(); + } + + @Test + public void setParentLinks_EmptyList() { + StartSpanOptions options = new StartSpanOptions(); + options.setParentLinks(new LinkedList()); + assertThat(options.getSampler()).isNull(); + assertThat(options.getParentLinks().size()).isEqualTo(0); + assertThat(options.getRecordEvents()).isNull(); + } + + @Test + public void setParentLinks_MultipleParents() { + StartSpanOptions options = new StartSpanOptions(); + options.setParentLinks(Arrays.asList(BlankSpan.INSTANCE, BlankSpan.INSTANCE)); + assertThat(options.getSampler()).isNull(); + assertThat(options.getParentLinks().size()).isEqualTo(2); + assertThat(options.getRecordEvents()).isNull(); + } + + @Test + public void setRecordEvents() { + StartSpanOptions options = new StartSpanOptions(); + options.setRecordEvents(true); + assertThat(options.getSampler()).isNull(); + assertThat(options.getParentLinks().isEmpty()).isTrue(); + assertThat(options.getRecordEvents()).isTrue(); + } + + @Test + public void setAllProperties() { + StartSpanOptions options = new StartSpanOptions(); + options.setSampler(Samplers.neverSample()); + options.setSampler(Samplers.alwaysSample()); // second SetSampler should apply + options.setRecordEvents(true); + options.setParentLinks(singleParentList); + assertThat(options.getSampler()).isEqualTo(Samplers.alwaysSample()); + assertThat(options.getParentLinks()).isEqualTo(singleParentList); + assertThat(options.getRecordEvents()).isTrue(); + } + + @Test + public void startSpanOptions_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + StartSpanOptions optionsWithAlwaysSampler1 = new StartSpanOptions(); + optionsWithAlwaysSampler1.setSampler(Samplers.alwaysSample()); + StartSpanOptions optionsWithAlwaysSampler2 = new StartSpanOptions(); + optionsWithAlwaysSampler2.setSampler(Samplers.alwaysSample()); + tester.addEqualityGroup(optionsWithAlwaysSampler1, optionsWithAlwaysSampler2); + StartSpanOptions optionsWithNeverSampler = new StartSpanOptions(); + optionsWithNeverSampler.setSampler(Samplers.neverSample()); + tester.addEqualityGroup(optionsWithNeverSampler); + tester.addEqualityGroup(new StartSpanOptions()); + tester.testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/trace/StatusTest.java b/api/src/test/java/io/opencensus/trace/StatusTest.java new file mode 100644 index 00000000..c66a3428 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/StatusTest.java @@ -0,0 +1,51 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Status}. */ +@RunWith(JUnit4.class) +public class StatusTest { + @Test + public void status_Ok() { + assertThat(Status.OK.getCanonicalCode()).isEqualTo(Status.CanonicalCode.OK); + assertThat(Status.OK.getDescription()).isNull(); + assertThat(Status.OK.isOk()).isTrue(); + } + + @Test + public void createStatus_WithDescription() { + Status status = Status.UNKNOWN.withDescription("This is an error."); + assertThat(status.getCanonicalCode()).isEqualTo(Status.CanonicalCode.UNKNOWN); + assertThat(status.getDescription()).isEqualTo("This is an error."); + assertThat(status.isOk()).isFalse(); + } + + @Test + public void status_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup(Status.OK, Status.OK.withDescription(null)); + tester.addEqualityGroup( + Status.CANCELLED.withDescription("ThisIsAnError"), + Status.CANCELLED.withDescription("ThisIsAnError")); + tester.addEqualityGroup(Status.UNKNOWN.withDescription("This is an error.")); + tester.testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/trace/TraceComponentTest.java b/api/src/test/java/io/opencensus/trace/TraceComponentTest.java new file mode 100644 index 00000000..106cb965 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/TraceComponentTest.java @@ -0,0 +1,53 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.internal.ZeroTimeClock; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TraceComponent}. */ +@RunWith(JUnit4.class) +public class TraceComponentTest { + @Test + public void defaultTracer() { + assertThat(TraceComponent.getNoopTraceComponent().getTracer()).isSameAs(Tracer.getNoopTracer()); + } + + @Test + public void defaultBinaryPropagationHandler() { + assertThat(TraceComponent.getNoopTraceComponent().getBinaryPropagationHandler()) + .isSameAs(BinaryPropagationHandler.getNoopBinaryPropagationHandler()); + } + + @Test + public void defaultClock() { + assertThat(TraceComponent.getNoopTraceComponent().getClock()).isInstanceOf(ZeroTimeClock.class); + } + + @Test + public void defaultTraceExporter() { + assertThat(TraceComponent.getNoopTraceComponent().getTraceExporter()) + .isSameAs(TraceExporter.getNoopTraceExporter()); + } + + @Test + public void defaultTraceConfig() { + assertThat(TraceComponent.getNoopTraceComponent().getTraceConfig()) + .isSameAs(TraceConfig.getNoopTraceConfig()); + } +} diff --git a/api/src/test/java/io/opencensus/trace/TraceExporterTest.java b/api/src/test/java/io/opencensus/trace/TraceExporterTest.java new file mode 100644 index 00000000..3837a1ad --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/TraceExporterTest.java @@ -0,0 +1,47 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.verify; + +import io.opencensus.trace.TraceExporter.LoggingServiceHandler; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** Unit tests for {@link TraceExporter}. */ +@RunWith(JUnit4.class) +public class TraceExporterTest { + @Mock private TraceExporter traceExporter; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void registerUnregisterLoggingService() { + LoggingServiceHandler.registerService(traceExporter); + verify(traceExporter) + .registerServiceHandler( + eq("io.opencensus.trace.LoggingServiceHandler"), any(LoggingServiceHandler.class)); + LoggingServiceHandler.unregisterService(traceExporter); + verify(traceExporter).unregisterServiceHandler(eq("io.opencensus.trace.LoggingServiceHandler")); + } +} diff --git a/api/src/test/java/io/opencensus/trace/TraceIdTest.java b/api/src/test/java/io/opencensus/trace/TraceIdTest.java new file mode 100644 index 00000000..cd1b7c24 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/TraceIdTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 2016, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import java.util.Arrays; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TraceId}. */ +@RunWith(JUnit4.class) +public class TraceIdTest { + private static final byte[] firstBytes = + new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'a'}; + private static final byte[] secondBytes = + new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'A'}; + private static final TraceId first = TraceId.fromBytes(firstBytes); + private static final TraceId second = TraceId.fromBytes(secondBytes); + + @Test + public void invalidTraceId() { + assertThat(TraceId.INVALID.getBytes()).isEqualTo(new byte[16]); + } + + @Test + public void isValid() { + assertThat(TraceId.INVALID.isValid()).isFalse(); + assertThat(first.isValid()).isTrue(); + assertThat(second.isValid()).isTrue(); + } + + @Test + public void getBytes() { + assertThat(first.getBytes()).isEqualTo(firstBytes); + assertThat(second.getBytes()).isEqualTo(secondBytes); + } + + @Test + public void traceId_CompareTo() { + assertThat(first.compareTo(second)).isGreaterThan(0); + assertThat(second.compareTo(first)).isLessThan(0); + assertThat(first.compareTo(TraceId.fromBytes(firstBytes))).isEqualTo(0); + } + + @Test + public void traceId_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup(TraceId.INVALID, TraceId.INVALID); + tester.addEqualityGroup(first, TraceId.fromBytes(Arrays.copyOf(firstBytes, firstBytes.length))); + tester.addEqualityGroup( + second, TraceId.fromBytes(Arrays.copyOf(secondBytes, secondBytes.length))); + tester.testEquals(); + } + + @Test + public void traceId_ToString() { + assertThat(TraceId.INVALID.toString()).contains("00000000000000000000000000000000"); + assertThat(first.toString()).contains("00000000000000000000000000000061"); + assertThat(second.toString()).contains("00000000000000000000000000000041"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java b/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java new file mode 100644 index 00000000..fb240646 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java @@ -0,0 +1,77 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TraceOptions}. */ +@RunWith(JUnit4.class) +public class TraceOptionsTest { + private static final byte[] firstBytes = {(byte) 0xff}; + private static final byte[] secondBytes = {1}; + private static final byte[] thirdBytes = {6}; + + @Test + public void getOptions() { + assertThat(TraceOptions.DEFAULT.getOptions()).isEqualTo(0); + assertThat(TraceOptions.builder().setIsSampled().build().getOptions()).isEqualTo(1); + assertThat(TraceOptions.fromBytes(firstBytes).getOptions()).isEqualTo(-1); + assertThat(TraceOptions.fromBytes(secondBytes).getOptions()).isEqualTo(1); + assertThat(TraceOptions.fromBytes(thirdBytes).getOptions()).isEqualTo(6); + } + + @Test + public void isSampled() { + assertThat(TraceOptions.DEFAULT.isSampled()).isFalse(); + assertThat(TraceOptions.builder().setIsSampled().build().isSampled()).isTrue(); + } + + @Test + public void toFromBytes() { + assertThat(TraceOptions.fromBytes(firstBytes).getBytes()).isEqualTo(firstBytes); + assertThat(TraceOptions.fromBytes(secondBytes).getBytes()).isEqualTo(secondBytes); + assertThat(TraceOptions.fromBytes(thirdBytes).getBytes()).isEqualTo(thirdBytes); + } + + @Test + public void builder_FromOptions() { + assertThat( + TraceOptions.builder(TraceOptions.fromBytes(thirdBytes)) + .setIsSampled() + .build() + .getOptions()) + .isEqualTo(6 | 1); + } + + @Test + public void traceOptions_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup(TraceOptions.DEFAULT); + tester.addEqualityGroup( + TraceOptions.fromBytes(secondBytes), TraceOptions.builder().setIsSampled().build()); + tester.addEqualityGroup(TraceOptions.fromBytes(firstBytes)); + tester.testEquals(); + } + + @Test + public void traceOptions_ToString() { + assertThat(TraceOptions.DEFAULT.toString()).contains("sampled=false"); + assertThat(TraceOptions.builder().setIsSampled().build().toString()).contains("sampled=true"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/TraceParamsTest.java b/api/src/test/java/io/opencensus/trace/TraceParamsTest.java new file mode 100644 index 00000000..60f40deb --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/TraceParamsTest.java @@ -0,0 +1,77 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.trace.TraceConfig.TraceParams; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TraceParams}. */ +@RunWith(JUnit4.class) +public class TraceParamsTest { + @Test + public void defaultTraceParams() { + assertThat(TraceParams.DEFAULT.getSampler()).isEqualTo(Samplers.probabilitySampler(1e-4)); + assertThat(TraceParams.DEFAULT.getMaxNumberOfAttributes()).isEqualTo(32); + assertThat(TraceParams.DEFAULT.getMaxNumberOfAnnotations()).isEqualTo(32); + assertThat(TraceParams.DEFAULT.getMaxNumberOfNetworkEvents()).isEqualTo(128); + assertThat(TraceParams.DEFAULT.getMaxNumberOfLinks()).isEqualTo(128); + } + + @Test(expected = NullPointerException.class) + public void updateTraceParams_NullSampler() { + TraceParams.DEFAULT.toBuilder().setSampler(null).build(); + } + + @Test(expected = IllegalArgumentException.class) + public void updateTraceParams_NonPositiveMaxNumberOfAttributes() { + TraceParams.DEFAULT.toBuilder().setMaxNumberOfAttributes(0).build(); + } + + @Test(expected = IllegalArgumentException.class) + public void updateTraceParams_NonPositiveMaxNumberOfAnnotations() { + TraceParams.DEFAULT.toBuilder().setMaxNumberOfAnnotations(0).build(); + } + + @Test(expected = IllegalArgumentException.class) + public void updateTraceParams_NonPositiveMaxNumberOfNetworkEvents() { + TraceParams.DEFAULT.toBuilder().setMaxNumberOfNetworkEvents(0).build(); + } + + @Test(expected = IllegalArgumentException.class) + public void updateTraceParams_NonPositiveMaxNumberOfLinks() { + TraceParams.DEFAULT.toBuilder().setMaxNumberOfLinks(0).build(); + } + + @Test + public void updateTraceParams_All() { + TraceParams traceParams = + TraceParams.DEFAULT + .toBuilder() + .setSampler(Samplers.alwaysSample()) + .setMaxNumberOfAttributes(8) + .setMaxNumberOfAnnotations(9) + .setMaxNumberOfNetworkEvents(10) + .setMaxNumberOfLinks(11) + .build(); + assertThat(traceParams.getSampler()).isEqualTo(Samplers.alwaysSample()); + assertThat(traceParams.getMaxNumberOfAttributes()).isEqualTo(8); + assertThat(traceParams.getMaxNumberOfAnnotations()).isEqualTo(9); + assertThat(traceParams.getMaxNumberOfNetworkEvents()).isEqualTo(10); + assertThat(traceParams.getMaxNumberOfLinks()).isEqualTo(11); + } +} diff --git a/api/src/test/java/io/opencensus/trace/TracerTest.java b/api/src/test/java/io/opencensus/trace/TracerTest.java new file mode 100644 index 00000000..cc46956c --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/TracerTest.java @@ -0,0 +1,210 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.isNull; +import static org.mockito.Matchers.same; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.grpc.Context; +import io.opencensus.common.NonThrowingCloseable; +import java.util.Random; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** Unit tests for {@link Tracer}. */ +@RunWith(JUnit4.class) +public class TracerTest { + private static final Tracer tracer = Tracing.getTracer(); + private static final String SPAN_NAME = "MySpanName"; + @Rule public ExpectedException thrown = ExpectedException.none(); + @Mock private SpanFactory spanFactory; + @Mock private Span span; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void defaultGetCurrentSpan() { + assertThat(tracer.getCurrentSpan()).isEqualTo(BlankSpan.INSTANCE); + } + + @Test(expected = NullPointerException.class) + public void withSpan_NullSpan() { + tracer.withSpan(null); + } + + @Test + public void getCurrentSpan_WithSpan() { + assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + NonThrowingCloseable ws = tracer.withSpan(span); + try { + assertThat(tracer.getCurrentSpan()).isSameAs(span); + } finally { + ws.close(); + } + assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + } + + @Test + public void propagationViaRunnable() { + Runnable runnable = null; + NonThrowingCloseable ws = tracer.withSpan(span); + try { + assertThat(tracer.getCurrentSpan()).isSameAs(span); + runnable = + Context.current() + .wrap( + new Runnable() { + @Override + public void run() { + assertThat(tracer.getCurrentSpan()).isSameAs(span); + } + }); + } finally { + ws.close(); + } + assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + // When we run the runnable we will have the span in the current Context. + runnable.run(); + assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + } + + @Test(expected = NullPointerException.class) + public void spanBuilderWithName_NullName() { + assertThat(tracer.spanBuilder(null).startSpan()).isSameAs(BlankSpan.INSTANCE); + } + + @Test + public void defaultSpanBuilderWithName() { + assertThat(tracer.spanBuilder(SPAN_NAME).startSpan()).isSameAs(BlankSpan.INSTANCE); + } + + @Test(expected = NullPointerException.class) + public void spanBuilderWithParentAndName_NullName() { + assertThat(tracer.spanBuilder(null, null).startSpan()).isSameAs(BlankSpan.INSTANCE); + } + + @Test + public void defaultSpanBuilderWithParentAndName() { + assertThat(tracer.spanBuilder(null, SPAN_NAME).startSpan()).isSameAs(BlankSpan.INSTANCE); + } + + @Test(expected = NullPointerException.class) + public void spanBuilderWithRemoteParent_NullName() { + assertThat(tracer.spanBuilderWithRemoteParent(null, null).startSpan()) + .isSameAs(BlankSpan.INSTANCE); + } + + @Test + public void defaultSpanBuilderWitRemoteParent() { + assertThat(tracer.spanBuilderWithRemoteParent(null, SPAN_NAME).startSpan()) + .isSameAs(BlankSpan.INSTANCE); + } + + @Test + public void startScopedSpanRoot() { + Tracer mockTracer = new MockTracer(spanFactory); + when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(new StartSpanOptions()))) + .thenReturn(span); + NonThrowingCloseable ss = mockTracer.spanBuilder(SPAN_NAME).becomeRoot().startScopedSpan(); + try { + assertThat(tracer.getCurrentSpan()).isSameAs(span); + } finally { + ss.close(); + } + verify(span).end(same(EndSpanOptions.DEFAULT)); + } + + @Test + public void startScopedSpanChild() { + Tracer mockTracer = new MockTracer(spanFactory); + NonThrowingCloseable ws = mockTracer.withSpan(BlankSpan.INSTANCE); + try { + assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + when(spanFactory.startSpan( + same(BlankSpan.INSTANCE), same(SPAN_NAME), eq(new StartSpanOptions()))) + .thenReturn(span); + NonThrowingCloseable ss = mockTracer.spanBuilder(SPAN_NAME).startScopedSpan(); + try { + assertThat(tracer.getCurrentSpan()).isSameAs(span); + } finally { + ss.close(); + } + assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + } finally { + ws.close(); + } + verify(span).end(same(EndSpanOptions.DEFAULT)); + } + + @Test + public void startRootSpan() { + Tracer mockTracer = new MockTracer(spanFactory); + when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(new StartSpanOptions()))) + .thenReturn(span); + Span rootSpan = mockTracer.spanBuilder(BlankSpan.INSTANCE, SPAN_NAME).becomeRoot().startSpan(); + assertThat(rootSpan).isEqualTo(span); + rootSpan.end(); + verify(span).end(same(EndSpanOptions.DEFAULT)); + } + + @Test + public void startChildSpan() { + Tracer mockTracer = new MockTracer(spanFactory); + when(spanFactory.startSpan( + same(BlankSpan.INSTANCE), same(SPAN_NAME), eq(new StartSpanOptions()))) + .thenReturn(span); + Span childSpan = mockTracer.spanBuilder(BlankSpan.INSTANCE, SPAN_NAME).startSpan(); + assertThat(childSpan).isEqualTo(span); + childSpan.end(); + verify(span).end(same(EndSpanOptions.DEFAULT)); + } + + @Test + public void startSpanWitRemoteParent() { + Random random = new Random(1234); + Tracer mockTracer = new MockTracer(spanFactory); + SpanContext spanContext = + SpanContext.create( + TraceId.generateRandomId(random), + SpanId.generateRandomId(random), + TraceOptions.DEFAULT); + when(spanFactory.startSpanWithRemoteParent( + same(spanContext), same(SPAN_NAME), eq(new StartSpanOptions()))) + .thenReturn(span); + Span remoteChildSpan = + mockTracer.spanBuilderWithRemoteParent(spanContext, SPAN_NAME).startSpan(); + assertThat(remoteChildSpan).isEqualTo(span); + remoteChildSpan.end(); + verify(span).end(same(EndSpanOptions.DEFAULT)); + } + + private static final class MockTracer extends Tracer { + private MockTracer(SpanFactory spanFactory) { + super(spanFactory); + } + } +} diff --git a/api/src/test/java/io/opencensus/trace/TracingTest.java b/api/src/test/java/io/opencensus/trace/TracingTest.java new file mode 100644 index 00000000..b7c9be25 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/TracingTest.java @@ -0,0 +1,78 @@ +/* + * Copyright 2016, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Tracing}. */ +@RunWith(JUnit4.class) +public class TracingTest { + @Rule public ExpectedException thrown = ExpectedException.none(); + + @Test + public void loadTraceService_UsesProvidedClassLoader() { + final RuntimeException toThrow = new RuntimeException("UseClassLoader"); + thrown.expect(RuntimeException.class); + thrown.expectMessage("UseClassLoader"); + Tracing.loadTraceComponent( + new ClassLoader() { + @Override + public Class loadClass(String name) { + throw toThrow; + } + }); + } + + @Test + public void loadSpanFactory_IgnoresMissingClasses() { + assertThat( + Tracing.loadTraceComponent( + new ClassLoader() { + @Override + public Class loadClass(String name) throws ClassNotFoundException { + throw new ClassNotFoundException(); + } + }) + .getClass() + .getName()) + .isEqualTo("io.opencensus.trace.TraceComponent$NoopTraceComponent"); + } + + @Test + public void defaultTracer() { + assertThat(Tracing.getTracer()).isSameAs(Tracer.getNoopTracer()); + } + + @Test + public void defaultBinaryPropagationHandler() { + assertThat(Tracing.getBinaryPropagationHandler()) + .isSameAs(BinaryPropagationHandler.getNoopBinaryPropagationHandler()); + } + + @Test + public void defaultTraceExporter() { + assertThat(Tracing.getTraceExporter()).isSameAs(TraceExporter.getNoopTraceExporter()); + } + + @Test + public void defaultTraceConfig() { + assertThat(Tracing.getTraceConfig()).isSameAs(TraceConfig.getNoopTraceConfig()); + } +} -- cgit v1.2.3 From e9c1373c29df2a7b3426c2f71c94a2467f1129ed Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Mon, 5 Jun 2017 12:03:39 -0700 Subject: Define latency buckets boundaries in the API to allow UIs to use them when display data. --- .../java/io/opencensus/trace/TraceExporter.java | 230 ++++++++++----------- 1 file changed, 110 insertions(+), 120 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/TraceExporter.java b/api/src/main/java/io/opencensus/trace/TraceExporter.java index 7da2d604..4328e80d 100644 --- a/api/src/main/java/io/opencensus/trace/TraceExporter.java +++ b/api/src/main/java/io/opencensus/trace/TraceExporter.java @@ -22,8 +22,8 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; @@ -172,6 +172,99 @@ public abstract class TraceExporter { */ public abstract void unregisterSpanNamesForCollection(Collection spanNames); + /** + * The latency buckets boundaries. Samples based on latency for successful spans (the status of + * the span has a canonical code different than {@link CanonicalCode#OK}) are collected in one + * of these latency buckets. + */ + public enum LatencyBucketsBoundaries { + // Stores finished successful requests of duration within the interval [0, 10us) + ZERO_MICROSx10(0, TimeUnit.MICROSECONDS.toNanos(10), "0", "10us)"), + // Stores finished successful requests of duration within the interval [10us, 100us) + MICROSx10_MICROSx100( + TimeUnit.MICROSECONDS.toNanos(10), TimeUnit.MICROSECONDS.toNanos(100), "10us", "100us"), + // Stores finished successful requests of duration within the interval [100us, 1ms) + MICROSx100_MILLIx1( + TimeUnit.MICROSECONDS.toNanos(100), TimeUnit.MILLISECONDS.toNanos(1), "100us", "1ms"), + // Stores finished successful requests of duration within the interval [1ms, 10ms) + MILLIx1_MILLIx10( + TimeUnit.MILLISECONDS.toNanos(1), TimeUnit.MILLISECONDS.toNanos(10), "1ms", "10ms"), + // Stores finished successful requests of duration within the interval [10ms, 100ms) + MILLIx10_MILLIx100( + TimeUnit.MILLISECONDS.toNanos(10), TimeUnit.MILLISECONDS.toNanos(100), "10ms", "100ms"), + // Stores finished successful requests of duration within the interval [100ms, 1sec) + MILLIx100_SECONDx1( + TimeUnit.MILLISECONDS.toNanos(100), TimeUnit.SECONDS.toNanos(1), "100ms", "1sec"), + // Stores finished successful requests of duration within the interval [1sec, 10sec) + SECONDx1_SECONDx10( + TimeUnit.SECONDS.toNanos(1), TimeUnit.SECONDS.toNanos(10), "1sec", "10sec"), + // Stores finished successful requests of duration within the interval [10sec, 100sec) + SECONDx10_SECONDx100( + TimeUnit.SECONDS.toNanos(10), TimeUnit.SECONDS.toNanos(100), "10sec", "100sec"), + // Stores finished successful requests of duration >= 100sec + SECONDx100_MAX(TimeUnit.SECONDS.toNanos(100), Long.MAX_VALUE, "100sec", "INF"); + + /** + * Constructs a {@code LatencyBucketsBoundaries} with the given boundaries and label. + * + * @param latencyLowerNs the latency lower bound of the bucket. + * @param latencyUpperNs the latency upper bound of the bucket. + * @param latencyLowerString the human readable string of the {@code latencyLowerNs} value. + * @param latencyUpperString the human readable string of the {@code latencyUpperNs} value. + */ + LatencyBucketsBoundaries( + long latencyLowerNs, + long latencyUpperNs, + String latencyLowerString, + String latencyUpperString) { + this.latencyLowerNs = latencyLowerNs; + this.latencyUpperNs = latencyUpperNs; + this.latencyLowerString = latencyLowerString; + this.latencyUpperString = latencyUpperString; + } + + /** + * Returns the latency lower bound of the bucket. + * + * @return the latency lower bound of the bucket. + */ + public long getLatencyLowerNs() { + return latencyLowerNs; + } + + /** + * Returns the latency upper bound of the bucket. + * + * @return the latency upper bound of the bucket. + */ + public long getLatencyUpperNs() { + return latencyUpperNs; + } + + /** + * Returns the human readable string of the {@code getLatencyLowerNs()} value. + * + * @return the human readable string of the {@code getLatencyLowerNs()} value. + */ + public String getLatencyLowerString() { + return latencyLowerString; + } + + /** + * Returns the human readable string of the {@code getLatencyUpperNs()} value. + * + * @return the human readable string of the {@code getLatencyUpperNs()} value. + */ + public String getLatencyUpperString() { + return latencyUpperString; + } + + private final long latencyLowerNs; + private final long latencyUpperNs; + private final String latencyLowerString; + private final String latencyUpperString; + } + /** The summary of all in-process debugging information. */ @AutoValue @Immutable @@ -211,8 +304,8 @@ public abstract class TraceExporter { * Returns a new instance of {@code PerSpanNameSummary}. * * @param numActiveSpans the number of sampled spans. - * @param latencyBucketSummaries the summary for the latency buckets. - * @param errorBucketSummaries the summary for the error buckets. + * @param latencyBucketsSummaries the summary for the latency buckets. + * @param errorBucketsSummaries the summary for the error buckets. * @return a new instance of {@code PerSpanNameSummary}. * @throws NullPointerException if {@code latencyBucketSummaries} or {@code * errorBucketSummaries} are {@code null}. @@ -220,17 +313,17 @@ public abstract class TraceExporter { */ public static PerSpanNameSummary create( int numActiveSpans, - List latencyBucketSummaries, - List errorBucketSummaries) { + Map latencyBucketsSummaries, + Map errorBucketsSummaries) { checkArgument(numActiveSpans >= 0, "Negative numActiveSpans."); return new AutoValue_TraceExporter_InProcessDebuggingHandler_Summary_PerSpanNameSummary( numActiveSpans, - Collections.unmodifiableList( - new ArrayList( - checkNotNull(latencyBucketSummaries, "latencyBucketSummaries"))), - Collections.unmodifiableList( - new ArrayList( - checkNotNull(errorBucketSummaries, "errorBucketSummaries")))); + Collections.unmodifiableMap( + new HashMap( + checkNotNull(latencyBucketsSummaries, "latencyBucketsSummaries"))), + Collections.unmodifiableMap( + new HashMap( + checkNotNull(errorBucketsSummaries, "errorBucketsSummaries")))); } /** @@ -241,121 +334,18 @@ public abstract class TraceExporter { public abstract int getNumActiveSpans(); /** - * Returns the list of all latency based sampled buckets summary. - * - *

The list is sorted based on the lower latency boundary, and the upper bound of one - * match the lower bound of the next. Every bucket contains samples with latency within the - * interval [lowerBoundary, upperBoundary). + * Returns the number of samples for each latency based sampled bucket. * - * @return the list of all latency based sampled buckets summary. + * @return the number of samples for each latency based sampled bucket. */ - public abstract List getLatencyBucketSummaries(); + public abstract Map getLatencyBucketsSummaries(); /** - * Returns the list of all error based sampled buckets summary. - * - *

The list is sorted based on the {@link CanonicalCode#value()} and contains an entry - * for each of the values other than {@link CanonicalCode#OK}. + * Returns the number of samples for each error based sampled bucket. * - * @return the list of all error based sampled buckets summary. + * @return the number of samples for each error based sampled bucket. */ - public abstract List getErrorBucketSummaries(); - - /** - * Summary of a latency based sampled spans bucket. Contains {@code Span} samples with - * latency between [latencyLowerNs, latencyUpperNs). - */ - @AutoValue - @Immutable - public abstract static class LatencyBucketSummary { - - LatencyBucketSummary() {} - - /** - * Returns a new instance of {@code LatencyBucketSummary}. The latency of the samples is - * in the interval [latencyLowerNs, latencyUpperNs). - * - * @param numSamples the number of sampled spans. - * @param latencyLowerNs the latency lower bound. - * @param latencyUpperNs the latency upper bound. - * @return a new instance of {@code LatencyBucketSummary}. - * @throws IllegalArgumentException if {@code numSamples} or {@code latencyLowerNs} or - * {@code latencyUpperNs} are negative. - */ - public static LatencyBucketSummary create( - int numSamples, long latencyLowerNs, long latencyUpperNs) { - checkArgument(numSamples >= 0, "Negative numSamples."); - checkArgument(latencyLowerNs >= 0, "Negative latencyLowerNs"); - checkArgument(latencyUpperNs >= 0, "Negative latencyUpperNs"); - //CHECKSTYLE:OFF: Long class name. - return new AutoValue_TraceExporter_InProcessDebuggingHandler_Summary_PerSpanNameSummary_LatencyBucketSummary( - numSamples, latencyLowerNs, latencyUpperNs); - //CHECKSTYLE:ON: Long class name. - } - - /** - * Returns the number of sampled spans in this bucket. - * - * @return the number of sampled spans in this bucket. - */ - public abstract int getNumSamples(); - - /** - * Returns the latency lower bound of this bucket (inclusive). - * - * @return the latency lower bound of this bucket. - */ - public abstract long getLatencyLowerNs(); - - /** - * Returns the latency upper bound of this bucket (exclusive). - * - * @return the latency upper bound of this bucket. - */ - public abstract long getLatencyUpperNs(); - } - - /** Summary of an error based sampled spans bucket. */ - @AutoValue - @Immutable - public abstract static class ErrorBucketSummary { - - ErrorBucketSummary() {} - - /** - * Returns a new instance of {@code ErrorBucketSummary}. - * - * @param numSamples the number of sampled spans. - * @param canonicalCode the error code of the bucket. - * @return a new instance of {@code ErrorBucketSummary}. - * @throws NullPointerException if {@code canonicalCode} is {@code null}. - * @throws IllegalArgumentException if {@code canonicalCode} is {@link CanonicalCode#OK} - * or {@code numSamples} is negative. - */ - public static ErrorBucketSummary create(int numSamples, CanonicalCode canonicalCode) { - checkArgument(numSamples >= 0, "Negative numSamples."); - checkArgument(canonicalCode != CanonicalCode.OK, "Invalid canonical code."); - //CHECKSTYLE:OFF: Long class name. - return new AutoValue_TraceExporter_InProcessDebuggingHandler_Summary_PerSpanNameSummary_ErrorBucketSummary( - numSamples, canonicalCode); - //CHECKSTYLE:ON: Long class name. - } - - /** - * Returns the number of sampled spans in this bucket. - * - * @return the number of sampled spans in this bucket. - */ - public abstract int getNumSamples(); - - /** - * Returns the {@code CanonicalCode} for this bucket. Always different than {@link - * CanonicalCode#OK}. - * - * @return the {@code CanonicalCode} for this bucket. - */ - public abstract CanonicalCode getCanonicalCode(); - } + public abstract Map getErrorBucketsSummaries(); } } -- cgit v1.2.3 From 63377c818802f072380b04fef798a50385bc49de Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Tue, 6 Jun 2017 14:01:35 -0700 Subject: Remove string format of the boundaries. Rename the enum to LatencyBucketBoundaries. --- .../java/io/opencensus/trace/TraceExporter.java | 63 +++++++--------------- 1 file changed, 18 insertions(+), 45 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/TraceExporter.java b/api/src/main/java/io/opencensus/trace/TraceExporter.java index 4328e80d..7d6c8c7f 100644 --- a/api/src/main/java/io/opencensus/trace/TraceExporter.java +++ b/api/src/main/java/io/opencensus/trace/TraceExporter.java @@ -18,7 +18,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; import io.opencensus.trace.Status.CanonicalCode; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -174,53 +173,47 @@ public abstract class TraceExporter { /** * The latency buckets boundaries. Samples based on latency for successful spans (the status of - * the span has a canonical code different than {@link CanonicalCode#OK}) are collected in one - * of these latency buckets. + * the span has a canonical code equal to {@link CanonicalCode#OK}) are collected in one of + * these latency buckets. */ - public enum LatencyBucketsBoundaries { + public enum LatencyBucketBoundaries { // Stores finished successful requests of duration within the interval [0, 10us) - ZERO_MICROSx10(0, TimeUnit.MICROSECONDS.toNanos(10), "0", "10us)"), + ZERO_MICROSx10(0, TimeUnit.MICROSECONDS.toNanos(10)), // Stores finished successful requests of duration within the interval [10us, 100us) MICROSx10_MICROSx100( - TimeUnit.MICROSECONDS.toNanos(10), TimeUnit.MICROSECONDS.toNanos(100), "10us", "100us"), + TimeUnit.MICROSECONDS.toNanos(10), TimeUnit.MICROSECONDS.toNanos(100)), // Stores finished successful requests of duration within the interval [100us, 1ms) MICROSx100_MILLIx1( - TimeUnit.MICROSECONDS.toNanos(100), TimeUnit.MILLISECONDS.toNanos(1), "100us", "1ms"), + TimeUnit.MICROSECONDS.toNanos(100), TimeUnit.MILLISECONDS.toNanos(1)), // Stores finished successful requests of duration within the interval [1ms, 10ms) MILLIx1_MILLIx10( - TimeUnit.MILLISECONDS.toNanos(1), TimeUnit.MILLISECONDS.toNanos(10), "1ms", "10ms"), + TimeUnit.MILLISECONDS.toNanos(1), TimeUnit.MILLISECONDS.toNanos(10)), // Stores finished successful requests of duration within the interval [10ms, 100ms) MILLIx10_MILLIx100( - TimeUnit.MILLISECONDS.toNanos(10), TimeUnit.MILLISECONDS.toNanos(100), "10ms", "100ms"), + TimeUnit.MILLISECONDS.toNanos(10), TimeUnit.MILLISECONDS.toNanos(100)), // Stores finished successful requests of duration within the interval [100ms, 1sec) MILLIx100_SECONDx1( - TimeUnit.MILLISECONDS.toNanos(100), TimeUnit.SECONDS.toNanos(1), "100ms", "1sec"), + TimeUnit.MILLISECONDS.toNanos(100), TimeUnit.SECONDS.toNanos(1)), // Stores finished successful requests of duration within the interval [1sec, 10sec) SECONDx1_SECONDx10( - TimeUnit.SECONDS.toNanos(1), TimeUnit.SECONDS.toNanos(10), "1sec", "10sec"), + TimeUnit.SECONDS.toNanos(1), TimeUnit.SECONDS.toNanos(10)), // Stores finished successful requests of duration within the interval [10sec, 100sec) SECONDx10_SECONDx100( - TimeUnit.SECONDS.toNanos(10), TimeUnit.SECONDS.toNanos(100), "10sec", "100sec"), + TimeUnit.SECONDS.toNanos(10), TimeUnit.SECONDS.toNanos(100)), // Stores finished successful requests of duration >= 100sec - SECONDx100_MAX(TimeUnit.SECONDS.toNanos(100), Long.MAX_VALUE, "100sec", "INF"); + SECONDx100_MAX(TimeUnit.SECONDS.toNanos(100), Long.MAX_VALUE); /** - * Constructs a {@code LatencyBucketsBoundaries} with the given boundaries and label. + * Constructs a {@code LatencyBucketBoundaries} with the given boundaries and label. * * @param latencyLowerNs the latency lower bound of the bucket. * @param latencyUpperNs the latency upper bound of the bucket. - * @param latencyLowerString the human readable string of the {@code latencyLowerNs} value. - * @param latencyUpperString the human readable string of the {@code latencyUpperNs} value. */ - LatencyBucketsBoundaries( + LatencyBucketBoundaries( long latencyLowerNs, - long latencyUpperNs, - String latencyLowerString, - String latencyUpperString) { + long latencyUpperNs) { this.latencyLowerNs = latencyLowerNs; this.latencyUpperNs = latencyUpperNs; - this.latencyLowerString = latencyLowerString; - this.latencyUpperString = latencyUpperString; } /** @@ -241,28 +234,8 @@ public abstract class TraceExporter { return latencyUpperNs; } - /** - * Returns the human readable string of the {@code getLatencyLowerNs()} value. - * - * @return the human readable string of the {@code getLatencyLowerNs()} value. - */ - public String getLatencyLowerString() { - return latencyLowerString; - } - - /** - * Returns the human readable string of the {@code getLatencyUpperNs()} value. - * - * @return the human readable string of the {@code getLatencyUpperNs()} value. - */ - public String getLatencyUpperString() { - return latencyUpperString; - } - private final long latencyLowerNs; private final long latencyUpperNs; - private final String latencyLowerString; - private final String latencyUpperString; } /** The summary of all in-process debugging information. */ @@ -313,13 +286,13 @@ public abstract class TraceExporter { */ public static PerSpanNameSummary create( int numActiveSpans, - Map latencyBucketsSummaries, + Map latencyBucketsSummaries, Map errorBucketsSummaries) { checkArgument(numActiveSpans >= 0, "Negative numActiveSpans."); return new AutoValue_TraceExporter_InProcessDebuggingHandler_Summary_PerSpanNameSummary( numActiveSpans, Collections.unmodifiableMap( - new HashMap( + new HashMap( checkNotNull(latencyBucketsSummaries, "latencyBucketsSummaries"))), Collections.unmodifiableMap( new HashMap( @@ -338,7 +311,7 @@ public abstract class TraceExporter { * * @return the number of samples for each latency based sampled bucket. */ - public abstract Map getLatencyBucketsSummaries(); + public abstract Map getLatencyBucketsSummaries(); /** * Returns the number of samples for each error based sampled bucket. -- cgit v1.2.3 From 9f0e5d3cb6b80357dabc3ee9771335096cd35437 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Wed, 7 Jun 2017 14:23:30 -0700 Subject: Move TraceConfig into its own package, extract inner class TraceParams. (#340) --- .../java/io/opencensus/trace/TraceComponent.java | 1 + .../main/java/io/opencensus/trace/TraceConfig.java | 213 --------------------- api/src/main/java/io/opencensus/trace/Tracing.java | 1 + .../io/opencensus/trace/config/TraceConfig.java | 67 +++++++ .../io/opencensus/trace/config/TraceParams.java | 165 ++++++++++++++++ .../io/opencensus/trace/TraceComponentTest.java | 1 + .../java/io/opencensus/trace/TraceParamsTest.java | 2 +- .../test/java/io/opencensus/trace/TracingTest.java | 1 + 8 files changed, 237 insertions(+), 214 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/trace/TraceConfig.java create mode 100644 api/src/main/java/io/opencensus/trace/config/TraceConfig.java create mode 100644 api/src/main/java/io/opencensus/trace/config/TraceParams.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/TraceComponent.java b/api/src/main/java/io/opencensus/trace/TraceComponent.java index 1829417f..bee02dae 100644 --- a/api/src/main/java/io/opencensus/trace/TraceComponent.java +++ b/api/src/main/java/io/opencensus/trace/TraceComponent.java @@ -15,6 +15,7 @@ package io.opencensus.trace; import io.opencensus.common.Clock; import io.opencensus.internal.ZeroTimeClock; +import io.opencensus.trace.config.TraceConfig; /** * Class that holds the implementation instances for {@link Tracer}, {@link diff --git a/api/src/main/java/io/opencensus/trace/TraceConfig.java b/api/src/main/java/io/opencensus/trace/TraceConfig.java deleted file mode 100644 index 41fa75b8..00000000 --- a/api/src/main/java/io/opencensus/trace/TraceConfig.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.auto.value.AutoValue; -import javax.annotation.concurrent.Immutable; - -/** - * Global configuration of the trace service. This allows users to change configs for the default - * sampler, maximum events to be kept, etc. (see {@link TraceParams} for details). - */ -public abstract class TraceConfig { - private static final NoopTraceConfig noopTraceConfig = new NoopTraceConfig(); - - /** - * Returns the active {@code TraceParams}. - * - * @return the active {@code TraceParams}. - */ - public abstract TraceParams getActiveTraceParams(); - - /** - * Updates the active {@link TraceParams}. - * - * @param traceParams the new active {@code TraceParams}. - */ - public abstract void updateActiveTraceParams(TraceParams traceParams); - - /** - * Temporary updates the active {@link TraceParams} for {@code durationNs} nanoseconds. - * - * @param traceParams the new active {@code TraceParams}. - * @param durationNs the duration for how long the new params will be active. - */ - public abstract void temporaryUpdateActiveTraceParams(TraceParams traceParams, long durationNs); - - /** - * Returns the no-op implementation of the {@code TraceConfig}. - * - * @return the no-op implementation of the {@code TraceConfig}. - */ - static TraceConfig getNoopTraceConfig() { - return noopTraceConfig; - } - - /** Class that holds global trace parameters. */ - @AutoValue - @Immutable - public abstract static class TraceParams { - // These values are the default values for all the global parameters. - private static final double DEFAULT_PROBABILITY = 1e-4; - private static final Sampler DEFAULT_SAMPLER = Samplers.probabilitySampler(DEFAULT_PROBABILITY); - private static final int DEFAULT_SPAN_MAX_NUM_ATTRIBUTES = 32; - private static final int DEFAULT_SPAN_MAX_NUM_ANNOTATIONS = 32; - private static final int DEFAULT_SPAN_MAX_NUM_NETWORK_EVENTS = 128; - private static final int DEFAULT_SPAN_MAX_NUM_LINKS = 128; - - public static final TraceParams DEFAULT = - TraceParams.builder() - .setSampler(DEFAULT_SAMPLER) - .setMaxNumberOfAttributes(DEFAULT_SPAN_MAX_NUM_ATTRIBUTES) - .setMaxNumberOfAnnotations(DEFAULT_SPAN_MAX_NUM_ANNOTATIONS) - .setMaxNumberOfNetworkEvents(DEFAULT_SPAN_MAX_NUM_NETWORK_EVENTS) - .setMaxNumberOfLinks(DEFAULT_SPAN_MAX_NUM_LINKS) - .build(); - - /** - * Returns the global default {@code Sampler}. Used if no {@code Sampler} is provided in {@link - * StartSpanOptions}. - * - * @return the global default {@code Sampler}. - */ - public abstract Sampler getSampler(); - - /** - * Returns the global default max number of attributes per {@link Span}. - * - * @return the global default max number of attributes per {@link Span}. - */ - public abstract int getMaxNumberOfAttributes(); - - /** - * Returns the global default max number of {@link Annotation} events per {@link Span}. - * - * @return the global default max number of {@code Annotation} events per {@code Span}. - */ - public abstract int getMaxNumberOfAnnotations(); - - /** - * Returns the global default max number of {@link NetworkEvent} events per {@link Span}. - * - * @return the global default max number of {@code NetworkEvent} events per {@code Span}. - */ - public abstract int getMaxNumberOfNetworkEvents(); - - /** - * Returns the global default max number of {@link Link} entries per {@link Span}. - * - * @return the global default max number of {@code Link} entries per {@code Span}. - */ - public abstract int getMaxNumberOfLinks(); - - private static Builder builder() { - return new AutoValue_TraceConfig_TraceParams.Builder(); - } - - /** - * Returns a {@link Builder} initialized to the same property values as the current instance. - * - * @return a {@link Builder} initialized to the same property values as the current instance. - */ - public abstract Builder toBuilder(); - - /** A {@code Builder} class for {@link TraceParams}. */ - @AutoValue.Builder - public abstract static class Builder { - - /** - * Sets the global default {@code Sampler}. It must be not {@code null} otherwise {@link - * #build()} will throw an exception. - * - * @param sampler the global default {@code Sampler}. - * @return this. - */ - public abstract Builder setSampler(Sampler sampler); - - /** - * Sets the global default max number of attributes per {@link Span}. - * - * @param maxNumberOfAttributes the global default max number of attributes per {@link Span}. - * It must be positive otherwise {@link #build()} will throw an exception. - * @return this. - */ - public abstract Builder setMaxNumberOfAttributes(int maxNumberOfAttributes); - - /** - * Sets the global default max number of {@link Annotation} events per {@link Span}. - * - * @param maxNumberOfAnnotations the global default max number of {@link Annotation} events - * per {@link Span}. It must be positive otherwise {@link #build()} will throw an - * exception. - * @return this. - */ - public abstract Builder setMaxNumberOfAnnotations(int maxNumberOfAnnotations); - - /** - * Sets the global default max number of {@link NetworkEvent} events per {@link Span}. - * - * @param maxNumberOfNetworkEvents the global default max number of {@link NetworkEvent} - * events per {@link Span}. It must be positive otherwise {@link #build()} will throw an - * exception. - * @return this. - */ - public abstract Builder setMaxNumberOfNetworkEvents(int maxNumberOfNetworkEvents); - - /** - * Sets the global default max number of {@link Link} entries per {@link Span}. - * - * @param maxNumberOfLinks the global default max number of {@link Link} entries per {@link - * Span}. It must be positive otherwise {@link #build()} will throw an exception. - * @return this. - */ - public abstract Builder setMaxNumberOfLinks(int maxNumberOfLinks); - - abstract TraceParams autoBuild(); - - /** - * Builds and returns a {@code TraceParams} with the desired values. - * - * @return a {@code TraceParams} with the desired values. - * @throws NullPointerException if the sampler is {@code null}. - * @throws IllegalArgumentException if any of the max numbers are not positive. - */ - public TraceParams build() { - TraceParams traceParams = autoBuild(); - checkNotNull(traceParams.getSampler(), "sampler"); - checkArgument(traceParams.getMaxNumberOfAttributes() > 0, "maxNumberOfAttributes"); - checkArgument(traceParams.getMaxNumberOfAnnotations() > 0, "maxNumberOfAnnotations"); - checkArgument(traceParams.getMaxNumberOfNetworkEvents() > 0, "maxNumberOfNetworkEvents"); - checkArgument(traceParams.getMaxNumberOfLinks() > 0, "maxNumberOfLinks"); - return traceParams; - } - } - } - - private static final class NoopTraceConfig extends TraceConfig { - - @Override - public TraceParams getActiveTraceParams() { - return TraceParams.DEFAULT; - } - - @Override - public void updateActiveTraceParams(TraceParams traceParams) {} - - @Override - public void temporaryUpdateActiveTraceParams(TraceParams traceParams, long durationNs) {} - } -} diff --git a/api/src/main/java/io/opencensus/trace/Tracing.java b/api/src/main/java/io/opencensus/trace/Tracing.java index e6d34a45..771b8553 100644 --- a/api/src/main/java/io/opencensus/trace/Tracing.java +++ b/api/src/main/java/io/opencensus/trace/Tracing.java @@ -16,6 +16,7 @@ package io.opencensus.trace; import com.google.common.annotations.VisibleForTesting; import io.opencensus.common.Clock; import io.opencensus.internal.Provider; +import io.opencensus.trace.config.TraceConfig; import java.util.logging.Level; import java.util.logging.Logger; diff --git a/api/src/main/java/io/opencensus/trace/config/TraceConfig.java b/api/src/main/java/io/opencensus/trace/config/TraceConfig.java new file mode 100644 index 00000000..80f206c9 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/config/TraceConfig.java @@ -0,0 +1,67 @@ +/* + * Copyright 2017, Google Inc. + * 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.config; + +/** + * Global configuration of the trace service. This allows users to change configs for the default + * sampler, maximum events to be kept, etc. (see {@link TraceParams} for details). + */ +public abstract class TraceConfig { + private static final NoopTraceConfig NOOP_TRACE_CONFIG = new NoopTraceConfig(); + + /** + * Returns the active {@code TraceParams}. + * + * @return the active {@code TraceParams}. + */ + public abstract TraceParams getActiveTraceParams(); + + /** + * Updates the active {@link TraceParams}. + * + * @param traceParams the new active {@code TraceParams}. + */ + public abstract void updateActiveTraceParams(TraceParams traceParams); + + /** + * Temporary updates the active {@link TraceParams} for {@code durationNs} nanoseconds. + * + * @param traceParams the new active {@code TraceParams}. + * @param durationNs the duration for how long the new params will be active. + */ + public abstract void temporaryUpdateActiveTraceParams(TraceParams traceParams, long durationNs); + + /** + * Returns the no-op implementation of the {@code TraceConfig}. + * + * @return the no-op implementation of the {@code TraceConfig}. + */ + public static TraceConfig getNoopTraceConfig() { + return NOOP_TRACE_CONFIG; + } + + private static final class NoopTraceConfig extends TraceConfig { + + @Override + public TraceParams getActiveTraceParams() { + return TraceParams.DEFAULT; + } + + @Override + public void updateActiveTraceParams(TraceParams traceParams) {} + + @Override + public void temporaryUpdateActiveTraceParams(TraceParams traceParams, long durationNs) {} + } +} diff --git a/api/src/main/java/io/opencensus/trace/config/TraceParams.java b/api/src/main/java/io/opencensus/trace/config/TraceParams.java new file mode 100644 index 00000000..c4463342 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/config/TraceParams.java @@ -0,0 +1,165 @@ +/* + * Copyright 2017, Google Inc. + * 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.config; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.auto.value.AutoValue; +import io.opencensus.trace.Annotation; +import io.opencensus.trace.Link; +import io.opencensus.trace.NetworkEvent; +import io.opencensus.trace.Sampler; +import io.opencensus.trace.Samplers; +import io.opencensus.trace.Span; +import io.opencensus.trace.StartSpanOptions; +import javax.annotation.concurrent.Immutable; + +/** Class that holds global trace parameters. */ +@AutoValue +@Immutable +public abstract class TraceParams { + // These values are the default values for all the global parameters. + private static final double DEFAULT_PROBABILITY = 1e-4; + private static final Sampler DEFAULT_SAMPLER = Samplers.probabilitySampler(DEFAULT_PROBABILITY); + private static final int DEFAULT_SPAN_MAX_NUM_ATTRIBUTES = 32; + private static final int DEFAULT_SPAN_MAX_NUM_ANNOTATIONS = 32; + private static final int DEFAULT_SPAN_MAX_NUM_NETWORK_EVENTS = 128; + private static final int DEFAULT_SPAN_MAX_NUM_LINKS = 128; + + public static final TraceParams DEFAULT = + TraceParams.builder() + .setSampler(DEFAULT_SAMPLER) + .setMaxNumberOfAttributes(DEFAULT_SPAN_MAX_NUM_ATTRIBUTES) + .setMaxNumberOfAnnotations(DEFAULT_SPAN_MAX_NUM_ANNOTATIONS) + .setMaxNumberOfNetworkEvents(DEFAULT_SPAN_MAX_NUM_NETWORK_EVENTS) + .setMaxNumberOfLinks(DEFAULT_SPAN_MAX_NUM_LINKS) + .build(); + + /** + * Returns the global default {@code Sampler}. Used if no {@code Sampler} is provided in {@link + * StartSpanOptions}. + * + * @return the global default {@code Sampler}. + */ + public abstract Sampler getSampler(); + + /** + * Returns the global default max number of attributes per {@link Span}. + * + * @return the global default max number of attributes per {@link Span}. + */ + public abstract int getMaxNumberOfAttributes(); + + /** + * Returns the global default max number of {@link Annotation} events per {@link Span}. + * + * @return the global default max number of {@code Annotation} events per {@code Span}. + */ + public abstract int getMaxNumberOfAnnotations(); + + /** + * Returns the global default max number of {@link NetworkEvent} events per {@link Span}. + * + * @return the global default max number of {@code NetworkEvent} events per {@code Span}. + */ + public abstract int getMaxNumberOfNetworkEvents(); + + /** + * Returns the global default max number of {@link Link} entries per {@link Span}. + * + * @return the global default max number of {@code Link} entries per {@code Span}. + */ + public abstract int getMaxNumberOfLinks(); + + private static Builder builder() { + return new AutoValue_TraceParams.Builder(); + } + + /** + * Returns a {@link Builder} initialized to the same property values as the current instance. + * + * @return a {@link Builder} initialized to the same property values as the current instance. + */ + public abstract Builder toBuilder(); + + /** A {@code Builder} class for {@link TraceParams}. */ + @AutoValue.Builder + public abstract static class Builder { + + /** + * Sets the global default {@code Sampler}. It must be not {@code null} otherwise {@link + * #build()} will throw an exception. + * + * @param sampler the global default {@code Sampler}. + * @return this. + */ + public abstract Builder setSampler(Sampler sampler); + + /** + * Sets the global default max number of attributes per {@link Span}. + * + * @param maxNumberOfAttributes the global default max number of attributes per {@link Span}. + * It must be positive otherwise {@link #build()} will throw an exception. + * @return this. + */ + public abstract Builder setMaxNumberOfAttributes(int maxNumberOfAttributes); + + /** + * Sets the global default max number of {@link Annotation} events per {@link Span}. + * + * @param maxNumberOfAnnotations the global default max number of {@link Annotation} events + * per {@link Span}. It must be positive otherwise {@link #build()} will throw an + * exception. + * @return this. + */ + public abstract Builder setMaxNumberOfAnnotations(int maxNumberOfAnnotations); + + /** + * Sets the global default max number of {@link NetworkEvent} events per {@link Span}. + * + * @param maxNumberOfNetworkEvents the global default max number of {@link NetworkEvent} + * events per {@link Span}. It must be positive otherwise {@link #build()} will throw an + * exception. + * @return this. + */ + public abstract Builder setMaxNumberOfNetworkEvents(int maxNumberOfNetworkEvents); + + /** + * Sets the global default max number of {@link Link} entries per {@link Span}. + * + * @param maxNumberOfLinks the global default max number of {@link Link} entries per {@link + * Span}. It must be positive otherwise {@link #build()} will throw an exception. + * @return this. + */ + public abstract Builder setMaxNumberOfLinks(int maxNumberOfLinks); + + abstract TraceParams autoBuild(); + + /** + * Builds and returns a {@code TraceParams} with the desired values. + * + * @return a {@code TraceParams} with the desired values. + * @throws NullPointerException if the sampler is {@code null}. + * @throws IllegalArgumentException if any of the max numbers are not positive. + */ + public TraceParams build() { + TraceParams traceParams = autoBuild(); + checkArgument(traceParams.getMaxNumberOfAttributes() > 0, "maxNumberOfAttributes"); + checkArgument(traceParams.getMaxNumberOfAnnotations() > 0, "maxNumberOfAnnotations"); + checkArgument(traceParams.getMaxNumberOfNetworkEvents() > 0, "maxNumberOfNetworkEvents"); + checkArgument(traceParams.getMaxNumberOfLinks() > 0, "maxNumberOfLinks"); + return traceParams; + } + } +} diff --git a/api/src/test/java/io/opencensus/trace/TraceComponentTest.java b/api/src/test/java/io/opencensus/trace/TraceComponentTest.java index 106cb965..cd42a98a 100644 --- a/api/src/test/java/io/opencensus/trace/TraceComponentTest.java +++ b/api/src/test/java/io/opencensus/trace/TraceComponentTest.java @@ -16,6 +16,7 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; import io.opencensus.internal.ZeroTimeClock; +import io.opencensus.trace.config.TraceConfig; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; diff --git a/api/src/test/java/io/opencensus/trace/TraceParamsTest.java b/api/src/test/java/io/opencensus/trace/TraceParamsTest.java index 60f40deb..e21485e1 100644 --- a/api/src/test/java/io/opencensus/trace/TraceParamsTest.java +++ b/api/src/test/java/io/opencensus/trace/TraceParamsTest.java @@ -15,7 +15,7 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; -import io.opencensus.trace.TraceConfig.TraceParams; +import io.opencensus.trace.config.TraceParams; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; diff --git a/api/src/test/java/io/opencensus/trace/TracingTest.java b/api/src/test/java/io/opencensus/trace/TracingTest.java index b7c9be25..c23e7c6f 100644 --- a/api/src/test/java/io/opencensus/trace/TracingTest.java +++ b/api/src/test/java/io/opencensus/trace/TracingTest.java @@ -15,6 +15,7 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; +import io.opencensus.trace.config.TraceConfig; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -- cgit v1.2.3 From f3930443b38c92b4775a25756b1fb30d49660234 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Wed, 7 Jun 2017 16:00:18 -0700 Subject: Split TraceExporter class into ExportComponent and all the sub-components in an export package. (#332) --- .../java/io/opencensus/trace/TraceComponent.java | 13 +- .../java/io/opencensus/trace/TraceExporter.java | 572 --------------------- api/src/main/java/io/opencensus/trace/Tracing.java | 7 +- .../opencensus/trace/export/ExportComponent.java | 69 +++ .../trace/export/InProcessDebuggingHandler.java | 417 +++++++++++++++ .../io/opencensus/trace/export/SpanExporter.java | 127 +++++ .../io/opencensus/trace/TraceComponentTest.java | 3 +- .../io/opencensus/trace/TraceExporterTest.java | 47 -- .../test/java/io/opencensus/trace/TracingTest.java | 3 +- .../opencensus/trace/export/SpanExporterTest.java | 49 ++ 10 files changed, 677 insertions(+), 630 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/trace/TraceExporter.java create mode 100644 api/src/main/java/io/opencensus/trace/export/ExportComponent.java create mode 100644 api/src/main/java/io/opencensus/trace/export/InProcessDebuggingHandler.java create mode 100644 api/src/main/java/io/opencensus/trace/export/SpanExporter.java delete mode 100644 api/src/test/java/io/opencensus/trace/TraceExporterTest.java create mode 100644 api/src/test/java/io/opencensus/trace/export/SpanExporterTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/TraceComponent.java b/api/src/main/java/io/opencensus/trace/TraceComponent.java index bee02dae..54c2c8a1 100644 --- a/api/src/main/java/io/opencensus/trace/TraceComponent.java +++ b/api/src/main/java/io/opencensus/trace/TraceComponent.java @@ -16,10 +16,11 @@ package io.opencensus.trace; import io.opencensus.common.Clock; import io.opencensus.internal.ZeroTimeClock; import io.opencensus.trace.config.TraceConfig; +import io.opencensus.trace.export.ExportComponent; /** * Class that holds the implementation instances for {@link Tracer}, {@link - * BinaryPropagationHandler}, {@link Clock}, {@link TraceExporter} and {@link TraceConfig}. + * BinaryPropagationHandler}, {@link Clock}, {@link ExportComponent} and {@link TraceConfig}. * *

Unless otherwise noted all methods (on component) results are cacheable. */ @@ -50,12 +51,12 @@ public abstract class TraceComponent { public abstract Clock getClock(); /** - * Returns the {@link TraceExporter} with the provided implementation. If no implementation is + * Returns the {@link ExportComponent} with the provided implementation. If no implementation is * provided then no-op implementations will be used. * - * @return the {@link TraceExporter} implementation. + * @return the {@link ExportComponent} implementation. */ - public abstract TraceExporter getTraceExporter(); + public abstract ExportComponent getTraceExporter(); /** * Returns the {@link TraceConfig} with the provided implementation. If no implementation is @@ -94,8 +95,8 @@ public abstract class TraceComponent { } @Override - public TraceExporter getTraceExporter() { - return TraceExporter.getNoopTraceExporter(); + public ExportComponent getTraceExporter() { + return ExportComponent.getNoopExportComponent(); } @Override diff --git a/api/src/main/java/io/opencensus/trace/TraceExporter.java b/api/src/main/java/io/opencensus/trace/TraceExporter.java deleted file mode 100644 index 7d6c8c7f..00000000 --- a/api/src/main/java/io/opencensus/trace/TraceExporter.java +++ /dev/null @@ -1,572 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.auto.value.AutoValue; -import io.opencensus.trace.Status.CanonicalCode; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; -import javax.annotation.concurrent.ThreadSafe; - -/** - * The main exporting API for the trace library. - * - *

Implementation MUST ensure that all functions are thread safe. - */ -@ThreadSafe -public abstract class TraceExporter { - - private static final NoopTraceExporter noopTraceExporter = new NoopTraceExporter(); - - /** - * Returns the no-op implementation of the {@code TraceExporter}. - * - * @return the no-op implementation of the {@code TraceExporter}. - */ - static TraceExporter getNoopTraceExporter() { - return noopTraceExporter; - } - - /** - * Registers a new service handler that is used by the library to export {@code SpanData} for - * sampled spans (see {@link TraceOptions#isSampled()}). - * - *

Example of usage: - * - *

{@code
-   * public static void main(String[] args) {
-   *   Tracing.getTraceExporter().registerServiceHandler(
-   *       "com.google.stackdriver.tracing", new StackdriverTracingServiceHandler());
-   *   // ...
-   * }
-   * }
- * - * @param name the name of the service handler. Must be unique for each service. - * @param serviceHandler the service handler that is called for each ended sampled span. - */ - public abstract void registerServiceHandler(String name, ServiceHandler serviceHandler); - - /** - * Unregisters the service handler with the provided name. - * - * @param name the name of the service handler that will be unregistered. - */ - public abstract void unregisterServiceHandler(String name); - - /** - * Returns the {@code InProcessDebuggingHandler} that can be used to get useful debugging - * information such as (active spans, latency based sampled spans, error based sampled spans). - * - * @return the {@code InProcessDebuggingHandler} or {@code null} if in-process debugging is not - * supported. - */ - @Nullable - public abstract InProcessDebuggingHandler getInProcessDebuggingHandler(); - - /** - * This class allows users to access in-process debugging information such as (getting access to - * all active spans, support latency based sampled spans and error based sampled spans). - * - *

The active spans tracking is available for all the spans with the option {@link - * Span.Options#RECORD_EVENTS}. This functionality allows users to debug stuck operations or long - * living operations. - * - *

For all completed spans with the option {@link Span.Options#RECORD_EVENTS} the library can - * store samples based on latency for succeeded operations or based on error code for failed - * operations. To activate this, users MUST manually configure all the span names for which - * samples will be collected (see {@link #registerSpanNamesForCollection(Collection)}). - */ - public abstract static class InProcessDebuggingHandler { - - InProcessDebuggingHandler() {} - - /** - * Returns the summary of all available in-process debugging data such as number of active - * spans, number of sampled spans in the latency based samples or error based samples. - * - *

Latency based sampled summary buckets and error based sampled summary buckets are - * available only for span names registered using {@link - * #registerSpanNamesForCollection(Collection)}. - * - * @return the summary of all available in-process debugging data. - */ - public abstract Summary getSummary(); - - /** - * Returns a list of active spans that match the {@code filter}. - * - *

Active spans are available for all the span names. - * - * @param filter used to filter the returned spans. - * @return a list of active spans that match the {@code filter}. - */ - public abstract Collection getActiveSpans(ActiveSpansFilter filter); - - /** - * Returns a list of succeeded spans (spans with {@link Status} equal to {@link Status#OK}) that - * match the {@code filter}. - * - *

Latency based sampled spans are available only for span names registered using {@link - * #registerSpanNamesForCollection(Collection)}. - * - * @param filter used to filter the returned sampled spans. - * @return a list of succeeded spans that match the {@code filter}. - */ - public abstract Collection getLatencyBasedSampledSpans( - LatencyBasedSampledSpansFilter filter); - - /** - * Returns a list of failed spans (spans with {@link Status} other than {@link Status#OK}) that - * match the {@code filter}. - * - *

Error based sampled spans are available only for span names registered using {@link - * #registerSpanNamesForCollection(Collection)}. - * - * @param filter used to filter the returned sampled spans. - * @return a list of failed spans that match the {@code filter}. - */ - public abstract Collection getErrorBasedSampledSpans( - ErrorBasedSampledSpansFilter filter); - - /** - * Appends a list of span names for which the library will collect latency based sampled spans - * and error based sampled spans. - * - *

If called multiple times the library keeps the list of unique span names from all the - * calls. - * - * @param spanNames list of span names for which the library will collect samples. - */ - public abstract void registerSpanNamesForCollection(Collection spanNames); - - /** - * Removes a list of span names for which the library will collect latency based sampled spans - * and error based sampled spans. - * - *

The library keeps the list of unique registered span names for which samples will be - * called. This method allows users to remove span names from that list. - * - * @param spanNames list of span names for which the library will no longer collect samples. - */ - public abstract void unregisterSpanNamesForCollection(Collection spanNames); - - /** - * The latency buckets boundaries. Samples based on latency for successful spans (the status of - * the span has a canonical code equal to {@link CanonicalCode#OK}) are collected in one of - * these latency buckets. - */ - public enum LatencyBucketBoundaries { - // Stores finished successful requests of duration within the interval [0, 10us) - ZERO_MICROSx10(0, TimeUnit.MICROSECONDS.toNanos(10)), - // Stores finished successful requests of duration within the interval [10us, 100us) - MICROSx10_MICROSx100( - TimeUnit.MICROSECONDS.toNanos(10), TimeUnit.MICROSECONDS.toNanos(100)), - // Stores finished successful requests of duration within the interval [100us, 1ms) - MICROSx100_MILLIx1( - TimeUnit.MICROSECONDS.toNanos(100), TimeUnit.MILLISECONDS.toNanos(1)), - // Stores finished successful requests of duration within the interval [1ms, 10ms) - MILLIx1_MILLIx10( - TimeUnit.MILLISECONDS.toNanos(1), TimeUnit.MILLISECONDS.toNanos(10)), - // Stores finished successful requests of duration within the interval [10ms, 100ms) - MILLIx10_MILLIx100( - TimeUnit.MILLISECONDS.toNanos(10), TimeUnit.MILLISECONDS.toNanos(100)), - // Stores finished successful requests of duration within the interval [100ms, 1sec) - MILLIx100_SECONDx1( - TimeUnit.MILLISECONDS.toNanos(100), TimeUnit.SECONDS.toNanos(1)), - // Stores finished successful requests of duration within the interval [1sec, 10sec) - SECONDx1_SECONDx10( - TimeUnit.SECONDS.toNanos(1), TimeUnit.SECONDS.toNanos(10)), - // Stores finished successful requests of duration within the interval [10sec, 100sec) - SECONDx10_SECONDx100( - TimeUnit.SECONDS.toNanos(10), TimeUnit.SECONDS.toNanos(100)), - // Stores finished successful requests of duration >= 100sec - SECONDx100_MAX(TimeUnit.SECONDS.toNanos(100), Long.MAX_VALUE); - - /** - * Constructs a {@code LatencyBucketBoundaries} with the given boundaries and label. - * - * @param latencyLowerNs the latency lower bound of the bucket. - * @param latencyUpperNs the latency upper bound of the bucket. - */ - LatencyBucketBoundaries( - long latencyLowerNs, - long latencyUpperNs) { - this.latencyLowerNs = latencyLowerNs; - this.latencyUpperNs = latencyUpperNs; - } - - /** - * Returns the latency lower bound of the bucket. - * - * @return the latency lower bound of the bucket. - */ - public long getLatencyLowerNs() { - return latencyLowerNs; - } - - /** - * Returns the latency upper bound of the bucket. - * - * @return the latency upper bound of the bucket. - */ - public long getLatencyUpperNs() { - return latencyUpperNs; - } - - private final long latencyLowerNs; - private final long latencyUpperNs; - } - - /** The summary of all in-process debugging information. */ - @AutoValue - @Immutable - public abstract static class Summary { - - Summary() {} - - /** - * Returns a new instance of {@code Summary}. - * - * @param perSpanNameSummary a map with summary for each different span name. - * @return a new instance of {@code Summary}. - * @throws NullPointerException if {@code perSpanNameSummary} is {@code null}. - */ - public static Summary create(Map perSpanNameSummary) { - return new AutoValue_TraceExporter_InProcessDebuggingHandler_Summary( - Collections.unmodifiableMap( - new HashMap( - checkNotNull(perSpanNameSummary, "perSpanNameSummary")))); - } - - /** - * Returns a map with summary of available data for each different span name. - * - * @return a map with all the span names and the summary. - */ - public abstract Map getPerSpanNameSummary(); - - /** Summary of all available data for a span name. */ - @AutoValue - @Immutable - public abstract static class PerSpanNameSummary { - - PerSpanNameSummary() {} - - /** - * Returns a new instance of {@code PerSpanNameSummary}. - * - * @param numActiveSpans the number of sampled spans. - * @param latencyBucketsSummaries the summary for the latency buckets. - * @param errorBucketsSummaries the summary for the error buckets. - * @return a new instance of {@code PerSpanNameSummary}. - * @throws NullPointerException if {@code latencyBucketSummaries} or {@code - * errorBucketSummaries} are {@code null}. - * @throws IllegalArgumentException if {@code numActiveSpans} is negative. - */ - public static PerSpanNameSummary create( - int numActiveSpans, - Map latencyBucketsSummaries, - Map errorBucketsSummaries) { - checkArgument(numActiveSpans >= 0, "Negative numActiveSpans."); - return new AutoValue_TraceExporter_InProcessDebuggingHandler_Summary_PerSpanNameSummary( - numActiveSpans, - Collections.unmodifiableMap( - new HashMap( - checkNotNull(latencyBucketsSummaries, "latencyBucketsSummaries"))), - Collections.unmodifiableMap( - new HashMap( - checkNotNull(errorBucketsSummaries, "errorBucketsSummaries")))); - } - - /** - * Returns the number of active spans. - * - * @return the number of active spans. - */ - public abstract int getNumActiveSpans(); - - /** - * Returns the number of samples for each latency based sampled bucket. - * - * @return the number of samples for each latency based sampled bucket. - */ - public abstract Map getLatencyBucketsSummaries(); - - /** - * Returns the number of samples for each error based sampled bucket. - * - * @return the number of samples for each error based sampled bucket. - */ - public abstract Map getErrorBucketsSummaries(); - } - } - - /** - * Filter for active spans. Used to filter results returned by the {@link - * #getActiveSpans(ActiveSpansFilter)} request. - */ - @AutoValue - @Immutable - public abstract static class ActiveSpansFilter { - - ActiveSpansFilter() {} - - /** - * Returns a new instance of {@code ActiveSpansFilter}. - * - *

Filters all the spans based on {@code spanName} and returns a maximum of {@code - * maxSpansToReturn}. - * - * @param spanName the name of the span. - * @param maxSpansToReturn the maximum number of results to be returned. {@code 0} means all. - * @return a new instance of {@code ActiveSpansFilter}. - * @throws NullPointerException if {@code spanName} is {@code null}. - * @throws IllegalArgumentException if {@code maxSpansToReturn} is negative. - */ - public static ActiveSpansFilter create(String spanName, int maxSpansToReturn) { - checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); - return new AutoValue_TraceExporter_InProcessDebuggingHandler_ActiveSpansFilter( - spanName, maxSpansToReturn); - } - - /** - * Returns the span name. - * - * @return the span name. - */ - public abstract String getSpanName(); - - /** - * Returns the maximum number of spans to be returned. {@code 0} means all. - * - * @return the maximum number of spans to be returned. - */ - public abstract int getMaxSpansToReturn(); - } - - /** - * Filter for latency based sampled spans. Used to filter results returned by the {@link - * #getLatencyBasedSampledSpans(LatencyBasedSampledSpansFilter)} request. - */ - @AutoValue - @Immutable - public abstract static class LatencyBasedSampledSpansFilter { - - LatencyBasedSampledSpansFilter() {} - - /** - * Returns a new instance of {@code LatencyBasedSampledSpansFilter}. - * - *

Filters all the spans based on {@code spanName} and latency in the interval - * [latencyLowerNs, latencyUpperNs) and returns a maximum of {@code maxSpansToReturn}. - * - * @param spanName the name of the span. - * @param latencyLowerNs the latency lower bound. - * @param latencyUpperNs the latency upper bound. - * @param maxSpansToReturn the maximum number of results to be returned. {@code 0} means all. - * @return a new instance of {@code LatencyBasedSampledSpansFilter}. - * @throws NullPointerException if {@code spanName} is {@code null}. - * @throws IllegalArgumentException if {@code maxSpansToReturn} or {@code latencyLowerNs} or - * {@code latencyUpperNs} are negative. - */ - public static LatencyBasedSampledSpansFilter create( - String spanName, long latencyLowerNs, long latencyUpperNs, int maxSpansToReturn) { - checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); - checkArgument(latencyLowerNs >= 0, "Negative latencyLowerNs"); - checkArgument(latencyUpperNs >= 0, "Negative latencyUpperNs"); - return new AutoValue_TraceExporter_InProcessDebuggingHandler_LatencyBasedSampledSpansFilter( - spanName, latencyLowerNs, latencyUpperNs, maxSpansToReturn); - } - - /** - * Returns the span name used by this filter. - * - * @return the span name used by this filter. - */ - public abstract String getSpanName(); - - /** - * Returns the latency lower bound of this bucket (inclusive). - * - * @return the latency lower bound of this bucket. - */ - public abstract long getLatencyLowerNs(); - - /** - * Returns the latency upper bound of this bucket (exclusive). - * - * @return the latency upper bound of this bucket. - */ - public abstract long getLatencyUpperNs(); - - /** - * Returns the maximum number of spans to be returned. {@code 0} means all. - * - * @return the maximum number of spans to be returned. - */ - public abstract int getMaxSpansToReturn(); - } - - /** Filter for error based sampled spans. */ - @AutoValue - @Immutable - public abstract static class ErrorBasedSampledSpansFilter { - - ErrorBasedSampledSpansFilter() {} - - /** - * Returns a new instance of {@code ErrorBasedSampledSpansFilter}. - * - *

Filters all the spans based on {@code spanName} and {@code canonicalCode} and returns a - * maximum of {@code maxSpansToReturn}. - * - * @param spanName the name of the span. - * @param canonicalCode the error code of the span. - * @param maxSpansToReturn the maximum number of results to be returned. {@code 0} means all. - * @return a new instance of {@code ErrorBasedSampledSpansFilter}. - * @throws NullPointerException if {@code spanName} or {@code canonicalCode} are {@code null}. - * @throws IllegalArgumentException if {@code canonicalCode} is {@link CanonicalCode#OK} or - * {@code maxSpansToReturn} is negative. - */ - public static ErrorBasedSampledSpansFilter create( - String spanName, CanonicalCode canonicalCode, int maxSpansToReturn) { - checkArgument(canonicalCode != CanonicalCode.OK, "Invalid canonical code."); - checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); - return new AutoValue_TraceExporter_InProcessDebuggingHandler_ErrorBasedSampledSpansFilter( - spanName, canonicalCode, maxSpansToReturn); - } - - /** - * Returns the span name used by this filter. - * - * @return the span name used by this filter. - */ - public abstract String getSpanName(); - - /** - * Returns the canonical code used by this filter. Always different than {@link - * CanonicalCode#OK}. - * - * @return the canonical code used by this filter. - */ - public abstract CanonicalCode getCanonicalCode(); - - /** - * Returns the maximum number of spans to be returned. Used to enforce the number of returned - * {@code SpanData}. {@code 0} means all. - * - * @return the maximum number of spans to be returned. - */ - public abstract int getMaxSpansToReturn(); - } - } - - /** - * An abstract class that allows different tracing services to export recorded data for sampled - * spans in their own format. - * - *

To export data this MUST be register to to the TraceExporter using {@link - * #registerServiceHandler(String, ServiceHandler)}. - */ - public abstract static class ServiceHandler { - - /** - * Exports a list of sampled (see {@link TraceOptions#isSampled()}) {@link Span}s using the - * immutable representation {@link SpanData}. - * - *

This may be called from a different thread than the one that called {@link Span#end()}. - * - *

Implementation SHOULD not block the calling thread. It should execute the export on a - * different thread if possible. - * - * @param spanDataList a list of {@code SpanData} objects to be exported. - */ - public abstract void export(Collection spanDataList); - } - - /** - * Implementation of the {@link ServiceHandler} which logs all the exported {@link SpanData}. - * - *

Example of usage: - * - *

{@code
-   * public static void main(String[] args) {
-   *   Tracing.getTraceExporter().registerServiceHandler(
-   *       "io.opencensus.LoggingServiceHandler", LoggingServiceHandler.getInstance());
-   *   // ...
-   * }
-   * }
- */ - @ThreadSafe - public static final class LoggingServiceHandler extends ServiceHandler { - - private static final Logger logger = Logger.getLogger(LoggingServiceHandler.class.getName()); - private static final String SERVICE_NAME = "io.opencensus.trace.LoggingServiceHandler"; - private static final LoggingServiceHandler INSTANCE = new LoggingServiceHandler(); - - private LoggingServiceHandler() {} - - /** - * Registers the {@code LoggingServiceHandler} to the {@code TraceExporter}. - * - * @param traceExporter the instance of the {@code TraceExporter} where this service is - * registered. - */ - public static void registerService(TraceExporter traceExporter) { - traceExporter.registerServiceHandler(SERVICE_NAME, INSTANCE); - } - - /** - * Unregisters the {@code LoggingServiceHandler} from the {@code TraceExporter}. - * - * @param traceExporter the instance of the {@code TraceExporter} from where this service is - * unregistered. - */ - public static void unregisterService(TraceExporter traceExporter) { - traceExporter.unregisterServiceHandler(SERVICE_NAME); - } - - @Override - public void export(Collection spanDataList) { - for (SpanData spanData : spanDataList) { - logger.log(Level.INFO, spanData.toString()); - } - } - } - - private static final class NoopTraceExporter extends TraceExporter { - - @Override - public void registerServiceHandler(String name, @Nullable ServiceHandler serviceHandler) {} - - @Override - public void unregisterServiceHandler(String name) {} - - @Nullable - @Override - public InProcessDebuggingHandler getInProcessDebuggingHandler() { - return null; - } - } -} diff --git a/api/src/main/java/io/opencensus/trace/Tracing.java b/api/src/main/java/io/opencensus/trace/Tracing.java index 771b8553..daf5b3c9 100644 --- a/api/src/main/java/io/opencensus/trace/Tracing.java +++ b/api/src/main/java/io/opencensus/trace/Tracing.java @@ -17,6 +17,7 @@ import com.google.common.annotations.VisibleForTesting; import io.opencensus.common.Clock; import io.opencensus.internal.Provider; import io.opencensus.trace.config.TraceConfig; +import io.opencensus.trace.export.ExportComponent; import java.util.logging.Level; import java.util.logging.Logger; @@ -54,11 +55,11 @@ public final class Tracing { } /** - * Returns the global {@link TraceExporter}. + * Returns the global {@link ExportComponent}. * - * @return the global {@code TraceExporter}. + * @return the global {@code ExportComponent}. */ - public static TraceExporter getTraceExporter() { + public static ExportComponent getTraceExporter() { return traceComponent.getTraceExporter(); } diff --git a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java new file mode 100644 index 00000000..5407c46b --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java @@ -0,0 +1,69 @@ +/* + * Copyright 2017, Google Inc. + * 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.export; + +import io.opencensus.trace.TraceOptions; +import javax.annotation.Nullable; + +/** + * Class that holds the implementation instances for {@link SpanExporter} and {@link + * InProcessDebuggingHandler}. + * + *

Unless otherwise noted all methods (on component) results are cacheable. + */ +public abstract class ExportComponent { + + private static final NoopExportComponent NOOP_EXPORT_COMPONENT = new NoopExportComponent(); + + /** + * Returns the no-op implementation of the {@code ExportComponent}. + * + * @return the no-op implementation of the {@code ExportComponent}. + */ + public static ExportComponent getNoopExportComponent() { + return NOOP_EXPORT_COMPONENT; + } + + /** + * Returns the {@link SpanExporter} which can be used to register handlers to export all the spans + * that are part of a distributed sampled trace (see {@link TraceOptions#isSampled()}). + * + * @return the implementation of the {@code SpanExporter} or no-op if no implementation linked in + * the binary. + */ + public abstract SpanExporter getSpanExporter(); + + /** + * Returns the {@link InProcessDebuggingHandler} that can be used to get useful debugging + * information such as (active spans, latency based sampled spans, error based sampled spans). + * + * @return the {@code InProcessDebuggingHandler} or {@code null} if in-process debugging is not + * supported. + */ + @Nullable + public abstract InProcessDebuggingHandler getInProcessDebuggingHandler(); + + private static final class NoopExportComponent extends ExportComponent { + @Override + public SpanExporter getSpanExporter() { + return SpanExporter.getNoopSpanExporter(); + } + + @Nullable + @Override + public InProcessDebuggingHandler getInProcessDebuggingHandler() { + return null; + } + } +} diff --git a/api/src/main/java/io/opencensus/trace/export/InProcessDebuggingHandler.java b/api/src/main/java/io/opencensus/trace/export/InProcessDebuggingHandler.java new file mode 100644 index 00000000..56318bd9 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/export/InProcessDebuggingHandler.java @@ -0,0 +1,417 @@ +/* + * Copyright 2017, Google Inc. + * 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.export; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import io.opencensus.trace.Span; +import io.opencensus.trace.SpanData; +import io.opencensus.trace.Status; +import io.opencensus.trace.Status.CanonicalCode; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import javax.annotation.concurrent.Immutable; +import javax.annotation.concurrent.ThreadSafe; + +/** + * This class allows users to access in-process debugging information such as (getting access to all + * active spans, support latency based sampled spans and error based sampled spans). + * + *

The active spans tracking is available for all the spans with the option {@link + * Span.Options#RECORD_EVENTS}. This functionality allows users to debug stuck operations or long + * living operations. + * + *

For all completed spans with the option {@link Span.Options#RECORD_EVENTS} the library can + * store samples based on latency for succeeded operations or based on error code for failed + * operations. To activate this, users MUST manually configure all the span names for which samples + * will be collected (see {@link #registerSpanNamesForCollection(Collection)}). + */ +@ThreadSafe +public abstract class InProcessDebuggingHandler { + + InProcessDebuggingHandler() {} + + /** + * Returns the summary of all available in-process debugging data such as number of active spans, + * number of sampled spans in the latency based samples or error based samples. + * + *

Latency based sampled summary buckets and error based sampled summary buckets are available + * only for span names registered using {@link #registerSpanNamesForCollection(Collection)}. + * + * @return the summary of all available in-process debugging data. + */ + public abstract Summary getSummary(); + + /** + * Returns a list of active spans that match the {@code filter}. + * + *

Active spans are available for all the span names. + * + * @param filter used to filter the returned spans. + * @return a list of active spans that match the {@code filter}. + */ + public abstract Collection getActiveSpans(ActiveSpansFilter filter); + + /** + * Returns a list of succeeded spans (spans with {@link Status} equal to {@link Status#OK}) that + * match the {@code filter}. + * + *

Latency based sampled spans are available only for span names registered using {@link + * #registerSpanNamesForCollection(Collection)}. + * + * @param filter used to filter the returned sampled spans. + * @return a list of succeeded spans that match the {@code filter}. + */ + public abstract Collection getLatencyBasedSampledSpans( + LatencyBasedSampledSpansFilter filter); + + /** + * Returns a list of failed spans (spans with {@link Status} other than {@link Status#OK}) that + * match the {@code filter}. + * + *

Error based sampled spans are available only for span names registered using {@link + * #registerSpanNamesForCollection(Collection)}. + * + * @param filter used to filter the returned sampled spans. + * @return a list of failed spans that match the {@code filter}. + */ + public abstract Collection getErrorBasedSampledSpans( + ErrorBasedSampledSpansFilter filter); + + /** + * Appends a list of span names for which the library will collect latency based sampled spans and + * error based sampled spans. + * + *

If called multiple times the library keeps the list of unique span names from all the calls. + * + * @param spanNames list of span names for which the library will collect samples. + */ + public abstract void registerSpanNamesForCollection(Collection spanNames); + + /** + * Removes a list of span names for which the library will collect latency based sampled spans and + * error based sampled spans. + * + *

The library keeps the list of unique registered span names for which samples will be called. + * This method allows users to remove span names from that list. + * + * @param spanNames list of span names for which the library will no longer collect samples. + */ + public abstract void unregisterSpanNamesForCollection(Collection spanNames); + + /** + * The latency buckets boundaries. Samples based on latency for successful spans (the status of + * the span has a canonical code equal to {@link CanonicalCode#OK}) are collected in one of these + * latency buckets. + */ + public enum LatencyBucketBoundaries { + // Stores finished successful requests of duration within the interval [0, 10us) + ZERO_MICROSx10(0, TimeUnit.MICROSECONDS.toNanos(10)), + // Stores finished successful requests of duration within the interval [10us, 100us) + MICROSx10_MICROSx100(TimeUnit.MICROSECONDS.toNanos(10), TimeUnit.MICROSECONDS.toNanos(100)), + // Stores finished successful requests of duration within the interval [100us, 1ms) + MICROSx100_MILLIx1(TimeUnit.MICROSECONDS.toNanos(100), TimeUnit.MILLISECONDS.toNanos(1)), + // Stores finished successful requests of duration within the interval [1ms, 10ms) + MILLIx1_MILLIx10(TimeUnit.MILLISECONDS.toNanos(1), TimeUnit.MILLISECONDS.toNanos(10)), + // Stores finished successful requests of duration within the interval [10ms, 100ms) + MILLIx10_MILLIx100(TimeUnit.MILLISECONDS.toNanos(10), TimeUnit.MILLISECONDS.toNanos(100)), + // Stores finished successful requests of duration within the interval [100ms, 1sec) + MILLIx100_SECONDx1(TimeUnit.MILLISECONDS.toNanos(100), TimeUnit.SECONDS.toNanos(1)), + // Stores finished successful requests of duration within the interval [1sec, 10sec) + SECONDx1_SECONDx10(TimeUnit.SECONDS.toNanos(1), TimeUnit.SECONDS.toNanos(10)), + // Stores finished successful requests of duration within the interval [10sec, 100sec) + SECONDx10_SECONDx100(TimeUnit.SECONDS.toNanos(10), TimeUnit.SECONDS.toNanos(100)), + // Stores finished successful requests of duration >= 100sec + SECONDx100_MAX(TimeUnit.SECONDS.toNanos(100), Long.MAX_VALUE); + + /** + * Constructs a {@code LatencyBucketBoundaries} with the given boundaries and label. + * + * @param latencyLowerNs the latency lower bound of the bucket. + * @param latencyUpperNs the latency upper bound of the bucket. + */ + LatencyBucketBoundaries(long latencyLowerNs, long latencyUpperNs) { + this.latencyLowerNs = latencyLowerNs; + this.latencyUpperNs = latencyUpperNs; + } + + /** + * Returns the latency lower bound of the bucket. + * + * @return the latency lower bound of the bucket. + */ + public long getLatencyLowerNs() { + return latencyLowerNs; + } + + /** + * Returns the latency upper bound of the bucket. + * + * @return the latency upper bound of the bucket. + */ + public long getLatencyUpperNs() { + return latencyUpperNs; + } + + private final long latencyLowerNs; + private final long latencyUpperNs; + } + + /** The summary of all in-process debugging information. */ + @AutoValue + @Immutable + public abstract static class Summary { + + Summary() {} + + /** + * Returns a new instance of {@code Summary}. + * + * @param perSpanNameSummary a map with summary for each different span name. + * @return a new instance of {@code Summary}. + * @throws NullPointerException if {@code perSpanNameSummary} is {@code null}. + */ + public static Summary create(Map perSpanNameSummary) { + return new AutoValue_InProcessDebuggingHandler_Summary( + Collections.unmodifiableMap( + new HashMap( + checkNotNull(perSpanNameSummary, "perSpanNameSummary")))); + } + + /** + * Returns a map with summary of available data for each different span name. + * + * @return a map with all the span names and the summary. + */ + public abstract Map getPerSpanNameSummary(); + + /** Summary of all available data for a span name. */ + @AutoValue + @Immutable + public abstract static class PerSpanNameSummary { + + PerSpanNameSummary() {} + + /** + * Returns a new instance of {@code PerSpanNameSummary}. + * + * @param numActiveSpans the number of sampled spans. + * @param latencyBucketsSummaries the summary for the latency buckets. + * @param errorBucketsSummaries the summary for the error buckets. + * @return a new instance of {@code PerSpanNameSummary}. + * @throws NullPointerException if {@code latencyBucketSummaries} or {@code + * errorBucketSummaries} are {@code null}. + * @throws IllegalArgumentException if {@code numActiveSpans} is negative. + */ + public static Summary.PerSpanNameSummary create( + int numActiveSpans, + Map latencyBucketsSummaries, + Map errorBucketsSummaries) { + checkArgument(numActiveSpans >= 0, "Negative numActiveSpans."); + return new AutoValue_InProcessDebuggingHandler_Summary_PerSpanNameSummary( + numActiveSpans, + Collections.unmodifiableMap( + new HashMap( + checkNotNull(latencyBucketsSummaries, "latencyBucketsSummaries"))), + Collections.unmodifiableMap( + new HashMap( + checkNotNull(errorBucketsSummaries, "errorBucketsSummaries")))); + } + + /** + * Returns the number of active spans. + * + * @return the number of active spans. + */ + public abstract int getNumActiveSpans(); + + /** + * Returns the number of samples for each latency based sampled bucket. + * + * @return the number of samples for each latency based sampled bucket. + */ + public abstract Map getLatencyBucketsSummaries(); + + /** + * Returns the number of samples for each error based sampled bucket. + * + * @return the number of samples for each error based sampled bucket. + */ + public abstract Map getErrorBucketsSummaries(); + } + } + + /** + * Filter for active spans. Used to filter results returned by the {@link + * #getActiveSpans(ActiveSpansFilter)} request. + */ + @AutoValue + @Immutable + public abstract static class ActiveSpansFilter { + + ActiveSpansFilter() {} + + /** + * Returns a new instance of {@code ActiveSpansFilter}. + * + *

Filters all the spans based on {@code spanName} and returns a maximum of {@code + * maxSpansToReturn}. + * + * @param spanName the name of the span. + * @param maxSpansToReturn the maximum number of results to be returned. {@code 0} means all. + * @return a new instance of {@code ActiveSpansFilter}. + * @throws NullPointerException if {@code spanName} is {@code null}. + * @throws IllegalArgumentException if {@code maxSpansToReturn} is negative. + */ + public static ActiveSpansFilter create(String spanName, int maxSpansToReturn) { + checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); + return new AutoValue_InProcessDebuggingHandler_ActiveSpansFilter(spanName, maxSpansToReturn); + } + + /** + * Returns the span name. + * + * @return the span name. + */ + public abstract String getSpanName(); + + /** + * Returns the maximum number of spans to be returned. {@code 0} means all. + * + * @return the maximum number of spans to be returned. + */ + public abstract int getMaxSpansToReturn(); + } + + /** + * Filter for latency based sampled spans. Used to filter results returned by the {@link + * #getLatencyBasedSampledSpans(LatencyBasedSampledSpansFilter)} request. + */ + @AutoValue + @Immutable + public abstract static class LatencyBasedSampledSpansFilter { + + LatencyBasedSampledSpansFilter() {} + + /** + * Returns a new instance of {@code LatencyBasedSampledSpansFilter}. + * + *

Filters all the spans based on {@code spanName} and latency in the interval + * [latencyLowerNs, latencyUpperNs) and returns a maximum of {@code maxSpansToReturn}. + * + * @param spanName the name of the span. + * @param latencyLowerNs the latency lower bound. + * @param latencyUpperNs the latency upper bound. + * @param maxSpansToReturn the maximum number of results to be returned. {@code 0} means all. + * @return a new instance of {@code LatencyBasedSampledSpansFilter}. + * @throws NullPointerException if {@code spanName} is {@code null}. + * @throws IllegalArgumentException if {@code maxSpansToReturn} or {@code latencyLowerNs} or + * {@code latencyUpperNs} are negative. + */ + public static LatencyBasedSampledSpansFilter create( + String spanName, long latencyLowerNs, long latencyUpperNs, int maxSpansToReturn) { + checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); + checkArgument(latencyLowerNs >= 0, "Negative latencyLowerNs"); + checkArgument(latencyUpperNs >= 0, "Negative latencyUpperNs"); + return new AutoValue_InProcessDebuggingHandler_LatencyBasedSampledSpansFilter( + spanName, latencyLowerNs, latencyUpperNs, maxSpansToReturn); + } + + /** + * Returns the span name used by this filter. + * + * @return the span name used by this filter. + */ + public abstract String getSpanName(); + + /** + * Returns the latency lower bound of this bucket (inclusive). + * + * @return the latency lower bound of this bucket. + */ + public abstract long getLatencyLowerNs(); + + /** + * Returns the latency upper bound of this bucket (exclusive). + * + * @return the latency upper bound of this bucket. + */ + public abstract long getLatencyUpperNs(); + + /** + * Returns the maximum number of spans to be returned. {@code 0} means all. + * + * @return the maximum number of spans to be returned. + */ + public abstract int getMaxSpansToReturn(); + } + + /** Filter for error based sampled spans. */ + @AutoValue + @Immutable + public abstract static class ErrorBasedSampledSpansFilter { + + ErrorBasedSampledSpansFilter() {} + + /** + * Returns a new instance of {@code ErrorBasedSampledSpansFilter}. + * + *

Filters all the spans based on {@code spanName} and {@code canonicalCode} and returns a + * maximum of {@code maxSpansToReturn}. + * + * @param spanName the name of the span. + * @param canonicalCode the error code of the span. + * @param maxSpansToReturn the maximum number of results to be returned. {@code 0} means all. + * @return a new instance of {@code ErrorBasedSampledSpansFilter}. + * @throws NullPointerException if {@code spanName} or {@code canonicalCode} are {@code null}. + * @throws IllegalArgumentException if {@code canonicalCode} is {@link CanonicalCode#OK} or + * {@code maxSpansToReturn} is negative. + */ + public static ErrorBasedSampledSpansFilter create( + String spanName, CanonicalCode canonicalCode, int maxSpansToReturn) { + checkArgument(canonicalCode != CanonicalCode.OK, "Invalid canonical code."); + checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); + return new AutoValue_InProcessDebuggingHandler_ErrorBasedSampledSpansFilter( + spanName, canonicalCode, maxSpansToReturn); + } + + /** + * Returns the span name used by this filter. + * + * @return the span name used by this filter. + */ + public abstract String getSpanName(); + + /** + * Returns the canonical code used by this filter. Always different than {@link + * CanonicalCode#OK}. + * + * @return the canonical code used by this filter. + */ + public abstract CanonicalCode getCanonicalCode(); + + /** + * Returns the maximum number of spans to be returned. Used to enforce the number of returned + * {@code SpanData}. {@code 0} means all. + * + * @return the maximum number of spans to be returned. + */ + public abstract int getMaxSpansToReturn(); + } +} diff --git a/api/src/main/java/io/opencensus/trace/export/SpanExporter.java b/api/src/main/java/io/opencensus/trace/export/SpanExporter.java new file mode 100644 index 00000000..5e10d8be --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/export/SpanExporter.java @@ -0,0 +1,127 @@ +/* + * Copyright 2017, Google Inc. + * 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.export; + +import io.opencensus.trace.Span; +import io.opencensus.trace.SpanData; +import io.opencensus.trace.TraceOptions; +import java.util.Collection; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.concurrent.ThreadSafe; + +/** + * A service that is used by the library to export {@code SpanData} for all the spans that are part + * of a distributed sampled trace (see {@link TraceOptions#isSampled()}). + */ +@ThreadSafe +public abstract class SpanExporter { + private static final SpanExporter NOOP_SPAN_EXPORTER = new NoopSpanExporter(); + + /** + * Returns the no-op implementation of the {@code ExportComponent}. + * + * @return the no-op implementation of the {@code ExportComponent}. + */ + public static SpanExporter getNoopSpanExporter() { + return NOOP_SPAN_EXPORTER; + } + + /** + * Registers a new service handler that is used by the library to export {@code SpanData} for + * sampled spans (see {@link TraceOptions#isSampled()}). + * + * @param name the name of the service handler. Must be unique for each service. + * @param handler the service handler that is called for each ended sampled span. + */ + public abstract void registerHandler(String name, Handler handler); + + /** + * Unregisters the service handler with the provided name. + * + * @param name the name of the service handler that will be unregistered. + */ + public abstract void unregisterHandler(String name); + + /** + * An abstract class that allows different tracing services to export recorded data for sampled + * spans in their own format. + * + *

To export data this MUST be register to to the ExportComponent using {@link + * #registerHandler(String, Handler)}. + */ + public abstract static class Handler { + + /** + * Exports a list of sampled (see {@link TraceOptions#isSampled()}) {@link Span}s using the + * immutable representation {@link SpanData}. + * + *

This may be called from a different thread than the one that called {@link Span#end()}. + * + *

Implementation SHOULD not block the calling thread. It should execute the export on a + * different thread if possible. + * + * @param spanDataList a list of {@code SpanData} objects to be exported. + */ + public abstract void export(Collection spanDataList); + } + + private static final class NoopSpanExporter extends SpanExporter { + + @Override + public void registerHandler(String name, Handler handler) {} + + @Override + public void unregisterHandler(String name) {} + } + + /** Implementation of the {@link Handler} which logs all the exported {@link SpanData}. */ + @ThreadSafe + public static final class LoggingHandler extends Handler { + + private static final Logger logger = Logger.getLogger(LoggingHandler.class.getName()); + private static final String REGISTER_NAME = + "io.opencensus.trace.export.SpanExporter$LoggingHandler"; + private static final LoggingHandler INSTANCE = new LoggingHandler(); + + private LoggingHandler() {} + + /** + * Registers the {@code LoggingHandler} to the {@code ExportComponent}. + * + * @param spanExporter the instance of the {@code SpanExporter} where this service is + * registered. + */ + public static void register(SpanExporter spanExporter) { + spanExporter.registerHandler(REGISTER_NAME, INSTANCE); + } + + /** + * Unregisters the {@code LoggingHandler} from the {@code ExportComponent}. + * + * @param spanExporter the instance of the {@code SpanExporter} from where this service is + * unregistered. + */ + public static void unregister(SpanExporter spanExporter) { + spanExporter.unregisterHandler(REGISTER_NAME); + } + + @Override + public void export(Collection spanDataList) { + for (SpanData spanData : spanDataList) { + logger.log(Level.INFO, spanData.toString()); + } + } + } +} diff --git a/api/src/test/java/io/opencensus/trace/TraceComponentTest.java b/api/src/test/java/io/opencensus/trace/TraceComponentTest.java index cd42a98a..4a0c3594 100644 --- a/api/src/test/java/io/opencensus/trace/TraceComponentTest.java +++ b/api/src/test/java/io/opencensus/trace/TraceComponentTest.java @@ -17,6 +17,7 @@ import static com.google.common.truth.Truth.assertThat; import io.opencensus.internal.ZeroTimeClock; import io.opencensus.trace.config.TraceConfig; +import io.opencensus.trace.export.ExportComponent; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -43,7 +44,7 @@ public class TraceComponentTest { @Test public void defaultTraceExporter() { assertThat(TraceComponent.getNoopTraceComponent().getTraceExporter()) - .isSameAs(TraceExporter.getNoopTraceExporter()); + .isSameAs(ExportComponent.getNoopExportComponent()); } @Test diff --git a/api/src/test/java/io/opencensus/trace/TraceExporterTest.java b/api/src/test/java/io/opencensus/trace/TraceExporterTest.java deleted file mode 100644 index 3837a1ad..00000000 --- a/api/src/test/java/io/opencensus/trace/TraceExporterTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.verify; - -import io.opencensus.trace.TraceExporter.LoggingServiceHandler; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** Unit tests for {@link TraceExporter}. */ -@RunWith(JUnit4.class) -public class TraceExporterTest { - @Mock private TraceExporter traceExporter; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void registerUnregisterLoggingService() { - LoggingServiceHandler.registerService(traceExporter); - verify(traceExporter) - .registerServiceHandler( - eq("io.opencensus.trace.LoggingServiceHandler"), any(LoggingServiceHandler.class)); - LoggingServiceHandler.unregisterService(traceExporter); - verify(traceExporter).unregisterServiceHandler(eq("io.opencensus.trace.LoggingServiceHandler")); - } -} diff --git a/api/src/test/java/io/opencensus/trace/TracingTest.java b/api/src/test/java/io/opencensus/trace/TracingTest.java index c23e7c6f..0076cc77 100644 --- a/api/src/test/java/io/opencensus/trace/TracingTest.java +++ b/api/src/test/java/io/opencensus/trace/TracingTest.java @@ -16,6 +16,7 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; import io.opencensus.trace.config.TraceConfig; +import io.opencensus.trace.export.ExportComponent; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -69,7 +70,7 @@ public class TracingTest { @Test public void defaultTraceExporter() { - assertThat(Tracing.getTraceExporter()).isSameAs(TraceExporter.getNoopTraceExporter()); + assertThat(Tracing.getTraceExporter()).isSameAs(ExportComponent.getNoopExportComponent()); } @Test diff --git a/api/src/test/java/io/opencensus/trace/export/SpanExporterTest.java b/api/src/test/java/io/opencensus/trace/export/SpanExporterTest.java new file mode 100644 index 00000000..46480688 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/export/SpanExporterTest.java @@ -0,0 +1,49 @@ +/* + * Copyright 2017, Google Inc. + * 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.export; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.verify; + +import io.opencensus.trace.export.SpanExporter.LoggingHandler; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** Unit tests for {@link ExportComponent}. */ +@RunWith(JUnit4.class) +public class SpanExporterTest { + @Mock private SpanExporter spanExporter; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void registerUnregisterLoggingService() { + LoggingHandler.register(spanExporter); + verify(spanExporter) + .registerHandler( + eq("io.opencensus.trace.export.SpanExporter$LoggingHandler"), + any(LoggingHandler.class)); + LoggingHandler.unregister(spanExporter); + verify(spanExporter) + .unregisterHandler(eq("io.opencensus.trace.export.SpanExporter$LoggingHandler")); + } +} -- cgit v1.2.3 From 95870ac86d5e2164b7872b1f17a1ba748fa619e0 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Wed, 7 Jun 2017 18:41:15 -0700 Subject: Fix all javadocs warnings and errors and re-enable javadoc for api module. (#344) --- api/build.gradle | 2 +- api/src/main/java/io/opencensus/common/Duration.java | 19 ++++++++++++++++--- api/src/main/java/io/opencensus/common/Function.java | 5 +++-- api/src/main/java/io/opencensus/common/Timestamp.java | 3 +-- api/src/main/java/io/opencensus/tags/TagKey.java | 1 + .../main/java/io/opencensus/trace/SpanContext.java | 1 + 6 files changed, 23 insertions(+), 8 deletions(-) (limited to 'api') diff --git a/api/build.gradle b/api/build.gradle index 7cfb33b2..99000c2c 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -8,4 +8,4 @@ dependencies { signature "org.codehaus.mojo.signature:java16:+@signature" } -javadoc.exclude 'io/opencensus/**' \ No newline at end of file +javadoc.exclude 'io/opencensus/internal/**' \ No newline at end of file diff --git a/api/src/main/java/io/opencensus/common/Duration.java b/api/src/main/java/io/opencensus/common/Duration.java index c0e9f1bc..bf490c39 100644 --- a/api/src/main/java/io/opencensus/common/Duration.java +++ b/api/src/main/java/io/opencensus/common/Duration.java @@ -45,19 +45,32 @@ public class Duration { return new Duration(seconds, nanos); } - /** Creates a new {@link Duration} from given milliseconds. */ + /** + * Creates a new {@link Duration} from given milliseconds. + * + * @param millis the duration in milliseconds. + * @return a new {@link Duration} from given milliseconds. + */ public static Duration fromMillis(long millis) { long seconds = millis / NUM_MILLIS_PER_SECOND; int nanos = (int) (millis % NUM_MILLIS_PER_SECOND) * NUM_NANOS_PER_MILLI; return new Duration(seconds, nanos); } - /** Returns the number of seconds in the {@link Duration}. */ + /** + * Returns the number of seconds in the {@link Duration}. + * + * @return the number of seconds in the {@link Duration}. + */ public long getSeconds() { return seconds; } - /** Returns the number of nanoseconds in the {@link Duration}. */ + /** + * Returns the number of nanoseconds in the {@link Duration}. + * + * @return the number of nanoseconds in the {@link Duration}. + */ public int getNanos() { return nanos; } diff --git a/api/src/main/java/io/opencensus/common/Function.java b/api/src/main/java/io/opencensus/common/Function.java index 51bf845c..6105c3e6 100644 --- a/api/src/main/java/io/opencensus/common/Function.java +++ b/api/src/main/java/io/opencensus/common/Function.java @@ -14,12 +14,13 @@ package io.opencensus.common; /** - * Used to specify matching functions for use encoding tagged unions (i.e. sum types) in Java. See - * {@link io.opencensus.stats.ViewDescriptor} for an example of it's use. + * Used to specify matching functions for use encoding tagged unions (i.e. sum types) in Java. * *

Note: This class is based on the java.util.Function class added in Java 1.8. We cannot use the * Function from Java 1.8 because this library is Java 1.6 compatible. */ +// TODO(bdrutu): Add back "See {@link io.opencensus.stats.ViewDescriptor} for an example of its +// use." public interface Function { B apply(A arg); } diff --git a/api/src/main/java/io/opencensus/common/Timestamp.java b/api/src/main/java/io/opencensus/common/Timestamp.java index 34c4c851..9a1dd8bb 100644 --- a/api/src/main/java/io/opencensus/common/Timestamp.java +++ b/api/src/main/java/io/opencensus/common/Timestamp.java @@ -37,8 +37,6 @@ public final class Timestamp { this.nanos = nanos; } - // TODO(bdrutu): Make create and fromMillis package-protected. - /** * Creates a new timestamp from given seconds and nanoseconds. * @@ -63,6 +61,7 @@ public final class Timestamp { /** * Creates a new timestamp from the given milliseconds. * + * @param millis the timestamp represented in milliseconds since epoch. * @return a new timestamp from the given milliseconds. */ public static Timestamp fromMillis(long millis) { diff --git a/api/src/main/java/io/opencensus/tags/TagKey.java b/api/src/main/java/io/opencensus/tags/TagKey.java index 970ee925..efd3e6e9 100644 --- a/api/src/main/java/io/opencensus/tags/TagKey.java +++ b/api/src/main/java/io/opencensus/tags/TagKey.java @@ -53,6 +53,7 @@ public abstract class TagKey { * * * @param name the name of the key. + * @return a {@code TagKey} with the given name. * @throws IllegalArgumentException if the name is not valid. */ public static TagKey createStringKey(String name) { diff --git a/api/src/main/java/io/opencensus/trace/SpanContext.java b/api/src/main/java/io/opencensus/trace/SpanContext.java index 4902f15f..56a046f1 100644 --- a/api/src/main/java/io/opencensus/trace/SpanContext.java +++ b/api/src/main/java/io/opencensus/trace/SpanContext.java @@ -39,6 +39,7 @@ public final class SpanContext { * @param traceId the trace identifier of the span context. * @param spanId the span identifier of the span context. * @param traceOptions the trace options for the span context. + * @return a new {@code SpanContext} with the given identifiers and options. */ public static SpanContext create(TraceId traceId, SpanId spanId, TraceOptions traceOptions) { return new SpanContext(traceId, spanId, traceOptions); -- cgit v1.2.3 From 1258b41748672df306155dd694ee55b744ae9359 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Thu, 8 Jun 2017 10:48:01 -0700 Subject: Change StartSpanOptions to use Autovalue. (#345) --- .../main/java/io/opencensus/trace/SpanBuilder.java | 13 +-- .../java/io/opencensus/trace/StartSpanOptions.java | 118 ++++++++++++--------- .../java/io/opencensus/trace/SpanBuilderTest.java | 30 +++--- .../io/opencensus/trace/StartSpanOptionsTest.java | 47 ++++---- .../test/java/io/opencensus/trace/TracerTest.java | 10 +- 5 files changed, 121 insertions(+), 97 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java index 4b988dfc..150932e0 100644 --- a/api/src/main/java/io/opencensus/trace/SpanBuilder.java +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -101,7 +101,7 @@ import javax.annotation.Nullable; public final class SpanBuilder { private final SpanFactory spanFactory; private final String name; - private final StartSpanOptions startSpanOption = new StartSpanOptions(); + private final StartSpanOptions.Builder startSpanOptionsBuilder = StartSpanOptions.builder(); private Span parentSpan; private SpanContext parentSpanContext; private boolean remoteParent; @@ -123,7 +123,7 @@ public final class SpanBuilder { * @return this. */ public SpanBuilder setSampler(@Nullable Sampler sampler) { - startSpanOption.setSampler(sampler); + startSpanOptionsBuilder.setSampler(sampler); return this; } @@ -136,7 +136,7 @@ public final class SpanBuilder { * @return this. */ public SpanBuilder setParentLinks(@Nullable List parentLinks) { - startSpanOption.setParentLinks(parentLinks); + startSpanOptionsBuilder.setParentLinks(parentLinks); return this; } @@ -148,7 +148,7 @@ public final class SpanBuilder { * @return this. */ public SpanBuilder setRecordEvents(boolean recordEvents) { - startSpanOption.setRecordEvents(recordEvents); + startSpanOptionsBuilder.setRecordEvents(recordEvents); return this; } @@ -276,7 +276,8 @@ public final class SpanBuilder { // Utility method to start a Span. private Span start() { return remoteParent - ? spanFactory.startSpanWithRemoteParent(parentSpanContext, name, startSpanOption) - : spanFactory.startSpan(parentSpan, name, startSpanOption); + ? spanFactory.startSpanWithRemoteParent( + parentSpanContext, name, startSpanOptionsBuilder.build()) + : spanFactory.startSpan(parentSpan, name, startSpanOptionsBuilder.build()); } } diff --git a/api/src/main/java/io/opencensus/trace/StartSpanOptions.java b/api/src/main/java/io/opencensus/trace/StartSpanOptions.java index 01bc8885..9b7ccb65 100644 --- a/api/src/main/java/io/opencensus/trace/StartSpanOptions.java +++ b/api/src/main/java/io/opencensus/trace/StartSpanOptions.java @@ -13,26 +13,27 @@ package io.opencensus.trace; -import com.google.common.base.Objects; +import com.google.auto.value.AutoValue; +import com.google.common.annotations.VisibleForTesting; +import io.opencensus.trace.config.TraceConfig; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; /** * A class that enables overriding the default values used when starting a {@link Span}. Allows * overriding the {@link Sampler sampler}, the parent links, and option to record all the events * even if the {@code Span} is not sampled. */ -public final class StartSpanOptions { - private Sampler sampler; - private List parentLinks; - private Boolean recordEvents; - - StartSpanOptions() { - this.sampler = null; - this.parentLinks = null; - this.recordEvents = null; - } +@AutoValue +@Immutable +public abstract class StartSpanOptions { + private static final List EMPTY_PARENT_LINKS_LIST = Collections.emptyList(); + + /** The default {@code StartSpanOptions}. */ + @VisibleForTesting static final StartSpanOptions DEFAULT = builder().build(); /** * Returns the {@link Sampler} to be used, or {@code null} if default. @@ -40,62 +41,81 @@ public final class StartSpanOptions { * @return the {@code Sampler} to be used, or {@code null} if default. */ @Nullable - public Sampler getSampler() { - return sampler; - } + public abstract Sampler getSampler(); /** * Returns the parent links to be set for the {@link Span}. * * @return the parent links to be set for the {@code Span}. */ - public List getParentLinks() { - // Return an unmodifiable list. - return parentLinks == null - ? Collections.emptyList() - : Collections.unmodifiableList(parentLinks); - } + public abstract List getParentLinks(); /** - * Returns the record events option setting. + * Returns the record events option, or {@code null} if default. + * + *

See {@link Span.Options#RECORD_EVENTS} for more details. * - * @return the record events option setting. + * @return the record events option, or {@code null} if default. */ @Nullable - public Boolean getRecordEvents() { - return recordEvents; + public abstract Boolean getRecordEvents(); + + /** + * Returns a new {@link Builder} with default options. + * + * @return a new {@code Builder} with default options. + */ + public static Builder builder() { + return new AutoValue_StartSpanOptions.Builder().setParentLinks(EMPTY_PARENT_LINKS_LIST); } - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } + /** Builder class for {@link StartSpanOptions}. */ + @AutoValue.Builder + public abstract static class Builder { - if (!(obj instanceof StartSpanOptions)) { - return false; - } + /** + * Sets the {@link Sampler} to be used. If {@code null} the default {@code Sampler} from the + * {@link TraceConfig#getActiveTraceParams()} will be used. + * + * @param sampler the {@link Sampler} to be used. + * @return this. + */ + public abstract Builder setSampler(@Nullable Sampler sampler); - StartSpanOptions that = (StartSpanOptions) obj; - return Objects.equal(sampler, that.sampler) - && Objects.equal(parentLinks, that.parentLinks) - && Objects.equal(recordEvents, that.recordEvents); - } + /** + * Sets the parent links to be set for the {@link Span}. + * + * @param parentLinks the parent links to be set for the {@link Span}. + * @return this. + * @throws NullPointerException if {@code parentLinks} is {@code null}. + */ + public abstract Builder setParentLinks(List parentLinks); - @Override - public int hashCode() { - return Objects.hashCode(sampler, parentLinks, recordEvents); - } + /** + * Sets the record events option. If {@code null} the default value from the {@link + * TraceConfig#getActiveTraceParams()} will be used. + * + *

See {@link Span.Options#RECORD_EVENTS} for more details. + * + * @param recordEvents the record events option. + * @return this. + */ + public abstract Builder setRecordEvents(@Nullable Boolean recordEvents); - void setSampler(@Nullable Sampler sampler) { - this.sampler = sampler; - } + abstract List getParentLinks(); // not public - void setParentLinks(@Nullable List parentLinks) { - this.parentLinks = parentLinks; - } + abstract StartSpanOptions autoBuild(); // not public - void setRecordEvents(@Nullable Boolean recordEvents) { - this.recordEvents = recordEvents; + /** + * Builds and returns a {@code StartSpanOptions} with the desired settings. + * + * @return a {@code StartSpanOptions} with the desired settings. + */ + public StartSpanOptions build() { + setParentLinks(Collections.unmodifiableList(new ArrayList(getParentLinks()))); + return autoBuild(); + } } + + StartSpanOptions() {} } diff --git a/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java b/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java index ccd3d806..1b8035e7 100644 --- a/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java @@ -52,7 +52,7 @@ public class SpanBuilderTest { @Test public void startScopedSpanRoot() { - when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(new StartSpanOptions()))) + when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) .thenReturn(span); NonThrowingCloseable ss = spanBuilder.becomeRoot().startScopedSpan(); try { @@ -65,8 +65,8 @@ public class SpanBuilderTest { @Test public void startScopedSpanRootWithOptions() { - StartSpanOptions startSpanOptions = new StartSpanOptions(); - startSpanOptions.setSampler(Samplers.neverSample()); + StartSpanOptions startSpanOptions = + StartSpanOptions.builder().setSampler(Samplers.neverSample()).build(); when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(startSpanOptions))) .thenReturn(span); NonThrowingCloseable ss = @@ -81,7 +81,7 @@ public class SpanBuilderTest { @Test public void startRootSpan() { - when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(new StartSpanOptions()))) + when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) .thenReturn(span); Span rootSpan = spanBuilder.becomeRoot().startSpan(); assertThat(rootSpan).isEqualTo(span); @@ -92,7 +92,7 @@ public class SpanBuilderTest { @Test public void startSpan_WithNullParent() { spanBuilder = SpanBuilder.builder(spanFactory, null, SPAN_NAME); - when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(new StartSpanOptions()))) + when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) .thenReturn(span); Span rootSpan = spanBuilder.startSpan(); assertThat(rootSpan).isEqualTo(span); @@ -103,9 +103,11 @@ public class SpanBuilderTest { @Test public void startRootSpanWithOptions() { List parentList = Arrays.asList(BlankSpan.INSTANCE); - StartSpanOptions startSpanOptions = new StartSpanOptions(); - startSpanOptions.setParentLinks(parentList); - startSpanOptions.setSampler(Samplers.neverSample()); + StartSpanOptions startSpanOptions = + StartSpanOptions.builder() + .setSampler(Samplers.neverSample()) + .setParentLinks(parentList) + .build(); when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(startSpanOptions))) .thenReturn(span); Span rootSpan = @@ -122,7 +124,7 @@ public class SpanBuilderTest { @Test public void startChildSpan() { when(spanFactory.startSpan( - same(BlankSpan.INSTANCE), same(SPAN_NAME), eq(new StartSpanOptions()))) + same(BlankSpan.INSTANCE), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) .thenReturn(span); Span childSpan = spanBuilder.startSpan(); assertThat(childSpan).isEqualTo(span); @@ -132,9 +134,9 @@ public class SpanBuilderTest { @Test public void startChildSpanWithOptions() { - StartSpanOptions startSpanOptions = new StartSpanOptions(); - startSpanOptions.setSampler(Samplers.neverSample()); - startSpanOptions.setRecordEvents(true); + StartSpanOptions startSpanOptions = + StartSpanOptions.builder().setSampler(Samplers.neverSample()).setRecordEvents(true).build(); + ; when(spanFactory.startSpan(same(BlankSpan.INSTANCE), same(SPAN_NAME), eq(startSpanOptions))) .thenReturn(span); Span childSpan = @@ -148,7 +150,7 @@ public class SpanBuilderTest { public void startSpanWitRemoteParent() { spanBuilder = SpanBuilder.builderWithRemoteParent(spanFactory, spanContext, SPAN_NAME); when(spanFactory.startSpanWithRemoteParent( - same(spanContext), same(SPAN_NAME), eq(new StartSpanOptions()))) + same(spanContext), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) .thenReturn(span); Span remoteChildSpan = spanBuilder.startSpan(); assertThat(remoteChildSpan).isEqualTo(span); @@ -160,7 +162,7 @@ public class SpanBuilderTest { public void startSpanWitRemoteParent_WithNullParent() { spanBuilder = SpanBuilder.builderWithRemoteParent(spanFactory, null, SPAN_NAME); when(spanFactory.startSpanWithRemoteParent( - isNull(SpanContext.class), same(SPAN_NAME), eq(new StartSpanOptions()))) + isNull(SpanContext.class), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) .thenReturn(span); Span remoteChildSpan = spanBuilder.startSpan(); assertThat(remoteChildSpan).isEqualTo(span); diff --git a/api/src/test/java/io/opencensus/trace/StartSpanOptionsTest.java b/api/src/test/java/io/opencensus/trace/StartSpanOptionsTest.java index b91e78ee..c37324ab 100644 --- a/api/src/test/java/io/opencensus/trace/StartSpanOptionsTest.java +++ b/api/src/test/java/io/opencensus/trace/StartSpanOptionsTest.java @@ -30,7 +30,7 @@ public class StartSpanOptionsTest { @Test public void defaultOptions() { - StartSpanOptions defaultOptions = new StartSpanOptions(); + StartSpanOptions defaultOptions = StartSpanOptions.builder().build(); assertThat(defaultOptions.getSampler()).isNull(); assertThat(defaultOptions.getParentLinks().isEmpty()).isTrue(); assertThat(defaultOptions.getRecordEvents()).isNull(); @@ -38,8 +38,8 @@ public class StartSpanOptionsTest { @Test public void setSampler() { - StartSpanOptions options = new StartSpanOptions(); - options.setSampler(Samplers.neverSample()); + StartSpanOptions options = + StartSpanOptions.builder().setSampler(Samplers.neverSample()).build(); assertThat(options.getSampler()).isEqualTo(Samplers.neverSample()); assertThat(options.getParentLinks().isEmpty()).isTrue(); assertThat(options.getRecordEvents()).isNull(); @@ -47,8 +47,7 @@ public class StartSpanOptionsTest { @Test public void setParentLinks() { - StartSpanOptions options = new StartSpanOptions(); - options.setParentLinks(singleParentList); + StartSpanOptions options = StartSpanOptions.builder().setParentLinks(singleParentList).build(); assertThat(options.getSampler()).isNull(); assertThat(options.getParentLinks()).isEqualTo(singleParentList); assertThat(options.getRecordEvents()).isNull(); @@ -56,8 +55,8 @@ public class StartSpanOptionsTest { @Test public void setParentLinks_EmptyList() { - StartSpanOptions options = new StartSpanOptions(); - options.setParentLinks(new LinkedList()); + StartSpanOptions options = + StartSpanOptions.builder().setParentLinks(new LinkedList()).build(); assertThat(options.getSampler()).isNull(); assertThat(options.getParentLinks().size()).isEqualTo(0); assertThat(options.getRecordEvents()).isNull(); @@ -65,8 +64,10 @@ public class StartSpanOptionsTest { @Test public void setParentLinks_MultipleParents() { - StartSpanOptions options = new StartSpanOptions(); - options.setParentLinks(Arrays.asList(BlankSpan.INSTANCE, BlankSpan.INSTANCE)); + StartSpanOptions options = + StartSpanOptions.builder() + .setParentLinks(Arrays.asList(BlankSpan.INSTANCE, BlankSpan.INSTANCE)) + .build(); assertThat(options.getSampler()).isNull(); assertThat(options.getParentLinks().size()).isEqualTo(2); assertThat(options.getRecordEvents()).isNull(); @@ -74,8 +75,7 @@ public class StartSpanOptionsTest { @Test public void setRecordEvents() { - StartSpanOptions options = new StartSpanOptions(); - options.setRecordEvents(true); + StartSpanOptions options = StartSpanOptions.builder().setRecordEvents(true).build(); assertThat(options.getSampler()).isNull(); assertThat(options.getParentLinks().isEmpty()).isTrue(); assertThat(options.getRecordEvents()).isTrue(); @@ -83,11 +83,12 @@ public class StartSpanOptionsTest { @Test public void setAllProperties() { - StartSpanOptions options = new StartSpanOptions(); - options.setSampler(Samplers.neverSample()); - options.setSampler(Samplers.alwaysSample()); // second SetSampler should apply - options.setRecordEvents(true); - options.setParentLinks(singleParentList); + StartSpanOptions options = + StartSpanOptions.builder() + .setSampler(Samplers.alwaysSample()) + .setRecordEvents(true) + .setParentLinks(singleParentList) + .build(); assertThat(options.getSampler()).isEqualTo(Samplers.alwaysSample()); assertThat(options.getParentLinks()).isEqualTo(singleParentList); assertThat(options.getRecordEvents()).isTrue(); @@ -96,15 +97,15 @@ public class StartSpanOptionsTest { @Test public void startSpanOptions_EqualsAndHashCode() { EqualsTester tester = new EqualsTester(); - StartSpanOptions optionsWithAlwaysSampler1 = new StartSpanOptions(); - optionsWithAlwaysSampler1.setSampler(Samplers.alwaysSample()); - StartSpanOptions optionsWithAlwaysSampler2 = new StartSpanOptions(); - optionsWithAlwaysSampler2.setSampler(Samplers.alwaysSample()); + StartSpanOptions optionsWithAlwaysSampler1 = + StartSpanOptions.builder().setSampler(Samplers.alwaysSample()).build(); + StartSpanOptions optionsWithAlwaysSampler2 = + StartSpanOptions.builder().setSampler(Samplers.alwaysSample()).build(); tester.addEqualityGroup(optionsWithAlwaysSampler1, optionsWithAlwaysSampler2); - StartSpanOptions optionsWithNeverSampler = new StartSpanOptions(); - optionsWithNeverSampler.setSampler(Samplers.neverSample()); + StartSpanOptions optionsWithNeverSampler = + StartSpanOptions.builder().setSampler(Samplers.neverSample()).build(); tester.addEqualityGroup(optionsWithNeverSampler); - tester.addEqualityGroup(new StartSpanOptions()); + tester.addEqualityGroup(StartSpanOptions.DEFAULT); tester.testEquals(); } } diff --git a/api/src/test/java/io/opencensus/trace/TracerTest.java b/api/src/test/java/io/opencensus/trace/TracerTest.java index cc46956c..80e16baf 100644 --- a/api/src/test/java/io/opencensus/trace/TracerTest.java +++ b/api/src/test/java/io/opencensus/trace/TracerTest.java @@ -127,7 +127,7 @@ public class TracerTest { @Test public void startScopedSpanRoot() { Tracer mockTracer = new MockTracer(spanFactory); - when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(new StartSpanOptions()))) + when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) .thenReturn(span); NonThrowingCloseable ss = mockTracer.spanBuilder(SPAN_NAME).becomeRoot().startScopedSpan(); try { @@ -145,7 +145,7 @@ public class TracerTest { try { assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); when(spanFactory.startSpan( - same(BlankSpan.INSTANCE), same(SPAN_NAME), eq(new StartSpanOptions()))) + same(BlankSpan.INSTANCE), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) .thenReturn(span); NonThrowingCloseable ss = mockTracer.spanBuilder(SPAN_NAME).startScopedSpan(); try { @@ -163,7 +163,7 @@ public class TracerTest { @Test public void startRootSpan() { Tracer mockTracer = new MockTracer(spanFactory); - when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(new StartSpanOptions()))) + when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) .thenReturn(span); Span rootSpan = mockTracer.spanBuilder(BlankSpan.INSTANCE, SPAN_NAME).becomeRoot().startSpan(); assertThat(rootSpan).isEqualTo(span); @@ -175,7 +175,7 @@ public class TracerTest { public void startChildSpan() { Tracer mockTracer = new MockTracer(spanFactory); when(spanFactory.startSpan( - same(BlankSpan.INSTANCE), same(SPAN_NAME), eq(new StartSpanOptions()))) + same(BlankSpan.INSTANCE), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) .thenReturn(span); Span childSpan = mockTracer.spanBuilder(BlankSpan.INSTANCE, SPAN_NAME).startSpan(); assertThat(childSpan).isEqualTo(span); @@ -193,7 +193,7 @@ public class TracerTest { SpanId.generateRandomId(random), TraceOptions.DEFAULT); when(spanFactory.startSpanWithRemoteParent( - same(spanContext), same(SPAN_NAME), eq(new StartSpanOptions()))) + same(spanContext), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) .thenReturn(span); Span remoteChildSpan = mockTracer.spanBuilderWithRemoteParent(spanContext, SPAN_NAME).startSpan(); -- cgit v1.2.3 From ddcf44bdec4fa1dea15513c8949280457292e3e7 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Thu, 8 Jun 2017 13:57:45 -0700 Subject: Move all base types into a different package called base. (#342) --- .../main/java/io/opencensus/trace/Annotation.java | 73 ----- .../java/io/opencensus/trace/AttributeValue.java | 91 ------ .../main/java/io/opencensus/trace/BlankSpan.java | 5 + .../java/io/opencensus/trace/EndSpanOptions.java | 78 ----- api/src/main/java/io/opencensus/trace/Link.java | 72 ----- .../java/io/opencensus/trace/NetworkEvent.java | 124 -------- api/src/main/java/io/opencensus/trace/Sampler.java | 2 + .../main/java/io/opencensus/trace/Samplers.java | 2 + api/src/main/java/io/opencensus/trace/Span.java | 5 + .../main/java/io/opencensus/trace/SpanBuilder.java | 1 + .../main/java/io/opencensus/trace/SpanContext.java | 3 + .../main/java/io/opencensus/trace/SpanData.java | 6 + api/src/main/java/io/opencensus/trace/SpanId.java | 171 ----------- api/src/main/java/io/opencensus/trace/Status.java | 327 -------------------- api/src/main/java/io/opencensus/trace/TraceId.java | 185 ------------ .../java/io/opencensus/trace/TraceOptions.java | 210 ------------- .../java/io/opencensus/trace/base/Annotation.java | 73 +++++ .../io/opencensus/trace/base/AttributeValue.java | 91 ++++++ .../io/opencensus/trace/base/EndSpanOptions.java | 79 +++++ .../main/java/io/opencensus/trace/base/Link.java | 74 +++++ .../io/opencensus/trace/base/NetworkEvent.java | 124 ++++++++ .../main/java/io/opencensus/trace/base/SpanId.java | 171 +++++++++++ .../main/java/io/opencensus/trace/base/Status.java | 328 +++++++++++++++++++++ .../java/io/opencensus/trace/base/TraceId.java | 193 ++++++++++++ .../io/opencensus/trace/base/TraceOptions.java | 211 +++++++++++++ .../io/opencensus/trace/config/TraceParams.java | 6 +- .../opencensus/trace/export/ExportComponent.java | 2 +- .../trace/export/InProcessDebuggingHandler.java | 4 +- .../io/opencensus/trace/export/SpanExporter.java | 2 +- .../java/io/opencensus/trace/AnnotationTest.java | 99 ------- .../io/opencensus/trace/AttributeValueTest.java | 75 ----- .../java/io/opencensus/trace/BlankSpanTest.java | 5 + .../io/opencensus/trace/EndSpanOptionsTest.java | 68 ----- .../test/java/io/opencensus/trace/LinkTest.java | 75 ----- .../java/io/opencensus/trace/NetworkEventTest.java | 87 ------ .../java/io/opencensus/trace/SamplersTest.java | 3 + .../io/opencensus/trace/ScopedSpanHandleTest.java | 1 + .../java/io/opencensus/trace/SpanBuilderTest.java | 4 + .../java/io/opencensus/trace/SpanContextTest.java | 3 + .../java/io/opencensus/trace/SpanDataTest.java | 10 +- .../test/java/io/opencensus/trace/SpanIdTest.java | 73 ----- .../test/java/io/opencensus/trace/SpanTest.java | 8 + .../test/java/io/opencensus/trace/StatusTest.java | 51 ---- .../test/java/io/opencensus/trace/TraceIdTest.java | 75 ----- .../java/io/opencensus/trace/TraceOptionsTest.java | 77 ----- .../test/java/io/opencensus/trace/TracerTest.java | 4 + .../io/opencensus/trace/base/AnnotationTest.java | 99 +++++++ .../opencensus/trace/base/AttributeValueTest.java | 75 +++++ .../opencensus/trace/base/EndSpanOptionsTest.java | 68 +++++ .../java/io/opencensus/trace/base/LinkTest.java | 76 +++++ .../io/opencensus/trace/base/NetworkEventTest.java | 87 ++++++ .../java/io/opencensus/trace/base/SpanIdTest.java | 73 +++++ .../java/io/opencensus/trace/base/StatusTest.java | 51 ++++ .../java/io/opencensus/trace/base/TraceIdTest.java | 75 +++++ .../io/opencensus/trace/base/TraceOptionsTest.java | 77 +++++ 55 files changed, 2093 insertions(+), 2019 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/trace/Annotation.java delete mode 100644 api/src/main/java/io/opencensus/trace/AttributeValue.java delete mode 100644 api/src/main/java/io/opencensus/trace/EndSpanOptions.java delete mode 100644 api/src/main/java/io/opencensus/trace/Link.java delete mode 100644 api/src/main/java/io/opencensus/trace/NetworkEvent.java delete mode 100644 api/src/main/java/io/opencensus/trace/SpanId.java delete mode 100644 api/src/main/java/io/opencensus/trace/Status.java delete mode 100644 api/src/main/java/io/opencensus/trace/TraceId.java delete mode 100644 api/src/main/java/io/opencensus/trace/TraceOptions.java create mode 100644 api/src/main/java/io/opencensus/trace/base/Annotation.java create mode 100644 api/src/main/java/io/opencensus/trace/base/AttributeValue.java create mode 100644 api/src/main/java/io/opencensus/trace/base/EndSpanOptions.java create mode 100644 api/src/main/java/io/opencensus/trace/base/Link.java create mode 100644 api/src/main/java/io/opencensus/trace/base/NetworkEvent.java create mode 100644 api/src/main/java/io/opencensus/trace/base/SpanId.java create mode 100644 api/src/main/java/io/opencensus/trace/base/Status.java create mode 100644 api/src/main/java/io/opencensus/trace/base/TraceId.java create mode 100644 api/src/main/java/io/opencensus/trace/base/TraceOptions.java delete mode 100644 api/src/test/java/io/opencensus/trace/AnnotationTest.java delete mode 100644 api/src/test/java/io/opencensus/trace/AttributeValueTest.java delete mode 100644 api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java delete mode 100644 api/src/test/java/io/opencensus/trace/LinkTest.java delete mode 100644 api/src/test/java/io/opencensus/trace/NetworkEventTest.java delete mode 100644 api/src/test/java/io/opencensus/trace/SpanIdTest.java delete mode 100644 api/src/test/java/io/opencensus/trace/StatusTest.java delete mode 100644 api/src/test/java/io/opencensus/trace/TraceIdTest.java delete mode 100644 api/src/test/java/io/opencensus/trace/TraceOptionsTest.java create mode 100644 api/src/test/java/io/opencensus/trace/base/AnnotationTest.java create mode 100644 api/src/test/java/io/opencensus/trace/base/AttributeValueTest.java create mode 100644 api/src/test/java/io/opencensus/trace/base/EndSpanOptionsTest.java create mode 100644 api/src/test/java/io/opencensus/trace/base/LinkTest.java create mode 100644 api/src/test/java/io/opencensus/trace/base/NetworkEventTest.java create mode 100644 api/src/test/java/io/opencensus/trace/base/SpanIdTest.java create mode 100644 api/src/test/java/io/opencensus/trace/base/StatusTest.java create mode 100644 api/src/test/java/io/opencensus/trace/base/TraceIdTest.java create mode 100644 api/src/test/java/io/opencensus/trace/base/TraceOptionsTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/Annotation.java b/api/src/main/java/io/opencensus/trace/Annotation.java deleted file mode 100644 index f72070e8..00000000 --- a/api/src/main/java/io/opencensus/trace/Annotation.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.auto.value.AutoValue; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import javax.annotation.concurrent.Immutable; - -/** A text annotation with a set of attributes. */ -@Immutable -@AutoValue -public abstract class Annotation { - private static final Map EMPTY_ATTRIBUTES = - Collections.unmodifiableMap(Collections.emptyMap()); - - /** - * Returns a new {@code Annotation} with the given description. - * - * @param description the text description of the {@code Annotation}. - * @return a new {@code Annotation} with the given description. - * @throws NullPointerException if {@code description} is {@code null}. - */ - public static Annotation fromDescription(String description) { - return new AutoValue_Annotation(description, EMPTY_ATTRIBUTES); - } - - /** - * Returns a new {@code Annotation} with the given description and set of attributes. - * - * @param description the text description of the {@code Annotation}. - * @param attributes the attributes of the {@code Annotation}. - * @return a new {@code Annotation} with the given description and set of attributes. - * @throws NullPointerException if {@code description} or {@code attributes} are {@code null}. - */ - public static Annotation fromDescriptionAndAttributes( - String description, Map attributes) { - return new AutoValue_Annotation( - description, - Collections.unmodifiableMap( - new HashMap(checkNotNull(attributes, "attributes")))); - } - - /** - * Return the description of the {@code Annotation}. - * - * @return the description of the {@code Annotation}. - */ - public abstract String getDescription(); - - /** - * Return the attributes of the {@code Annotation}. - * - * @return the attributes of the {@code Annotation}. - */ - public abstract Map getAttributes(); - - Annotation() {} -} diff --git a/api/src/main/java/io/opencensus/trace/AttributeValue.java b/api/src/main/java/io/opencensus/trace/AttributeValue.java deleted file mode 100644 index f66fd425..00000000 --- a/api/src/main/java/io/opencensus/trace/AttributeValue.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * 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; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.auto.value.AutoValue; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; - -/** - * A class that represents all the possible values for an attribute. An attribute can have 3 types - * of values: {@code String}, {@code Boolean} or {@code Long}. - */ -@Immutable -@AutoValue -public abstract class AttributeValue { - /** - * Returns an {@code AttributeValue} with a string value. - * - * @param stringValue The new value. - * @return an {@code AttributeValue} with a string value. - * @throws NullPointerException if {@code stringValue} is {@code null}. - */ - public static AttributeValue stringAttributeValue(String stringValue) { - return new AutoValue_AttributeValue(checkNotNull(stringValue, "stringValue"), null, null); - } - - /** - * Returns an {@code AttributeValue} with a boolean value. - * - * @param booleanValue The new value. - * @return an {@code AttributeValue} with a boolean value. - */ - public static AttributeValue booleanAttributeValue(boolean booleanValue) { - return new AutoValue_AttributeValue(null, booleanValue, null); - } - - /** - * Returns an {@code AttributeValue} with a long value. - * - * @param longValue The new value. - * @return an {@code AttributeValue} with a long value. - */ - public static AttributeValue longAttributeValue(long longValue) { - return new AutoValue_AttributeValue(null, null, longValue); - } - - AttributeValue() {} - - /** - * Returns the {@code String} value if this is a string {@code AttributeValue}, otherwise {@code - * null}. - * - * @return the {@code String} value if this is a string {@code AttributeValue}, otherwise {@code - * null}. - */ - @Nullable - public abstract String getStringValue(); - - /** - * Returns the {@code Boolean} value if this is a boolean {@code AttributeValue}, otherwise {@code - * null}. - * - * @return the {@code Boolean} value if this is a boolean {@code AttributeValue}, otherwise {@code - * null}. - */ - @Nullable - public abstract Boolean getBooleanValue(); - - /** - * Returns the {@code Long} value if this is a long {@code AttributeValue}, otherwise {@code - * null}. - * - * @return the {@code Long} value if this is a long {@code AttributeValue}, otherwise {@code - * null}. - */ - @Nullable - public abstract Long getLongValue(); -} diff --git a/api/src/main/java/io/opencensus/trace/BlankSpan.java b/api/src/main/java/io/opencensus/trace/BlankSpan.java index 40e49551..f78c3907 100644 --- a/api/src/main/java/io/opencensus/trace/BlankSpan.java +++ b/api/src/main/java/io/opencensus/trace/BlankSpan.java @@ -13,6 +13,11 @@ package io.opencensus.trace; +import io.opencensus.trace.base.Annotation; +import io.opencensus.trace.base.AttributeValue; +import io.opencensus.trace.base.EndSpanOptions; +import io.opencensus.trace.base.Link; +import io.opencensus.trace.base.NetworkEvent; import java.util.Map; import javax.annotation.concurrent.Immutable; diff --git a/api/src/main/java/io/opencensus/trace/EndSpanOptions.java b/api/src/main/java/io/opencensus/trace/EndSpanOptions.java deleted file mode 100644 index e58a06c3..00000000 --- a/api/src/main/java/io/opencensus/trace/EndSpanOptions.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.auto.value.AutoValue; -import javax.annotation.concurrent.Immutable; - -/** - * A class that enables overriding the default values used when ending a {@link Span}. Allows - * overriding the {@link Status status}. - */ -@Immutable -@AutoValue -public abstract class EndSpanOptions { - /** The default {@code EndSpanOptions}. */ - public static final EndSpanOptions DEFAULT = builder().build(); - - /** - * Returns a new {@link Builder} with default options. - * - * @return a new {@code Builder} with default options. - */ - public static Builder builder() { - return new AutoValue_EndSpanOptions.Builder().setStatus(Status.OK); - } - - /** - * Returns the status. - * - * @return the status. - */ - public abstract Status getStatus(); - - /** Builder class for {@link EndSpanOptions}. */ - @AutoValue.Builder - public abstract static class Builder { - /** - * Sets the status for the {@link Span}. - * - *

If set, this will override the default {@code Span} status. Default is {@link Status#OK}. - * - * @param status the status. - * @return this. - */ - public abstract Builder setStatus(Status status); - - abstract EndSpanOptions autoBuild(); // not public - - /** - * Builds and returns a {@code EndSpanOptions} with the desired settings. - * - * @return a {@code EndSpanOptions} with the desired settings. - * @throws NullPointerException if {@code status} is {@code null}. - */ - public EndSpanOptions build() { - EndSpanOptions endSpanOptions = autoBuild(); - checkNotNull(endSpanOptions.getStatus(), "status"); - return endSpanOptions; - } - - Builder() {} - } - - EndSpanOptions() {} -} diff --git a/api/src/main/java/io/opencensus/trace/Link.java b/api/src/main/java/io/opencensus/trace/Link.java deleted file mode 100644 index d582b68b..00000000 --- a/api/src/main/java/io/opencensus/trace/Link.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import com.google.auto.value.AutoValue; -import javax.annotation.concurrent.Immutable; - -/** - * A link to a {@link Span} from a different trace. - * - *

It requires a {@link Type} which describes the relationship with the linked {@code Span} and - * the identifiers of the linked {@code Span}. - * - *

Used (for example) in batching operations, where a single batch handler processes multiple - * requests from different traces. - */ -@Immutable -@AutoValue -public abstract class Link { - /** The relationship with the linked {@code Span} relative to the current {@code Span}. */ - public enum Type { - /** When the linked {@code Span} is a child of the current {@code Span}. */ - CHILD, - /** When the linked {@code Span} is a parent of the current {@code Span}. */ - PARENT - } - - /** - * Returns a new {@code Link}. - * - * @param context the context of the linked {@code Span}. - * @param type the type of the relationship with the linked {@code Span}. - * @return a new {@code Link}. - */ - public static Link fromSpanContext(SpanContext context, Type type) { - return new AutoValue_Link(context.getTraceId(), context.getSpanId(), type); - } - - /** - * Returns the {@code TraceId}. - * - * @return the {@code TraceId}. - */ - public abstract TraceId getTraceId(); - - /** - * Returns the {@code SpanId}. - * - * @return the {@code SpanId} - */ - public abstract SpanId getSpanId(); - - /** - * Returns the {@code Type}. - * - * @return the {@code Type}. - */ - public abstract Type getType(); - - Link() {} -} diff --git a/api/src/main/java/io/opencensus/trace/NetworkEvent.java b/api/src/main/java/io/opencensus/trace/NetworkEvent.java deleted file mode 100644 index 10687074..00000000 --- a/api/src/main/java/io/opencensus/trace/NetworkEvent.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * 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; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.auto.value.AutoValue; -import io.opencensus.common.Timestamp; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; - -/** - * A class that represents a network event. It requires a {@link Type type} and a message id that - * serves to uniquely identify each network message. It can optionally can have information about - * the kernel time and message size. - */ -@Immutable -@AutoValue -public abstract class NetworkEvent { - /** Available types for a {@code NetworkEvent}. */ - public enum Type { - /** When the message was sent. */ - SENT, - /** When the message was received. */ - RECV, - } - - /** - * Returns a new {@link Builder} with default values. - * - * @param type designates whether this is a network send or receive message. - * @param messageId serves to uniquely identify each network message. - * @return a new {@code Builder} with default values. - * @throws NullPointerException if {@code type} is {@code null}. - */ - public static Builder builder(Type type, long messageId) { - return new AutoValue_NetworkEvent.Builder() - .setType(checkNotNull(type, "type")) - .setMessageId(messageId) - // We need to set a value for the message size because the autovalue requires all - // primitives to be initialized. - // TODO(bdrutu): Consider to change the API to require message size. - .setMessageSize(0); - } - - /** - * Returns the kernel timestamp associated with the {@code NetworkEvent} or {@code null} if not - * set. - * - * @return the kernel timestamp associated with the {@code NetworkEvent} or {@code null} if not - * set. - */ - @Nullable - public abstract Timestamp getKernelTimestamp(); - - /** - * Returns the type of the {@code NetworkEvent}. - * - * @return the type of the {@code NetworkEvent}. - */ - public abstract Type getType(); - - /** - * Returns the message id argument that serves to uniquely identify each network message. - * - * @return The message id of the {@code NetworkEvent}. - */ - public abstract long getMessageId(); - - /** - * Returns The message size in bytes of the {@code NetworkEvent}. - * - * @return The message size in bytes of the {@code NetworkEvent}. - */ - public abstract long getMessageSize(); - - /** Builder class for {@link NetworkEvent}. */ - @AutoValue.Builder - public abstract static class Builder { - // Package protected methods because these values are mandatory and set only in the - // NetworkEvent#builder() function. - abstract Builder setType(Type type); - - abstract Builder setMessageId(long messageId); - - /** - * Sets the kernel timestamp. - * - * @param kernelTimestamp The kernel timestamp of the event. - * @return this. - */ - public abstract Builder setKernelTimestamp(@Nullable Timestamp kernelTimestamp); - - /** - * Sets the message size. - * - * @param messageSize represents the size in bytes of this network message. - * @return this. - */ - public abstract Builder setMessageSize(long messageSize); - - /** - * Builds and returns a {@code NetworkEvent} with the desired values. - * - * @return a {@code NetworkEvent} with the desired values. - */ - public abstract NetworkEvent build(); - - Builder() {} - } - - NetworkEvent() {} -} diff --git a/api/src/main/java/io/opencensus/trace/Sampler.java b/api/src/main/java/io/opencensus/trace/Sampler.java index e5014fa4..d231f41b 100644 --- a/api/src/main/java/io/opencensus/trace/Sampler.java +++ b/api/src/main/java/io/opencensus/trace/Sampler.java @@ -13,6 +13,8 @@ package io.opencensus.trace; +import io.opencensus.trace.base.SpanId; +import io.opencensus.trace.base.TraceId; import java.util.List; import javax.annotation.Nullable; diff --git a/api/src/main/java/io/opencensus/trace/Samplers.java b/api/src/main/java/io/opencensus/trace/Samplers.java index 33c2a006..8d7908ec 100644 --- a/api/src/main/java/io/opencensus/trace/Samplers.java +++ b/api/src/main/java/io/opencensus/trace/Samplers.java @@ -16,6 +16,8 @@ package io.opencensus.trace; import static com.google.common.base.Preconditions.checkArgument; import com.google.auto.value.AutoValue; +import io.opencensus.trace.base.SpanId; +import io.opencensus.trace.base.TraceId; import java.util.List; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; diff --git a/api/src/main/java/io/opencensus/trace/Span.java b/api/src/main/java/io/opencensus/trace/Span.java index 76dcd9c7..0a941287 100644 --- a/api/src/main/java/io/opencensus/trace/Span.java +++ b/api/src/main/java/io/opencensus/trace/Span.java @@ -16,6 +16,11 @@ package io.opencensus.trace; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import io.opencensus.trace.base.Annotation; +import io.opencensus.trace.base.AttributeValue; +import io.opencensus.trace.base.EndSpanOptions; +import io.opencensus.trace.base.Link; +import io.opencensus.trace.base.NetworkEvent; import java.util.Collections; import java.util.EnumSet; import java.util.Map; diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java index 150932e0..ec9719fc 100644 --- a/api/src/main/java/io/opencensus/trace/SpanBuilder.java +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -14,6 +14,7 @@ package io.opencensus.trace; import io.opencensus.common.NonThrowingCloseable; +import io.opencensus.trace.base.EndSpanOptions; import java.util.List; import javax.annotation.Nullable; diff --git a/api/src/main/java/io/opencensus/trace/SpanContext.java b/api/src/main/java/io/opencensus/trace/SpanContext.java index 56a046f1..8847a3ce 100644 --- a/api/src/main/java/io/opencensus/trace/SpanContext.java +++ b/api/src/main/java/io/opencensus/trace/SpanContext.java @@ -15,6 +15,9 @@ package io.opencensus.trace; import com.google.common.base.MoreObjects; import com.google.common.base.Objects; +import io.opencensus.trace.base.SpanId; +import io.opencensus.trace.base.TraceId; +import io.opencensus.trace.base.TraceOptions; import javax.annotation.concurrent.Immutable; /** diff --git a/api/src/main/java/io/opencensus/trace/SpanData.java b/api/src/main/java/io/opencensus/trace/SpanData.java index f9a8140f..02c89528 100644 --- a/api/src/main/java/io/opencensus/trace/SpanData.java +++ b/api/src/main/java/io/opencensus/trace/SpanData.java @@ -17,6 +17,12 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; import io.opencensus.common.Timestamp; +import io.opencensus.trace.base.Annotation; +import io.opencensus.trace.base.AttributeValue; +import io.opencensus.trace.base.Link; +import io.opencensus.trace.base.NetworkEvent; +import io.opencensus.trace.base.SpanId; +import io.opencensus.trace.base.Status; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; diff --git a/api/src/main/java/io/opencensus/trace/SpanId.java b/api/src/main/java/io/opencensus/trace/SpanId.java deleted file mode 100644 index 8128c9d7..00000000 --- a/api/src/main/java/io/opencensus/trace/SpanId.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.base.MoreObjects; -import com.google.common.io.BaseEncoding; -import java.util.Arrays; -import java.util.Random; -import javax.annotation.concurrent.Immutable; - -/** - * A class that represents a span identifier. A valid span identifier is an 8-byte array with at - * least one non-zero byte. - */ -@Immutable -public final class SpanId implements Comparable { - /** The size in bytes of the {@code SpanId}. */ - public static final int SIZE = 8; - - /** The invalid {@code SpanId}. All bytes are 0. */ - public static final SpanId INVALID = new SpanId(new byte[SIZE]); - - // The internal representation of the SpanId. - private final byte[] bytes; - - private SpanId(byte[] bytes) { - this.bytes = bytes; - } - - /** - * Returns a {@code SpanId} built from a byte representation. - * - *

Equivalent with: - * - *

{@code
-   * SpanId.fromBytes(buffer, 0);
-   * }
- * - * @param buffer the representation of the {@code SpanId}. - * @return a {@code SpanId} whose representation is given by the {@code buffer} parameter. - * @throws NullPointerException if {@code buffer} is null. - * @throws IllegalArgumentException if {@code buffer.length} is not {@link SpanId#SIZE}. - */ - public static SpanId fromBytes(byte[] buffer) { - checkNotNull(buffer, "buffer"); - checkArgument(buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); - byte[] bytesCopied = Arrays.copyOf(buffer, SIZE); - return new SpanId(bytesCopied); - } - - /** - * Returns a {@code SpanId} whose representation is copied from the {@code src} beginning at the - * {@code srcOffset} offset. - * - * @param src the buffer where the representation of the {@code SpanId} is copied. - * @param srcOffset the offset in the buffer where the representation of the {@code SpanId} - * begins. - * @return a {@code SpanId} whose representation is copied from the buffer. - * @throws NullPointerException if {@code src} is null. - * @throws IndexOutOfBoundsException if {@code srcOffset+SpanId.SIZE} is greater than {@code - * src.length}. - */ - public static SpanId fromBytes(byte[] src, int srcOffset) { - byte[] bytes = new byte[SIZE]; - System.arraycopy(src, srcOffset, bytes, 0, SIZE); - return new SpanId(bytes); - } - - /** - * Generates a new random {@code SpanId}. - * - * @param random The random number generator. - * @return a valid new {@code SpanId}. - */ - public static SpanId generateRandomId(Random random) { - byte[] bytes = new byte[SIZE]; - do { - random.nextBytes(bytes); - } while (Arrays.equals(bytes, INVALID.bytes)); - return new SpanId(bytes); - } - - /** - * Returns the byte representation of the {@code SpanId}. - * - * @return the byte representation of the {@code SpanId}. - */ - public byte[] getBytes() { - return Arrays.copyOf(bytes, SIZE); - } - - /** - * Copies the byte array representations of the {@code SpanId} into the {@code dest} beginning at - * the {@code destOffset} offset. - * - *

Equivalent with (but faster because it avoids any new allocations): - * - *

{@code
-   * System.arraycopy(getBytes(), 0, dest, destOffset, SpanId.SIZE);
-   * }
- * - * @param dest the destination buffer. - * @param destOffset the starting offset in the destination buffer. - * @throws NullPointerException if {@code dest} is null. - * @throws IndexOutOfBoundsException if {@code destOffset+SpanId.SIZE} is greater than {@code - * dest.length}. - */ - public void copyBytesTo(byte[] dest, int destOffset) { - System.arraycopy(bytes, 0, dest, destOffset, SIZE); - } - - /** - * Returns whether the span identifier is valid. A valid span identifier is an 8-byte array with - * at least one non-zero byte. - * - * @return {@code true} if the span identifier is valid. - */ - public boolean isValid() { - return !Arrays.equals(bytes, INVALID.bytes); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (!(obj instanceof SpanId)) { - return false; - } - - SpanId that = (SpanId) obj; - return Arrays.equals(bytes, that.bytes); - } - - @Override - public int hashCode() { - return Arrays.hashCode(bytes); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("spanId", BaseEncoding.base16().lowerCase().encode(bytes)) - .toString(); - } - - @Override - public int compareTo(SpanId that) { - for (int i = 0; i < SIZE; i++) { - if (bytes[i] != that.bytes[i]) { - return bytes[i] < that.bytes[i] ? -1 : 1; - } - } - return 0; - } -} diff --git a/api/src/main/java/io/opencensus/trace/Status.java b/api/src/main/java/io/opencensus/trace/Status.java deleted file mode 100644 index 22cb5287..00000000 --- a/api/src/main/java/io/opencensus/trace/Status.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * 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; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.base.MoreObjects; -import com.google.common.base.Objects; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.TreeMap; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; - -/** - * Defines the status of a {@link Span} by providing a standard {@link CanonicalCode} in conjunction - * with an optional descriptive message. Instances of {@code Status} are created by starting with - * the template for the appropriate {@link Status.CanonicalCode} and supplementing it with - * additional information: {@code Status.NOT_FOUND.withDescription("Could not find - * 'important_file.txt'");} - */ -@Immutable -public final class Status { - /** - * The set of canonical status codes. If new codes are added over time they must choose a - * numerical value that does not collide with any previously used value. - */ - public enum CanonicalCode { - /** The operation completed successfully. */ - OK(0), - - /** The operation was cancelled (typically by the caller). */ - CANCELLED(1), - - /** - * Unknown error. An example of where this error may be returned is if a Status value received - * from another address space belongs to an error-space that is not known in this address space. - * Also errors raised by APIs that do not return enough error information may be converted to - * this error. - */ - UNKNOWN(2), - - /** - * Client specified an invalid argument. Note that this differs from FAILED_PRECONDITION. - * INVALID_ARGUMENT indicates arguments that are problematic regardless of the state of the - * system (e.g., a malformed file name). - */ - INVALID_ARGUMENT(3), - - /** - * Deadline expired before operation could complete. For operations that change the state of the - * system, this error may be returned even if the operation has completed successfully. For - * example, a successful response from a server could have been delayed long enough for the - * deadline to expire. - */ - DEADLINE_EXCEEDED(4), - - /** Some requested entity (e.g., file or directory) was not found. */ - NOT_FOUND(5), - - /** Some entity that we attempted to create (e.g., file or directory) already exists. */ - ALREADY_EXISTS(6), - - /** - * The caller does not have permission to execute the specified operation. PERMISSION_DENIED - * must not be used for rejections caused by exhausting some resource (use RESOURCE_EXHAUSTED - * instead for those errors). PERMISSION_DENIED must not be used if the caller cannot be - * identified (use UNAUTHENTICATED instead for those errors). - */ - PERMISSION_DENIED(7), - - /** - * Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system - * is out of space. - */ - RESOURCE_EXHAUSTED(8), - - /** - * Operation was rejected because the system is not in a state required for the operation's - * execution. For example, directory to be deleted may be non-empty, an rmdir operation is - * applied to a non-directory, etc. - * - *

A litmus test that may help a service implementor in deciding between FAILED_PRECONDITION, - * ABORTED, and UNAVAILABLE: (a) Use UNAVAILABLE if the client can retry just the failing call. - * (b) Use ABORTED if the client should retry at a higher-level (e.g., restarting a - * read-modify-write sequence). (c) Use FAILED_PRECONDITION if the client should not retry until - * the system state has been explicitly fixed. E.g., if an "rmdir" fails because the directory - * is non-empty, FAILED_PRECONDITION should be returned since the client should not retry unless - * they have first fixed up the directory by deleting files from it. - */ - FAILED_PRECONDITION(9), - - /** - * The operation was aborted, typically due to a concurrency issue like sequencer check - * failures, transaction aborts, etc. - * - *

See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE. - */ - ABORTED(10), - - /** - * Operation was attempted past the valid range. E.g., seeking or reading past end of file. - * - *

Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed if the system - * state changes. For example, a 32-bit file system will generate INVALID_ARGUMENT if asked to - * read at an offset that is not in the range [0,2^32-1], but it will generate OUT_OF_RANGE if - * asked to read from an offset past the current file size. - * - *

There is a fair bit of overlap between FAILED_PRECONDITION and OUT_OF_RANGE. We recommend - * using OUT_OF_RANGE (the more specific error) when it applies so that callers who are - * iterating through a space can easily look for an OUT_OF_RANGE error to detect when they are - * done. - */ - OUT_OF_RANGE(11), - - /** Operation is not implemented or not supported/enabled in this service. */ - UNIMPLEMENTED(12), - - /** - * Internal errors. Means some invariants expected by underlying system has been broken. If you - * see one of these errors, something is very broken. - */ - INTERNAL(13), - - /** - * The service is currently unavailable. This is a most likely a transient condition and may be - * corrected by retrying with a backoff. - * - *

See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE. - */ - UNAVAILABLE(14), - - /** Unrecoverable data loss or corruption. */ - DATA_LOSS(15), - - /** The request does not have valid authentication credentials for the operation. */ - UNAUTHENTICATED(16); - - private final int value; - - private CanonicalCode(int value) { - this.value = value; - } - - /** - * Returns the numerical value of the code. - * - * @return the numerical value of the code. - */ - public int value() { - return value; - } - - Status toStatus() { - return STATUS_LIST.get(value); - } - } - - // Create the canonical list of Status instances indexed by their code values. - private static final List STATUS_LIST = buildStatusList(); - - private static List buildStatusList() { - TreeMap canonicalizer = new TreeMap(); - for (CanonicalCode code : CanonicalCode.values()) { - Status replaced = canonicalizer.put(code.value(), new Status(code, null)); - if (replaced != null) { - throw new IllegalStateException( - "Code value duplication between " - + replaced.getCanonicalCode().name() - + " & " - + code.name()); - } - } - return Collections.unmodifiableList(new ArrayList(canonicalizer.values())); - } - - // A pseudo-enum of Status instances mapped 1:1 with values in CanonicalCode. This simplifies - // construction patterns for derived instances of Status. - /** The operation completed successfully. */ - public static final Status OK = CanonicalCode.OK.toStatus(); - /** The operation was cancelled (typically by the caller). */ - public static final Status CANCELLED = CanonicalCode.CANCELLED.toStatus(); - /** Unknown error. See {@link CanonicalCode#UNKNOWN}. */ - public static final Status UNKNOWN = CanonicalCode.UNKNOWN.toStatus(); - /** Client specified an invalid argument. See {@link CanonicalCode#INVALID_ARGUMENT}. */ - public static final Status INVALID_ARGUMENT = CanonicalCode.INVALID_ARGUMENT.toStatus(); - /** - * Deadline expired before operation could complete. See {@link CanonicalCode#DEADLINE_EXCEEDED}. - */ - public static final Status DEADLINE_EXCEEDED = CanonicalCode.DEADLINE_EXCEEDED.toStatus(); - /** Some requested entity (e.g., file or directory) was not found. */ - public static final Status NOT_FOUND = CanonicalCode.NOT_FOUND.toStatus(); - /** Some entity that we attempted to create (e.g., file or directory) already exists. */ - public static final Status ALREADY_EXISTS = CanonicalCode.ALREADY_EXISTS.toStatus(); - /** - * The caller does not have permission to execute the specified operation. See {@link - * CanonicalCode#PERMISSION_DENIED}. - */ - public static final Status PERMISSION_DENIED = CanonicalCode.PERMISSION_DENIED.toStatus(); - /** The request does not have valid authentication credentials for the operation. */ - public static final Status UNAUTHENTICATED = CanonicalCode.UNAUTHENTICATED.toStatus(); - /** - * Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system - * is out of space. - */ - public static final Status RESOURCE_EXHAUSTED = CanonicalCode.RESOURCE_EXHAUSTED.toStatus(); - /** - * Operation was rejected because the system is not in a state required for the operation's - * execution. See {@link CanonicalCode#FAILED_PRECONDITION}. - */ - public static final Status FAILED_PRECONDITION = CanonicalCode.FAILED_PRECONDITION.toStatus(); - /** - * The operation was aborted, typically due to a concurrency issue like sequencer check failures, - * transaction aborts, etc. See {@link CanonicalCode#ABORTED}. - */ - public static final Status ABORTED = CanonicalCode.ABORTED.toStatus(); - /** Operation was attempted past the valid range. See {@link CanonicalCode#OUT_OF_RANGE}. */ - public static final Status OUT_OF_RANGE = CanonicalCode.OUT_OF_RANGE.toStatus(); - /** Operation is not implemented or not supported/enabled in this service. */ - public static final Status UNIMPLEMENTED = CanonicalCode.UNIMPLEMENTED.toStatus(); - /** Internal errors. See {@link CanonicalCode#INTERNAL}. */ - public static final Status INTERNAL = CanonicalCode.INTERNAL.toStatus(); - /** The service is currently unavailable. See {@link CanonicalCode#UNAVAILABLE}. */ - public static final Status UNAVAILABLE = CanonicalCode.UNAVAILABLE.toStatus(); - /** Unrecoverable data loss or corruption. */ - public static final Status DATA_LOSS = CanonicalCode.DATA_LOSS.toStatus(); - - // The canonical code of this message. - private final CanonicalCode canonicalCode; - // An additional error message. - private final String description; - - private Status(CanonicalCode canonicalCode, @Nullable String description) { - this.canonicalCode = checkNotNull(canonicalCode, "canonicalCode"); - this.description = description; - } - - /** - * Creates a derived instance of {@code Status} with the given description. - * - * @param description the new description of the {@code Status}. - * @return The newly created {@code Status} with the given description. - */ - public Status withDescription(String description) { - if (Objects.equal(this.description, description)) { - return this; - } - return new Status(this.canonicalCode, description); - } - - /** - * Returns the canonical status code. - * - * @return the canonical status code. - */ - public CanonicalCode getCanonicalCode() { - return canonicalCode; - } - - /** - * Returns the description of this {@code Status} for human consumption. - * - * @return the description of this {@code Status}. - */ - @Nullable - public String getDescription() { - return description; - } - - /** - * Returns {@code true} if this {@code Status} is OK, i.e., not an error. - * - * @return {@code true} if this {@code Status} is OK. - */ - public boolean isOk() { - return CanonicalCode.OK == canonicalCode; - } - - /** - * Equality on Statuses is not well defined. Instead, do comparison based on their CanonicalCode - * with {@link #getCanonicalCode}. The description of the Status is unlikely to be stable, and - * additional fields may be added to Status in the future. - */ - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (!(obj instanceof Status)) { - return false; - } - - Status that = (Status) obj; - return canonicalCode == that.canonicalCode && Objects.equal(description, that.description); - } - - /** - * Hash codes on Statuses are not well defined. - * - * @see #equals - */ - @Override - public int hashCode() { - return Objects.hashCode(canonicalCode, description); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("canonicalCode", canonicalCode) - .add("description", description) - .toString(); - } -} diff --git a/api/src/main/java/io/opencensus/trace/TraceId.java b/api/src/main/java/io/opencensus/trace/TraceId.java deleted file mode 100644 index 5684efdf..00000000 --- a/api/src/main/java/io/opencensus/trace/TraceId.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * 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; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.base.MoreObjects; -import com.google.common.io.BaseEncoding; -import java.util.Arrays; -import java.util.Random; -import javax.annotation.concurrent.Immutable; - -/** - * A class that represents a trace identifier. A valid trace identifier is a 16-byte array with at - * least one non-zero byte. - */ -@Immutable -public final class TraceId implements Comparable { - /** The size in bytes of the {@code TraceId}. */ - public static final int SIZE = 16; - - /** The invalid {@code TraceId}. All bytes are '\0'. */ - public static final TraceId INVALID = new TraceId(new byte[SIZE]); - - // The internal representation of the TraceId. - private final byte[] bytes; - - private TraceId(byte[] bytes) { - this.bytes = bytes; - } - - /** - * Returns a {@code TraceId} built from a byte representation. - * - *

Equivalent with: - * - *

{@code
-   * TraceId.fromBytes(buffer, 0);
-   * }
- * - * @param buffer the representation of the {@code TraceId}. - * @return a {@code TraceId} whose representation is given by the {@code buffer} parameter. - * @throws NullPointerException if {@code buffer} is null. - * @throws IllegalArgumentException if {@code buffer.length} is not {@link TraceId#SIZE}. - */ - public static TraceId fromBytes(byte[] buffer) { - checkNotNull(buffer, "buffer"); - checkArgument(buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); - byte[] bytesCopied = Arrays.copyOf(buffer, SIZE); - return new TraceId(bytesCopied); - } - - /** - * Returns a {@code TraceId} whose representation is copied from the {@code src} beginning at the - * {@code srcOffset} offset. - * - * @param src the buffer where the representation of the {@code TraceId} is copied. - * @param srcOffset the offset in the buffer where the representation of the {@code TraceId} - * begins. - * @return a {@code TraceId} whose representation is copied from the buffer. - * @throws NullPointerException if {@code src} is null. - * @throws IndexOutOfBoundsException if {@code srcOffset+TraceId.SIZE} is greater than {@code - * src.length}. - */ - public static TraceId fromBytes(byte[] src, int srcOffset) { - byte[] bytes = new byte[SIZE]; - System.arraycopy(src, srcOffset, bytes, 0, SIZE); - return new TraceId(bytes); - } - - /** - * Generates a new random {@code TraceId}. - * - * @param random the random number generator. - * @return a new valid {@code TraceId}. - */ - public static TraceId generateRandomId(Random random) { - byte[] bytes = new byte[SIZE]; - do { - random.nextBytes(bytes); - } while (Arrays.equals(bytes, INVALID.bytes)); - return new TraceId(bytes); - } - - /** - * Returns the 16-bytes array representation of the {@code TraceId}. - * - * @return the 16-bytes array representation of the {@code TraceId}. - */ - public byte[] getBytes() { - return Arrays.copyOf(bytes, SIZE); - } - - /** - * Copies the byte array representations of the {@code TraceId} into the {@code dest} beginning at - * the {@code destOffset} offset. - * - *

Equivalent with (but faster because it avoids any new allocations): - * - *

{@code
-   * System.arraycopy(getBytes(), 0, dest, destOffset, TraceId.SIZE);
-   * }
- * - * @param dest the destination buffer. - * @param destOffset the starting offset in the destination buffer. - * @throws NullPointerException if {@code dest} is null. - * @throws IndexOutOfBoundsException if {@code destOffset+TraceId.SIZE} is greater than {@code - * dest.length}. - */ - public void copyBytesTo(byte[] dest, int destOffset) { - System.arraycopy(bytes, 0, dest, destOffset, SIZE); - } - - /** - * Returns whether the {@code TraceId} is valid. A valid trace identifier is a 16-byte array with - * at least one non-zero byte. - * - * @return {@code true} if the {@code TraceId} is valid. - */ - public boolean isValid() { - return !Arrays.equals(bytes, INVALID.bytes); - } - - // Return the lower 8 bytes of the trace-id as a long value, assuming little-endian order. This - // is used in ProbabilitySampler. - long getLowerLong() { - long result = 0; - for (int i = 0; i < Long.SIZE / Byte.SIZE; i++) { - result <<= Byte.SIZE; - result |= (bytes[i] & 0xff); - } - if (result < 0) { - return -result; - } - return result; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (!(obj instanceof TraceId)) { - return false; - } - - TraceId that = (TraceId) obj; - return Arrays.equals(bytes, that.bytes); - } - - @Override - public int hashCode() { - return Arrays.hashCode(bytes); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("traceId", BaseEncoding.base16().lowerCase().encode(bytes)) - .toString(); - } - - @Override - public int compareTo(TraceId that) { - for (int i = 0; i < SIZE; i++) { - if (bytes[i] != that.bytes[i]) { - return bytes[i] < that.bytes[i] ? -1 : 1; - } - } - return 0; - } -} diff --git a/api/src/main/java/io/opencensus/trace/TraceOptions.java b/api/src/main/java/io/opencensus/trace/TraceOptions.java deleted file mode 100644 index 6fc04bb9..00000000 --- a/api/src/main/java/io/opencensus/trace/TraceOptions.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkElementIndex; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.MoreObjects; -import com.google.common.base.Objects; -import javax.annotation.concurrent.Immutable; - -/** - * A class that represents global trace options. These options are propagated to all child {@link - * Span spans}. These determine features such as whether a {@code Span} should be traced. It is - * implemented as a bitmask. - */ -@Immutable -public final class TraceOptions { - // Default options. Nothing set. - private static final byte DEFAULT_OPTIONS = 0; - // Bit to represent whether trace is sampled or not. - private static final byte IS_SAMPLED = 0x1; - - /** The size in bytes of the {@code TraceOptions}. */ - public static final int SIZE = 1; - - /** The default {@code TraceOptions}. */ - public static final TraceOptions DEFAULT = new TraceOptions(DEFAULT_OPTIONS); - - // The set of enabled features is determined by all the enabled bits. - private final byte options; - - // Creates a new {@code TraceOptions} with the given options. - private TraceOptions(byte options) { - this.options = options; - } - - /** - * Returns a {@code TraceOptions} built from a byte representation. - * - *

Equivalent with: - * - *

{@code
-   * TraceOptions.fromBytes(buffer, 0);
-   * }
- * - * @param buffer the representation of the {@code TraceOptions}. - * @return a {@code TraceOptions} whose representation is given by the {@code buffer} parameter. - * @throws NullPointerException if {@code buffer} is null. - * @throws IllegalArgumentException if {@code buffer.length} is not {@link TraceOptions#SIZE}. - */ - public static TraceOptions fromBytes(byte[] buffer) { - checkNotNull(buffer, "buffer"); - checkArgument(buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); - return new TraceOptions(buffer[0]); - } - - /** - * Returns a {@code TraceOptions} whose representation is copied from the {@code src} beginning at - * the {@code srcOffset} offset. - * - * @param src the buffer where the representation of the {@code TraceOptions} is copied. - * @param srcOffset the offset in the buffer where the representation of the {@code TraceOptions} - * begins. - * @return a {@code TraceOptions} whose representation is copied from the buffer. - * @throws NullPointerException if {@code src} is null. - * @throws IndexOutOfBoundsException if {@code srcOffset+TraceOptions.SIZE} is greater than {@code - * src.length}. - */ - public static TraceOptions fromBytes(byte[] src, int srcOffset) { - checkElementIndex(srcOffset, src.length); - return new TraceOptions(src[srcOffset]); - } - - /** - * Returns the 1-byte array representation of the {@code TraceOptions}. - * - * @return the 1-byte array representation of the {@code TraceOptions}. - */ - public byte[] getBytes() { - byte[] bytes = new byte[SIZE]; - bytes[0] = options; - return bytes; - } - - /** - * Copies the byte representations of the {@code TraceOptions} into the {@code dest} beginning at - * the {@code destOffset} offset. - * - *

Equivalent with (but faster because it avoids any new allocations): - * - *

{@code
-   * System.arraycopy(getBytes(), 0, dest, destOffset, TraceOptions.SIZE);
-   * }
- * - * @param dest the destination buffer. - * @param destOffset the starting offset in the destination buffer. - * @throws NullPointerException if {@code dest} is null. - * @throws IndexOutOfBoundsException if {@code destOffset+TraceOptions.SIZE} is greater than - * {@code dest.length}. - */ - public void copyBytesTo(byte[] dest, int destOffset) { - checkElementIndex(destOffset, dest.length); - dest[destOffset] = options; - } - - /** - * Returns a new {@link Builder} with default options. - * - * @return a new {@code Builder} with default options. - */ - public static Builder builder() { - return new Builder(DEFAULT_OPTIONS); - } - - /** - * Returns a new {@link Builder} with all given options set. - * - * @param traceOptions the given options set. - * @return a new {@code Builder} with all given options set. - */ - public static Builder builder(TraceOptions traceOptions) { - return new Builder(traceOptions.options); - } - - /** - * Returns a boolean indicating whether this {@code Span} is part of a sampled trace and data - * should be exported to a persistent store. - * - * @return a boolean indicating whether the trace is sampled. - */ - public boolean isSampled() { - return hasOption(IS_SAMPLED); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (!(obj instanceof TraceOptions)) { - return false; - } - - TraceOptions that = (TraceOptions) obj; - return options == that.options; - } - - @Override - public int hashCode() { - return Objects.hashCode(options); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this).add("sampled", isSampled()).toString(); - } - - /** Builder class for {@link TraceOptions}. */ - public static final class Builder { - private byte options; - - private Builder(byte options) { - this.options = options; - } - - /** - * Marks this trace as sampled. - * - * @return this. - */ - public Builder setIsSampled() { - options |= IS_SAMPLED; - return this; - } - - /** - * Builds and returns a {@code TraceOptions} with the desired options. - * - * @return a {@code TraceOptions} with the desired options. - */ - public TraceOptions build() { - return new TraceOptions(options); - } - } - - // Returns the current set of options bitmask. - @VisibleForTesting - byte getOptions() { - return options; - } - - private boolean hasOption(int mask) { - return (this.options & mask) != 0; - } -} diff --git a/api/src/main/java/io/opencensus/trace/base/Annotation.java b/api/src/main/java/io/opencensus/trace/base/Annotation.java new file mode 100644 index 00000000..b86b93d8 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/base/Annotation.java @@ -0,0 +1,73 @@ +/* + * Copyright 2017, Google Inc. + * 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.base; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.concurrent.Immutable; + +/** A text annotation with a set of attributes. */ +@Immutable +@AutoValue +public abstract class Annotation { + private static final Map EMPTY_ATTRIBUTES = + Collections.unmodifiableMap(Collections.emptyMap()); + + /** + * Returns a new {@code Annotation} with the given description. + * + * @param description the text description of the {@code Annotation}. + * @return a new {@code Annotation} with the given description. + * @throws NullPointerException if {@code description} is {@code null}. + */ + public static Annotation fromDescription(String description) { + return new AutoValue_Annotation(description, EMPTY_ATTRIBUTES); + } + + /** + * Returns a new {@code Annotation} with the given description and set of attributes. + * + * @param description the text description of the {@code Annotation}. + * @param attributes the attributes of the {@code Annotation}. + * @return a new {@code Annotation} with the given description and set of attributes. + * @throws NullPointerException if {@code description} or {@code attributes} are {@code null}. + */ + public static Annotation fromDescriptionAndAttributes( + String description, Map attributes) { + return new AutoValue_Annotation( + description, + Collections.unmodifiableMap( + new HashMap(checkNotNull(attributes, "attributes")))); + } + + /** + * Return the description of the {@code Annotation}. + * + * @return the description of the {@code Annotation}. + */ + public abstract String getDescription(); + + /** + * Return the attributes of the {@code Annotation}. + * + * @return the attributes of the {@code Annotation}. + */ + public abstract Map getAttributes(); + + Annotation() {} +} diff --git a/api/src/main/java/io/opencensus/trace/base/AttributeValue.java b/api/src/main/java/io/opencensus/trace/base/AttributeValue.java new file mode 100644 index 00000000..86f0c84a --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/base/AttributeValue.java @@ -0,0 +1,91 @@ +/* + * Copyright 2016, Google Inc. + * 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.base; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * A class that represents all the possible values for an attribute. An attribute can have 3 types + * of values: {@code String}, {@code Boolean} or {@code Long}. + */ +@Immutable +@AutoValue +public abstract class AttributeValue { + /** + * Returns an {@code AttributeValue} with a string value. + * + * @param stringValue The new value. + * @return an {@code AttributeValue} with a string value. + * @throws NullPointerException if {@code stringValue} is {@code null}. + */ + public static AttributeValue stringAttributeValue(String stringValue) { + return new AutoValue_AttributeValue(checkNotNull(stringValue, "stringValue"), null, null); + } + + /** + * Returns an {@code AttributeValue} with a boolean value. + * + * @param booleanValue The new value. + * @return an {@code AttributeValue} with a boolean value. + */ + public static AttributeValue booleanAttributeValue(boolean booleanValue) { + return new AutoValue_AttributeValue(null, booleanValue, null); + } + + /** + * Returns an {@code AttributeValue} with a long value. + * + * @param longValue The new value. + * @return an {@code AttributeValue} with a long value. + */ + public static AttributeValue longAttributeValue(long longValue) { + return new AutoValue_AttributeValue(null, null, longValue); + } + + AttributeValue() {} + + /** + * Returns the {@code String} value if this is a string {@code AttributeValue}, otherwise {@code + * null}. + * + * @return the {@code String} value if this is a string {@code AttributeValue}, otherwise {@code + * null}. + */ + @Nullable + public abstract String getStringValue(); + + /** + * Returns the {@code Boolean} value if this is a boolean {@code AttributeValue}, otherwise {@code + * null}. + * + * @return the {@code Boolean} value if this is a boolean {@code AttributeValue}, otherwise {@code + * null}. + */ + @Nullable + public abstract Boolean getBooleanValue(); + + /** + * Returns the {@code Long} value if this is a long {@code AttributeValue}, otherwise {@code + * null}. + * + * @return the {@code Long} value if this is a long {@code AttributeValue}, otherwise {@code + * null}. + */ + @Nullable + public abstract Long getLongValue(); +} diff --git a/api/src/main/java/io/opencensus/trace/base/EndSpanOptions.java b/api/src/main/java/io/opencensus/trace/base/EndSpanOptions.java new file mode 100644 index 00000000..00cd8ffb --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/base/EndSpanOptions.java @@ -0,0 +1,79 @@ +/* + * Copyright 2017, Google Inc. + * 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.base; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import io.opencensus.trace.Span; +import javax.annotation.concurrent.Immutable; + +/** + * A class that enables overriding the default values used when ending a {@link Span}. Allows + * overriding the {@link Status status}. + */ +@Immutable +@AutoValue +public abstract class EndSpanOptions { + /** The default {@code EndSpanOptions}. */ + public static final EndSpanOptions DEFAULT = builder().build(); + + /** + * Returns a new {@link Builder} with default options. + * + * @return a new {@code Builder} with default options. + */ + public static Builder builder() { + return new AutoValue_EndSpanOptions.Builder().setStatus(Status.OK); + } + + /** + * Returns the status. + * + * @return the status. + */ + public abstract Status getStatus(); + + /** Builder class for {@link EndSpanOptions}. */ + @AutoValue.Builder + public abstract static class Builder { + /** + * Sets the status for the {@link Span}. + * + *

If set, this will override the default {@code Span} status. Default is {@link Status#OK}. + * + * @param status the status. + * @return this. + */ + public abstract Builder setStatus(Status status); + + abstract EndSpanOptions autoBuild(); // not public + + /** + * Builds and returns a {@code EndSpanOptions} with the desired settings. + * + * @return a {@code EndSpanOptions} with the desired settings. + * @throws NullPointerException if {@code status} is {@code null}. + */ + public EndSpanOptions build() { + EndSpanOptions endSpanOptions = autoBuild(); + checkNotNull(endSpanOptions.getStatus(), "status"); + return endSpanOptions; + } + + Builder() {} + } + + EndSpanOptions() {} +} diff --git a/api/src/main/java/io/opencensus/trace/base/Link.java b/api/src/main/java/io/opencensus/trace/base/Link.java new file mode 100644 index 00000000..363bd212 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/base/Link.java @@ -0,0 +1,74 @@ +/* + * Copyright 2017, Google Inc. + * 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.base; + +import com.google.auto.value.AutoValue; +import io.opencensus.trace.Span; +import io.opencensus.trace.SpanContext; +import javax.annotation.concurrent.Immutable; + +/** + * A link to a {@link Span} from a different trace. + * + *

It requires a {@link Type} which describes the relationship with the linked {@code Span} and + * the identifiers of the linked {@code Span}. + * + *

Used (for example) in batching operations, where a single batch handler processes multiple + * requests from different traces. + */ +@Immutable +@AutoValue +public abstract class Link { + /** The relationship with the linked {@code Span} relative to the current {@code Span}. */ + public enum Type { + /** When the linked {@code Span} is a child of the current {@code Span}. */ + CHILD, + /** When the linked {@code Span} is a parent of the current {@code Span}. */ + PARENT + } + + /** + * Returns a new {@code Link}. + * + * @param context the context of the linked {@code Span}. + * @param type the type of the relationship with the linked {@code Span}. + * @return a new {@code Link}. + */ + public static Link fromSpanContext(SpanContext context, Type type) { + return new AutoValue_Link(context.getTraceId(), context.getSpanId(), type); + } + + /** + * Returns the {@code TraceId}. + * + * @return the {@code TraceId}. + */ + public abstract TraceId getTraceId(); + + /** + * Returns the {@code SpanId}. + * + * @return the {@code SpanId} + */ + public abstract SpanId getSpanId(); + + /** + * Returns the {@code Type}. + * + * @return the {@code Type}. + */ + public abstract Type getType(); + + Link() {} +} diff --git a/api/src/main/java/io/opencensus/trace/base/NetworkEvent.java b/api/src/main/java/io/opencensus/trace/base/NetworkEvent.java new file mode 100644 index 00000000..9edc6f25 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/base/NetworkEvent.java @@ -0,0 +1,124 @@ +/* + * Copyright 2016, Google Inc. + * 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.base; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.Timestamp; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * A class that represents a network event. It requires a {@link Type type} and a message id that + * serves to uniquely identify each network message. It can optionally can have information about + * the kernel time and message size. + */ +@Immutable +@AutoValue +public abstract class NetworkEvent { + /** Available types for a {@code NetworkEvent}. */ + public enum Type { + /** When the message was sent. */ + SENT, + /** When the message was received. */ + RECV, + } + + /** + * Returns a new {@link Builder} with default values. + * + * @param type designates whether this is a network send or receive message. + * @param messageId serves to uniquely identify each network message. + * @return a new {@code Builder} with default values. + * @throws NullPointerException if {@code type} is {@code null}. + */ + public static Builder builder(Type type, long messageId) { + return new AutoValue_NetworkEvent.Builder() + .setType(checkNotNull(type, "type")) + .setMessageId(messageId) + // We need to set a value for the message size because the autovalue requires all + // primitives to be initialized. + // TODO(bdrutu): Consider to change the API to require message size. + .setMessageSize(0); + } + + /** + * Returns the kernel timestamp associated with the {@code NetworkEvent} or {@code null} if not + * set. + * + * @return the kernel timestamp associated with the {@code NetworkEvent} or {@code null} if not + * set. + */ + @Nullable + public abstract Timestamp getKernelTimestamp(); + + /** + * Returns the type of the {@code NetworkEvent}. + * + * @return the type of the {@code NetworkEvent}. + */ + public abstract Type getType(); + + /** + * Returns the message id argument that serves to uniquely identify each network message. + * + * @return The message id of the {@code NetworkEvent}. + */ + public abstract long getMessageId(); + + /** + * Returns The message size in bytes of the {@code NetworkEvent}. + * + * @return The message size in bytes of the {@code NetworkEvent}. + */ + public abstract long getMessageSize(); + + /** Builder class for {@link NetworkEvent}. */ + @AutoValue.Builder + public abstract static class Builder { + // Package protected methods because these values are mandatory and set only in the + // NetworkEvent#builder() function. + abstract Builder setType(Type type); + + abstract Builder setMessageId(long messageId); + + /** + * Sets the kernel timestamp. + * + * @param kernelTimestamp The kernel timestamp of the event. + * @return this. + */ + public abstract Builder setKernelTimestamp(@Nullable Timestamp kernelTimestamp); + + /** + * Sets the message size. + * + * @param messageSize represents the size in bytes of this network message. + * @return this. + */ + public abstract Builder setMessageSize(long messageSize); + + /** + * Builds and returns a {@code NetworkEvent} with the desired values. + * + * @return a {@code NetworkEvent} with the desired values. + */ + public abstract NetworkEvent build(); + + Builder() {} + } + + NetworkEvent() {} +} diff --git a/api/src/main/java/io/opencensus/trace/base/SpanId.java b/api/src/main/java/io/opencensus/trace/base/SpanId.java new file mode 100644 index 00000000..4e0b1bed --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/base/SpanId.java @@ -0,0 +1,171 @@ +/* + * Copyright 2017, Google Inc. + * 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.base; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.MoreObjects; +import com.google.common.io.BaseEncoding; +import java.util.Arrays; +import java.util.Random; +import javax.annotation.concurrent.Immutable; + +/** + * A class that represents a span identifier. A valid span identifier is an 8-byte array with at + * least one non-zero byte. + */ +@Immutable +public final class SpanId implements Comparable { + /** The size in bytes of the {@code SpanId}. */ + public static final int SIZE = 8; + + /** The invalid {@code SpanId}. All bytes are 0. */ + public static final SpanId INVALID = new SpanId(new byte[SIZE]); + + // The internal representation of the SpanId. + private final byte[] bytes; + + private SpanId(byte[] bytes) { + this.bytes = bytes; + } + + /** + * Returns a {@code SpanId} built from a byte representation. + * + *

Equivalent with: + * + *

{@code
+   * SpanId.fromBytes(buffer, 0);
+   * }
+ * + * @param buffer the representation of the {@code SpanId}. + * @return a {@code SpanId} whose representation is given by the {@code buffer} parameter. + * @throws NullPointerException if {@code buffer} is null. + * @throws IllegalArgumentException if {@code buffer.length} is not {@link SpanId#SIZE}. + */ + public static SpanId fromBytes(byte[] buffer) { + checkNotNull(buffer, "buffer"); + checkArgument(buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); + byte[] bytesCopied = Arrays.copyOf(buffer, SIZE); + return new SpanId(bytesCopied); + } + + /** + * Returns a {@code SpanId} whose representation is copied from the {@code src} beginning at the + * {@code srcOffset} offset. + * + * @param src the buffer where the representation of the {@code SpanId} is copied. + * @param srcOffset the offset in the buffer where the representation of the {@code SpanId} + * begins. + * @return a {@code SpanId} whose representation is copied from the buffer. + * @throws NullPointerException if {@code src} is null. + * @throws IndexOutOfBoundsException if {@code srcOffset+SpanId.SIZE} is greater than {@code + * src.length}. + */ + public static SpanId fromBytes(byte[] src, int srcOffset) { + byte[] bytes = new byte[SIZE]; + System.arraycopy(src, srcOffset, bytes, 0, SIZE); + return new SpanId(bytes); + } + + /** + * Generates a new random {@code SpanId}. + * + * @param random The random number generator. + * @return a valid new {@code SpanId}. + */ + public static SpanId generateRandomId(Random random) { + byte[] bytes = new byte[SIZE]; + do { + random.nextBytes(bytes); + } while (Arrays.equals(bytes, INVALID.bytes)); + return new SpanId(bytes); + } + + /** + * Returns the byte representation of the {@code SpanId}. + * + * @return the byte representation of the {@code SpanId}. + */ + public byte[] getBytes() { + return Arrays.copyOf(bytes, SIZE); + } + + /** + * Copies the byte array representations of the {@code SpanId} into the {@code dest} beginning at + * the {@code destOffset} offset. + * + *

Equivalent with (but faster because it avoids any new allocations): + * + *

{@code
+   * System.arraycopy(getBytes(), 0, dest, destOffset, SpanId.SIZE);
+   * }
+ * + * @param dest the destination buffer. + * @param destOffset the starting offset in the destination buffer. + * @throws NullPointerException if {@code dest} is null. + * @throws IndexOutOfBoundsException if {@code destOffset+SpanId.SIZE} is greater than {@code + * dest.length}. + */ + public void copyBytesTo(byte[] dest, int destOffset) { + System.arraycopy(bytes, 0, dest, destOffset, SIZE); + } + + /** + * Returns whether the span identifier is valid. A valid span identifier is an 8-byte array with + * at least one non-zero byte. + * + * @return {@code true} if the span identifier is valid. + */ + public boolean isValid() { + return !Arrays.equals(bytes, INVALID.bytes); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof SpanId)) { + return false; + } + + SpanId that = (SpanId) obj; + return Arrays.equals(bytes, that.bytes); + } + + @Override + public int hashCode() { + return Arrays.hashCode(bytes); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("spanId", BaseEncoding.base16().lowerCase().encode(bytes)) + .toString(); + } + + @Override + public int compareTo(SpanId that) { + for (int i = 0; i < SIZE; i++) { + if (bytes[i] != that.bytes[i]) { + return bytes[i] < that.bytes[i] ? -1 : 1; + } + } + return 0; + } +} diff --git a/api/src/main/java/io/opencensus/trace/base/Status.java b/api/src/main/java/io/opencensus/trace/base/Status.java new file mode 100644 index 00000000..6166c17c --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/base/Status.java @@ -0,0 +1,328 @@ +/* + * Copyright 2016, Google Inc. + * 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.base; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Objects; +import io.opencensus.trace.Span; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.TreeMap; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * Defines the status of a {@link Span} by providing a standard {@link CanonicalCode} in conjunction + * with an optional descriptive message. Instances of {@code Status} are created by starting with + * the template for the appropriate {@link Status.CanonicalCode} and supplementing it with + * additional information: {@code Status.NOT_FOUND.withDescription("Could not find + * 'important_file.txt'");} + */ +@Immutable +public final class Status { + /** + * The set of canonical status codes. If new codes are added over time they must choose a + * numerical value that does not collide with any previously used value. + */ + public enum CanonicalCode { + /** The operation completed successfully. */ + OK(0), + + /** The operation was cancelled (typically by the caller). */ + CANCELLED(1), + + /** + * Unknown error. An example of where this error may be returned is if a Status value received + * from another address space belongs to an error-space that is not known in this address space. + * Also errors raised by APIs that do not return enough error information may be converted to + * this error. + */ + UNKNOWN(2), + + /** + * Client specified an invalid argument. Note that this differs from FAILED_PRECONDITION. + * INVALID_ARGUMENT indicates arguments that are problematic regardless of the state of the + * system (e.g., a malformed file name). + */ + INVALID_ARGUMENT(3), + + /** + * Deadline expired before operation could complete. For operations that change the state of the + * system, this error may be returned even if the operation has completed successfully. For + * example, a successful response from a server could have been delayed long enough for the + * deadline to expire. + */ + DEADLINE_EXCEEDED(4), + + /** Some requested entity (e.g., file or directory) was not found. */ + NOT_FOUND(5), + + /** Some entity that we attempted to create (e.g., file or directory) already exists. */ + ALREADY_EXISTS(6), + + /** + * The caller does not have permission to execute the specified operation. PERMISSION_DENIED + * must not be used for rejections caused by exhausting some resource (use RESOURCE_EXHAUSTED + * instead for those errors). PERMISSION_DENIED must not be used if the caller cannot be + * identified (use UNAUTHENTICATED instead for those errors). + */ + PERMISSION_DENIED(7), + + /** + * Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system + * is out of space. + */ + RESOURCE_EXHAUSTED(8), + + /** + * Operation was rejected because the system is not in a state required for the operation's + * execution. For example, directory to be deleted may be non-empty, an rmdir operation is + * applied to a non-directory, etc. + * + *

A litmus test that may help a service implementor in deciding between FAILED_PRECONDITION, + * ABORTED, and UNAVAILABLE: (a) Use UNAVAILABLE if the client can retry just the failing call. + * (b) Use ABORTED if the client should retry at a higher-level (e.g., restarting a + * read-modify-write sequence). (c) Use FAILED_PRECONDITION if the client should not retry until + * the system state has been explicitly fixed. E.g., if an "rmdir" fails because the directory + * is non-empty, FAILED_PRECONDITION should be returned since the client should not retry unless + * they have first fixed up the directory by deleting files from it. + */ + FAILED_PRECONDITION(9), + + /** + * The operation was aborted, typically due to a concurrency issue like sequencer check + * failures, transaction aborts, etc. + * + *

See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE. + */ + ABORTED(10), + + /** + * Operation was attempted past the valid range. E.g., seeking or reading past end of file. + * + *

Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed if the system + * state changes. For example, a 32-bit file system will generate INVALID_ARGUMENT if asked to + * read at an offset that is not in the range [0,2^32-1], but it will generate OUT_OF_RANGE if + * asked to read from an offset past the current file size. + * + *

There is a fair bit of overlap between FAILED_PRECONDITION and OUT_OF_RANGE. We recommend + * using OUT_OF_RANGE (the more specific error) when it applies so that callers who are + * iterating through a space can easily look for an OUT_OF_RANGE error to detect when they are + * done. + */ + OUT_OF_RANGE(11), + + /** Operation is not implemented or not supported/enabled in this service. */ + UNIMPLEMENTED(12), + + /** + * Internal errors. Means some invariants expected by underlying system has been broken. If you + * see one of these errors, something is very broken. + */ + INTERNAL(13), + + /** + * The service is currently unavailable. This is a most likely a transient condition and may be + * corrected by retrying with a backoff. + * + *

See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE. + */ + UNAVAILABLE(14), + + /** Unrecoverable data loss or corruption. */ + DATA_LOSS(15), + + /** The request does not have valid authentication credentials for the operation. */ + UNAUTHENTICATED(16); + + private final int value; + + private CanonicalCode(int value) { + this.value = value; + } + + /** + * Returns the numerical value of the code. + * + * @return the numerical value of the code. + */ + public int value() { + return value; + } + + Status toStatus() { + return STATUS_LIST.get(value); + } + } + + // Create the canonical list of Status instances indexed by their code values. + private static final List STATUS_LIST = buildStatusList(); + + private static List buildStatusList() { + TreeMap canonicalizer = new TreeMap(); + for (CanonicalCode code : CanonicalCode.values()) { + Status replaced = canonicalizer.put(code.value(), new Status(code, null)); + if (replaced != null) { + throw new IllegalStateException( + "Code value duplication between " + + replaced.getCanonicalCode().name() + + " & " + + code.name()); + } + } + return Collections.unmodifiableList(new ArrayList(canonicalizer.values())); + } + + // A pseudo-enum of Status instances mapped 1:1 with values in CanonicalCode. This simplifies + // construction patterns for derived instances of Status. + /** The operation completed successfully. */ + public static final Status OK = CanonicalCode.OK.toStatus(); + /** The operation was cancelled (typically by the caller). */ + public static final Status CANCELLED = CanonicalCode.CANCELLED.toStatus(); + /** Unknown error. See {@link CanonicalCode#UNKNOWN}. */ + public static final Status UNKNOWN = CanonicalCode.UNKNOWN.toStatus(); + /** Client specified an invalid argument. See {@link CanonicalCode#INVALID_ARGUMENT}. */ + public static final Status INVALID_ARGUMENT = CanonicalCode.INVALID_ARGUMENT.toStatus(); + /** + * Deadline expired before operation could complete. See {@link CanonicalCode#DEADLINE_EXCEEDED}. + */ + public static final Status DEADLINE_EXCEEDED = CanonicalCode.DEADLINE_EXCEEDED.toStatus(); + /** Some requested entity (e.g., file or directory) was not found. */ + public static final Status NOT_FOUND = CanonicalCode.NOT_FOUND.toStatus(); + /** Some entity that we attempted to create (e.g., file or directory) already exists. */ + public static final Status ALREADY_EXISTS = CanonicalCode.ALREADY_EXISTS.toStatus(); + /** + * The caller does not have permission to execute the specified operation. See {@link + * CanonicalCode#PERMISSION_DENIED}. + */ + public static final Status PERMISSION_DENIED = CanonicalCode.PERMISSION_DENIED.toStatus(); + /** The request does not have valid authentication credentials for the operation. */ + public static final Status UNAUTHENTICATED = CanonicalCode.UNAUTHENTICATED.toStatus(); + /** + * Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system + * is out of space. + */ + public static final Status RESOURCE_EXHAUSTED = CanonicalCode.RESOURCE_EXHAUSTED.toStatus(); + /** + * Operation was rejected because the system is not in a state required for the operation's + * execution. See {@link CanonicalCode#FAILED_PRECONDITION}. + */ + public static final Status FAILED_PRECONDITION = CanonicalCode.FAILED_PRECONDITION.toStatus(); + /** + * The operation was aborted, typically due to a concurrency issue like sequencer check failures, + * transaction aborts, etc. See {@link CanonicalCode#ABORTED}. + */ + public static final Status ABORTED = CanonicalCode.ABORTED.toStatus(); + /** Operation was attempted past the valid range. See {@link CanonicalCode#OUT_OF_RANGE}. */ + public static final Status OUT_OF_RANGE = CanonicalCode.OUT_OF_RANGE.toStatus(); + /** Operation is not implemented or not supported/enabled in this service. */ + public static final Status UNIMPLEMENTED = CanonicalCode.UNIMPLEMENTED.toStatus(); + /** Internal errors. See {@link CanonicalCode#INTERNAL}. */ + public static final Status INTERNAL = CanonicalCode.INTERNAL.toStatus(); + /** The service is currently unavailable. See {@link CanonicalCode#UNAVAILABLE}. */ + public static final Status UNAVAILABLE = CanonicalCode.UNAVAILABLE.toStatus(); + /** Unrecoverable data loss or corruption. */ + public static final Status DATA_LOSS = CanonicalCode.DATA_LOSS.toStatus(); + + // The canonical code of this message. + private final CanonicalCode canonicalCode; + // An additional error message. + private final String description; + + private Status(CanonicalCode canonicalCode, @Nullable String description) { + this.canonicalCode = checkNotNull(canonicalCode, "canonicalCode"); + this.description = description; + } + + /** + * Creates a derived instance of {@code Status} with the given description. + * + * @param description the new description of the {@code Status}. + * @return The newly created {@code Status} with the given description. + */ + public Status withDescription(String description) { + if (Objects.equal(this.description, description)) { + return this; + } + return new Status(this.canonicalCode, description); + } + + /** + * Returns the canonical status code. + * + * @return the canonical status code. + */ + public CanonicalCode getCanonicalCode() { + return canonicalCode; + } + + /** + * Returns the description of this {@code Status} for human consumption. + * + * @return the description of this {@code Status}. + */ + @Nullable + public String getDescription() { + return description; + } + + /** + * Returns {@code true} if this {@code Status} is OK, i.e., not an error. + * + * @return {@code true} if this {@code Status} is OK. + */ + public boolean isOk() { + return CanonicalCode.OK == canonicalCode; + } + + /** + * Equality on Statuses is not well defined. Instead, do comparison based on their CanonicalCode + * with {@link #getCanonicalCode}. The description of the Status is unlikely to be stable, and + * additional fields may be added to Status in the future. + */ + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof Status)) { + return false; + } + + Status that = (Status) obj; + return canonicalCode == that.canonicalCode && Objects.equal(description, that.description); + } + + /** + * Hash codes on Statuses are not well defined. + * + * @see #equals + */ + @Override + public int hashCode() { + return Objects.hashCode(canonicalCode, description); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("canonicalCode", canonicalCode) + .add("description", description) + .toString(); + } +} diff --git a/api/src/main/java/io/opencensus/trace/base/TraceId.java b/api/src/main/java/io/opencensus/trace/base/TraceId.java new file mode 100644 index 00000000..293e2a72 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/base/TraceId.java @@ -0,0 +1,193 @@ +/* + * Copyright 2016, Google Inc. + * 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.base; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.MoreObjects; +import com.google.common.io.BaseEncoding; +import io.opencensus.common.Internal; +import java.util.Arrays; +import java.util.Random; +import javax.annotation.concurrent.Immutable; + +/** + * A class that represents a trace identifier. A valid trace identifier is a 16-byte array with at + * least one non-zero byte. + */ +@Immutable +public final class TraceId implements Comparable { + /** The size in bytes of the {@code TraceId}. */ + public static final int SIZE = 16; + + /** The invalid {@code TraceId}. All bytes are '\0'. */ + public static final TraceId INVALID = new TraceId(new byte[SIZE]); + + // The internal representation of the TraceId. + private final byte[] bytes; + + private TraceId(byte[] bytes) { + this.bytes = bytes; + } + + /** + * Returns a {@code TraceId} built from a byte representation. + * + *

Equivalent with: + * + *

{@code
+   * TraceId.fromBytes(buffer, 0);
+   * }
+ * + * @param buffer the representation of the {@code TraceId}. + * @return a {@code TraceId} whose representation is given by the {@code buffer} parameter. + * @throws NullPointerException if {@code buffer} is null. + * @throws IllegalArgumentException if {@code buffer.length} is not {@link TraceId#SIZE}. + */ + public static TraceId fromBytes(byte[] buffer) { + checkNotNull(buffer, "buffer"); + checkArgument(buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); + byte[] bytesCopied = Arrays.copyOf(buffer, SIZE); + return new TraceId(bytesCopied); + } + + /** + * Returns a {@code TraceId} whose representation is copied from the {@code src} beginning at the + * {@code srcOffset} offset. + * + * @param src the buffer where the representation of the {@code TraceId} is copied. + * @param srcOffset the offset in the buffer where the representation of the {@code TraceId} + * begins. + * @return a {@code TraceId} whose representation is copied from the buffer. + * @throws NullPointerException if {@code src} is null. + * @throws IndexOutOfBoundsException if {@code srcOffset+TraceId.SIZE} is greater than {@code + * src.length}. + */ + public static TraceId fromBytes(byte[] src, int srcOffset) { + byte[] bytes = new byte[SIZE]; + System.arraycopy(src, srcOffset, bytes, 0, SIZE); + return new TraceId(bytes); + } + + /** + * Generates a new random {@code TraceId}. + * + * @param random the random number generator. + * @return a new valid {@code TraceId}. + */ + public static TraceId generateRandomId(Random random) { + byte[] bytes = new byte[SIZE]; + do { + random.nextBytes(bytes); + } while (Arrays.equals(bytes, INVALID.bytes)); + return new TraceId(bytes); + } + + /** + * Returns the 16-bytes array representation of the {@code TraceId}. + * + * @return the 16-bytes array representation of the {@code TraceId}. + */ + public byte[] getBytes() { + return Arrays.copyOf(bytes, SIZE); + } + + /** + * Copies the byte array representations of the {@code TraceId} into the {@code dest} beginning at + * the {@code destOffset} offset. + * + *

Equivalent with (but faster because it avoids any new allocations): + * + *

{@code
+   * System.arraycopy(getBytes(), 0, dest, destOffset, TraceId.SIZE);
+   * }
+ * + * @param dest the destination buffer. + * @param destOffset the starting offset in the destination buffer. + * @throws NullPointerException if {@code dest} is null. + * @throws IndexOutOfBoundsException if {@code destOffset+TraceId.SIZE} is greater than {@code + * dest.length}. + */ + public void copyBytesTo(byte[] dest, int destOffset) { + System.arraycopy(bytes, 0, dest, destOffset, SIZE); + } + + /** + * Returns whether the {@code TraceId} is valid. A valid trace identifier is a 16-byte array with + * at least one non-zero byte. + * + * @return {@code true} if the {@code TraceId} is valid. + */ + public boolean isValid() { + return !Arrays.equals(bytes, INVALID.bytes); + } + + /** + * Returns the lower 8 bytes of the trace-id as a long value, assuming little-endian order. This + * is used in ProbabilitySampler. + * + *

This method is marked as internal and subject to change. + * + * @return the lower 8 bytes of the trace-id as a long value, assuming little-endian order. + */ + @Internal + public long getLowerLong() { + long result = 0; + for (int i = 0; i < Long.SIZE / Byte.SIZE; i++) { + result <<= Byte.SIZE; + result |= (bytes[i] & 0xff); + } + if (result < 0) { + return -result; + } + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof TraceId)) { + return false; + } + + TraceId that = (TraceId) obj; + return Arrays.equals(bytes, that.bytes); + } + + @Override + public int hashCode() { + return Arrays.hashCode(bytes); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("traceId", BaseEncoding.base16().lowerCase().encode(bytes)) + .toString(); + } + + @Override + public int compareTo(TraceId that) { + for (int i = 0; i < SIZE; i++) { + if (bytes[i] != that.bytes[i]) { + return bytes[i] < that.bytes[i] ? -1 : 1; + } + } + return 0; + } +} diff --git a/api/src/main/java/io/opencensus/trace/base/TraceOptions.java b/api/src/main/java/io/opencensus/trace/base/TraceOptions.java new file mode 100644 index 00000000..57733238 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/base/TraceOptions.java @@ -0,0 +1,211 @@ +/* + * Copyright 2017, Google Inc. + * 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.base; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkElementIndex; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.MoreObjects; +import com.google.common.base.Objects; +import io.opencensus.trace.Span; +import javax.annotation.concurrent.Immutable; + +/** + * A class that represents global trace options. These options are propagated to all child {@link + * Span spans}. These determine features such as whether a {@code Span} should be traced. It is + * implemented as a bitmask. + */ +@Immutable +public final class TraceOptions { + // Default options. Nothing set. + private static final byte DEFAULT_OPTIONS = 0; + // Bit to represent whether trace is sampled or not. + private static final byte IS_SAMPLED = 0x1; + + /** The size in bytes of the {@code TraceOptions}. */ + public static final int SIZE = 1; + + /** The default {@code TraceOptions}. */ + public static final TraceOptions DEFAULT = new TraceOptions(DEFAULT_OPTIONS); + + // The set of enabled features is determined by all the enabled bits. + private final byte options; + + // Creates a new {@code TraceOptions} with the given options. + private TraceOptions(byte options) { + this.options = options; + } + + /** + * Returns a {@code TraceOptions} built from a byte representation. + * + *

Equivalent with: + * + *

{@code
+   * TraceOptions.fromBytes(buffer, 0);
+   * }
+ * + * @param buffer the representation of the {@code TraceOptions}. + * @return a {@code TraceOptions} whose representation is given by the {@code buffer} parameter. + * @throws NullPointerException if {@code buffer} is null. + * @throws IllegalArgumentException if {@code buffer.length} is not {@link TraceOptions#SIZE}. + */ + public static TraceOptions fromBytes(byte[] buffer) { + checkNotNull(buffer, "buffer"); + checkArgument(buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); + return new TraceOptions(buffer[0]); + } + + /** + * Returns a {@code TraceOptions} whose representation is copied from the {@code src} beginning at + * the {@code srcOffset} offset. + * + * @param src the buffer where the representation of the {@code TraceOptions} is copied. + * @param srcOffset the offset in the buffer where the representation of the {@code TraceOptions} + * begins. + * @return a {@code TraceOptions} whose representation is copied from the buffer. + * @throws NullPointerException if {@code src} is null. + * @throws IndexOutOfBoundsException if {@code srcOffset+TraceOptions.SIZE} is greater than {@code + * src.length}. + */ + public static TraceOptions fromBytes(byte[] src, int srcOffset) { + checkElementIndex(srcOffset, src.length); + return new TraceOptions(src[srcOffset]); + } + + /** + * Returns the 1-byte array representation of the {@code TraceOptions}. + * + * @return the 1-byte array representation of the {@code TraceOptions}. + */ + public byte[] getBytes() { + byte[] bytes = new byte[SIZE]; + bytes[0] = options; + return bytes; + } + + /** + * Copies the byte representations of the {@code TraceOptions} into the {@code dest} beginning at + * the {@code destOffset} offset. + * + *

Equivalent with (but faster because it avoids any new allocations): + * + *

{@code
+   * System.arraycopy(getBytes(), 0, dest, destOffset, TraceOptions.SIZE);
+   * }
+ * + * @param dest the destination buffer. + * @param destOffset the starting offset in the destination buffer. + * @throws NullPointerException if {@code dest} is null. + * @throws IndexOutOfBoundsException if {@code destOffset+TraceOptions.SIZE} is greater than + * {@code dest.length}. + */ + public void copyBytesTo(byte[] dest, int destOffset) { + checkElementIndex(destOffset, dest.length); + dest[destOffset] = options; + } + + /** + * Returns a new {@link Builder} with default options. + * + * @return a new {@code Builder} with default options. + */ + public static Builder builder() { + return new Builder(DEFAULT_OPTIONS); + } + + /** + * Returns a new {@link Builder} with all given options set. + * + * @param traceOptions the given options set. + * @return a new {@code Builder} with all given options set. + */ + public static Builder builder(TraceOptions traceOptions) { + return new Builder(traceOptions.options); + } + + /** + * Returns a boolean indicating whether this {@code Span} is part of a sampled trace and data + * should be exported to a persistent store. + * + * @return a boolean indicating whether the trace is sampled. + */ + public boolean isSampled() { + return hasOption(IS_SAMPLED); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof TraceOptions)) { + return false; + } + + TraceOptions that = (TraceOptions) obj; + return options == that.options; + } + + @Override + public int hashCode() { + return Objects.hashCode(options); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this).add("sampled", isSampled()).toString(); + } + + /** Builder class for {@link TraceOptions}. */ + public static final class Builder { + private byte options; + + private Builder(byte options) { + this.options = options; + } + + /** + * Marks this trace as sampled. + * + * @return this. + */ + public Builder setIsSampled() { + options |= IS_SAMPLED; + return this; + } + + /** + * Builds and returns a {@code TraceOptions} with the desired options. + * + * @return a {@code TraceOptions} with the desired options. + */ + public TraceOptions build() { + return new TraceOptions(options); + } + } + + // Returns the current set of options bitmask. + @VisibleForTesting + byte getOptions() { + return options; + } + + private boolean hasOption(int mask) { + return (this.options & mask) != 0; + } +} diff --git a/api/src/main/java/io/opencensus/trace/config/TraceParams.java b/api/src/main/java/io/opencensus/trace/config/TraceParams.java index c4463342..1f0e093f 100644 --- a/api/src/main/java/io/opencensus/trace/config/TraceParams.java +++ b/api/src/main/java/io/opencensus/trace/config/TraceParams.java @@ -16,13 +16,13 @@ package io.opencensus.trace.config; import static com.google.common.base.Preconditions.checkArgument; import com.google.auto.value.AutoValue; -import io.opencensus.trace.Annotation; -import io.opencensus.trace.Link; -import io.opencensus.trace.NetworkEvent; import io.opencensus.trace.Sampler; import io.opencensus.trace.Samplers; import io.opencensus.trace.Span; import io.opencensus.trace.StartSpanOptions; +import io.opencensus.trace.base.Annotation; +import io.opencensus.trace.base.Link; +import io.opencensus.trace.base.NetworkEvent; import javax.annotation.concurrent.Immutable; /** Class that holds global trace parameters. */ diff --git a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java index 5407c46b..03f1cc6c 100644 --- a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java +++ b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java @@ -13,7 +13,7 @@ package io.opencensus.trace.export; -import io.opencensus.trace.TraceOptions; +import io.opencensus.trace.base.TraceOptions; import javax.annotation.Nullable; /** diff --git a/api/src/main/java/io/opencensus/trace/export/InProcessDebuggingHandler.java b/api/src/main/java/io/opencensus/trace/export/InProcessDebuggingHandler.java index 56318bd9..40fdcae0 100644 --- a/api/src/main/java/io/opencensus/trace/export/InProcessDebuggingHandler.java +++ b/api/src/main/java/io/opencensus/trace/export/InProcessDebuggingHandler.java @@ -19,8 +19,8 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; import io.opencensus.trace.Span; import io.opencensus.trace.SpanData; -import io.opencensus.trace.Status; -import io.opencensus.trace.Status.CanonicalCode; +import io.opencensus.trace.base.Status; +import io.opencensus.trace.base.Status.CanonicalCode; import java.util.Collection; import java.util.Collections; import java.util.HashMap; diff --git a/api/src/main/java/io/opencensus/trace/export/SpanExporter.java b/api/src/main/java/io/opencensus/trace/export/SpanExporter.java index 5e10d8be..199427b1 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanExporter.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanExporter.java @@ -15,7 +15,7 @@ package io.opencensus.trace.export; import io.opencensus.trace.Span; import io.opencensus.trace.SpanData; -import io.opencensus.trace.TraceOptions; +import io.opencensus.trace.base.TraceOptions; import java.util.Collection; import java.util.logging.Level; import java.util.logging.Logger; diff --git a/api/src/test/java/io/opencensus/trace/AnnotationTest.java b/api/src/test/java/io/opencensus/trace/AnnotationTest.java deleted file mode 100644 index fbfe5fd3..00000000 --- a/api/src/test/java/io/opencensus/trace/AnnotationTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link Link}. */ -@RunWith(JUnit4.class) -public class AnnotationTest { - @Test(expected = NullPointerException.class) - public void fromDescription_NullDescription() { - Annotation.fromDescription(null); - } - - @Test - public void fromDescription() { - Annotation annotation = Annotation.fromDescription("MyAnnotationText"); - assertThat(annotation.getDescription()).isEqualTo("MyAnnotationText"); - assertThat(annotation.getAttributes().size()).isEqualTo(0); - } - - @Test(expected = NullPointerException.class) - public void fromDescriptionAndAttributes_NullDescription() { - Annotation.fromDescriptionAndAttributes(null, Collections.emptyMap()); - } - - @Test(expected = NullPointerException.class) - public void fromDescriptionAndAttributes_NullAttributes() { - Annotation.fromDescriptionAndAttributes("", null); - } - - @Test - public void fromDescriptionAndAttributes() { - Map attributes = new HashMap(); - attributes.put( - "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); - Annotation annotation = Annotation.fromDescriptionAndAttributes("MyAnnotationText", attributes); - assertThat(annotation.getDescription()).isEqualTo("MyAnnotationText"); - assertThat(annotation.getAttributes()).isEqualTo(attributes); - } - - @Test - public void fromDescriptionAndAttributes_EmptyAttributes() { - Annotation annotation = - Annotation.fromDescriptionAndAttributes( - "MyAnnotationText", Collections.emptyMap()); - assertThat(annotation.getDescription()).isEqualTo("MyAnnotationText"); - assertThat(annotation.getAttributes().size()).isEqualTo(0); - } - - @Test - public void annotation_EqualsAndHashCode() { - EqualsTester tester = new EqualsTester(); - Map attributes = new HashMap(); - attributes.put( - "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); - tester - .addEqualityGroup( - Annotation.fromDescription("MyAnnotationText"), - Annotation.fromDescriptionAndAttributes( - "MyAnnotationText", Collections.emptyMap())) - .addEqualityGroup( - Annotation.fromDescriptionAndAttributes("MyAnnotationText", attributes), - Annotation.fromDescriptionAndAttributes("MyAnnotationText", attributes)) - .addEqualityGroup(Annotation.fromDescription("MyAnnotationText2")); - tester.testEquals(); - } - - @Test - public void annotation_ToString() { - Annotation annotation = Annotation.fromDescription("MyAnnotationText"); - assertThat(annotation.toString()).contains("MyAnnotationText"); - Map attributes = new HashMap(); - attributes.put( - "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); - annotation = Annotation.fromDescriptionAndAttributes("MyAnnotationText2", attributes); - assertThat(annotation.toString()).contains("MyAnnotationText2"); - assertThat(annotation.toString()).contains(attributes.toString()); - } -} diff --git a/api/src/test/java/io/opencensus/trace/AttributeValueTest.java b/api/src/test/java/io/opencensus/trace/AttributeValueTest.java deleted file mode 100644 index 7a999604..00000000 --- a/api/src/test/java/io/opencensus/trace/AttributeValueTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link AttributeValue}. */ -@RunWith(JUnit4.class) -public class AttributeValueTest { - @Test - public void stringAttributeValue() { - AttributeValue attribute = AttributeValue.stringAttributeValue("MyStringAttributeValue"); - assertThat(attribute.getStringValue()).isEqualTo("MyStringAttributeValue"); - assertThat(attribute.getBooleanValue()).isNull(); - assertThat(attribute.getLongValue()).isNull(); - } - - @Test - public void booleanAttributeValue() { - AttributeValue attribute = AttributeValue.booleanAttributeValue(true); - assertThat(attribute.getStringValue()).isNull(); - assertThat(attribute.getBooleanValue()).isTrue(); - assertThat(attribute.getLongValue()).isNull(); - } - - @Test - public void longAttributeValue() { - AttributeValue attribute = AttributeValue.longAttributeValue(123456L); - assertThat(attribute.getStringValue()).isNull(); - assertThat(attribute.getBooleanValue()).isNull(); - assertThat(attribute.getLongValue()).isEqualTo(123456L); - } - - @Test - public void attributeValue_EqualsAndHashCode() { - EqualsTester tester = new EqualsTester(); - tester.addEqualityGroup( - AttributeValue.stringAttributeValue("MyStringAttributeValue"), - AttributeValue.stringAttributeValue("MyStringAttributeValue")); - tester.addEqualityGroup(AttributeValue.stringAttributeValue("MyStringAttributeDiffValue")); - tester.addEqualityGroup( - AttributeValue.booleanAttributeValue(true), AttributeValue.booleanAttributeValue(true)); - tester.addEqualityGroup(AttributeValue.booleanAttributeValue(false)); - tester.addEqualityGroup( - AttributeValue.longAttributeValue(123456L), AttributeValue.longAttributeValue(123456L)); - tester.addEqualityGroup(AttributeValue.longAttributeValue(1234567L)); - tester.testEquals(); - } - - @Test - public void attributeValue_ToString() { - AttributeValue attribute = AttributeValue.stringAttributeValue("MyStringAttributeValue"); - assertThat(attribute.toString()).contains("MyStringAttributeValue"); - attribute = AttributeValue.booleanAttributeValue(true); - assertThat(attribute.toString()).contains("true"); - attribute = AttributeValue.longAttributeValue(123456L); - assertThat(attribute.toString()).contains("123456"); - } -} diff --git a/api/src/test/java/io/opencensus/trace/BlankSpanTest.java b/api/src/test/java/io/opencensus/trace/BlankSpanTest.java index 252d02ff..c2f4c35d 100644 --- a/api/src/test/java/io/opencensus/trace/BlankSpanTest.java +++ b/api/src/test/java/io/opencensus/trace/BlankSpanTest.java @@ -15,6 +15,11 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; +import io.opencensus.trace.base.Annotation; +import io.opencensus.trace.base.AttributeValue; +import io.opencensus.trace.base.EndSpanOptions; +import io.opencensus.trace.base.Link; +import io.opencensus.trace.base.NetworkEvent; import java.util.HashMap; import java.util.Map; import org.junit.Test; diff --git a/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java b/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java deleted file mode 100644 index d531fba5..00000000 --- a/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link EndSpanOptions}. */ -@RunWith(JUnit4.class) -public class EndSpanOptionsTest { - @Test(expected = NullPointerException.class) - public void setNullStatus() { - EndSpanOptions.builder().setStatus(null).build(); - } - - @Test - public void endSpanOptions_DefaultOptions() { - assertThat(EndSpanOptions.DEFAULT.getStatus()).isEqualTo(Status.OK); - } - - @Test - public void setStatus() { - EndSpanOptions endSpanOptions = - EndSpanOptions.builder() - .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) - .build(); - assertThat(endSpanOptions.getStatus()) - .isEqualTo(Status.CANCELLED.withDescription("ThisIsAnError")); - } - - @Test - public void endSpanOptions_EqualsAndHashCode() { - EqualsTester tester = new EqualsTester(); - tester.addEqualityGroup( - EndSpanOptions.builder() - .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) - .build(), - EndSpanOptions.builder() - .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) - .build()); - tester.addEqualityGroup(EndSpanOptions.builder().build(), EndSpanOptions.DEFAULT); - tester.testEquals(); - } - - @Test - public void endSpanOptions_ToString() { - EndSpanOptions endSpanOptions = - EndSpanOptions.builder() - .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) - .build(); - assertThat(endSpanOptions.toString()).contains("ThisIsAnError"); - } -} diff --git a/api/src/test/java/io/opencensus/trace/LinkTest.java b/api/src/test/java/io/opencensus/trace/LinkTest.java deleted file mode 100644 index e1289f33..00000000 --- a/api/src/test/java/io/opencensus/trace/LinkTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import io.opencensus.trace.Link.Type; -import java.util.Random; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link Link}. */ -@RunWith(JUnit4.class) -public class LinkTest { - private final Random random = new Random(1234); - private final SpanContext spanContext = - SpanContext.create( - TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); - - @Test - public void fromSpanContext_ChildLink() { - Link link = Link.fromSpanContext(spanContext, Type.CHILD); - assertThat(link.getTraceId()).isEqualTo(spanContext.getTraceId()); - assertThat(link.getSpanId()).isEqualTo(spanContext.getSpanId()); - assertThat(link.getType()).isEqualTo(Type.CHILD); - } - - @Test - public void fromSpanContext_ParentLink() { - Link link = Link.fromSpanContext(spanContext, Type.PARENT); - assertThat(link.getTraceId()).isEqualTo(spanContext.getTraceId()); - assertThat(link.getSpanId()).isEqualTo(spanContext.getSpanId()); - assertThat(link.getType()).isEqualTo(Type.PARENT); - } - - @Test - public void link_EqualsAndHashCode() { - EqualsTester tester = new EqualsTester(); - tester - .addEqualityGroup( - Link.fromSpanContext(spanContext, Type.PARENT), - Link.fromSpanContext(spanContext, Type.PARENT)) - .addEqualityGroup( - Link.fromSpanContext(spanContext, Type.CHILD), - Link.fromSpanContext(spanContext, Type.CHILD)) - .addEqualityGroup(Link.fromSpanContext(SpanContext.INVALID, Type.CHILD)) - .addEqualityGroup(Link.fromSpanContext(SpanContext.INVALID, Type.PARENT)); - tester.testEquals(); - } - - @Test - public void link_ToString() { - Link link = Link.fromSpanContext(spanContext, Type.CHILD); - assertThat(link.toString()).contains(spanContext.getTraceId().toString()); - assertThat(link.toString()).contains(spanContext.getSpanId().toString()); - assertThat(link.toString()).contains("CHILD"); - link = Link.fromSpanContext(spanContext, Type.PARENT); - assertThat(link.toString()).contains(spanContext.getTraceId().toString()); - assertThat(link.toString()).contains(spanContext.getSpanId().toString()); - assertThat(link.toString()).contains("PARENT"); - } -} diff --git a/api/src/test/java/io/opencensus/trace/NetworkEventTest.java b/api/src/test/java/io/opencensus/trace/NetworkEventTest.java deleted file mode 100644 index 946e8ce1..00000000 --- a/api/src/test/java/io/opencensus/trace/NetworkEventTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.truth.Truth.assertThat; - -import io.opencensus.common.Timestamp; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link NetworkEvent}. */ -@RunWith(JUnit4.class) -public class NetworkEventTest { - @Test(expected = NullPointerException.class) - public void buildNetworkEvent_NullType() { - NetworkEvent.builder(null, 1L).build(); - } - - @Test - public void buildNetworkEvent_WithRequiredFields() { - NetworkEvent networkEvent = NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).build(); - assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); - assertThat(networkEvent.getMessageId()).isEqualTo(1L); - assertThat(networkEvent.getKernelTimestamp()).isNull(); - assertThat(networkEvent.getMessageSize()).isEqualTo(0L); - } - - @Test - public void buildNetworkEvent_WithTimestamp() { - NetworkEvent networkEvent = - NetworkEvent.builder(NetworkEvent.Type.SENT, 1L) - .setKernelTimestamp(Timestamp.fromMillis(123456L)) - .build(); - assertThat(networkEvent.getKernelTimestamp()).isEqualTo(Timestamp.fromMillis(123456L)); - assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); - assertThat(networkEvent.getMessageId()).isEqualTo(1L); - assertThat(networkEvent.getMessageSize()).isEqualTo(0L); - } - - @Test - public void buildNetworkEvent_WithMessageSize() { - NetworkEvent networkEvent = - NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).setMessageSize(123L).build(); - assertThat(networkEvent.getKernelTimestamp()).isNull(); - assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); - assertThat(networkEvent.getMessageId()).isEqualTo(1L); - assertThat(networkEvent.getMessageSize()).isEqualTo(123L); - } - - @Test - public void buildNetworkEvent_WithAllValues() { - NetworkEvent networkEvent = - NetworkEvent.builder(NetworkEvent.Type.RECV, 1L) - .setKernelTimestamp(Timestamp.fromMillis(123456L)) - .setMessageSize(123L) - .build(); - assertThat(networkEvent.getKernelTimestamp()).isEqualTo(Timestamp.fromMillis(123456L)); - assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.RECV); - assertThat(networkEvent.getMessageId()).isEqualTo(1L); - assertThat(networkEvent.getMessageSize()).isEqualTo(123L); - } - - @Test - public void networkEvent_ToString() { - NetworkEvent networkEvent = - NetworkEvent.builder(NetworkEvent.Type.SENT, 1L) - .setKernelTimestamp(Timestamp.fromMillis(123456L)) - .setMessageSize(123L) - .build(); - assertThat(networkEvent.toString()).contains(Timestamp.fromMillis(123456L).toString()); - assertThat(networkEvent.toString()).contains("type=SENT"); - assertThat(networkEvent.toString()).contains("messageId=1"); - assertThat(networkEvent.toString()).contains("messageSize=123"); - } -} diff --git a/api/src/test/java/io/opencensus/trace/SamplersTest.java b/api/src/test/java/io/opencensus/trace/SamplersTest.java index af7fcaf5..52351f2c 100644 --- a/api/src/test/java/io/opencensus/trace/SamplersTest.java +++ b/api/src/test/java/io/opencensus/trace/SamplersTest.java @@ -15,6 +15,9 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; +import io.opencensus.trace.base.SpanId; +import io.opencensus.trace.base.TraceId; +import io.opencensus.trace.base.TraceOptions; import java.util.Collections; import java.util.Random; import org.junit.Test; diff --git a/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java b/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java index 8922f4c2..cf043d09 100644 --- a/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java +++ b/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java @@ -18,6 +18,7 @@ import static org.mockito.Matchers.same; import static org.mockito.Mockito.verify; import io.opencensus.common.NonThrowingCloseable; +import io.opencensus.trace.base.EndSpanOptions; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java b/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java index 1b8035e7..e1123768 100644 --- a/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java @@ -21,6 +21,10 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import io.opencensus.common.NonThrowingCloseable; +import io.opencensus.trace.base.EndSpanOptions; +import io.opencensus.trace.base.SpanId; +import io.opencensus.trace.base.TraceId; +import io.opencensus.trace.base.TraceOptions; import java.util.Arrays; import java.util.List; import java.util.Random; diff --git a/api/src/test/java/io/opencensus/trace/SpanContextTest.java b/api/src/test/java/io/opencensus/trace/SpanContextTest.java index c0eb5d40..eaa5bfc9 100644 --- a/api/src/test/java/io/opencensus/trace/SpanContextTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanContextTest.java @@ -16,6 +16,9 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; import com.google.common.testing.EqualsTester; +import io.opencensus.trace.base.SpanId; +import io.opencensus.trace.base.TraceId; +import io.opencensus.trace.base.TraceOptions; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; diff --git a/api/src/test/java/io/opencensus/trace/SpanDataTest.java b/api/src/test/java/io/opencensus/trace/SpanDataTest.java index 7a7f7899..ce10c35e 100644 --- a/api/src/test/java/io/opencensus/trace/SpanDataTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanDataTest.java @@ -17,11 +17,19 @@ import static com.google.common.truth.Truth.assertThat; import com.google.common.testing.EqualsTester; import io.opencensus.common.Timestamp; -import io.opencensus.trace.Link.Type; +import io.opencensus.trace.base.Link; +import io.opencensus.trace.base.Link.Type; import io.opencensus.trace.SpanData.Attributes; import io.opencensus.trace.SpanData.Links; import io.opencensus.trace.SpanData.TimedEvent; import io.opencensus.trace.SpanData.TimedEvents; +import io.opencensus.trace.base.Annotation; +import io.opencensus.trace.base.AttributeValue; +import io.opencensus.trace.base.NetworkEvent; +import io.opencensus.trace.base.SpanId; +import io.opencensus.trace.base.Status; +import io.opencensus.trace.base.TraceId; +import io.opencensus.trace.base.TraceOptions; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; diff --git a/api/src/test/java/io/opencensus/trace/SpanIdTest.java b/api/src/test/java/io/opencensus/trace/SpanIdTest.java deleted file mode 100644 index a35fddce..00000000 --- a/api/src/test/java/io/opencensus/trace/SpanIdTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import java.util.Arrays; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link SpanId}. */ -@RunWith(JUnit4.class) -public class SpanIdTest { - private static final byte[] firstBytes = new byte[] {0, 0, 0, 0, 0, 0, 0, 'a'}; - private static final byte[] secondBytes = new byte[] {(byte) 0xFF, 0, 0, 0, 0, 0, 0, 0}; - private static final SpanId first = SpanId.fromBytes(firstBytes); - private static final SpanId second = SpanId.fromBytes(secondBytes); - - @Test - public void invalidSpanId() { - assertThat(SpanId.INVALID.getBytes()).isEqualTo(new byte[8]); - } - - @Test - public void isValid() { - assertThat(SpanId.INVALID.isValid()).isFalse(); - assertThat(first.isValid()).isTrue(); - assertThat(second.isValid()).isTrue(); - } - - @Test - public void getBytes() { - assertThat(first.getBytes()).isEqualTo(firstBytes); - assertThat(second.getBytes()).isEqualTo(secondBytes); - } - - @Test - public void traceId_CompareTo() { - assertThat(first.compareTo(second)).isGreaterThan(0); - assertThat(second.compareTo(first)).isLessThan(0); - assertThat(first.compareTo(SpanId.fromBytes(firstBytes))).isEqualTo(0); - } - - @Test - public void traceId_EqualsAndHashCode() { - EqualsTester tester = new EqualsTester(); - tester.addEqualityGroup(SpanId.INVALID, SpanId.INVALID); - tester.addEqualityGroup(first, SpanId.fromBytes(Arrays.copyOf(firstBytes, firstBytes.length))); - tester.addEqualityGroup( - second, SpanId.fromBytes(Arrays.copyOf(secondBytes, secondBytes.length))); - tester.testEquals(); - } - - @Test - public void traceId_ToString() { - assertThat(SpanId.INVALID.toString()).contains("0000000000000000"); - assertThat(first.toString()).contains("0000000000000061"); - assertThat(second.toString()).contains("ff00000000000000"); - } -} diff --git a/api/src/test/java/io/opencensus/trace/SpanTest.java b/api/src/test/java/io/opencensus/trace/SpanTest.java index c8f7cb50..0ab481d9 100644 --- a/api/src/test/java/io/opencensus/trace/SpanTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanTest.java @@ -17,6 +17,14 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Matchers.same; import static org.mockito.Mockito.verify; +import io.opencensus.trace.base.Annotation; +import io.opencensus.trace.base.AttributeValue; +import io.opencensus.trace.base.EndSpanOptions; +import io.opencensus.trace.base.Link; +import io.opencensus.trace.base.NetworkEvent; +import io.opencensus.trace.base.SpanId; +import io.opencensus.trace.base.TraceId; +import io.opencensus.trace.base.TraceOptions; import java.util.EnumSet; import java.util.Map; import java.util.Random; diff --git a/api/src/test/java/io/opencensus/trace/StatusTest.java b/api/src/test/java/io/opencensus/trace/StatusTest.java deleted file mode 100644 index c66a3428..00000000 --- a/api/src/test/java/io/opencensus/trace/StatusTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link Status}. */ -@RunWith(JUnit4.class) -public class StatusTest { - @Test - public void status_Ok() { - assertThat(Status.OK.getCanonicalCode()).isEqualTo(Status.CanonicalCode.OK); - assertThat(Status.OK.getDescription()).isNull(); - assertThat(Status.OK.isOk()).isTrue(); - } - - @Test - public void createStatus_WithDescription() { - Status status = Status.UNKNOWN.withDescription("This is an error."); - assertThat(status.getCanonicalCode()).isEqualTo(Status.CanonicalCode.UNKNOWN); - assertThat(status.getDescription()).isEqualTo("This is an error."); - assertThat(status.isOk()).isFalse(); - } - - @Test - public void status_EqualsAndHashCode() { - EqualsTester tester = new EqualsTester(); - tester.addEqualityGroup(Status.OK, Status.OK.withDescription(null)); - tester.addEqualityGroup( - Status.CANCELLED.withDescription("ThisIsAnError"), - Status.CANCELLED.withDescription("ThisIsAnError")); - tester.addEqualityGroup(Status.UNKNOWN.withDescription("This is an error.")); - tester.testEquals(); - } -} diff --git a/api/src/test/java/io/opencensus/trace/TraceIdTest.java b/api/src/test/java/io/opencensus/trace/TraceIdTest.java deleted file mode 100644 index cd1b7c24..00000000 --- a/api/src/test/java/io/opencensus/trace/TraceIdTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * 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; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import java.util.Arrays; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link TraceId}. */ -@RunWith(JUnit4.class) -public class TraceIdTest { - private static final byte[] firstBytes = - new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'a'}; - private static final byte[] secondBytes = - new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'A'}; - private static final TraceId first = TraceId.fromBytes(firstBytes); - private static final TraceId second = TraceId.fromBytes(secondBytes); - - @Test - public void invalidTraceId() { - assertThat(TraceId.INVALID.getBytes()).isEqualTo(new byte[16]); - } - - @Test - public void isValid() { - assertThat(TraceId.INVALID.isValid()).isFalse(); - assertThat(first.isValid()).isTrue(); - assertThat(second.isValid()).isTrue(); - } - - @Test - public void getBytes() { - assertThat(first.getBytes()).isEqualTo(firstBytes); - assertThat(second.getBytes()).isEqualTo(secondBytes); - } - - @Test - public void traceId_CompareTo() { - assertThat(first.compareTo(second)).isGreaterThan(0); - assertThat(second.compareTo(first)).isLessThan(0); - assertThat(first.compareTo(TraceId.fromBytes(firstBytes))).isEqualTo(0); - } - - @Test - public void traceId_EqualsAndHashCode() { - EqualsTester tester = new EqualsTester(); - tester.addEqualityGroup(TraceId.INVALID, TraceId.INVALID); - tester.addEqualityGroup(first, TraceId.fromBytes(Arrays.copyOf(firstBytes, firstBytes.length))); - tester.addEqualityGroup( - second, TraceId.fromBytes(Arrays.copyOf(secondBytes, secondBytes.length))); - tester.testEquals(); - } - - @Test - public void traceId_ToString() { - assertThat(TraceId.INVALID.toString()).contains("00000000000000000000000000000000"); - assertThat(first.toString()).contains("00000000000000000000000000000061"); - assertThat(second.toString()).contains("00000000000000000000000000000041"); - } -} diff --git a/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java b/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java deleted file mode 100644 index fb240646..00000000 --- a/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link TraceOptions}. */ -@RunWith(JUnit4.class) -public class TraceOptionsTest { - private static final byte[] firstBytes = {(byte) 0xff}; - private static final byte[] secondBytes = {1}; - private static final byte[] thirdBytes = {6}; - - @Test - public void getOptions() { - assertThat(TraceOptions.DEFAULT.getOptions()).isEqualTo(0); - assertThat(TraceOptions.builder().setIsSampled().build().getOptions()).isEqualTo(1); - assertThat(TraceOptions.fromBytes(firstBytes).getOptions()).isEqualTo(-1); - assertThat(TraceOptions.fromBytes(secondBytes).getOptions()).isEqualTo(1); - assertThat(TraceOptions.fromBytes(thirdBytes).getOptions()).isEqualTo(6); - } - - @Test - public void isSampled() { - assertThat(TraceOptions.DEFAULT.isSampled()).isFalse(); - assertThat(TraceOptions.builder().setIsSampled().build().isSampled()).isTrue(); - } - - @Test - public void toFromBytes() { - assertThat(TraceOptions.fromBytes(firstBytes).getBytes()).isEqualTo(firstBytes); - assertThat(TraceOptions.fromBytes(secondBytes).getBytes()).isEqualTo(secondBytes); - assertThat(TraceOptions.fromBytes(thirdBytes).getBytes()).isEqualTo(thirdBytes); - } - - @Test - public void builder_FromOptions() { - assertThat( - TraceOptions.builder(TraceOptions.fromBytes(thirdBytes)) - .setIsSampled() - .build() - .getOptions()) - .isEqualTo(6 | 1); - } - - @Test - public void traceOptions_EqualsAndHashCode() { - EqualsTester tester = new EqualsTester(); - tester.addEqualityGroup(TraceOptions.DEFAULT); - tester.addEqualityGroup( - TraceOptions.fromBytes(secondBytes), TraceOptions.builder().setIsSampled().build()); - tester.addEqualityGroup(TraceOptions.fromBytes(firstBytes)); - tester.testEquals(); - } - - @Test - public void traceOptions_ToString() { - assertThat(TraceOptions.DEFAULT.toString()).contains("sampled=false"); - assertThat(TraceOptions.builder().setIsSampled().build().toString()).contains("sampled=true"); - } -} diff --git a/api/src/test/java/io/opencensus/trace/TracerTest.java b/api/src/test/java/io/opencensus/trace/TracerTest.java index 80e16baf..ad98483b 100644 --- a/api/src/test/java/io/opencensus/trace/TracerTest.java +++ b/api/src/test/java/io/opencensus/trace/TracerTest.java @@ -22,6 +22,10 @@ import static org.mockito.Mockito.when; import io.grpc.Context; import io.opencensus.common.NonThrowingCloseable; +import io.opencensus.trace.base.EndSpanOptions; +import io.opencensus.trace.base.SpanId; +import io.opencensus.trace.base.TraceId; +import io.opencensus.trace.base.TraceOptions; import java.util.Random; import org.junit.Before; import org.junit.Rule; diff --git a/api/src/test/java/io/opencensus/trace/base/AnnotationTest.java b/api/src/test/java/io/opencensus/trace/base/AnnotationTest.java new file mode 100644 index 00000000..c6e0c2ce --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/base/AnnotationTest.java @@ -0,0 +1,99 @@ +/* + * Copyright 2017, Google Inc. + * 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.base; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Link}. */ +@RunWith(JUnit4.class) +public class AnnotationTest { + @Test(expected = NullPointerException.class) + public void fromDescription_NullDescription() { + Annotation.fromDescription(null); + } + + @Test + public void fromDescription() { + Annotation annotation = Annotation.fromDescription("MyAnnotationText"); + assertThat(annotation.getDescription()).isEqualTo("MyAnnotationText"); + assertThat(annotation.getAttributes().size()).isEqualTo(0); + } + + @Test(expected = NullPointerException.class) + public void fromDescriptionAndAttributes_NullDescription() { + Annotation.fromDescriptionAndAttributes(null, Collections.emptyMap()); + } + + @Test(expected = NullPointerException.class) + public void fromDescriptionAndAttributes_NullAttributes() { + Annotation.fromDescriptionAndAttributes("", null); + } + + @Test + public void fromDescriptionAndAttributes() { + Map attributes = new HashMap(); + attributes.put( + "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); + Annotation annotation = Annotation.fromDescriptionAndAttributes("MyAnnotationText", attributes); + assertThat(annotation.getDescription()).isEqualTo("MyAnnotationText"); + assertThat(annotation.getAttributes()).isEqualTo(attributes); + } + + @Test + public void fromDescriptionAndAttributes_EmptyAttributes() { + Annotation annotation = + Annotation.fromDescriptionAndAttributes( + "MyAnnotationText", Collections.emptyMap()); + assertThat(annotation.getDescription()).isEqualTo("MyAnnotationText"); + assertThat(annotation.getAttributes().size()).isEqualTo(0); + } + + @Test + public void annotation_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + Map attributes = new HashMap(); + attributes.put( + "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); + tester + .addEqualityGroup( + Annotation.fromDescription("MyAnnotationText"), + Annotation.fromDescriptionAndAttributes( + "MyAnnotationText", Collections.emptyMap())) + .addEqualityGroup( + Annotation.fromDescriptionAndAttributes("MyAnnotationText", attributes), + Annotation.fromDescriptionAndAttributes("MyAnnotationText", attributes)) + .addEqualityGroup(Annotation.fromDescription("MyAnnotationText2")); + tester.testEquals(); + } + + @Test + public void annotation_ToString() { + Annotation annotation = Annotation.fromDescription("MyAnnotationText"); + assertThat(annotation.toString()).contains("MyAnnotationText"); + Map attributes = new HashMap(); + attributes.put( + "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); + annotation = Annotation.fromDescriptionAndAttributes("MyAnnotationText2", attributes); + assertThat(annotation.toString()).contains("MyAnnotationText2"); + assertThat(annotation.toString()).contains(attributes.toString()); + } +} diff --git a/api/src/test/java/io/opencensus/trace/base/AttributeValueTest.java b/api/src/test/java/io/opencensus/trace/base/AttributeValueTest.java new file mode 100644 index 00000000..43f85aa4 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/base/AttributeValueTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017, Google Inc. + * 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.base; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link AttributeValue}. */ +@RunWith(JUnit4.class) +public class AttributeValueTest { + @Test + public void stringAttributeValue() { + AttributeValue attribute = AttributeValue.stringAttributeValue("MyStringAttributeValue"); + assertThat(attribute.getStringValue()).isEqualTo("MyStringAttributeValue"); + assertThat(attribute.getBooleanValue()).isNull(); + assertThat(attribute.getLongValue()).isNull(); + } + + @Test + public void booleanAttributeValue() { + AttributeValue attribute = AttributeValue.booleanAttributeValue(true); + assertThat(attribute.getStringValue()).isNull(); + assertThat(attribute.getBooleanValue()).isTrue(); + assertThat(attribute.getLongValue()).isNull(); + } + + @Test + public void longAttributeValue() { + AttributeValue attribute = AttributeValue.longAttributeValue(123456L); + assertThat(attribute.getStringValue()).isNull(); + assertThat(attribute.getBooleanValue()).isNull(); + assertThat(attribute.getLongValue()).isEqualTo(123456L); + } + + @Test + public void attributeValue_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup( + AttributeValue.stringAttributeValue("MyStringAttributeValue"), + AttributeValue.stringAttributeValue("MyStringAttributeValue")); + tester.addEqualityGroup(AttributeValue.stringAttributeValue("MyStringAttributeDiffValue")); + tester.addEqualityGroup( + AttributeValue.booleanAttributeValue(true), AttributeValue.booleanAttributeValue(true)); + tester.addEqualityGroup(AttributeValue.booleanAttributeValue(false)); + tester.addEqualityGroup( + AttributeValue.longAttributeValue(123456L), AttributeValue.longAttributeValue(123456L)); + tester.addEqualityGroup(AttributeValue.longAttributeValue(1234567L)); + tester.testEquals(); + } + + @Test + public void attributeValue_ToString() { + AttributeValue attribute = AttributeValue.stringAttributeValue("MyStringAttributeValue"); + assertThat(attribute.toString()).contains("MyStringAttributeValue"); + attribute = AttributeValue.booleanAttributeValue(true); + assertThat(attribute.toString()).contains("true"); + attribute = AttributeValue.longAttributeValue(123456L); + assertThat(attribute.toString()).contains("123456"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/base/EndSpanOptionsTest.java b/api/src/test/java/io/opencensus/trace/base/EndSpanOptionsTest.java new file mode 100644 index 00000000..87ff8df8 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/base/EndSpanOptionsTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 2017, Google Inc. + * 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.base; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link EndSpanOptions}. */ +@RunWith(JUnit4.class) +public class EndSpanOptionsTest { + @Test(expected = NullPointerException.class) + public void setNullStatus() { + EndSpanOptions.builder().setStatus(null).build(); + } + + @Test + public void endSpanOptions_DefaultOptions() { + assertThat(EndSpanOptions.DEFAULT.getStatus()).isEqualTo(Status.OK); + } + + @Test + public void setStatus() { + EndSpanOptions endSpanOptions = + EndSpanOptions.builder() + .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) + .build(); + assertThat(endSpanOptions.getStatus()) + .isEqualTo(Status.CANCELLED.withDescription("ThisIsAnError")); + } + + @Test + public void endSpanOptions_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup( + EndSpanOptions.builder() + .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) + .build(), + EndSpanOptions.builder() + .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) + .build()); + tester.addEqualityGroup(EndSpanOptions.builder().build(), EndSpanOptions.DEFAULT); + tester.testEquals(); + } + + @Test + public void endSpanOptions_ToString() { + EndSpanOptions endSpanOptions = + EndSpanOptions.builder() + .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) + .build(); + assertThat(endSpanOptions.toString()).contains("ThisIsAnError"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/base/LinkTest.java b/api/src/test/java/io/opencensus/trace/base/LinkTest.java new file mode 100644 index 00000000..4fafa02a --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/base/LinkTest.java @@ -0,0 +1,76 @@ +/* + * Copyright 2017, Google Inc. + * 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.base; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.trace.SpanContext; +import io.opencensus.trace.base.Link.Type; +import java.util.Random; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Link}. */ +@RunWith(JUnit4.class) +public class LinkTest { + private final Random random = new Random(1234); + private final SpanContext spanContext = + SpanContext.create( + TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); + + @Test + public void fromSpanContext_ChildLink() { + Link link = Link.fromSpanContext(spanContext, Type.CHILD); + assertThat(link.getTraceId()).isEqualTo(spanContext.getTraceId()); + assertThat(link.getSpanId()).isEqualTo(spanContext.getSpanId()); + assertThat(link.getType()).isEqualTo(Type.CHILD); + } + + @Test + public void fromSpanContext_ParentLink() { + Link link = Link.fromSpanContext(spanContext, Type.PARENT); + assertThat(link.getTraceId()).isEqualTo(spanContext.getTraceId()); + assertThat(link.getSpanId()).isEqualTo(spanContext.getSpanId()); + assertThat(link.getType()).isEqualTo(Type.PARENT); + } + + @Test + public void link_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester + .addEqualityGroup( + Link.fromSpanContext(spanContext, Type.PARENT), + Link.fromSpanContext(spanContext, Type.PARENT)) + .addEqualityGroup( + Link.fromSpanContext(spanContext, Type.CHILD), + Link.fromSpanContext(spanContext, Type.CHILD)) + .addEqualityGroup(Link.fromSpanContext(SpanContext.INVALID, Type.CHILD)) + .addEqualityGroup(Link.fromSpanContext(SpanContext.INVALID, Type.PARENT)); + tester.testEquals(); + } + + @Test + public void link_ToString() { + Link link = Link.fromSpanContext(spanContext, Type.CHILD); + assertThat(link.toString()).contains(spanContext.getTraceId().toString()); + assertThat(link.toString()).contains(spanContext.getSpanId().toString()); + assertThat(link.toString()).contains("CHILD"); + link = Link.fromSpanContext(spanContext, Type.PARENT); + assertThat(link.toString()).contains(spanContext.getTraceId().toString()); + assertThat(link.toString()).contains(spanContext.getSpanId().toString()); + assertThat(link.toString()).contains("PARENT"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/base/NetworkEventTest.java b/api/src/test/java/io/opencensus/trace/base/NetworkEventTest.java new file mode 100644 index 00000000..09d796ee --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/base/NetworkEventTest.java @@ -0,0 +1,87 @@ +/* + * Copyright 2017, Google Inc. + * 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.base; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.common.Timestamp; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link NetworkEvent}. */ +@RunWith(JUnit4.class) +public class NetworkEventTest { + @Test(expected = NullPointerException.class) + public void buildNetworkEvent_NullType() { + NetworkEvent.builder(null, 1L).build(); + } + + @Test + public void buildNetworkEvent_WithRequiredFields() { + NetworkEvent networkEvent = NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).build(); + assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); + assertThat(networkEvent.getMessageId()).isEqualTo(1L); + assertThat(networkEvent.getKernelTimestamp()).isNull(); + assertThat(networkEvent.getMessageSize()).isEqualTo(0L); + } + + @Test + public void buildNetworkEvent_WithTimestamp() { + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.SENT, 1L) + .setKernelTimestamp(Timestamp.fromMillis(123456L)) + .build(); + assertThat(networkEvent.getKernelTimestamp()).isEqualTo(Timestamp.fromMillis(123456L)); + assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); + assertThat(networkEvent.getMessageId()).isEqualTo(1L); + assertThat(networkEvent.getMessageSize()).isEqualTo(0L); + } + + @Test + public void buildNetworkEvent_WithMessageSize() { + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).setMessageSize(123L).build(); + assertThat(networkEvent.getKernelTimestamp()).isNull(); + assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); + assertThat(networkEvent.getMessageId()).isEqualTo(1L); + assertThat(networkEvent.getMessageSize()).isEqualTo(123L); + } + + @Test + public void buildNetworkEvent_WithAllValues() { + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.RECV, 1L) + .setKernelTimestamp(Timestamp.fromMillis(123456L)) + .setMessageSize(123L) + .build(); + assertThat(networkEvent.getKernelTimestamp()).isEqualTo(Timestamp.fromMillis(123456L)); + assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.RECV); + assertThat(networkEvent.getMessageId()).isEqualTo(1L); + assertThat(networkEvent.getMessageSize()).isEqualTo(123L); + } + + @Test + public void networkEvent_ToString() { + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.SENT, 1L) + .setKernelTimestamp(Timestamp.fromMillis(123456L)) + .setMessageSize(123L) + .build(); + assertThat(networkEvent.toString()).contains(Timestamp.fromMillis(123456L).toString()); + assertThat(networkEvent.toString()).contains("type=SENT"); + assertThat(networkEvent.toString()).contains("messageId=1"); + assertThat(networkEvent.toString()).contains("messageSize=123"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/base/SpanIdTest.java b/api/src/test/java/io/opencensus/trace/base/SpanIdTest.java new file mode 100644 index 00000000..6db2dc81 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/base/SpanIdTest.java @@ -0,0 +1,73 @@ +/* + * Copyright 2017, Google Inc. + * 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.base; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import java.util.Arrays; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link SpanId}. */ +@RunWith(JUnit4.class) +public class SpanIdTest { + private static final byte[] firstBytes = new byte[] {0, 0, 0, 0, 0, 0, 0, 'a'}; + private static final byte[] secondBytes = new byte[] {(byte) 0xFF, 0, 0, 0, 0, 0, 0, 0}; + private static final SpanId first = SpanId.fromBytes(firstBytes); + private static final SpanId second = SpanId.fromBytes(secondBytes); + + @Test + public void invalidSpanId() { + assertThat(SpanId.INVALID.getBytes()).isEqualTo(new byte[8]); + } + + @Test + public void isValid() { + assertThat(SpanId.INVALID.isValid()).isFalse(); + assertThat(first.isValid()).isTrue(); + assertThat(second.isValid()).isTrue(); + } + + @Test + public void getBytes() { + assertThat(first.getBytes()).isEqualTo(firstBytes); + assertThat(second.getBytes()).isEqualTo(secondBytes); + } + + @Test + public void traceId_CompareTo() { + assertThat(first.compareTo(second)).isGreaterThan(0); + assertThat(second.compareTo(first)).isLessThan(0); + assertThat(first.compareTo(SpanId.fromBytes(firstBytes))).isEqualTo(0); + } + + @Test + public void traceId_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup(SpanId.INVALID, SpanId.INVALID); + tester.addEqualityGroup(first, SpanId.fromBytes(Arrays.copyOf(firstBytes, firstBytes.length))); + tester.addEqualityGroup( + second, SpanId.fromBytes(Arrays.copyOf(secondBytes, secondBytes.length))); + tester.testEquals(); + } + + @Test + public void traceId_ToString() { + assertThat(SpanId.INVALID.toString()).contains("0000000000000000"); + assertThat(first.toString()).contains("0000000000000061"); + assertThat(second.toString()).contains("ff00000000000000"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/base/StatusTest.java b/api/src/test/java/io/opencensus/trace/base/StatusTest.java new file mode 100644 index 00000000..b8c2e19b --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/base/StatusTest.java @@ -0,0 +1,51 @@ +/* + * Copyright 2017, Google Inc. + * 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.base; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Status}. */ +@RunWith(JUnit4.class) +public class StatusTest { + @Test + public void status_Ok() { + assertThat(Status.OK.getCanonicalCode()).isEqualTo(Status.CanonicalCode.OK); + assertThat(Status.OK.getDescription()).isNull(); + assertThat(Status.OK.isOk()).isTrue(); + } + + @Test + public void createStatus_WithDescription() { + Status status = Status.UNKNOWN.withDescription("This is an error."); + assertThat(status.getCanonicalCode()).isEqualTo(Status.CanonicalCode.UNKNOWN); + assertThat(status.getDescription()).isEqualTo("This is an error."); + assertThat(status.isOk()).isFalse(); + } + + @Test + public void status_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup(Status.OK, Status.OK.withDescription(null)); + tester.addEqualityGroup( + Status.CANCELLED.withDescription("ThisIsAnError"), + Status.CANCELLED.withDescription("ThisIsAnError")); + tester.addEqualityGroup(Status.UNKNOWN.withDescription("This is an error.")); + tester.testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/trace/base/TraceIdTest.java b/api/src/test/java/io/opencensus/trace/base/TraceIdTest.java new file mode 100644 index 00000000..dd87d40d --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/base/TraceIdTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 2016, Google Inc. + * 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.base; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import java.util.Arrays; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TraceId}. */ +@RunWith(JUnit4.class) +public class TraceIdTest { + private static final byte[] firstBytes = + new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'a'}; + private static final byte[] secondBytes = + new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'A'}; + private static final TraceId first = TraceId.fromBytes(firstBytes); + private static final TraceId second = TraceId.fromBytes(secondBytes); + + @Test + public void invalidTraceId() { + assertThat(TraceId.INVALID.getBytes()).isEqualTo(new byte[16]); + } + + @Test + public void isValid() { + assertThat(TraceId.INVALID.isValid()).isFalse(); + assertThat(first.isValid()).isTrue(); + assertThat(second.isValid()).isTrue(); + } + + @Test + public void getBytes() { + assertThat(first.getBytes()).isEqualTo(firstBytes); + assertThat(second.getBytes()).isEqualTo(secondBytes); + } + + @Test + public void traceId_CompareTo() { + assertThat(first.compareTo(second)).isGreaterThan(0); + assertThat(second.compareTo(first)).isLessThan(0); + assertThat(first.compareTo(TraceId.fromBytes(firstBytes))).isEqualTo(0); + } + + @Test + public void traceId_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup(TraceId.INVALID, TraceId.INVALID); + tester.addEqualityGroup(first, TraceId.fromBytes(Arrays.copyOf(firstBytes, firstBytes.length))); + tester.addEqualityGroup( + second, TraceId.fromBytes(Arrays.copyOf(secondBytes, secondBytes.length))); + tester.testEquals(); + } + + @Test + public void traceId_ToString() { + assertThat(TraceId.INVALID.toString()).contains("00000000000000000000000000000000"); + assertThat(first.toString()).contains("00000000000000000000000000000061"); + assertThat(second.toString()).contains("00000000000000000000000000000041"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/base/TraceOptionsTest.java b/api/src/test/java/io/opencensus/trace/base/TraceOptionsTest.java new file mode 100644 index 00000000..0d247347 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/base/TraceOptionsTest.java @@ -0,0 +1,77 @@ +/* + * Copyright 2017, Google Inc. + * 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.base; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TraceOptions}. */ +@RunWith(JUnit4.class) +public class TraceOptionsTest { + private static final byte[] firstBytes = {(byte) 0xff}; + private static final byte[] secondBytes = {1}; + private static final byte[] thirdBytes = {6}; + + @Test + public void getOptions() { + assertThat(TraceOptions.DEFAULT.getOptions()).isEqualTo(0); + assertThat(TraceOptions.builder().setIsSampled().build().getOptions()).isEqualTo(1); + assertThat(TraceOptions.fromBytes(firstBytes).getOptions()).isEqualTo(-1); + assertThat(TraceOptions.fromBytes(secondBytes).getOptions()).isEqualTo(1); + assertThat(TraceOptions.fromBytes(thirdBytes).getOptions()).isEqualTo(6); + } + + @Test + public void isSampled() { + assertThat(TraceOptions.DEFAULT.isSampled()).isFalse(); + assertThat(TraceOptions.builder().setIsSampled().build().isSampled()).isTrue(); + } + + @Test + public void toFromBytes() { + assertThat(TraceOptions.fromBytes(firstBytes).getBytes()).isEqualTo(firstBytes); + assertThat(TraceOptions.fromBytes(secondBytes).getBytes()).isEqualTo(secondBytes); + assertThat(TraceOptions.fromBytes(thirdBytes).getBytes()).isEqualTo(thirdBytes); + } + + @Test + public void builder_FromOptions() { + assertThat( + TraceOptions.builder(TraceOptions.fromBytes(thirdBytes)) + .setIsSampled() + .build() + .getOptions()) + .isEqualTo(6 | 1); + } + + @Test + public void traceOptions_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup(TraceOptions.DEFAULT); + tester.addEqualityGroup( + TraceOptions.fromBytes(secondBytes), TraceOptions.builder().setIsSampled().build()); + tester.addEqualityGroup(TraceOptions.fromBytes(firstBytes)); + tester.testEquals(); + } + + @Test + public void traceOptions_ToString() { + assertThat(TraceOptions.DEFAULT.toString()).contains("sampled=false"); + assertThat(TraceOptions.builder().setIsSampled().build().toString()).contains("sampled=true"); + } +} -- cgit v1.2.3 From 7331a983599bddccc87dd1545301edff795322b2 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Thu, 8 Jun 2017 17:33:01 -0700 Subject: Create a new package for all supported propagations. (#341) --- .../opencensus/trace/BinaryPropagationHandler.java | 108 --------------------- .../java/io/opencensus/trace/TraceComponent.java | 17 ++-- api/src/main/java/io/opencensus/trace/Tracing.java | 11 ++- .../opencensus/trace/propagation/BinaryFormat.java | 107 ++++++++++++++++++++ .../trace/propagation/PropagationComponent.java | 47 +++++++++ .../trace/BinaryPropagationHandlerTest.java | 49 ---------- .../io/opencensus/trace/TraceComponentTest.java | 7 +- .../test/java/io/opencensus/trace/TracingTest.java | 5 +- .../trace/propagation/BinaryFormatTest.java | 49 ++++++++++ .../propagation/PropagationComponentTest.java | 33 +++++++ 10 files changed, 258 insertions(+), 175 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/trace/BinaryPropagationHandler.java create mode 100644 api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java create mode 100644 api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java delete mode 100644 api/src/test/java/io/opencensus/trace/BinaryPropagationHandlerTest.java create mode 100644 api/src/test/java/io/opencensus/trace/propagation/BinaryFormatTest.java create mode 100644 api/src/test/java/io/opencensus/trace/propagation/PropagationComponentTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/BinaryPropagationHandler.java b/api/src/main/java/io/opencensus/trace/BinaryPropagationHandler.java deleted file mode 100644 index bc86dd7f..00000000 --- a/api/src/main/java/io/opencensus/trace/BinaryPropagationHandler.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.base.Preconditions.checkNotNull; - -import java.text.ParseException; - -/** - * This is a helper class for {@link SpanContext} propagation on the wire using binary encoding. - * - *

Example of usage on the client: - * - *

{@code
- * private static final Tracer tracer = Tracing.getTracer();
- * private static final BinaryPropagationHandler binaryPropagationHandler =
- *     Tracing.getBinaryPropagationHandler();
- * void onSendRequest() {
- *   try (NonThrowingCloseable ss = tracer.spanBuilder("Sent.MyRequest").startScopedSpan()) {
- *     byte[] binaryValue = binaryPropagationHandler.toBinaryValue(
- *         tracer.getCurrentContext().context());
- *     // Send the request including the binaryValue and wait for the response.
- *   }
- * }
- * }
- * - *

Example of usage on the server: - * - *

{@code
- * private static final Tracer tracer = Tracing.getTracer();
- * private static final BinaryPropagationHandler binaryPropagationHandler =
- *     Tracing.getBinaryPropagationHandler();
- * void onRequestReceived() {
- *   // Get the binaryValue from the request.
- *   SpanContext spanContext = SpanContext.INVALID;
- *   try {
- *     if (binaryValue != null) {
- *       spanContext = binaryPropagationHandler.fromBinaryValue(binaryValue);
- *     }
- *   } catch (ParseException e) {
- *     // Maybe log the exception.
- *   }
- *   try (NonThrowingCloseable ss =
- *            tracer.spanBuilderWithRemoteParent(spanContext, "Recv.MyRequest").startScopedSpan()) {
- *     // Handle request and send response back.
- *   }
- * }
- * }
- */ -public abstract class BinaryPropagationHandler { - static final NoopBinaryPropagationHandler noopBinaryPropagationHandler = - new NoopBinaryPropagationHandler(); - - /** - * Serializes a {@link SpanContext} using the binary format. - * - * @param spanContext the {@code SpanContext} to serialize. - * @return the serialized binary value. - * @throws NullPointerException if the {@code spanContext} is {@code null}. - */ - public abstract byte[] toBinaryValue(SpanContext spanContext); - - /** - * Parses the {@link SpanContext} from the binary format. - * - * @param bytes a binary encoded buffer from which the {@code SpanContext} will be parsed. - * @return the parsed {@code SpanContext}. - * @throws NullPointerException if the {@code input} is {@code null}. - * @throws ParseException if the version is not supported or the input is invalid - */ - public abstract SpanContext fromBinaryValue(byte[] bytes) throws ParseException; - - /** - * Returns the no-op implementation of the {@code BinaryPropagationHandler}. - * - * @return the no-op implementation of the {@code BinaryPropagationHandler}. - */ - static BinaryPropagationHandler getNoopBinaryPropagationHandler() { - return noopBinaryPropagationHandler; - } - - private static final class NoopBinaryPropagationHandler extends BinaryPropagationHandler { - @Override - public byte[] toBinaryValue(SpanContext spanContext) { - checkNotNull(spanContext, "spanContext"); - return new byte[0]; - } - - @Override - public SpanContext fromBinaryValue(byte[] bytes) throws ParseException { - checkNotNull(bytes, "bytes"); - return SpanContext.INVALID; - } - - private NoopBinaryPropagationHandler() {} - } -} diff --git a/api/src/main/java/io/opencensus/trace/TraceComponent.java b/api/src/main/java/io/opencensus/trace/TraceComponent.java index 54c2c8a1..276999cc 100644 --- a/api/src/main/java/io/opencensus/trace/TraceComponent.java +++ b/api/src/main/java/io/opencensus/trace/TraceComponent.java @@ -17,10 +17,11 @@ import io.opencensus.common.Clock; import io.opencensus.internal.ZeroTimeClock; import io.opencensus.trace.config.TraceConfig; import io.opencensus.trace.export.ExportComponent; +import io.opencensus.trace.propagation.PropagationComponent; /** * Class that holds the implementation instances for {@link Tracer}, {@link - * BinaryPropagationHandler}, {@link Clock}, {@link ExportComponent} and {@link TraceConfig}. + * PropagationComponent}, {@link Clock}, {@link ExportComponent} and {@link TraceConfig}. * *

Unless otherwise noted all methods (on component) results are cacheable. */ @@ -36,12 +37,12 @@ public abstract class TraceComponent { public abstract Tracer getTracer(); /** - * Returns the {@link BinaryPropagationHandler} with the provided implementations. If no + * Returns the {@link PropagationComponent} with the provided implementation. If no * implementation is provided then no-op implementation will be used. * - * @return the {@code BinaryPropagationHandler} implementation. + * @return the {@code PropagationComponent} implementation. */ - public abstract BinaryPropagationHandler getBinaryPropagationHandler(); + public abstract PropagationComponent getPropagationComponent(); /** * Returns the {@link Clock} with the provided implementation. @@ -56,7 +57,7 @@ public abstract class TraceComponent { * * @return the {@link ExportComponent} implementation. */ - public abstract ExportComponent getTraceExporter(); + public abstract ExportComponent getExportComponent(); /** * Returns the {@link TraceConfig} with the provided implementation. If no implementation is @@ -85,8 +86,8 @@ public abstract class TraceComponent { } @Override - public BinaryPropagationHandler getBinaryPropagationHandler() { - return BinaryPropagationHandler.getNoopBinaryPropagationHandler(); + public PropagationComponent getPropagationComponent() { + return PropagationComponent.getNoopPropagationComponent(); } @Override @@ -95,7 +96,7 @@ public abstract class TraceComponent { } @Override - public ExportComponent getTraceExporter() { + public ExportComponent getExportComponent() { return ExportComponent.getNoopExportComponent(); } diff --git a/api/src/main/java/io/opencensus/trace/Tracing.java b/api/src/main/java/io/opencensus/trace/Tracing.java index daf5b3c9..3a4be463 100644 --- a/api/src/main/java/io/opencensus/trace/Tracing.java +++ b/api/src/main/java/io/opencensus/trace/Tracing.java @@ -18,6 +18,7 @@ import io.opencensus.common.Clock; import io.opencensus.internal.Provider; import io.opencensus.trace.config.TraceConfig; import io.opencensus.trace.export.ExportComponent; +import io.opencensus.trace.propagation.PropagationComponent; import java.util.logging.Level; import java.util.logging.Logger; @@ -37,12 +38,12 @@ public final class Tracing { } /** - * Returns the global {@link BinaryPropagationHandler}. + * Returns the global {@link PropagationComponent}. * - * @return the global {@code BinaryPropagationHandler}. + * @return the global {@code PropagationComponent}. */ - public static BinaryPropagationHandler getBinaryPropagationHandler() { - return traceComponent.getBinaryPropagationHandler(); + public static PropagationComponent getPropagationComponent() { + return traceComponent.getPropagationComponent(); } /** @@ -60,7 +61,7 @@ public final class Tracing { * @return the global {@code ExportComponent}. */ public static ExportComponent getTraceExporter() { - return traceComponent.getTraceExporter(); + return traceComponent.getExportComponent(); } /** diff --git a/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java b/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java new file mode 100644 index 00000000..d34f69f9 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java @@ -0,0 +1,107 @@ +/* + * Copyright 2017, Google Inc. + * 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.trace.SpanContext; +import java.text.ParseException; + +/** + * This is a helper class for {@link SpanContext} propagation on the wire using binary encoding. + * + *

Example of usage on the client: + * + *

{@code
+ * private static final Tracer tracer = Tracing.getTracer();
+ * private static final BinaryFormat binaryFormat =
+ *     Tracing.getPropagationComponent().getBinaryFormat();
+ * void onSendRequest() {
+ *   try (NonThrowingCloseable ss = tracer.spanBuilder("Sent.MyRequest").startScopedSpan()) {
+ *     byte[] binaryValue = binaryFormat.toBinaryValue(tracer.getCurrentContext().context());
+ *     // Send the request including the binaryValue and wait for the response.
+ *   }
+ * }
+ * }
+ * + *

Example of usage on the server: + * + *

{@code
+ * private static final Tracer tracer = Tracing.getTracer();
+ * private static final BinaryFormat binaryFormat =
+ *     Tracing.getPropagationComponent().getBinaryFormat();
+ * void onRequestReceived() {
+ *   // Get the binaryValue from the request.
+ *   SpanContext spanContext = SpanContext.INVALID;
+ *   try {
+ *     if (binaryValue != null) {
+ *       spanContext = binaryFormat.fromBinaryValue(binaryValue);
+ *     }
+ *   } catch (ParseException e) {
+ *     // Maybe log the exception.
+ *   }
+ *   try (NonThrowingCloseable ss =
+ *            tracer.spanBuilderWithRemoteParent(spanContext, "Recv.MyRequest").startScopedSpan()) {
+ *     // Handle request and send response back.
+ *   }
+ * }
+ * }
+ */ +public abstract class BinaryFormat { + static final NoopBinaryFormat NOOP_BINARY_FORMAT = new NoopBinaryFormat(); + + /** + * Serializes a {@link SpanContext} using the binary format. + * + * @param spanContext the {@code SpanContext} to serialize. + * @return the serialized binary value. + * @throws NullPointerException if the {@code spanContext} is {@code null}. + */ + public abstract byte[] toBinaryValue(SpanContext spanContext); + + /** + * Parses the {@link SpanContext} from the binary format. + * + * @param bytes a binary encoded buffer from which the {@code SpanContext} will be parsed. + * @return the parsed {@code SpanContext}. + * @throws NullPointerException if the {@code input} is {@code null}. + * @throws ParseException if the version is not supported or the input is invalid + */ + public abstract SpanContext fromBinaryValue(byte[] bytes) throws ParseException; + + /** + * Returns the no-op implementation of the {@code BinaryFormat}. + * + * @return the no-op implementation of the {@code BinaryFormat}. + */ + static BinaryFormat getNoopBinaryFormat() { + return NOOP_BINARY_FORMAT; + } + + private static final class NoopBinaryFormat extends BinaryFormat { + @Override + public byte[] toBinaryValue(SpanContext spanContext) { + checkNotNull(spanContext, "spanContext"); + return new byte[0]; + } + + @Override + public SpanContext fromBinaryValue(byte[] bytes) throws ParseException { + checkNotNull(bytes, "bytes"); + return SpanContext.INVALID; + } + + private NoopBinaryFormat() {} + } +} diff --git a/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java b/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java new file mode 100644 index 00000000..382333e3 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java @@ -0,0 +1,47 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +/** + * Container class for all the supported propagation formats. Currently supports only Binary + * format see {@link BinaryFormat} but more formats will be added. + */ +public abstract class PropagationComponent { + private static final PropagationComponent NOOP_PROPAGATION_COMPONENT = + new NoopPropagationComponent(); + + /** + * Returns the {@link BinaryFormat} with the provided implementations. If no implementation + * is provided then no-op implementation will be used. + * + * @return the {@code BinaryFormat} implementation. + */ + public abstract BinaryFormat getBinaryFormat(); + + /** + * Returns an instance that contains no-op implementations for all the instances. + * + * @return an instance that contains no-op implementations for all the instances. + */ + public static PropagationComponent getNoopPropagationComponent() { + return NOOP_PROPAGATION_COMPONENT; + } + + private static final class NoopPropagationComponent extends PropagationComponent { + @Override + public BinaryFormat getBinaryFormat() { + return BinaryFormat.getNoopBinaryFormat(); + } + } +} diff --git a/api/src/test/java/io/opencensus/trace/BinaryPropagationHandlerTest.java b/api/src/test/java/io/opencensus/trace/BinaryPropagationHandlerTest.java deleted file mode 100644 index d75effb6..00000000 --- a/api/src/test/java/io/opencensus/trace/BinaryPropagationHandlerTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.truth.Truth.assertThat; - -import java.text.ParseException; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link BinaryPropagationHandler}. */ -@RunWith(JUnit4.class) -public class BinaryPropagationHandlerTest { - private static final BinaryPropagationHandler binaryPropagationHandler = - BinaryPropagationHandler.getNoopBinaryPropagationHandler(); - - @Test(expected = NullPointerException.class) - public void toBinaryValue_NullSpanContext() { - binaryPropagationHandler.toBinaryValue(null); - } - - @Test - public void toBinaryValue_NotNullSpanContext() { - assertThat(binaryPropagationHandler.toBinaryValue(SpanContext.INVALID)).isEqualTo(new byte[0]); - } - - @Test(expected = NullPointerException.class) - public void fromBinaryValue_NullInput() throws ParseException { - binaryPropagationHandler.fromBinaryValue(null); - } - - @Test - public void fromBinaryValue_NotNullInput() throws ParseException { - assertThat(binaryPropagationHandler.fromBinaryValue(new byte[0])) - .isEqualTo(SpanContext.INVALID); - } -} diff --git a/api/src/test/java/io/opencensus/trace/TraceComponentTest.java b/api/src/test/java/io/opencensus/trace/TraceComponentTest.java index 4a0c3594..238a8420 100644 --- a/api/src/test/java/io/opencensus/trace/TraceComponentTest.java +++ b/api/src/test/java/io/opencensus/trace/TraceComponentTest.java @@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat; import io.opencensus.internal.ZeroTimeClock; import io.opencensus.trace.config.TraceConfig; import io.opencensus.trace.export.ExportComponent; +import io.opencensus.trace.propagation.PropagationComponent; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -32,8 +33,8 @@ public class TraceComponentTest { @Test public void defaultBinaryPropagationHandler() { - assertThat(TraceComponent.getNoopTraceComponent().getBinaryPropagationHandler()) - .isSameAs(BinaryPropagationHandler.getNoopBinaryPropagationHandler()); + assertThat(TraceComponent.getNoopTraceComponent().getPropagationComponent()) + .isSameAs(PropagationComponent.getNoopPropagationComponent()); } @Test @@ -43,7 +44,7 @@ public class TraceComponentTest { @Test public void defaultTraceExporter() { - assertThat(TraceComponent.getNoopTraceComponent().getTraceExporter()) + assertThat(TraceComponent.getNoopTraceComponent().getExportComponent()) .isSameAs(ExportComponent.getNoopExportComponent()); } diff --git a/api/src/test/java/io/opencensus/trace/TracingTest.java b/api/src/test/java/io/opencensus/trace/TracingTest.java index 0076cc77..33303896 100644 --- a/api/src/test/java/io/opencensus/trace/TracingTest.java +++ b/api/src/test/java/io/opencensus/trace/TracingTest.java @@ -17,6 +17,7 @@ import static com.google.common.truth.Truth.assertThat; import io.opencensus.trace.config.TraceConfig; import io.opencensus.trace.export.ExportComponent; +import io.opencensus.trace.propagation.PropagationComponent; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -64,8 +65,8 @@ public class TracingTest { @Test public void defaultBinaryPropagationHandler() { - assertThat(Tracing.getBinaryPropagationHandler()) - .isSameAs(BinaryPropagationHandler.getNoopBinaryPropagationHandler()); + assertThat(Tracing.getPropagationComponent()) + .isSameAs(PropagationComponent.getNoopPropagationComponent()); } @Test diff --git a/api/src/test/java/io/opencensus/trace/propagation/BinaryFormatTest.java b/api/src/test/java/io/opencensus/trace/propagation/BinaryFormatTest.java new file mode 100644 index 00000000..b5994ba0 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/propagation/BinaryFormatTest.java @@ -0,0 +1,49 @@ +/* + * Copyright 2017, Google Inc. + * 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 java.text.ParseException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link BinaryFormat}. */ +@RunWith(JUnit4.class) +public class BinaryFormatTest { + private static final BinaryFormat binaryFormat = + BinaryFormat.getNoopBinaryFormat(); + + @Test(expected = NullPointerException.class) + public void toBinaryValue_NullSpanContext() { + binaryFormat.toBinaryValue(null); + } + + @Test + public void toBinaryValue_NotNullSpanContext() { + assertThat(binaryFormat.toBinaryValue(SpanContext.INVALID)).isEqualTo(new byte[0]); + } + + @Test(expected = NullPointerException.class) + public void fromBinaryValue_NullInput() throws ParseException { + binaryFormat.fromBinaryValue(null); + } + + @Test + public void fromBinaryValue_NotNullInput() throws ParseException { + assertThat(binaryFormat.fromBinaryValue(new byte[0])).isEqualTo(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 new file mode 100644 index 00000000..24baee69 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/propagation/PropagationComponentTest.java @@ -0,0 +1,33 @@ +/* + * Copyright 2017, Google Inc. + * 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 org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link PropagationComponent}. */ +@RunWith(JUnit4.class) +public class PropagationComponentTest { + private final PropagationComponent propagationComponent = + PropagationComponent.getNoopPropagationComponent(); + + @Test + public void implementationOfBinary() { + assertThat(propagationComponent.getBinaryFormat()) + .isEqualTo(BinaryFormat.getNoopBinaryFormat()); + } +} -- cgit v1.2.3 From f27ee518014266152c87b87695964d6dfa54c7ad Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Thu, 8 Jun 2017 17:38:43 -0700 Subject: Cleanup in config package. (#346) * Remove unimplemented method from TraceConfig. * Move config implementations to config package. * Add tests for NoopTraceConfig. --- .../io/opencensus/trace/config/TraceConfig.java | 11 ---- .../java/io/opencensus/trace/TraceParamsTest.java | 77 ---------------------- .../opencensus/trace/config/TraceConfigTest.java | 47 +++++++++++++ .../opencensus/trace/config/TraceParamsTest.java | 77 ++++++++++++++++++++++ 4 files changed, 124 insertions(+), 88 deletions(-) delete mode 100644 api/src/test/java/io/opencensus/trace/TraceParamsTest.java create mode 100644 api/src/test/java/io/opencensus/trace/config/TraceConfigTest.java create mode 100644 api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/config/TraceConfig.java b/api/src/main/java/io/opencensus/trace/config/TraceConfig.java index 80f206c9..01cb6d04 100644 --- a/api/src/main/java/io/opencensus/trace/config/TraceConfig.java +++ b/api/src/main/java/io/opencensus/trace/config/TraceConfig.java @@ -34,14 +34,6 @@ public abstract class TraceConfig { */ public abstract void updateActiveTraceParams(TraceParams traceParams); - /** - * Temporary updates the active {@link TraceParams} for {@code durationNs} nanoseconds. - * - * @param traceParams the new active {@code TraceParams}. - * @param durationNs the duration for how long the new params will be active. - */ - public abstract void temporaryUpdateActiveTraceParams(TraceParams traceParams, long durationNs); - /** * Returns the no-op implementation of the {@code TraceConfig}. * @@ -60,8 +52,5 @@ public abstract class TraceConfig { @Override public void updateActiveTraceParams(TraceParams traceParams) {} - - @Override - public void temporaryUpdateActiveTraceParams(TraceParams traceParams, long durationNs) {} } } diff --git a/api/src/test/java/io/opencensus/trace/TraceParamsTest.java b/api/src/test/java/io/opencensus/trace/TraceParamsTest.java deleted file mode 100644 index e21485e1..00000000 --- a/api/src/test/java/io/opencensus/trace/TraceParamsTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.truth.Truth.assertThat; - -import io.opencensus.trace.config.TraceParams; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link TraceParams}. */ -@RunWith(JUnit4.class) -public class TraceParamsTest { - @Test - public void defaultTraceParams() { - assertThat(TraceParams.DEFAULT.getSampler()).isEqualTo(Samplers.probabilitySampler(1e-4)); - assertThat(TraceParams.DEFAULT.getMaxNumberOfAttributes()).isEqualTo(32); - assertThat(TraceParams.DEFAULT.getMaxNumberOfAnnotations()).isEqualTo(32); - assertThat(TraceParams.DEFAULT.getMaxNumberOfNetworkEvents()).isEqualTo(128); - assertThat(TraceParams.DEFAULT.getMaxNumberOfLinks()).isEqualTo(128); - } - - @Test(expected = NullPointerException.class) - public void updateTraceParams_NullSampler() { - TraceParams.DEFAULT.toBuilder().setSampler(null).build(); - } - - @Test(expected = IllegalArgumentException.class) - public void updateTraceParams_NonPositiveMaxNumberOfAttributes() { - TraceParams.DEFAULT.toBuilder().setMaxNumberOfAttributes(0).build(); - } - - @Test(expected = IllegalArgumentException.class) - public void updateTraceParams_NonPositiveMaxNumberOfAnnotations() { - TraceParams.DEFAULT.toBuilder().setMaxNumberOfAnnotations(0).build(); - } - - @Test(expected = IllegalArgumentException.class) - public void updateTraceParams_NonPositiveMaxNumberOfNetworkEvents() { - TraceParams.DEFAULT.toBuilder().setMaxNumberOfNetworkEvents(0).build(); - } - - @Test(expected = IllegalArgumentException.class) - public void updateTraceParams_NonPositiveMaxNumberOfLinks() { - TraceParams.DEFAULT.toBuilder().setMaxNumberOfLinks(0).build(); - } - - @Test - public void updateTraceParams_All() { - TraceParams traceParams = - TraceParams.DEFAULT - .toBuilder() - .setSampler(Samplers.alwaysSample()) - .setMaxNumberOfAttributes(8) - .setMaxNumberOfAnnotations(9) - .setMaxNumberOfNetworkEvents(10) - .setMaxNumberOfLinks(11) - .build(); - assertThat(traceParams.getSampler()).isEqualTo(Samplers.alwaysSample()); - assertThat(traceParams.getMaxNumberOfAttributes()).isEqualTo(8); - assertThat(traceParams.getMaxNumberOfAnnotations()).isEqualTo(9); - assertThat(traceParams.getMaxNumberOfNetworkEvents()).isEqualTo(10); - assertThat(traceParams.getMaxNumberOfLinks()).isEqualTo(11); - } -} diff --git a/api/src/test/java/io/opencensus/trace/config/TraceConfigTest.java b/api/src/test/java/io/opencensus/trace/config/TraceConfigTest.java new file mode 100644 index 00000000..2bf9356d --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/config/TraceConfigTest.java @@ -0,0 +1,47 @@ +/* + * Copyright 2017, Google Inc. + * 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.config; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.trace.Samplers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TraceConfig}. */ +@RunWith(JUnit4.class) +public class TraceConfigTest { + TraceConfig traceConfig = TraceConfig.getNoopTraceConfig(); + + @Test + public void activeTraceParams_NoOpImplementation() { + assertThat(traceConfig.getActiveTraceParams()).isEqualTo(TraceParams.DEFAULT); + } + + @Test + public void updateActiveTraceParams_NoOpImplementation() { + TraceParams traceParams = + TraceParams.DEFAULT + .toBuilder() + .setSampler(Samplers.alwaysSample()) + .setMaxNumberOfAttributes(8) + .setMaxNumberOfAnnotations(9) + .setMaxNumberOfNetworkEvents(10) + .setMaxNumberOfLinks(11) + .build(); + traceConfig.updateActiveTraceParams(traceParams); + assertThat(traceConfig.getActiveTraceParams()).isEqualTo(TraceParams.DEFAULT); + } +} diff --git a/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java b/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java new file mode 100644 index 00000000..76d828a9 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java @@ -0,0 +1,77 @@ +/* + * Copyright 2017, Google Inc. + * 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.config; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.trace.Samplers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TraceParams}. */ +@RunWith(JUnit4.class) +public class TraceParamsTest { + @Test + public void defaultTraceParams() { + assertThat(TraceParams.DEFAULT.getSampler()).isEqualTo(Samplers.probabilitySampler(1e-4)); + assertThat(TraceParams.DEFAULT.getMaxNumberOfAttributes()).isEqualTo(32); + assertThat(TraceParams.DEFAULT.getMaxNumberOfAnnotations()).isEqualTo(32); + assertThat(TraceParams.DEFAULT.getMaxNumberOfNetworkEvents()).isEqualTo(128); + assertThat(TraceParams.DEFAULT.getMaxNumberOfLinks()).isEqualTo(128); + } + + @Test(expected = NullPointerException.class) + public void updateTraceParams_NullSampler() { + TraceParams.DEFAULT.toBuilder().setSampler(null).build(); + } + + @Test(expected = IllegalArgumentException.class) + public void updateTraceParams_NonPositiveMaxNumberOfAttributes() { + TraceParams.DEFAULT.toBuilder().setMaxNumberOfAttributes(0).build(); + } + + @Test(expected = IllegalArgumentException.class) + public void updateTraceParams_NonPositiveMaxNumberOfAnnotations() { + TraceParams.DEFAULT.toBuilder().setMaxNumberOfAnnotations(0).build(); + } + + @Test(expected = IllegalArgumentException.class) + public void updateTraceParams_NonPositiveMaxNumberOfNetworkEvents() { + TraceParams.DEFAULT.toBuilder().setMaxNumberOfNetworkEvents(0).build(); + } + + @Test(expected = IllegalArgumentException.class) + public void updateTraceParams_NonPositiveMaxNumberOfLinks() { + TraceParams.DEFAULT.toBuilder().setMaxNumberOfLinks(0).build(); + } + + @Test + public void updateTraceParams_All() { + TraceParams traceParams = + TraceParams.DEFAULT + .toBuilder() + .setSampler(Samplers.alwaysSample()) + .setMaxNumberOfAttributes(8) + .setMaxNumberOfAnnotations(9) + .setMaxNumberOfNetworkEvents(10) + .setMaxNumberOfLinks(11) + .build(); + assertThat(traceParams.getSampler()).isEqualTo(Samplers.alwaysSample()); + assertThat(traceParams.getMaxNumberOfAttributes()).isEqualTo(8); + assertThat(traceParams.getMaxNumberOfAnnotations()).isEqualTo(9); + assertThat(traceParams.getMaxNumberOfNetworkEvents()).isEqualTo(10); + assertThat(traceParams.getMaxNumberOfLinks()).isEqualTo(11); + } +} -- cgit v1.2.3 From 453f93217f3561aeb9fc95984274bdc26751fbb7 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Fri, 9 Jun 2017 08:50:10 -0700 Subject: Temporarily move "tags" package back to "core" directory. The tags API isn't ready to be released, so it should be moved out of the "api" directory. --- api/src/main/java/io/opencensus/tags/TagKey.java | 105 --------------- api/src/main/java/io/opencensus/tags/TagMap.java | 141 --------------------- .../test/java/io/opencensus/tags/TagKeyTest.java | 75 ----------- .../test/java/io/opencensus/tags/TagMapTest.java | 114 ----------------- 4 files changed, 435 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/tags/TagKey.java delete mode 100644 api/src/main/java/io/opencensus/tags/TagMap.java delete mode 100644 api/src/test/java/io/opencensus/tags/TagKeyTest.java delete mode 100644 api/src/test/java/io/opencensus/tags/TagMapTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/tags/TagKey.java b/api/src/main/java/io/opencensus/tags/TagKey.java deleted file mode 100644 index efd3e6e9..00000000 --- a/api/src/main/java/io/opencensus/tags/TagKey.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.tags; - -import static com.google.common.base.Preconditions.checkArgument; -import static io.opencensus.tags.TagKey.TagType.TAG_BOOLEAN; -import static io.opencensus.tags.TagKey.TagType.TAG_LONG; -import static io.opencensus.tags.TagKey.TagType.TAG_STRING; - -import com.google.auto.value.AutoValue; -import io.opencensus.internal.StringUtil; -import javax.annotation.concurrent.Immutable; - -/** - * A key to a value stored in a {@link TagMap}. - * - * @param The type of value that can be paired with this {@code TagKey}. {@code TagKey}s - * can only be instantiated with types {@code String}, {@code Long}, and {@code Boolean}. - */ -@Immutable -@AutoValue -public abstract class TagKey { - /** The maximum length for a tag key name. */ - public static final int MAX_LENGTH = StringUtil.MAX_LENGTH; - - enum TagType { - TAG_STRING, - TAG_LONG, - TAG_BOOLEAN - } - - TagKey() {} - - /** - * Constructs a {@code TagKey} with the given name. - * - *

The name must meet the following requirements: - * - *

    - *
  1. It cannot be longer than {@link #MAX_LENGTH}. - *
  2. It can only contain printable ASCII characters. - *
- * - * @param name the name of the key. - * @return a {@code TagKey} with the given name. - * @throws IllegalArgumentException if the name is not valid. - */ - public static TagKey createStringKey(String name) { - checkArgument(StringUtil.isValid(name)); - return new AutoValue_TagKey(name, TAG_STRING); - } - - /** - * Constructs a {@code TagKey} with the given name. - * - *

The name must meet the following requirements: - * - *

    - *
  1. It cannot be longer than {@link #MAX_LENGTH}. - *
  2. It can only contain printable ASCII characters. - *
- * - * @param name the name of the key. - * @throws IllegalArgumentException if the name is not valid. - */ - // TODO(sebright): Make this public once we support types other than String. - static TagKey createLongKey(String name) { - checkArgument(StringUtil.isValid(name)); - return new AutoValue_TagKey(name, TAG_LONG); - } - - /** - * Constructs a {@code TagKey} with the given name. - * - *

The name must meet the following requirements: - * - *

    - *
  1. It cannot be longer than {@link #MAX_LENGTH}. - *
  2. It can only contain printable ASCII characters. - *
- * - * @param name the name of the key. - * @throws IllegalArgumentException if the name is not valid. - */ - // TODO(sebright): Make this public once we support types other than String. - static TagKey createBooleanKey(String name) { - checkArgument(StringUtil.isValid(name)); - return new AutoValue_TagKey(name, TAG_BOOLEAN); - } - - abstract String getName(); - - abstract TagType getTagType(); -} diff --git a/api/src/main/java/io/opencensus/tags/TagMap.java b/api/src/main/java/io/opencensus/tags/TagMap.java deleted file mode 100644 index 8edbda0d..00000000 --- a/api/src/main/java/io/opencensus/tags/TagMap.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.tags; - -import static com.google.common.base.Preconditions.checkArgument; - -import io.opencensus.internal.StringUtil; -import io.opencensus.tags.TagKey.TagType; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import javax.annotation.concurrent.Immutable; - -/** - * A map from keys to values that can be used to label anything that is associated with a specific - * operation. - * - *

For example, {@code TagMap}s can be used to label stats, log messages, or debugging - * information. - */ -@Immutable -public final class TagMap { - /** The maximum length for a string tag value. */ - public static final int MAX_STRING_LENGTH = StringUtil.MAX_LENGTH; - - // The types of the TagKey and value must match for each entry. - private final Map, Object> tags; - - TagMap(Map, Object> tags) { - this.tags = Collections.unmodifiableMap(new HashMap, Object>(tags)); - } - - Map, Object> getTags() { - return tags; - } - - /** - * Returns a builder based on this {@code TagMap}. - * - * @return a builder based on this {@code TagMap}. - */ - public Builder toBuilder() { - return new Builder(getTags()); - } - - /** Builder for the {@link TagMap} class. */ - public static final class Builder { - private final Map, Object> tags; - - private Builder(Map, Object> tags) { - this.tags = new HashMap, Object>(tags); - } - - Builder() { - this.tags = new HashMap, Object>(); - } - - /** - * Adds the key/value pair regardless of whether the key is present. - * - * @param key the {@code TagKey} which will be set. - * @param value the value to set for the given key. - * @return this - * @throws IllegalArgumentException if either argument is null, the key is the wrong type, or - * the value contains unprintable characters or is longer than {@link - * TagMap#MAX_STRING_LENGTH}. - */ - public Builder set(TagKey key, String value) { - checkArgument(key.getTagType() == TagType.TAG_STRING); - - // TODO(sebright): Consider adding a TagValue class to avoid validating the String every time - // it is set. - checkArgument(StringUtil.isValid(value)); - return setInternal(key, value); - } - - /** - * Adds the key/value pair regardless of whether the key is present. - * - * @param key the {@code TagKey} which will be set. - * @param value the value to set for the given key. - * @return this - * @throws IllegalArgumentException if the key is null or the key is the wrong type. - */ - // TODO(sebright): Make this public once we support types other than String. - Builder set(TagKey key, long value) { - checkArgument(key.getTagType() == TagType.TAG_LONG); - return setInternal(key, value); - } - - /** - * Adds the key/value pair regardless of whether the key is present. - * - * @param key the {@code TagKey} which will be set. - * @param value the value to set for the given key. - * @return this - * @throws IllegalArgumentException if the key is null or the key is the wrong type. - */ - // TODO(sebright): Make this public once we support types other than String. - Builder set(TagKey key, boolean value) { - checkArgument(key.getTagType() == TagType.TAG_BOOLEAN); - return setInternal(key, value); - } - - private Builder setInternal(TagKey key, TagValueT value) { - tags.put(key, value); - return this; - } - - /** - * Removes the key if it exists. - * - * @param key the {@code TagKey} which will be cleared. - * @return this - */ - public Builder clear(TagKey key) { - tags.remove(key); - return this; - } - - /** - * Creates a {@code TagMap} from this builder. - * - * @return a {@code TagMap} with the same tags as this builder. - */ - public TagMap build() { - return new TagMap(new HashMap, Object>(tags)); - } - } -} diff --git a/api/src/test/java/io/opencensus/tags/TagKeyTest.java b/api/src/test/java/io/opencensus/tags/TagKeyTest.java deleted file mode 100644 index aed02d3f..00000000 --- a/api/src/test/java/io/opencensus/tags/TagKeyTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.tags; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import io.opencensus.tags.TagKey.TagType; -import java.util.Arrays; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Tests for {@link TagKey} */ -@RunWith(JUnit4.class) -public final class TagKeyTest { - - @Rule public final ExpectedException thrown = ExpectedException.none(); - - @Test - public void testGetName() { - assertThat(TagKey.createStringKey("foo").getName()).isEqualTo("foo"); - } - - @Test - public void testGetTagType() { - assertThat(TagKey.createStringKey("key").getTagType()).isEqualTo(TagType.TAG_STRING); - assertThat(TagKey.createLongKey("key").getTagType()).isEqualTo(TagType.TAG_LONG); - assertThat(TagKey.createBooleanKey("key").getTagType()).isEqualTo(TagType.TAG_BOOLEAN); - } - - @Test - public void createString_AllowTagKeyNameWithMaxLength() { - char[] key = new char[TagKey.MAX_LENGTH]; - Arrays.fill(key, 'k'); - TagKey.createStringKey(new String(key)); - } - - @Test - public void createString_DisallowTagKeyNameOverMaxLength() { - char[] key = new char[TagKey.MAX_LENGTH + 1]; - Arrays.fill(key, 'k'); - thrown.expect(IllegalArgumentException.class); - TagKey.createStringKey(new String(key)); - } - - @Test - public void createString_DisallowUnprintableChars() { - thrown.expect(IllegalArgumentException.class); - TagKey.createStringKey("\2ab\3cd"); - } - - @Test - public void testTagKeyEquals() { - new EqualsTester() - .addEqualityGroup(TagKey.createStringKey("foo"), TagKey.createStringKey("foo")) - .addEqualityGroup(TagKey.createLongKey("foo")) - .addEqualityGroup(TagKey.createBooleanKey("foo")) - .addEqualityGroup(TagKey.createStringKey("bar")) - .testEquals(); - } -} diff --git a/api/src/test/java/io/opencensus/tags/TagMapTest.java b/api/src/test/java/io/opencensus/tags/TagMapTest.java deleted file mode 100644 index 41b3b247..00000000 --- a/api/src/test/java/io/opencensus/tags/TagMapTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.tags; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.collect.ImmutableMap; -import java.util.Arrays; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Tests for {@link TagMap}. */ -// TODO(sebright): Add more tests once the API is finalized. -@RunWith(JUnit4.class) -public class TagMapTest { - - @Rule public final ExpectedException thrown = ExpectedException.none(); - - private static final TagKey KS1 = TagKey.createStringKey("k1"); - private static final TagKey KS2 = TagKey.createStringKey("k2"); - - @Test - public void applyBuilderOperationsInOrder() { - assertThat(newBuilder().set(KS1, "v1").set(KS1, "v2").build().getTags()) - .containsExactly(KS1, "v2"); - } - - @Test - public void allowMutlipleKeysWithSameNameButDifferentTypes() { - TagKey stringKey = TagKey.createStringKey("key"); - TagKey longKey = TagKey.createLongKey("key"); - TagKey booleanKey = TagKey.createBooleanKey("key"); - assertThat( - newBuilder() - .set(stringKey, "value") - .set(longKey, 123) - .set(booleanKey, true) - .build() - .getTags()) - .containsExactly(stringKey, "value", longKey, 123L, booleanKey, true); - } - - @Test - public void testSet() { - TagMap tags = singletonTagMap(KS1, "v1"); - assertThat(tags.toBuilder().set(KS1, "v2").build().getTags()).containsExactly(KS1, "v2"); - assertThat(tags.toBuilder().set(KS2, "v2").build().getTags()) - .containsExactly(KS1, "v1", KS2, "v2"); - } - - @Test - public void testClear() { - TagMap tags = singletonTagMap(KS1, "v1"); - assertThat(tags.toBuilder().clear(KS1).build().getTags()).isEmpty(); - assertThat(tags.toBuilder().clear(KS2).build().getTags()).containsExactly(KS1, "v1"); - } - - @Test - public void allowStringTagValueWithMaxLength() { - char[] chars = new char[TagMap.MAX_STRING_LENGTH]; - Arrays.fill(chars, 'v'); - String value = new String(chars); - TagKey key = TagKey.createStringKey("K"); - newBuilder().set(key, value); - } - - @Test - public void disallowStringTagValueOverMaxLength() { - char[] chars = new char[TagMap.MAX_STRING_LENGTH + 1]; - Arrays.fill(chars, 'v'); - String value = new String(chars); - TagKey key = TagKey.createStringKey("K"); - thrown.expect(IllegalArgumentException.class); - newBuilder().set(key, value); - } - - @Test - public void disallowStringTagValueWithUnprintableChars() { - String value = "\2ab\3cd"; - TagKey key = TagKey.createStringKey("K"); - thrown.expect(IllegalArgumentException.class); - newBuilder().set(key, value); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - private final TagKey badLongKey = (TagKey) TagKey.createStringKey("Key"); - - @Test(expected = IllegalArgumentException.class) - public void disallowSettingWrongTypeOfKey() { - newBuilder().set(badLongKey, 123); - } - - private static TagMap.Builder newBuilder() { - return new TagMap.Builder(); - } - - private static TagMap singletonTagMap(TagKey key, TagValueT value) { - return new TagMap(ImmutableMap., Object>of(key, value)); - } -} -- cgit v1.2.3 From fe94d4afb9af7f13f351f0c38d794b3596bb8274 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Sat, 10 Jun 2017 13:11:39 -0700 Subject: Move SpanFactory into internal package. No need to be in the public API. (#352) --- .../main/java/io/opencensus/trace/SpanBuilder.java | 1 + .../main/java/io/opencensus/trace/SpanFactory.java | 44 -------------------- api/src/main/java/io/opencensus/trace/Tracer.java | 5 ++- .../io/opencensus/trace/internal/SpanFactory.java | 47 ++++++++++++++++++++++ .../java/io/opencensus/trace/SpanBuilderTest.java | 1 + .../test/java/io/opencensus/trace/TracerTest.java | 1 + 6 files changed, 53 insertions(+), 46 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/trace/SpanFactory.java create mode 100644 api/src/main/java/io/opencensus/trace/internal/SpanFactory.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java index ec9719fc..b3ad8a5f 100644 --- a/api/src/main/java/io/opencensus/trace/SpanBuilder.java +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -15,6 +15,7 @@ package io.opencensus.trace; import io.opencensus.common.NonThrowingCloseable; import io.opencensus.trace.base.EndSpanOptions; +import io.opencensus.trace.internal.SpanFactory; import java.util.List; import javax.annotation.Nullable; diff --git a/api/src/main/java/io/opencensus/trace/SpanFactory.java b/api/src/main/java/io/opencensus/trace/SpanFactory.java deleted file mode 100644 index aca5bd85..00000000 --- a/api/src/main/java/io/opencensus/trace/SpanFactory.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import javax.annotation.Nullable; - -/** Factory class to create and start a {@link Span}. */ -public abstract class SpanFactory { - /** - * Creates and starts a new child {@link Span} (or root if parent is {@code null}), with parent - * being the designated {@code Span} and the given options. - * - * @param parent The parent of the returned {@code Span}. - * @param name The name of the returned {@code Span}. - * @param options The options for the start of the {@code Span}. - * @return A child {@code Span} that will have the name provided. - */ - protected abstract Span startSpan(@Nullable Span parent, String name, StartSpanOptions options); - - /** - * Creates and starts a new child {@link Span} (or root if parent is {@code null}), with parent - * being the {@code Span} designated by the {@link SpanContext} and the given options. - * - *

This must be used to create a {@code Span} when the parent is on a different process. - * - * @param remoteParent The remote parent of the returned {@code Span}. - * @param name The name of the returned {@code Span}. - * @param options The options for the start of the {@code Span}. - * @return A child {@code Span} that will have the name provided. - */ - protected abstract Span startSpanWithRemoteParent( - @Nullable SpanContext remoteParent, String name, StartSpanOptions options); -} diff --git a/api/src/main/java/io/opencensus/trace/Tracer.java b/api/src/main/java/io/opencensus/trace/Tracer.java index 56c4280d..64f0ae49 100644 --- a/api/src/main/java/io/opencensus/trace/Tracer.java +++ b/api/src/main/java/io/opencensus/trace/Tracer.java @@ -16,6 +16,7 @@ package io.opencensus.trace; import static com.google.common.base.Preconditions.checkNotNull; import io.opencensus.common.NonThrowingCloseable; +import io.opencensus.trace.internal.SpanFactory; import javax.annotation.Nullable; /** @@ -210,12 +211,12 @@ public abstract class Tracer { // No-op implementation of the SpanFactory private static final class NoopSpanFactory extends SpanFactory { @Override - protected Span startSpan(@Nullable Span parent, String name, StartSpanOptions options) { + public Span startSpan(@Nullable Span parent, String name, StartSpanOptions options) { return BlankSpan.INSTANCE; } @Override - protected Span startSpanWithRemoteParent( + public Span startSpanWithRemoteParent( @Nullable SpanContext remoteParent, String name, StartSpanOptions options) { return BlankSpan.INSTANCE; } diff --git a/api/src/main/java/io/opencensus/trace/internal/SpanFactory.java b/api/src/main/java/io/opencensus/trace/internal/SpanFactory.java new file mode 100644 index 00000000..b93ec865 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/internal/SpanFactory.java @@ -0,0 +1,47 @@ +/* + * Copyright 2017, Google Inc. + * 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.internal; + +import io.opencensus.trace.Span; +import io.opencensus.trace.SpanContext; +import io.opencensus.trace.StartSpanOptions; +import javax.annotation.Nullable; + +/** Factory class to create and start a {@link Span}. */ +public abstract class SpanFactory { + /** + * Creates and starts a new child {@link Span} (or root if parent is {@code null}), with parent + * being the designated {@code Span} and the given options. + * + * @param parent The parent of the returned {@code Span}. + * @param name The name of the returned {@code Span}. + * @param options The options for the start of the {@code Span}. + * @return A child {@code Span} that will have the name provided. + */ + public abstract Span startSpan(@Nullable Span parent, String name, StartSpanOptions options); + + /** + * Creates and starts a new child {@link Span} (or root if parent is {@code null}), with parent + * being the {@code Span} designated by the {@link SpanContext} and the given options. + * + *

This must be used to create a {@code Span} when the parent is on a different process. + * + * @param remoteParent The remote parent of the returned {@code Span}. + * @param name The name of the returned {@code Span}. + * @param options The options for the start of the {@code Span}. + * @return A child {@code Span} that will have the name provided. + */ + public abstract Span startSpanWithRemoteParent( + @Nullable SpanContext remoteParent, String name, StartSpanOptions options); +} diff --git a/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java b/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java index e1123768..469fe9bb 100644 --- a/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java @@ -25,6 +25,7 @@ import io.opencensus.trace.base.EndSpanOptions; import io.opencensus.trace.base.SpanId; import io.opencensus.trace.base.TraceId; import io.opencensus.trace.base.TraceOptions; +import io.opencensus.trace.internal.SpanFactory; import java.util.Arrays; import java.util.List; import java.util.Random; diff --git a/api/src/test/java/io/opencensus/trace/TracerTest.java b/api/src/test/java/io/opencensus/trace/TracerTest.java index ad98483b..51b86b63 100644 --- a/api/src/test/java/io/opencensus/trace/TracerTest.java +++ b/api/src/test/java/io/opencensus/trace/TracerTest.java @@ -26,6 +26,7 @@ import io.opencensus.trace.base.EndSpanOptions; import io.opencensus.trace.base.SpanId; import io.opencensus.trace.base.TraceId; import io.opencensus.trace.base.TraceOptions; +import io.opencensus.trace.internal.SpanFactory; import java.util.Random; import org.junit.Before; import org.junit.Rule; -- cgit v1.2.3 From 4bc0242c17cbaa931f30ef031c312c8ee936b6e0 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Mon, 12 Jun 2017 13:17:06 -0700 Subject: Move Sampler and StartSpanOptions in base. Create a samplers package for all the Sampler implementations. (#347) --- api/src/main/java/io/opencensus/trace/Sampler.java | 43 ----- .../main/java/io/opencensus/trace/Samplers.java | 168 -------------------- api/src/main/java/io/opencensus/trace/Span.java | 1 + .../main/java/io/opencensus/trace/SpanBuilder.java | 2 + .../java/io/opencensus/trace/StartSpanOptions.java | 121 -------------- api/src/main/java/io/opencensus/trace/Tracer.java | 1 + .../java/io/opencensus/trace/base/Sampler.java | 44 ++++++ .../io/opencensus/trace/base/StartSpanOptions.java | 122 +++++++++++++++ .../io/opencensus/trace/config/TraceParams.java | 20 ++- .../io/opencensus/trace/internal/SpanFactory.java | 2 +- .../trace/samplers/AlwaysSampleSampler.java | 50 ++++++ .../trace/samplers/NeverSampleSampler.java | 50 ++++++ .../trace/samplers/ProbabilitySampler.java | 93 +++++++++++ .../io/opencensus/trace/samplers/Samplers.java | 55 +++++++ .../java/io/opencensus/trace/SamplersTest.java | 170 -------------------- .../java/io/opencensus/trace/SpanBuilderTest.java | 2 + .../io/opencensus/trace/StartSpanOptionsTest.java | 111 ------------- .../test/java/io/opencensus/trace/TracerTest.java | 1 + .../trace/base/StartSpanOptionsTest.java | 114 ++++++++++++++ .../opencensus/trace/config/TraceConfigTest.java | 2 +- .../opencensus/trace/config/TraceParamsTest.java | 2 +- .../io/opencensus/trace/samplers/SamplersTest.java | 173 +++++++++++++++++++++ 22 files changed, 720 insertions(+), 627 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/trace/Sampler.java delete mode 100644 api/src/main/java/io/opencensus/trace/Samplers.java delete mode 100644 api/src/main/java/io/opencensus/trace/StartSpanOptions.java create mode 100644 api/src/main/java/io/opencensus/trace/base/Sampler.java create mode 100644 api/src/main/java/io/opencensus/trace/base/StartSpanOptions.java create mode 100644 api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java create mode 100644 api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java create mode 100644 api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java create mode 100644 api/src/main/java/io/opencensus/trace/samplers/Samplers.java delete mode 100644 api/src/test/java/io/opencensus/trace/SamplersTest.java delete mode 100644 api/src/test/java/io/opencensus/trace/StartSpanOptionsTest.java create mode 100644 api/src/test/java/io/opencensus/trace/base/StartSpanOptionsTest.java create mode 100644 api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/Sampler.java b/api/src/main/java/io/opencensus/trace/Sampler.java deleted file mode 100644 index d231f41b..00000000 --- a/api/src/main/java/io/opencensus/trace/Sampler.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import io.opencensus.trace.base.SpanId; -import io.opencensus.trace.base.TraceId; -import java.util.List; -import javax.annotation.Nullable; - -/** Sampler is used to make decisions on {@link Span} sampling. */ -public abstract class Sampler { - /** - * Called during {@link Span} creation to make a sampling decision. - * - * @param parentContext The parent {@code Span} {@link SpanContext}. May be {@code null} if this - * is a root span. - * @param remoteParent true if the parentContext is remote. - * @param traceId The {@link TraceId} for the new {@code Span}. This will be identical to that in - * the parentContext, unless this is a root span. - * @param spanId The span ID for the new {@code Span}. - * @param name The name of the new {@code Span}. - * @param parentLinks The parentLinks associated with the new {@code Span}. - * @return {@code true} if the {@code Span} is sampled. - */ - protected abstract boolean shouldSample( - @Nullable SpanContext parentContext, - boolean remoteParent, - TraceId traceId, - SpanId spanId, - String name, - List parentLinks); -} diff --git a/api/src/main/java/io/opencensus/trace/Samplers.java b/api/src/main/java/io/opencensus/trace/Samplers.java deleted file mode 100644 index 8d7908ec..00000000 --- a/api/src/main/java/io/opencensus/trace/Samplers.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.base.Preconditions.checkArgument; - -import com.google.auto.value.AutoValue; -import io.opencensus.trace.base.SpanId; -import io.opencensus.trace.base.TraceId; -import java.util.List; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; - -/** Static class to access a set of pre-defined {@link Sampler Samplers}. */ -public final class Samplers { - private static final Sampler ALWAYS_SAMPLE = new AlwaysSampleSampler(); - private static final Sampler NEVER_SAMPLE = new NeverSampleSampler(); - - // No instance of this class. - private Samplers() {} - - /** - * Returns a {@link Sampler} that always makes a "yes" decision on {@link Span} sampling. - * - * @return a {@code Sampler} that always makes a "yes" decision on {@code Span} sampling. - */ - public static Sampler alwaysSample() { - return ALWAYS_SAMPLE; - } - - /** - * Returns a {@link Sampler} that always makes a "no" decision on {@link Span} sampling. - * - * @return a {@code Sampler} that always makes a "no" decision on {@code Span} sampling. - */ - public static Sampler neverSample() { - return NEVER_SAMPLE; - } - - /** - * Returns a {@link Sampler} that makes a "yes" decision with a given probability. - * - * @param probability The desired probability of sampling. Must be within [0.0, 1.0]. - * @return a {@code Sampler} that makes a "yes" decision with a given probability. - * @throws IllegalArgumentException if {@code probability} is out of range - */ - public static Sampler probabilitySampler(double probability) { - return ProbabilitySampler.create(probability); - } - - @Immutable - private static final class AlwaysSampleSampler extends Sampler { - private AlwaysSampleSampler() {} - - // Returns always makes a "yes" decision on {@link Span} sampling. - @Override - protected boolean shouldSample( - @Nullable SpanContext parentContext, - boolean remoteParent, - TraceId traceId, - SpanId spanId, - String name, - List parentLinks) { - return true; - } - - @Override - public String toString() { - return "AlwaysSampleSampler"; - } - } - - @Immutable - private static final class NeverSampleSampler extends Sampler { - private NeverSampleSampler() {} - - // Returns always makes a "no" decision on {@link Span} sampling. - @Override - protected boolean shouldSample( - @Nullable SpanContext parentContext, - boolean remoteParent, - TraceId traceId, - SpanId spanId, - String name, - List parentLinks) { - return false; - } - - @Override - public String toString() { - return "NeverSampleSampler"; - } - } - - // We assume the lower 64 bits of the traceId's are randomly distributed around the whole (long) - // range. We convert an incoming probability into an upper bound on that value, such that we can - // just compare the absolute value of the id and the bound to see if we are within the desired - // probability range. Using the low bits of the traceId also ensures that systems that only use - // 64 bit ID's will also work with this sampler. - @AutoValue - @Immutable - abstract static class ProbabilitySampler extends Sampler { - ProbabilitySampler() {} - - abstract double getProbability(); - - abstract long getIdUpperBound(); - - /** - * Returns a new {@link ProbabilitySampler}. The probability of sampling a trace is equal to - * that of the specified probability. - * - * @param probability The desired probability of sampling. Must be within [0.0, 1.0]. - * @return a new {@link ProbabilitySampler}. - * @throws IllegalArgumentException if {@code probability} is out of range - */ - private static ProbabilitySampler create(double probability) { - checkArgument( - probability >= 0.0 && probability <= 1.0, "probability must be in range [0.0, 1.0]"); - long idUpperBound = 0; - // Special case the limits, to avoid any possible issues with lack of precision across - // double/long boundaries. For probability == 0.0, we use Long.MIN_VALUE as this guarantees - // that we will never sample a trace, even in the case where the id == Long.MIN_VALUE, since - // Math.Abs(Long.MIN_VALUE) == Long.MIN_VALUE. - if (probability == 0.0) { - idUpperBound = Long.MIN_VALUE; - } else if (probability == 1.0) { - idUpperBound = Long.MAX_VALUE; - } else { - idUpperBound = (long) (probability * Long.MAX_VALUE); - } - return new AutoValue_Samplers_ProbabilitySampler(probability, idUpperBound); - } - - @Override - protected final boolean shouldSample( - @Nullable SpanContext parentContext, - boolean remoteParent, - TraceId traceId, - SpanId spanId, - String name, - @Nullable List parentLinks) { - // Always enable sampling if parent was sampled. - if (parentContext != null && parentContext.getTraceOptions().isSampled()) { - return true; - } - // Always sample if we are within probability range. This is true even for child spans (that - // may have had a different sampling decision made) to allow for different sampling policies, - // and dynamic increases to sampling probabilities for debugging purposes. - // Note use of '<' for comparison. This ensures that we never sample for probability == 0.0, - // while allowing for a (very) small chance of *not* sampling if the id == Long.MAX_VALUE. - // This is considered a reasonable tradeoff for the simplicity/performance requirements (this - // code is executed in-line for every Span creation). - return Math.abs(traceId.getLowerLong()) < getIdUpperBound(); - } - } -} diff --git a/api/src/main/java/io/opencensus/trace/Span.java b/api/src/main/java/io/opencensus/trace/Span.java index 0a941287..f1661901 100644 --- a/api/src/main/java/io/opencensus/trace/Span.java +++ b/api/src/main/java/io/opencensus/trace/Span.java @@ -21,6 +21,7 @@ import io.opencensus.trace.base.AttributeValue; import io.opencensus.trace.base.EndSpanOptions; import io.opencensus.trace.base.Link; import io.opencensus.trace.base.NetworkEvent; +import io.opencensus.trace.base.StartSpanOptions; import java.util.Collections; import java.util.EnumSet; import java.util.Map; diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java index b3ad8a5f..782248ba 100644 --- a/api/src/main/java/io/opencensus/trace/SpanBuilder.java +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -15,6 +15,8 @@ package io.opencensus.trace; import io.opencensus.common.NonThrowingCloseable; import io.opencensus.trace.base.EndSpanOptions; +import io.opencensus.trace.base.Sampler; +import io.opencensus.trace.base.StartSpanOptions; import io.opencensus.trace.internal.SpanFactory; import java.util.List; import javax.annotation.Nullable; diff --git a/api/src/main/java/io/opencensus/trace/StartSpanOptions.java b/api/src/main/java/io/opencensus/trace/StartSpanOptions.java deleted file mode 100644 index 9b7ccb65..00000000 --- a/api/src/main/java/io/opencensus/trace/StartSpanOptions.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * 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; - -import com.google.auto.value.AutoValue; -import com.google.common.annotations.VisibleForTesting; -import io.opencensus.trace.config.TraceConfig; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; - -/** - * A class that enables overriding the default values used when starting a {@link Span}. Allows - * overriding the {@link Sampler sampler}, the parent links, and option to record all the events - * even if the {@code Span} is not sampled. - */ -@AutoValue -@Immutable -public abstract class StartSpanOptions { - private static final List EMPTY_PARENT_LINKS_LIST = Collections.emptyList(); - - /** The default {@code StartSpanOptions}. */ - @VisibleForTesting static final StartSpanOptions DEFAULT = builder().build(); - - /** - * Returns the {@link Sampler} to be used, or {@code null} if default. - * - * @return the {@code Sampler} to be used, or {@code null} if default. - */ - @Nullable - public abstract Sampler getSampler(); - - /** - * Returns the parent links to be set for the {@link Span}. - * - * @return the parent links to be set for the {@code Span}. - */ - public abstract List getParentLinks(); - - /** - * Returns the record events option, or {@code null} if default. - * - *

See {@link Span.Options#RECORD_EVENTS} for more details. - * - * @return the record events option, or {@code null} if default. - */ - @Nullable - public abstract Boolean getRecordEvents(); - - /** - * Returns a new {@link Builder} with default options. - * - * @return a new {@code Builder} with default options. - */ - public static Builder builder() { - return new AutoValue_StartSpanOptions.Builder().setParentLinks(EMPTY_PARENT_LINKS_LIST); - } - - /** Builder class for {@link StartSpanOptions}. */ - @AutoValue.Builder - public abstract static class Builder { - - /** - * Sets the {@link Sampler} to be used. If {@code null} the default {@code Sampler} from the - * {@link TraceConfig#getActiveTraceParams()} will be used. - * - * @param sampler the {@link Sampler} to be used. - * @return this. - */ - public abstract Builder setSampler(@Nullable Sampler sampler); - - /** - * Sets the parent links to be set for the {@link Span}. - * - * @param parentLinks the parent links to be set for the {@link Span}. - * @return this. - * @throws NullPointerException if {@code parentLinks} is {@code null}. - */ - public abstract Builder setParentLinks(List parentLinks); - - /** - * Sets the record events option. If {@code null} the default value from the {@link - * TraceConfig#getActiveTraceParams()} will be used. - * - *

See {@link Span.Options#RECORD_EVENTS} for more details. - * - * @param recordEvents the record events option. - * @return this. - */ - public abstract Builder setRecordEvents(@Nullable Boolean recordEvents); - - abstract List getParentLinks(); // not public - - abstract StartSpanOptions autoBuild(); // not public - - /** - * Builds and returns a {@code StartSpanOptions} with the desired settings. - * - * @return a {@code StartSpanOptions} with the desired settings. - */ - public StartSpanOptions build() { - setParentLinks(Collections.unmodifiableList(new ArrayList(getParentLinks()))); - return autoBuild(); - } - } - - StartSpanOptions() {} -} diff --git a/api/src/main/java/io/opencensus/trace/Tracer.java b/api/src/main/java/io/opencensus/trace/Tracer.java index 64f0ae49..e6172bed 100644 --- a/api/src/main/java/io/opencensus/trace/Tracer.java +++ b/api/src/main/java/io/opencensus/trace/Tracer.java @@ -16,6 +16,7 @@ package io.opencensus.trace; import static com.google.common.base.Preconditions.checkNotNull; import io.opencensus.common.NonThrowingCloseable; +import io.opencensus.trace.base.StartSpanOptions; import io.opencensus.trace.internal.SpanFactory; import javax.annotation.Nullable; diff --git a/api/src/main/java/io/opencensus/trace/base/Sampler.java b/api/src/main/java/io/opencensus/trace/base/Sampler.java new file mode 100644 index 00000000..94bd2966 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/base/Sampler.java @@ -0,0 +1,44 @@ +/* + * Copyright 2017, Google Inc. + * 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.base; + +import io.opencensus.trace.Span; +import io.opencensus.trace.SpanContext; + +import java.util.List; +import javax.annotation.Nullable; + +/** Sampler is used to make decisions on {@link Span} sampling. */ +public abstract class Sampler { + /** + * Called during {@link Span} creation to make a sampling decision. + * + * @param parentContext The parent {@code Span} {@link SpanContext}. May be {@code null} if this + * is a root span. + * @param remoteParent true if the parentContext is remote. + * @param traceId The {@link TraceId} for the new {@code Span}. This will be identical to that in + * the parentContext, unless this is a root span. + * @param spanId The span ID for the new {@code Span}. + * @param name The name of the new {@code Span}. + * @param parentLinks The parentLinks associated with the new {@code Span}. + * @return {@code true} if the {@code Span} is sampled. + */ + public abstract boolean shouldSample( + @Nullable SpanContext parentContext, + boolean remoteParent, + TraceId traceId, + SpanId spanId, + String name, + List parentLinks); +} diff --git a/api/src/main/java/io/opencensus/trace/base/StartSpanOptions.java b/api/src/main/java/io/opencensus/trace/base/StartSpanOptions.java new file mode 100644 index 00000000..518f1e60 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/base/StartSpanOptions.java @@ -0,0 +1,122 @@ +/* + * Copyright 2016, Google Inc. + * 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.base; + +import com.google.auto.value.AutoValue; +import com.google.common.annotations.VisibleForTesting; +import io.opencensus.trace.Span; +import io.opencensus.trace.config.TraceConfig; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * A class that enables overriding the default values used when starting a {@link Span}. Allows + * overriding the {@link Sampler sampler}, the parent links, and option to record all the events + * even if the {@code Span} is not sampled. + */ +@AutoValue +@Immutable +public abstract class StartSpanOptions { + private static final List EMPTY_PARENT_LINKS_LIST = Collections.emptyList(); + + /** The default {@code StartSpanOptions}. */ + @VisibleForTesting public static final StartSpanOptions DEFAULT = builder().build(); + + /** + * Returns the {@link Sampler} to be used, or {@code null} if default. + * + * @return the {@code Sampler} to be used, or {@code null} if default. + */ + @Nullable + public abstract Sampler getSampler(); + + /** + * Returns the parent links to be set for the {@link Span}. + * + * @return the parent links to be set for the {@code Span}. + */ + public abstract List getParentLinks(); + + /** + * Returns the record events option, or {@code null} if default. + * + *

See {@link Span.Options#RECORD_EVENTS} for more details. + * + * @return the record events option, or {@code null} if default. + */ + @Nullable + public abstract Boolean getRecordEvents(); + + /** + * Returns a new {@link Builder} with default options. + * + * @return a new {@code Builder} with default options. + */ + public static Builder builder() { + return new AutoValue_StartSpanOptions.Builder().setParentLinks(EMPTY_PARENT_LINKS_LIST); + } + + /** Builder class for {@link StartSpanOptions}. */ + @AutoValue.Builder + public abstract static class Builder { + + /** + * Sets the {@link Sampler} to be used. If {@code null} the default {@code Sampler} from the + * {@link TraceConfig#getActiveTraceParams()} will be used. + * + * @param sampler the {@link Sampler} to be used. + * @return this. + */ + public abstract Builder setSampler(@Nullable Sampler sampler); + + /** + * Sets the parent links to be set for the {@link Span}. + * + * @param parentLinks the parent links to be set for the {@link Span}. + * @return this. + * @throws NullPointerException if {@code parentLinks} is {@code null}. + */ + public abstract Builder setParentLinks(List parentLinks); + + /** + * Sets the record events option. If {@code null} the default value from the {@link + * TraceConfig#getActiveTraceParams()} will be used. + * + *

See {@link Span.Options#RECORD_EVENTS} for more details. + * + * @param recordEvents the record events option. + * @return this. + */ + public abstract Builder setRecordEvents(@Nullable Boolean recordEvents); + + abstract List getParentLinks(); // not public + + abstract StartSpanOptions autoBuild(); // not public + + /** + * Builds and returns a {@code StartSpanOptions} with the desired settings. + * + * @return a {@code StartSpanOptions} with the desired settings. + */ + public StartSpanOptions build() { + setParentLinks(Collections.unmodifiableList(new ArrayList(getParentLinks()))); + return autoBuild(); + } + } + + StartSpanOptions() {} +} diff --git a/api/src/main/java/io/opencensus/trace/config/TraceParams.java b/api/src/main/java/io/opencensus/trace/config/TraceParams.java index 1f0e093f..74953cfd 100644 --- a/api/src/main/java/io/opencensus/trace/config/TraceParams.java +++ b/api/src/main/java/io/opencensus/trace/config/TraceParams.java @@ -16,13 +16,13 @@ package io.opencensus.trace.config; import static com.google.common.base.Preconditions.checkArgument; import com.google.auto.value.AutoValue; -import io.opencensus.trace.Sampler; -import io.opencensus.trace.Samplers; import io.opencensus.trace.Span; -import io.opencensus.trace.StartSpanOptions; import io.opencensus.trace.base.Annotation; import io.opencensus.trace.base.Link; import io.opencensus.trace.base.NetworkEvent; +import io.opencensus.trace.base.Sampler; +import io.opencensus.trace.base.StartSpanOptions; +import io.opencensus.trace.samplers.Samplers; import javax.annotation.concurrent.Immutable; /** Class that holds global trace parameters. */ @@ -109,8 +109,8 @@ public abstract class TraceParams { /** * Sets the global default max number of attributes per {@link Span}. * - * @param maxNumberOfAttributes the global default max number of attributes per {@link Span}. - * It must be positive otherwise {@link #build()} will throw an exception. + * @param maxNumberOfAttributes the global default max number of attributes per {@link Span}. It + * must be positive otherwise {@link #build()} will throw an exception. * @return this. */ public abstract Builder setMaxNumberOfAttributes(int maxNumberOfAttributes); @@ -118,9 +118,8 @@ public abstract class TraceParams { /** * Sets the global default max number of {@link Annotation} events per {@link Span}. * - * @param maxNumberOfAnnotations the global default max number of {@link Annotation} events - * per {@link Span}. It must be positive otherwise {@link #build()} will throw an - * exception. + * @param maxNumberOfAnnotations the global default max number of {@link Annotation} events per + * {@link Span}. It must be positive otherwise {@link #build()} will throw an exception. * @return this. */ public abstract Builder setMaxNumberOfAnnotations(int maxNumberOfAnnotations); @@ -128,9 +127,8 @@ public abstract class TraceParams { /** * Sets the global default max number of {@link NetworkEvent} events per {@link Span}. * - * @param maxNumberOfNetworkEvents the global default max number of {@link NetworkEvent} - * events per {@link Span}. It must be positive otherwise {@link #build()} will throw an - * exception. + * @param maxNumberOfNetworkEvents the global default max number of {@link NetworkEvent} events + * per {@link Span}. It must be positive otherwise {@link #build()} will throw an exception. * @return this. */ public abstract Builder setMaxNumberOfNetworkEvents(int maxNumberOfNetworkEvents); diff --git a/api/src/main/java/io/opencensus/trace/internal/SpanFactory.java b/api/src/main/java/io/opencensus/trace/internal/SpanFactory.java index b93ec865..a0306152 100644 --- a/api/src/main/java/io/opencensus/trace/internal/SpanFactory.java +++ b/api/src/main/java/io/opencensus/trace/internal/SpanFactory.java @@ -15,7 +15,7 @@ package io.opencensus.trace.internal; import io.opencensus.trace.Span; import io.opencensus.trace.SpanContext; -import io.opencensus.trace.StartSpanOptions; +import io.opencensus.trace.base.StartSpanOptions; import javax.annotation.Nullable; /** Factory class to create and start a {@link Span}. */ diff --git a/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java b/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java new file mode 100644 index 00000000..f3daed4b --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017, Google Inc. + * 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.samplers; + +import io.opencensus.trace.Span; +import io.opencensus.trace.SpanContext; +import io.opencensus.trace.base.Sampler; +import io.opencensus.trace.base.SpanId; +import io.opencensus.trace.base.TraceId; +import java.util.List; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * Sampler that always makes a "yes" decision on {@link Span} sampling. + */ +@Immutable +final class AlwaysSampleSampler extends Sampler { + + AlwaysSampleSampler() { + } + + // Returns always makes a "yes" decision on {@link Span} sampling. + @Override + public boolean shouldSample( + @Nullable SpanContext parentContext, + boolean remoteParent, + TraceId traceId, + SpanId spanId, + String name, + List parentLinks) { + return true; + } + + @Override + public String toString() { + return "AlwaysSampleSampler"; + } +} diff --git a/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java b/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java new file mode 100644 index 00000000..bca64df4 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017, Google Inc. + * 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.samplers; + +import io.opencensus.trace.Span; +import io.opencensus.trace.SpanContext; +import io.opencensus.trace.base.Sampler; +import io.opencensus.trace.base.SpanId; +import io.opencensus.trace.base.TraceId; +import java.util.List; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * Sampler that always makes a "no" decision on {@link Span} sampling. + */ +@Immutable +final class NeverSampleSampler extends Sampler { + + NeverSampleSampler() { + } + + // Returns always makes a "no" decision on {@link Span} sampling. + @Override + public boolean shouldSample( + @Nullable SpanContext parentContext, + boolean remoteParent, + TraceId traceId, + SpanId spanId, + String name, + List parentLinks) { + return false; + } + + @Override + public String toString() { + return "NeverSampleSampler"; + } +} diff --git a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java new file mode 100644 index 00000000..c5c9c002 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java @@ -0,0 +1,93 @@ +/* + * Copyright 2017, Google Inc. + * 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.samplers; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.auto.value.AutoValue; +import io.opencensus.trace.Span; +import io.opencensus.trace.SpanContext; +import io.opencensus.trace.base.Sampler; +import io.opencensus.trace.base.SpanId; +import io.opencensus.trace.base.TraceId; +import java.util.List; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * We assume the lower 64 bits of the traceId's are randomly distributed around the whole (long) + * range. We convert an incoming probability into an upper bound on that value, such that we can + * just compare the absolute value of the id and the bound to see if we are within the desired + * probability range. Using the low bits of the traceId also ensures that systems that only use + * 64 bit ID's will also work with this sampler. + */ +@AutoValue +@Immutable +abstract class ProbabilitySampler extends Sampler { + + ProbabilitySampler() { + } + + abstract double getProbability(); + + abstract long getIdUpperBound(); + + /** + * Returns a new {@link ProbabilitySampler}. The probability of sampling a trace is equal to + * that of the specified probability. + * + * @param probability The desired probability of sampling. Must be within [0.0, 1.0]. + * @return a new {@link ProbabilitySampler}. + * @throws IllegalArgumentException if {@code probability} is out of range + */ + static ProbabilitySampler create(double probability) { + checkArgument( + probability >= 0.0 && probability <= 1.0, "probability must be in range [0.0, 1.0]"); + long idUpperBound = 0; + // Special case the limits, to avoid any possible issues with lack of precision across + // double/long boundaries. For probability == 0.0, we use Long.MIN_VALUE as this guarantees + // that we will never sample a trace, even in the case where the id == Long.MIN_VALUE, since + // Math.Abs(Long.MIN_VALUE) == Long.MIN_VALUE. + if (probability == 0.0) { + idUpperBound = Long.MIN_VALUE; + } else if (probability == 1.0) { + idUpperBound = Long.MAX_VALUE; + } else { + idUpperBound = (long) (probability * Long.MAX_VALUE); + } + return new AutoValue_ProbabilitySampler(probability, idUpperBound); + } + + @Override + public final boolean shouldSample( + @Nullable SpanContext parentContext, + boolean remoteParent, + TraceId traceId, + SpanId spanId, + String name, + @Nullable List parentLinks) { + // Always enable sampling if parent was sampled. + if (parentContext != null && parentContext.getTraceOptions().isSampled()) { + return true; + } + // Always sample if we are within probability range. This is true even for child spans (that + // may have had a different sampling decision made) to allow for different sampling policies, + // and dynamic increases to sampling probabilities for debugging purposes. + // Note use of '<' for comparison. This ensures that we never sample for probability == 0.0, + // while allowing for a (very) small chance of *not* sampling if the id == Long.MAX_VALUE. + // This is considered a reasonable tradeoff for the simplicity/performance requirements (this + // code is executed in-line for every Span creation). + return Math.abs(traceId.getLowerLong()) < getIdUpperBound(); + } +} diff --git a/api/src/main/java/io/opencensus/trace/samplers/Samplers.java b/api/src/main/java/io/opencensus/trace/samplers/Samplers.java new file mode 100644 index 00000000..40d72931 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/samplers/Samplers.java @@ -0,0 +1,55 @@ +/* + * Copyright 2017, Google Inc. + * 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.samplers; + +import io.opencensus.trace.Span; +import io.opencensus.trace.base.Sampler; + +/** Static class to access a set of pre-defined {@link Sampler Samplers}. */ +public final class Samplers { + private static final Sampler ALWAYS_SAMPLE = new AlwaysSampleSampler(); + private static final Sampler NEVER_SAMPLE = new NeverSampleSampler(); + + // No instance of this class. + private Samplers() {} + + /** + * Returns a {@link Sampler} that always makes a "yes" decision on {@link Span} sampling. + * + * @return a {@code Sampler} that always makes a "yes" decision on {@code Span} sampling. + */ + public static Sampler alwaysSample() { + return ALWAYS_SAMPLE; + } + + /** + * Returns a {@link Sampler} that always makes a "no" decision on {@link Span} sampling. + * + * @return a {@code Sampler} that always makes a "no" decision on {@code Span} sampling. + */ + public static Sampler neverSample() { + return NEVER_SAMPLE; + } + + /** + * Returns a {@link Sampler} that makes a "yes" decision with a given probability. + * + * @param probability The desired probability of sampling. Must be within [0.0, 1.0]. + * @return a {@code Sampler} that makes a "yes" decision with a given probability. + * @throws IllegalArgumentException if {@code probability} is out of range + */ + public static Sampler probabilitySampler(double probability) { + return ProbabilitySampler.create(probability); + } +} diff --git a/api/src/test/java/io/opencensus/trace/SamplersTest.java b/api/src/test/java/io/opencensus/trace/SamplersTest.java deleted file mode 100644 index 52351f2c..00000000 --- a/api/src/test/java/io/opencensus/trace/SamplersTest.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.truth.Truth.assertThat; - -import io.opencensus.trace.base.SpanId; -import io.opencensus.trace.base.TraceId; -import io.opencensus.trace.base.TraceOptions; -import java.util.Collections; -import java.util.Random; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link Samplers}. */ -@RunWith(JUnit4.class) -public class SamplersTest { - private final Random random = new Random(1234); - private final TraceId traceId = TraceId.generateRandomId(random); - private final SpanId parentSpanId = SpanId.generateRandomId(random); - private final SpanId spanId = SpanId.generateRandomId(random); - private final SpanContext sampledSpanContext = - SpanContext.create(traceId, parentSpanId, TraceOptions.builder().setIsSampled().build()); - private final SpanContext notSampledSpanContext = - SpanContext.create(traceId, parentSpanId, TraceOptions.DEFAULT); - - @Test - public void alwaysSampleSampler_AlwaysReturnTrue() { - // Sampled parent. - assertThat( - Samplers.alwaysSample() - .shouldSample( - sampledSpanContext, - false, - traceId, - spanId, - "Another name", - Collections.emptyList())) - .isTrue(); - // Not sampled parent. - assertThat( - Samplers.alwaysSample() - .shouldSample( - notSampledSpanContext, - false, - traceId, - spanId, - "Yet another name", - Collections.emptyList())) - .isTrue(); - } - - @Test - public void alwaysSampleSampler_ToString() { - assertThat(Samplers.alwaysSample().toString()).isEqualTo("AlwaysSampleSampler"); - } - - @Test - public void neverSampleSampler_AlwaysReturnFalse() { - // Sampled parent. - assertThat( - Samplers.neverSample() - .shouldSample( - sampledSpanContext, - false, - traceId, - spanId, - "bar", - Collections.emptyList())) - .isFalse(); - // Not sampled parent. - assertThat( - Samplers.neverSample() - .shouldSample( - notSampledSpanContext, - false, - traceId, - spanId, - "quux", - Collections.emptyList())) - .isFalse(); - } - - @Test - public void neverSampleSampler_ToString() { - assertThat(Samplers.neverSample().toString()).isEqualTo("NeverSampleSampler"); - } - - @Test(expected = IllegalArgumentException.class) - public void probabilitySampler_outOfRangeHighProbability() { - Samplers.probabilitySampler(1.01); - } - - @Test(expected = IllegalArgumentException.class) - public void probabilitySampler_outOfRangeLowProbability() { - Samplers.probabilitySampler(-0.00001); - } - - private final void probabilitySampler_AlwaysReturnTrueForSampled(Sampler sampler) { - final int numSamples = 100; // Number of traces for which to generate sampling decisions. - for (int i = 0; i < numSamples; i++) { - assertThat( - sampler.shouldSample( - sampledSpanContext, - false, - TraceId.generateRandomId(random), - spanId, - "bar", - Collections.emptyList())) - .isTrue(); - } - } - - private final void probabilitySampler_SamplesWithProbabilityForUnsampled( - Sampler sampler, double probability) { - final int numSamples = 1000; // Number of traces for which to generate sampling decisions. - int count = 0; // Count of spans with sampling enabled - for (int i = 0; i < numSamples; i++) { - if (sampler.shouldSample( - notSampledSpanContext, - false, - TraceId.generateRandomId(random), - spanId, - "bar", - Collections.emptyList())) { - count++; - } - } - double proportionSampled = (double) count / numSamples; - // Allow for a large amount of slop (+/- 10%) in number of sampled traces, to avoid flakiness. - assertThat(proportionSampled < probability + 0.1 && proportionSampled > probability - 0.1) - .isTrue(); - } - - @Test - public void probabilitySamper_SamplesWithProbability() { - final Sampler neverSample = Samplers.probabilitySampler(0.0); - probabilitySampler_AlwaysReturnTrueForSampled(neverSample); - probabilitySampler_SamplesWithProbabilityForUnsampled(neverSample, 0.0); - final Sampler alwaysSample = Samplers.probabilitySampler(1.0); - probabilitySampler_AlwaysReturnTrueForSampled(alwaysSample); - probabilitySampler_SamplesWithProbabilityForUnsampled(alwaysSample, 1.0); - final Sampler fiftyPercentSample = Samplers.probabilitySampler(0.5); - probabilitySampler_AlwaysReturnTrueForSampled(fiftyPercentSample); - probabilitySampler_SamplesWithProbabilityForUnsampled(fiftyPercentSample, 0.5); - final Sampler twentyPercentSample = Samplers.probabilitySampler(0.2); - probabilitySampler_AlwaysReturnTrueForSampled(twentyPercentSample); - probabilitySampler_SamplesWithProbabilityForUnsampled(twentyPercentSample, 0.2); - final Sampler twoThirdsSample = Samplers.probabilitySampler(2.0 / 3.0); - probabilitySampler_AlwaysReturnTrueForSampled(twoThirdsSample); - probabilitySampler_SamplesWithProbabilityForUnsampled(twoThirdsSample, 2.0 / 3.0); - } - - @Test - public void probabilitySampler_ToString() { - assertThat((Samplers.probabilitySampler(0.5)).toString()).contains("0.5"); - } -} diff --git a/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java b/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java index 469fe9bb..10eccbe6 100644 --- a/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java @@ -23,9 +23,11 @@ import static org.mockito.Mockito.when; import io.opencensus.common.NonThrowingCloseable; import io.opencensus.trace.base.EndSpanOptions; import io.opencensus.trace.base.SpanId; +import io.opencensus.trace.base.StartSpanOptions; import io.opencensus.trace.base.TraceId; import io.opencensus.trace.base.TraceOptions; import io.opencensus.trace.internal.SpanFactory; +import io.opencensus.trace.samplers.Samplers; import java.util.Arrays; import java.util.List; import java.util.Random; diff --git a/api/src/test/java/io/opencensus/trace/StartSpanOptionsTest.java b/api/src/test/java/io/opencensus/trace/StartSpanOptionsTest.java deleted file mode 100644 index c37324ab..00000000 --- a/api/src/test/java/io/opencensus/trace/StartSpanOptionsTest.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link StartSpanOptions}. */ -@RunWith(JUnit4.class) -public class StartSpanOptionsTest { - private final List singleParentList = Arrays.asList(BlankSpan.INSTANCE); - - @Test - public void defaultOptions() { - StartSpanOptions defaultOptions = StartSpanOptions.builder().build(); - assertThat(defaultOptions.getSampler()).isNull(); - assertThat(defaultOptions.getParentLinks().isEmpty()).isTrue(); - assertThat(defaultOptions.getRecordEvents()).isNull(); - } - - @Test - public void setSampler() { - StartSpanOptions options = - StartSpanOptions.builder().setSampler(Samplers.neverSample()).build(); - assertThat(options.getSampler()).isEqualTo(Samplers.neverSample()); - assertThat(options.getParentLinks().isEmpty()).isTrue(); - assertThat(options.getRecordEvents()).isNull(); - } - - @Test - public void setParentLinks() { - StartSpanOptions options = StartSpanOptions.builder().setParentLinks(singleParentList).build(); - assertThat(options.getSampler()).isNull(); - assertThat(options.getParentLinks()).isEqualTo(singleParentList); - assertThat(options.getRecordEvents()).isNull(); - } - - @Test - public void setParentLinks_EmptyList() { - StartSpanOptions options = - StartSpanOptions.builder().setParentLinks(new LinkedList()).build(); - assertThat(options.getSampler()).isNull(); - assertThat(options.getParentLinks().size()).isEqualTo(0); - assertThat(options.getRecordEvents()).isNull(); - } - - @Test - public void setParentLinks_MultipleParents() { - StartSpanOptions options = - StartSpanOptions.builder() - .setParentLinks(Arrays.asList(BlankSpan.INSTANCE, BlankSpan.INSTANCE)) - .build(); - assertThat(options.getSampler()).isNull(); - assertThat(options.getParentLinks().size()).isEqualTo(2); - assertThat(options.getRecordEvents()).isNull(); - } - - @Test - public void setRecordEvents() { - StartSpanOptions options = StartSpanOptions.builder().setRecordEvents(true).build(); - assertThat(options.getSampler()).isNull(); - assertThat(options.getParentLinks().isEmpty()).isTrue(); - assertThat(options.getRecordEvents()).isTrue(); - } - - @Test - public void setAllProperties() { - StartSpanOptions options = - StartSpanOptions.builder() - .setSampler(Samplers.alwaysSample()) - .setRecordEvents(true) - .setParentLinks(singleParentList) - .build(); - assertThat(options.getSampler()).isEqualTo(Samplers.alwaysSample()); - assertThat(options.getParentLinks()).isEqualTo(singleParentList); - assertThat(options.getRecordEvents()).isTrue(); - } - - @Test - public void startSpanOptions_EqualsAndHashCode() { - EqualsTester tester = new EqualsTester(); - StartSpanOptions optionsWithAlwaysSampler1 = - StartSpanOptions.builder().setSampler(Samplers.alwaysSample()).build(); - StartSpanOptions optionsWithAlwaysSampler2 = - StartSpanOptions.builder().setSampler(Samplers.alwaysSample()).build(); - tester.addEqualityGroup(optionsWithAlwaysSampler1, optionsWithAlwaysSampler2); - StartSpanOptions optionsWithNeverSampler = - StartSpanOptions.builder().setSampler(Samplers.neverSample()).build(); - tester.addEqualityGroup(optionsWithNeverSampler); - tester.addEqualityGroup(StartSpanOptions.DEFAULT); - tester.testEquals(); - } -} diff --git a/api/src/test/java/io/opencensus/trace/TracerTest.java b/api/src/test/java/io/opencensus/trace/TracerTest.java index 51b86b63..7339eae2 100644 --- a/api/src/test/java/io/opencensus/trace/TracerTest.java +++ b/api/src/test/java/io/opencensus/trace/TracerTest.java @@ -24,6 +24,7 @@ import io.grpc.Context; import io.opencensus.common.NonThrowingCloseable; import io.opencensus.trace.base.EndSpanOptions; import io.opencensus.trace.base.SpanId; +import io.opencensus.trace.base.StartSpanOptions; import io.opencensus.trace.base.TraceId; import io.opencensus.trace.base.TraceOptions; import io.opencensus.trace.internal.SpanFactory; diff --git a/api/src/test/java/io/opencensus/trace/base/StartSpanOptionsTest.java b/api/src/test/java/io/opencensus/trace/base/StartSpanOptionsTest.java new file mode 100644 index 00000000..1a983b73 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/base/StartSpanOptionsTest.java @@ -0,0 +1,114 @@ +/* + * Copyright 2017, Google Inc. + * 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.base; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.trace.BlankSpan; +import io.opencensus.trace.Span; +import io.opencensus.trace.samplers.Samplers; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link StartSpanOptions}. */ +@RunWith(JUnit4.class) +public class StartSpanOptionsTest { + private final List singleParentList = Arrays.asList(BlankSpan.INSTANCE); + + @Test + public void defaultOptions() { + StartSpanOptions defaultOptions = StartSpanOptions.builder().build(); + assertThat(defaultOptions.getSampler()).isNull(); + assertThat(defaultOptions.getParentLinks().isEmpty()).isTrue(); + assertThat(defaultOptions.getRecordEvents()).isNull(); + } + + @Test + public void setSampler() { + StartSpanOptions options = + StartSpanOptions.builder().setSampler(Samplers.neverSample()).build(); + assertThat(options.getSampler()).isEqualTo(Samplers.neverSample()); + assertThat(options.getParentLinks().isEmpty()).isTrue(); + assertThat(options.getRecordEvents()).isNull(); + } + + @Test + public void setParentLinks() { + StartSpanOptions options = StartSpanOptions.builder().setParentLinks(singleParentList).build(); + assertThat(options.getSampler()).isNull(); + assertThat(options.getParentLinks()).isEqualTo(singleParentList); + assertThat(options.getRecordEvents()).isNull(); + } + + @Test + public void setParentLinks_EmptyList() { + StartSpanOptions options = + StartSpanOptions.builder().setParentLinks(new LinkedList()).build(); + assertThat(options.getSampler()).isNull(); + assertThat(options.getParentLinks().size()).isEqualTo(0); + assertThat(options.getRecordEvents()).isNull(); + } + + @Test + public void setParentLinks_MultipleParents() { + StartSpanOptions options = + StartSpanOptions.builder() + .setParentLinks(Arrays.asList(BlankSpan.INSTANCE, BlankSpan.INSTANCE)) + .build(); + assertThat(options.getSampler()).isNull(); + assertThat(options.getParentLinks().size()).isEqualTo(2); + assertThat(options.getRecordEvents()).isNull(); + } + + @Test + public void setRecordEvents() { + StartSpanOptions options = StartSpanOptions.builder().setRecordEvents(true).build(); + assertThat(options.getSampler()).isNull(); + assertThat(options.getParentLinks().isEmpty()).isTrue(); + assertThat(options.getRecordEvents()).isTrue(); + } + + @Test + public void setAllProperties() { + StartSpanOptions options = + StartSpanOptions.builder() + .setSampler(Samplers.alwaysSample()) + .setRecordEvents(true) + .setParentLinks(singleParentList) + .build(); + assertThat(options.getSampler()).isEqualTo(Samplers.alwaysSample()); + assertThat(options.getParentLinks()).isEqualTo(singleParentList); + assertThat(options.getRecordEvents()).isTrue(); + } + + @Test + public void startSpanOptions_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + StartSpanOptions optionsWithAlwaysSampler1 = + StartSpanOptions.builder().setSampler(Samplers.alwaysSample()).build(); + StartSpanOptions optionsWithAlwaysSampler2 = + StartSpanOptions.builder().setSampler(Samplers.alwaysSample()).build(); + tester.addEqualityGroup(optionsWithAlwaysSampler1, optionsWithAlwaysSampler2); + StartSpanOptions optionsWithNeverSampler = + StartSpanOptions.builder().setSampler(Samplers.neverSample()).build(); + tester.addEqualityGroup(optionsWithNeverSampler); + tester.addEqualityGroup(StartSpanOptions.DEFAULT); + tester.testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/trace/config/TraceConfigTest.java b/api/src/test/java/io/opencensus/trace/config/TraceConfigTest.java index 2bf9356d..cbb6092c 100644 --- a/api/src/test/java/io/opencensus/trace/config/TraceConfigTest.java +++ b/api/src/test/java/io/opencensus/trace/config/TraceConfigTest.java @@ -15,7 +15,7 @@ package io.opencensus.trace.config; import static com.google.common.truth.Truth.assertThat; -import io.opencensus.trace.Samplers; +import io.opencensus.trace.samplers.Samplers; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; diff --git a/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java b/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java index 76d828a9..165f0211 100644 --- a/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java +++ b/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java @@ -15,7 +15,7 @@ package io.opencensus.trace.config; import static com.google.common.truth.Truth.assertThat; -import io.opencensus.trace.Samplers; +import io.opencensus.trace.samplers.Samplers; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; diff --git a/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java b/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java new file mode 100644 index 00000000..5e996835 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java @@ -0,0 +1,173 @@ +/* + * Copyright 2017, Google Inc. + * 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.samplers; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.trace.Span; +import io.opencensus.trace.SpanContext; +import io.opencensus.trace.base.Sampler; +import io.opencensus.trace.base.SpanId; +import io.opencensus.trace.base.TraceId; +import io.opencensus.trace.base.TraceOptions; +import java.util.Collections; +import java.util.Random; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Samplers}. */ +@RunWith(JUnit4.class) +public class SamplersTest { + private final Random random = new Random(1234); + private final TraceId traceId = TraceId.generateRandomId(random); + private final SpanId parentSpanId = SpanId.generateRandomId(random); + private final SpanId spanId = SpanId.generateRandomId(random); + private final SpanContext sampledSpanContext = + SpanContext.create(traceId, parentSpanId, TraceOptions.builder().setIsSampled().build()); + private final SpanContext notSampledSpanContext = + SpanContext.create(traceId, parentSpanId, TraceOptions.DEFAULT); + + @Test + public void alwaysSampleSampler_AlwaysReturnTrue() { + // Sampled parent. + assertThat( + Samplers.alwaysSample() + .shouldSample( + sampledSpanContext, + false, + traceId, + spanId, + "Another name", + Collections.emptyList())) + .isTrue(); + // Not sampled parent. + assertThat( + Samplers.alwaysSample() + .shouldSample( + notSampledSpanContext, + false, + traceId, + spanId, + "Yet another name", + Collections.emptyList())) + .isTrue(); + } + + @Test + public void alwaysSampleSampler_ToString() { + assertThat(Samplers.alwaysSample().toString()).isEqualTo("AlwaysSampleSampler"); + } + + @Test + public void neverSampleSampler_AlwaysReturnFalse() { + // Sampled parent. + assertThat( + Samplers.neverSample() + .shouldSample( + sampledSpanContext, + false, + traceId, + spanId, + "bar", + Collections.emptyList())) + .isFalse(); + // Not sampled parent. + assertThat( + Samplers.neverSample() + .shouldSample( + notSampledSpanContext, + false, + traceId, + spanId, + "quux", + Collections.emptyList())) + .isFalse(); + } + + @Test + public void neverSampleSampler_ToString() { + assertThat(Samplers.neverSample().toString()).isEqualTo("NeverSampleSampler"); + } + + @Test(expected = IllegalArgumentException.class) + public void probabilitySampler_outOfRangeHighProbability() { + Samplers.probabilitySampler(1.01); + } + + @Test(expected = IllegalArgumentException.class) + public void probabilitySampler_outOfRangeLowProbability() { + Samplers.probabilitySampler(-0.00001); + } + + private final void probabilitySampler_AlwaysReturnTrueForSampled(Sampler sampler) { + final int numSamples = 100; // Number of traces for which to generate sampling decisions. + for (int i = 0; i < numSamples; i++) { + assertThat( + sampler.shouldSample( + sampledSpanContext, + false, + TraceId.generateRandomId(random), + spanId, + "bar", + Collections.emptyList())) + .isTrue(); + } + } + + private final void probabilitySampler_SamplesWithProbabilityForUnsampled( + Sampler sampler, double probability) { + final int numSamples = 1000; // Number of traces for which to generate sampling decisions. + int count = 0; // Count of spans with sampling enabled + for (int i = 0; i < numSamples; i++) { + if (sampler.shouldSample( + notSampledSpanContext, + false, + TraceId.generateRandomId(random), + spanId, + "bar", + Collections.emptyList())) { + count++; + } + } + double proportionSampled = (double) count / numSamples; + // Allow for a large amount of slop (+/- 10%) in number of sampled traces, to avoid flakiness. + assertThat(proportionSampled < probability + 0.1 && proportionSampled > probability - 0.1) + .isTrue(); + } + + @Test + public void probabilitySamper_SamplesWithProbability() { + final Sampler neverSample = Samplers.probabilitySampler(0.0); + probabilitySampler_AlwaysReturnTrueForSampled(neverSample); + probabilitySampler_SamplesWithProbabilityForUnsampled(neverSample, 0.0); + final Sampler alwaysSample = Samplers.probabilitySampler(1.0); + probabilitySampler_AlwaysReturnTrueForSampled(alwaysSample); + probabilitySampler_SamplesWithProbabilityForUnsampled(alwaysSample, 1.0); + final Sampler fiftyPercentSample = Samplers.probabilitySampler(0.5); + probabilitySampler_AlwaysReturnTrueForSampled(fiftyPercentSample); + probabilitySampler_SamplesWithProbabilityForUnsampled(fiftyPercentSample, 0.5); + final Sampler twentyPercentSample = Samplers.probabilitySampler(0.2); + probabilitySampler_AlwaysReturnTrueForSampled(twentyPercentSample); + probabilitySampler_SamplesWithProbabilityForUnsampled(twentyPercentSample, 0.2); + final Sampler twoThirdsSample = Samplers.probabilitySampler(2.0 / 3.0); + probabilitySampler_AlwaysReturnTrueForSampled(twoThirdsSample); + probabilitySampler_SamplesWithProbabilityForUnsampled(twoThirdsSample, 2.0 / 3.0); + } + + @Test + public void probabilitySampler_ToString() { + assertThat((Samplers.probabilitySampler(0.5)).toString()).contains("0.5"); + } +} -- cgit v1.2.3 From c6e146ba77ed74b8272c2d1142b3e17eda93d090 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Mon, 12 Jun 2017 14:34:59 -0700 Subject: Move SpanData to export package. Move implementation of export package class to export package. (#343) --- .../java/io/opencensus/internal/package-info.java | 2 +- .../main/java/io/opencensus/trace/SpanData.java | 314 -------------------- .../trace/export/InProcessDebuggingHandler.java | 1 - .../java/io/opencensus/trace/export/SpanData.java | 316 +++++++++++++++++++++ .../io/opencensus/trace/export/SpanExporter.java | 1 - .../java/io/opencensus/trace/SpanDataTest.java | 249 ---------------- .../trace/export/ExportComponentTest.java | 36 +++ .../io/opencensus/trace/export/SpanDataTest.java | 250 ++++++++++++++++ 8 files changed, 603 insertions(+), 566 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/trace/SpanData.java create mode 100644 api/src/main/java/io/opencensus/trace/export/SpanData.java delete mode 100644 api/src/test/java/io/opencensus/trace/SpanDataTest.java create mode 100644 api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java create mode 100644 api/src/test/java/io/opencensus/trace/export/SpanDataTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/package-info.java b/api/src/main/java/io/opencensus/internal/package-info.java index 5fe0010d..a9f94864 100644 --- a/api/src/main/java/io/opencensus/internal/package-info.java +++ b/api/src/main/java/io/opencensus/internal/package-info.java @@ -12,7 +12,7 @@ */ /** - * Interfaces and implementations that are internal to opencensus. + * Interfaces and implementations that are internal to OpenCensus. * *

All the content under this package and its subpackages are considered annotated with {@link * io.opencensus.common.Internal}. diff --git a/api/src/main/java/io/opencensus/trace/SpanData.java b/api/src/main/java/io/opencensus/trace/SpanData.java deleted file mode 100644 index 02c89528..00000000 --- a/api/src/main/java/io/opencensus/trace/SpanData.java +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.auto.value.AutoValue; -import io.opencensus.common.Timestamp; -import io.opencensus.trace.base.Annotation; -import io.opencensus.trace.base.AttributeValue; -import io.opencensus.trace.base.Link; -import io.opencensus.trace.base.NetworkEvent; -import io.opencensus.trace.base.SpanId; -import io.opencensus.trace.base.Status; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; - -/** Immutable representation of all data collected by the {@link Span} class. */ -@Immutable -@AutoValue -public abstract class SpanData { - - /** - * Returns a new immutable {@code SpanData}. - * - * @param context the {@code SpanContext} of the {@code Span}. - * @param parentSpanId the parent {@code SpanId} of the {@code Span}. {@code null} if the {@code - * Span} is a root. - * @param hasRemoteParent {@code true} if the parent is on a different process. - * @param displayName the name of the {@code Span}. - * @param startTimestamp the start {@code Timestamp} of the {@code Span}. - * @param attributes the attributes associated with the {@code Span}. - * @param annotations the annotations associated with the {@code Span}. - * @param networkEvents the network events associated with the {@code Span}. - * @param links the links associated with the {@code Span}. - * @param status the {@code Status} of the {@code Span}. {@code null} if the {@code Span} is still - * active. - * @param endTimestamp the end {@code Timestamp} of the {@code Span}. {@code null} if the {@code - * Span} is still active. - * @return a new immutable {@code SpanData}. - */ - public static SpanData create( - SpanContext context, - @Nullable SpanId parentSpanId, - boolean hasRemoteParent, - String displayName, - Timestamp startTimestamp, - Attributes attributes, - TimedEvents annotations, - TimedEvents networkEvents, - Links links, - @Nullable Status status, - @Nullable Timestamp endTimestamp) { - return new AutoValue_SpanData( - context, - parentSpanId, - hasRemoteParent, - displayName, - startTimestamp, - attributes, - annotations, - networkEvents, - links, - status, - endTimestamp); - } - - /** - * Returns the {@code SpanContext} associated with this {@code Span}. - * - * @return the {@code SpanContext} associated with this {@code Span}. - */ - public abstract SpanContext getContext(); - - /** - * Returns the parent {@code SpanId} or {@code null} if the {@code Span} is a root {@code Span}. - * - * @return the parent {@code SpanId} or {@code null} if the {@code Span} is a root {@code Span}. - */ - @Nullable - public abstract SpanId getParentSpanId(); - - /** - * Returns {@code true} if the parent is on a different process. - * - * @return {@code true} if the parent is on a different process. - */ - public abstract boolean getHasRemoteParent(); - - /** - * Returns the display name of this {@code Span}. - * - * @return the display name of this {@code Span}. - */ - public abstract String getDisplayName(); - - /** - * Returns the start {@code Timestamp} of this {@code Span}. - * - * @return the start {@code Timestamp} of this {@code Span}. - */ - public abstract Timestamp getStartTimestamp(); - - /** - * Returns the attributes recorded for this {@code Span}. - * - * @return the attributes recorded for this {@code Span}. - */ - public abstract Attributes getAttributes(); - - /** - * Returns the annotations recorded for this {@code Span}. - * - * @return the annotations recorded for this {@code Span}. - */ - public abstract TimedEvents getAnnotations(); - - /** - * Returns network events recorded for this {@code Span}. - * - * @return network events recorded for this {@code Span}. - */ - public abstract TimedEvents getNetworkEvents(); - - /** - * Returns links recorded for this {@code Span}. - * - * @return links recorded for this {@code Span}. - */ - public abstract Links getLinks(); - - /** - * Returns the {@code Status} or {@code null} if {@code Span} is still active. - * - * @return the {@code Status} or {@code null} if {@code Span} is still active. - */ - @Nullable - public abstract Status getStatus(); - - /** - * Returns the end {@code Timestamp} or {@code null} if the {@code Span} is still active. - * - * @return the end {@code Timestamp} or {@code null} if the {@code Span} is still active. - */ - @Nullable - public abstract Timestamp getEndTimestamp(); - - SpanData() {} - - /** - * A timed event representation. - * - * @param the type of value that is timed. - */ - @Immutable - @AutoValue - public abstract static class TimedEvent { - /** - * Returns a new immutable {@code TimedEvent}. - * - * @param timestamp the {@code Timestamp} of this event. - * @param event the event. - * @param the type of value that is timed. - * @return a new immutable {@code TimedEvent} - */ - public static TimedEvent create(Timestamp timestamp, T event) { - return new AutoValue_SpanData_TimedEvent(timestamp, event); - } - - /** - * Returns the {@code Timestamp} of this event. - * - * @return the {@code Timestamp} of this event. - */ - public abstract Timestamp getTimestamp(); - - /** - * Returns the event. - * - * @return the event. - */ - public abstract T getEvent(); - - TimedEvent() {} - } - - /** - * A list of timed events and the number of dropped events representation. - * - * @param the type of value that is timed. - */ - @Immutable - @AutoValue - public abstract static class TimedEvents { - /** - * Returns a new immutable {@code TimedEvents}. - * - * @param events the list of events. - * @param droppedEventsCount the number of dropped events. - * @param the type of value that is timed. - * @return a new immutable {@code TimedEvents} - */ - public static TimedEvents create(List> events, int droppedEventsCount) { - return new AutoValue_SpanData_TimedEvents( - Collections.unmodifiableList( - new ArrayList>(checkNotNull(events, "events"))), - droppedEventsCount); - } - - /** - * Returns the list of events. - * - * @return the list of events. - */ - public abstract List> getEvents(); - - /** - * Returns the number of dropped events. - * - * @return the number of dropped events. - */ - public abstract int getDroppedEventsCount(); - - TimedEvents() {} - } - - /** A set of attributes and the number of dropped attributes representation. */ - @Immutable - @AutoValue - public abstract static class Attributes { - /** - * Returns a new immutable {@code Attributes}. - * - * @param attributeMap the set of attributes. - * @param droppedAttributesCount the number of dropped attributes. - * @return a new immutable {@code Attributes}. - */ - public static Attributes create( - Map attributeMap, int droppedAttributesCount) { - // TODO(bdrutu): Consider to use LinkedHashMap here and everywhere else, less test flakes - // for others on account of determinism. - return new AutoValue_SpanData_Attributes( - Collections.unmodifiableMap( - new HashMap(checkNotNull(attributeMap, "attributeMap"))), - droppedAttributesCount); - } - - /** - * Returns the set of attributes. - * - * @return the set of attributes. - */ - public abstract Map getAttributeMap(); - - /** - * Returns the number of dropped attributes. - * - * @return the number of dropped attributes. - */ - public abstract int getDroppedAttributesCount(); - - Attributes() {} - } - - /** A list of links and the number of dropped links representation. */ - @Immutable - @AutoValue - public abstract static class Links { - /** - * Returns a new immutable {@code Links}. - * - * @param links the list of links. - * @param droppedLinksCount the number of dropped links. - * @return a new immutable {@code Links}. - */ - public static Links create(List links, int droppedLinksCount) { - return new AutoValue_SpanData_Links( - Collections.unmodifiableList(new ArrayList(checkNotNull(links, "links"))), - droppedLinksCount); - } - - /** - * Returns the list of links. - * - * @return the list of links. - */ - public abstract List getLinks(); - - /** - * Returns the number of dropped links. - * - * @return the number of dropped links. - */ - public abstract int getDroppedLinksCount(); - - Links() {} - } -} diff --git a/api/src/main/java/io/opencensus/trace/export/InProcessDebuggingHandler.java b/api/src/main/java/io/opencensus/trace/export/InProcessDebuggingHandler.java index 40fdcae0..c2e7ab1c 100644 --- a/api/src/main/java/io/opencensus/trace/export/InProcessDebuggingHandler.java +++ b/api/src/main/java/io/opencensus/trace/export/InProcessDebuggingHandler.java @@ -18,7 +18,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; import io.opencensus.trace.Span; -import io.opencensus.trace.SpanData; import io.opencensus.trace.base.Status; import io.opencensus.trace.base.Status.CanonicalCode; import java.util.Collection; diff --git a/api/src/main/java/io/opencensus/trace/export/SpanData.java b/api/src/main/java/io/opencensus/trace/export/SpanData.java new file mode 100644 index 00000000..73e03f46 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/export/SpanData.java @@ -0,0 +1,316 @@ +/* + * Copyright 2017, Google Inc. + * 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.export; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.Timestamp; +import io.opencensus.trace.Span; +import io.opencensus.trace.SpanContext; +import io.opencensus.trace.base.Annotation; +import io.opencensus.trace.base.AttributeValue; +import io.opencensus.trace.base.Link; +import io.opencensus.trace.base.NetworkEvent; +import io.opencensus.trace.base.SpanId; +import io.opencensus.trace.base.Status; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** Immutable representation of all data collected by the {@link Span} class. */ +@Immutable +@AutoValue +public abstract class SpanData { + + /** + * Returns a new immutable {@code SpanData}. + * + * @param context the {@code SpanContext} of the {@code Span}. + * @param parentSpanId the parent {@code SpanId} of the {@code Span}. {@code null} if the {@code + * Span} is a root. + * @param hasRemoteParent {@code true} if the parent is on a different process. + * @param displayName the name of the {@code Span}. + * @param startTimestamp the start {@code Timestamp} of the {@code Span}. + * @param attributes the attributes associated with the {@code Span}. + * @param annotations the annotations associated with the {@code Span}. + * @param networkEvents the network events associated with the {@code Span}. + * @param links the links associated with the {@code Span}. + * @param status the {@code Status} of the {@code Span}. {@code null} if the {@code Span} is still + * active. + * @param endTimestamp the end {@code Timestamp} of the {@code Span}. {@code null} if the {@code + * Span} is still active. + * @return a new immutable {@code SpanData}. + */ + public static SpanData create( + SpanContext context, + @Nullable SpanId parentSpanId, + boolean hasRemoteParent, + String displayName, + Timestamp startTimestamp, + Attributes attributes, + TimedEvents annotations, + TimedEvents networkEvents, + Links links, + @Nullable Status status, + @Nullable Timestamp endTimestamp) { + return new AutoValue_SpanData( + context, + parentSpanId, + hasRemoteParent, + displayName, + startTimestamp, + attributes, + annotations, + networkEvents, + links, + status, + endTimestamp); + } + + /** + * Returns the {@code SpanContext} associated with this {@code Span}. + * + * @return the {@code SpanContext} associated with this {@code Span}. + */ + public abstract SpanContext getContext(); + + /** + * Returns the parent {@code SpanId} or {@code null} if the {@code Span} is a root {@code Span}. + * + * @return the parent {@code SpanId} or {@code null} if the {@code Span} is a root {@code Span}. + */ + @Nullable + public abstract SpanId getParentSpanId(); + + /** + * Returns {@code true} if the parent is on a different process. + * + * @return {@code true} if the parent is on a different process. + */ + public abstract boolean getHasRemoteParent(); + + /** + * Returns the display name of this {@code Span}. + * + * @return the display name of this {@code Span}. + */ + public abstract String getDisplayName(); + + /** + * Returns the start {@code Timestamp} of this {@code Span}. + * + * @return the start {@code Timestamp} of this {@code Span}. + */ + public abstract Timestamp getStartTimestamp(); + + /** + * Returns the attributes recorded for this {@code Span}. + * + * @return the attributes recorded for this {@code Span}. + */ + public abstract Attributes getAttributes(); + + /** + * Returns the annotations recorded for this {@code Span}. + * + * @return the annotations recorded for this {@code Span}. + */ + public abstract TimedEvents getAnnotations(); + + /** + * Returns network events recorded for this {@code Span}. + * + * @return network events recorded for this {@code Span}. + */ + public abstract TimedEvents getNetworkEvents(); + + /** + * Returns links recorded for this {@code Span}. + * + * @return links recorded for this {@code Span}. + */ + public abstract Links getLinks(); + + /** + * Returns the {@code Status} or {@code null} if {@code Span} is still active. + * + * @return the {@code Status} or {@code null} if {@code Span} is still active. + */ + @Nullable + public abstract Status getStatus(); + + /** + * Returns the end {@code Timestamp} or {@code null} if the {@code Span} is still active. + * + * @return the end {@code Timestamp} or {@code null} if the {@code Span} is still active. + */ + @Nullable + public abstract Timestamp getEndTimestamp(); + + SpanData() {} + + /** + * A timed event representation. + * + * @param the type of value that is timed. + */ + @Immutable + @AutoValue + public abstract static class TimedEvent { + /** + * Returns a new immutable {@code TimedEvent}. + * + * @param timestamp the {@code Timestamp} of this event. + * @param event the event. + * @param the type of value that is timed. + * @return a new immutable {@code TimedEvent} + */ + public static TimedEvent create(Timestamp timestamp, T event) { + return new AutoValue_SpanData_TimedEvent(timestamp, event); + } + + /** + * Returns the {@code Timestamp} of this event. + * + * @return the {@code Timestamp} of this event. + */ + public abstract Timestamp getTimestamp(); + + /** + * Returns the event. + * + * @return the event. + */ + public abstract T getEvent(); + + TimedEvent() {} + } + + /** + * A list of timed events and the number of dropped events representation. + * + * @param the type of value that is timed. + */ + @Immutable + @AutoValue + public abstract static class TimedEvents { + /** + * Returns a new immutable {@code TimedEvents}. + * + * @param events the list of events. + * @param droppedEventsCount the number of dropped events. + * @param the type of value that is timed. + * @return a new immutable {@code TimedEvents} + */ + public static TimedEvents create(List> events, int droppedEventsCount) { + return new AutoValue_SpanData_TimedEvents( + Collections.unmodifiableList( + new ArrayList>(checkNotNull(events, "events"))), + droppedEventsCount); + } + + /** + * Returns the list of events. + * + * @return the list of events. + */ + public abstract List> getEvents(); + + /** + * Returns the number of dropped events. + * + * @return the number of dropped events. + */ + public abstract int getDroppedEventsCount(); + + TimedEvents() {} + } + + /** A set of attributes and the number of dropped attributes representation. */ + @Immutable + @AutoValue + public abstract static class Attributes { + /** + * Returns a new immutable {@code Attributes}. + * + * @param attributeMap the set of attributes. + * @param droppedAttributesCount the number of dropped attributes. + * @return a new immutable {@code Attributes}. + */ + public static Attributes create( + Map attributeMap, int droppedAttributesCount) { + // TODO(bdrutu): Consider to use LinkedHashMap here and everywhere else, less test flakes + // for others on account of determinism. + return new AutoValue_SpanData_Attributes( + Collections.unmodifiableMap( + new HashMap(checkNotNull(attributeMap, "attributeMap"))), + droppedAttributesCount); + } + + /** + * Returns the set of attributes. + * + * @return the set of attributes. + */ + public abstract Map getAttributeMap(); + + /** + * Returns the number of dropped attributes. + * + * @return the number of dropped attributes. + */ + public abstract int getDroppedAttributesCount(); + + Attributes() {} + } + + /** A list of links and the number of dropped links representation. */ + @Immutable + @AutoValue + public abstract static class Links { + /** + * Returns a new immutable {@code Links}. + * + * @param links the list of links. + * @param droppedLinksCount the number of dropped links. + * @return a new immutable {@code Links}. + */ + public static Links create(List links, int droppedLinksCount) { + return new AutoValue_SpanData_Links( + Collections.unmodifiableList(new ArrayList(checkNotNull(links, "links"))), + droppedLinksCount); + } + + /** + * Returns the list of links. + * + * @return the list of links. + */ + public abstract List getLinks(); + + /** + * Returns the number of dropped links. + * + * @return the number of dropped links. + */ + public abstract int getDroppedLinksCount(); + + Links() {} + } +} diff --git a/api/src/main/java/io/opencensus/trace/export/SpanExporter.java b/api/src/main/java/io/opencensus/trace/export/SpanExporter.java index 199427b1..39e0a583 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanExporter.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanExporter.java @@ -14,7 +14,6 @@ package io.opencensus.trace.export; import io.opencensus.trace.Span; -import io.opencensus.trace.SpanData; import io.opencensus.trace.base.TraceOptions; import java.util.Collection; import java.util.logging.Level; diff --git a/api/src/test/java/io/opencensus/trace/SpanDataTest.java b/api/src/test/java/io/opencensus/trace/SpanDataTest.java deleted file mode 100644 index ce10c35e..00000000 --- a/api/src/test/java/io/opencensus/trace/SpanDataTest.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import io.opencensus.common.Timestamp; -import io.opencensus.trace.base.Link; -import io.opencensus.trace.base.Link.Type; -import io.opencensus.trace.SpanData.Attributes; -import io.opencensus.trace.SpanData.Links; -import io.opencensus.trace.SpanData.TimedEvent; -import io.opencensus.trace.SpanData.TimedEvents; -import io.opencensus.trace.base.Annotation; -import io.opencensus.trace.base.AttributeValue; -import io.opencensus.trace.base.NetworkEvent; -import io.opencensus.trace.base.SpanId; -import io.opencensus.trace.base.Status; -import io.opencensus.trace.base.TraceId; -import io.opencensus.trace.base.TraceOptions; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Random; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link SpanData}. */ -@RunWith(JUnit4.class) -public class SpanDataTest { - private static final Timestamp startTimestamp = Timestamp.create(123, 456); - private static final Timestamp eventTimestamp1 = Timestamp.create(123, 457); - private static final Timestamp eventTimestamp2 = Timestamp.create(123, 458); - private static final Timestamp eventTimestamp3 = Timestamp.create(123, 459); - private static final Timestamp endTimestamp = Timestamp.create(123, 460); - private static final String DISPLAY_NAME = "MySpanDisplayName"; - private static final String ANNOTATION_TEXT = "MyAnnotationText"; - private static final Annotation annotation = Annotation.fromDescription(ANNOTATION_TEXT); - private static final NetworkEvent recvNetworkEvent = - NetworkEvent.builder(NetworkEvent.Type.RECV, 1).build(); - private static final NetworkEvent sentNetworkEvent = - NetworkEvent.builder(NetworkEvent.Type.SENT, 1).build(); - private static final Status status = Status.DEADLINE_EXCEEDED.withDescription("TooSlow"); - private final Random random = new Random(1234); - private final SpanContext spanContext = - SpanContext.create( - TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); - private final SpanId parentSpanId = SpanId.generateRandomId(random); - private final Map attributesMap = new HashMap(); - private final List> annotationsList = - new LinkedList>(); - private final List> networkEventsList = - new LinkedList>(); - private final List linksList = new LinkedList(); - private Attributes attributes; - private TimedEvents annotations; - private TimedEvents networkEvents; - private Links links; - - @Before - public void setUp() { - attributesMap.put("MyAttributeKey1", AttributeValue.longAttributeValue(10)); - attributesMap.put("MyAttributeKey2", AttributeValue.booleanAttributeValue(true)); - attributes = Attributes.create(attributesMap, 1); - annotationsList.add(SpanData.TimedEvent.create(eventTimestamp1, annotation)); - annotationsList.add(SpanData.TimedEvent.create(eventTimestamp3, annotation)); - annotations = TimedEvents.create(annotationsList, 2); - networkEventsList.add(SpanData.TimedEvent.create(eventTimestamp1, recvNetworkEvent)); - networkEventsList.add(SpanData.TimedEvent.create(eventTimestamp2, sentNetworkEvent)); - networkEvents = TimedEvents.create(networkEventsList, 3); - linksList.add(Link.fromSpanContext(spanContext, Type.CHILD)); - links = Links.create(linksList, 0); - } - - @Test - public void spanData_AllValues() { - SpanData spanData = - SpanData.create( - spanContext, - parentSpanId, - true, - DISPLAY_NAME, - startTimestamp, - attributes, - annotations, - networkEvents, - links, - status, - endTimestamp); - assertThat(spanData.getContext()).isEqualTo(spanContext); - assertThat(spanData.getParentSpanId()).isEqualTo(parentSpanId); - assertThat(spanData.getHasRemoteParent()).isTrue(); - assertThat(spanData.getDisplayName()).isEqualTo(DISPLAY_NAME); - assertThat(spanData.getStartTimestamp()).isEqualTo(startTimestamp); - assertThat(spanData.getAttributes()).isEqualTo(attributes); - assertThat(spanData.getAnnotations()).isEqualTo(annotations); - assertThat(spanData.getNetworkEvents()).isEqualTo(networkEvents); - assertThat(spanData.getLinks()).isEqualTo(links); - assertThat(spanData.getStatus()).isEqualTo(status); - assertThat(spanData.getEndTimestamp()).isEqualTo(endTimestamp); - } - - @Test - public void spanData_RootActiveSpan() { - SpanData spanData = - SpanData.create( - spanContext, - null, - false, - DISPLAY_NAME, - startTimestamp, - attributes, - annotations, - networkEvents, - links, - null, - null); - assertThat(spanData.getContext()).isEqualTo(spanContext); - assertThat(spanData.getParentSpanId()).isNull(); - assertThat(spanData.getHasRemoteParent()).isFalse(); - assertThat(spanData.getDisplayName()).isEqualTo(DISPLAY_NAME); - assertThat(spanData.getStartTimestamp()).isEqualTo(startTimestamp); - assertThat(spanData.getAttributes()).isEqualTo(attributes); - assertThat(spanData.getAnnotations()).isEqualTo(annotations); - assertThat(spanData.getNetworkEvents()).isEqualTo(networkEvents); - assertThat(spanData.getLinks()).isEqualTo(links); - assertThat(spanData.getStatus()).isNull(); - assertThat(spanData.getEndTimestamp()).isNull(); - } - - @Test - public void spanData_AllDataEmpty() { - SpanData spanData = - SpanData.create( - spanContext, - parentSpanId, - false, - DISPLAY_NAME, - startTimestamp, - Attributes.create(Collections.emptyMap(), 0), - TimedEvents.create(Collections.>emptyList(), 0), - TimedEvents.create(Collections.>emptyList(), 0), - Links.create(Collections.emptyList(), 0), - status, - endTimestamp); - assertThat(spanData.getContext()).isEqualTo(spanContext); - assertThat(spanData.getParentSpanId()).isEqualTo(parentSpanId); - assertThat(spanData.getHasRemoteParent()).isFalse(); - assertThat(spanData.getDisplayName()).isEqualTo(DISPLAY_NAME); - assertThat(spanData.getStartTimestamp()).isEqualTo(startTimestamp); - assertThat(spanData.getAttributes().getAttributeMap().isEmpty()).isTrue(); - assertThat(spanData.getAnnotations().getEvents().isEmpty()).isTrue(); - assertThat(spanData.getNetworkEvents().getEvents().isEmpty()).isTrue(); - assertThat(spanData.getLinks().getLinks().isEmpty()).isTrue(); - assertThat(spanData.getStatus()).isEqualTo(status); - assertThat(spanData.getEndTimestamp()).isEqualTo(endTimestamp); - } - - @Test - public void spanDataEquals() { - SpanData allSpanData1 = - SpanData.create( - spanContext, - parentSpanId, - false, - DISPLAY_NAME, - startTimestamp, - attributes, - annotations, - networkEvents, - links, - status, - endTimestamp); - SpanData allSpanData2 = - SpanData.create( - spanContext, - parentSpanId, - false, - DISPLAY_NAME, - startTimestamp, - attributes, - annotations, - networkEvents, - links, - status, - endTimestamp); - SpanData emptySpanData = - SpanData.create( - spanContext, - parentSpanId, - false, - DISPLAY_NAME, - startTimestamp, - Attributes.create(Collections.emptyMap(), 0), - TimedEvents.create(Collections.>emptyList(), 0), - TimedEvents.create(Collections.>emptyList(), 0), - Links.create(Collections.emptyList(), 0), - status, - endTimestamp); - new EqualsTester() - .addEqualityGroup(allSpanData1, allSpanData2) - .addEqualityGroup(emptySpanData) - .testEquals(); - } - - @Test - public void spanData_ToString() { - String spanDataString = - SpanData.create( - spanContext, - parentSpanId, - false, - DISPLAY_NAME, - startTimestamp, - attributes, - annotations, - networkEvents, - links, - status, - endTimestamp) - .toString(); - assertThat(spanDataString).contains(spanContext.toString()); - assertThat(spanDataString).contains(parentSpanId.toString()); - assertThat(spanDataString).contains(DISPLAY_NAME); - assertThat(spanDataString).contains(startTimestamp.toString()); - assertThat(spanDataString).contains(attributes.toString()); - assertThat(spanDataString).contains(annotations.toString()); - assertThat(spanDataString).contains(networkEvents.toString()); - assertThat(spanDataString).contains(links.toString()); - assertThat(spanDataString).contains(status.toString()); - assertThat(spanDataString).contains(endTimestamp.toString()); - } -} diff --git a/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java b/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java new file mode 100644 index 00000000..4125801c --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2017, Google Inc. + * 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.export; + +import static com.google.common.truth.Truth.assertThat; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link ExportComponent}. */ +@RunWith(JUnit4.class) +public class ExportComponentTest { + private final ExportComponent exportComponent = ExportComponent.getNoopExportComponent(); + + @Test + public void implementationOfSpanExporter() { + assertThat(exportComponent.getSpanExporter()).isEqualTo(SpanExporter.getNoopSpanExporter()); + } + + @Test + public void implementationOfInProcessDebuggingHandler() { + assertThat(exportComponent.getInProcessDebuggingHandler()).isNull(); + } +} diff --git a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java new file mode 100644 index 00000000..1a92b0e6 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java @@ -0,0 +1,250 @@ +/* + * Copyright 2017, Google Inc. + * 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.export; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Timestamp; +import io.opencensus.trace.SpanContext; +import io.opencensus.trace.base.Annotation; +import io.opencensus.trace.base.AttributeValue; +import io.opencensus.trace.base.Link; +import io.opencensus.trace.base.Link.Type; +import io.opencensus.trace.base.NetworkEvent; +import io.opencensus.trace.base.SpanId; +import io.opencensus.trace.base.Status; +import io.opencensus.trace.base.TraceId; +import io.opencensus.trace.base.TraceOptions; +import io.opencensus.trace.export.SpanData.Attributes; +import io.opencensus.trace.export.SpanData.Links; +import io.opencensus.trace.export.SpanData.TimedEvent; +import io.opencensus.trace.export.SpanData.TimedEvents; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Random; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link SpanData}. */ +@RunWith(JUnit4.class) +public class SpanDataTest { + private static final Timestamp startTimestamp = Timestamp.create(123, 456); + private static final Timestamp eventTimestamp1 = Timestamp.create(123, 457); + private static final Timestamp eventTimestamp2 = Timestamp.create(123, 458); + private static final Timestamp eventTimestamp3 = Timestamp.create(123, 459); + private static final Timestamp endTimestamp = Timestamp.create(123, 460); + private static final String DISPLAY_NAME = "MySpanDisplayName"; + private static final String ANNOTATION_TEXT = "MyAnnotationText"; + private static final Annotation annotation = Annotation.fromDescription(ANNOTATION_TEXT); + private static final NetworkEvent recvNetworkEvent = + NetworkEvent.builder(NetworkEvent.Type.RECV, 1).build(); + private static final NetworkEvent sentNetworkEvent = + NetworkEvent.builder(NetworkEvent.Type.SENT, 1).build(); + private static final Status status = Status.DEADLINE_EXCEEDED.withDescription("TooSlow"); + private final Random random = new Random(1234); + private final SpanContext spanContext = + SpanContext.create( + TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); + private final SpanId parentSpanId = SpanId.generateRandomId(random); + private final Map attributesMap = new HashMap(); + private final List> annotationsList = + new LinkedList>(); + private final List> networkEventsList = + new LinkedList>(); + private final List linksList = new LinkedList(); + private Attributes attributes; + private TimedEvents annotations; + private TimedEvents networkEvents; + private Links links; + + @Before + public void setUp() { + attributesMap.put("MyAttributeKey1", AttributeValue.longAttributeValue(10)); + attributesMap.put("MyAttributeKey2", AttributeValue.booleanAttributeValue(true)); + attributes = Attributes.create(attributesMap, 1); + annotationsList.add(SpanData.TimedEvent.create(eventTimestamp1, annotation)); + annotationsList.add(SpanData.TimedEvent.create(eventTimestamp3, annotation)); + annotations = TimedEvents.create(annotationsList, 2); + networkEventsList.add(SpanData.TimedEvent.create(eventTimestamp1, recvNetworkEvent)); + networkEventsList.add(SpanData.TimedEvent.create(eventTimestamp2, sentNetworkEvent)); + networkEvents = TimedEvents.create(networkEventsList, 3); + linksList.add(Link.fromSpanContext(spanContext, Type.CHILD)); + links = Links.create(linksList, 0); + } + + @Test + public void spanData_AllValues() { + SpanData spanData = + SpanData.create( + spanContext, + parentSpanId, + true, + DISPLAY_NAME, + startTimestamp, + attributes, + annotations, + networkEvents, + links, + status, + endTimestamp); + assertThat(spanData.getContext()).isEqualTo(spanContext); + assertThat(spanData.getParentSpanId()).isEqualTo(parentSpanId); + assertThat(spanData.getHasRemoteParent()).isTrue(); + assertThat(spanData.getDisplayName()).isEqualTo(DISPLAY_NAME); + assertThat(spanData.getStartTimestamp()).isEqualTo(startTimestamp); + assertThat(spanData.getAttributes()).isEqualTo(attributes); + assertThat(spanData.getAnnotations()).isEqualTo(annotations); + assertThat(spanData.getNetworkEvents()).isEqualTo(networkEvents); + assertThat(spanData.getLinks()).isEqualTo(links); + assertThat(spanData.getStatus()).isEqualTo(status); + assertThat(spanData.getEndTimestamp()).isEqualTo(endTimestamp); + } + + @Test + public void spanData_RootActiveSpan() { + SpanData spanData = + SpanData.create( + spanContext, + null, + false, + DISPLAY_NAME, + startTimestamp, + attributes, + annotations, + networkEvents, + links, + null, + null); + assertThat(spanData.getContext()).isEqualTo(spanContext); + assertThat(spanData.getParentSpanId()).isNull(); + assertThat(spanData.getHasRemoteParent()).isFalse(); + assertThat(spanData.getDisplayName()).isEqualTo(DISPLAY_NAME); + assertThat(spanData.getStartTimestamp()).isEqualTo(startTimestamp); + assertThat(spanData.getAttributes()).isEqualTo(attributes); + assertThat(spanData.getAnnotations()).isEqualTo(annotations); + assertThat(spanData.getNetworkEvents()).isEqualTo(networkEvents); + assertThat(spanData.getLinks()).isEqualTo(links); + assertThat(spanData.getStatus()).isNull(); + assertThat(spanData.getEndTimestamp()).isNull(); + } + + @Test + public void spanData_AllDataEmpty() { + SpanData spanData = + SpanData.create( + spanContext, + parentSpanId, + false, + DISPLAY_NAME, + startTimestamp, + Attributes.create(Collections.emptyMap(), 0), + TimedEvents.create(Collections.>emptyList(), 0), + TimedEvents.create(Collections.>emptyList(), 0), + Links.create(Collections.emptyList(), 0), + status, + endTimestamp); + assertThat(spanData.getContext()).isEqualTo(spanContext); + assertThat(spanData.getParentSpanId()).isEqualTo(parentSpanId); + assertThat(spanData.getHasRemoteParent()).isFalse(); + assertThat(spanData.getDisplayName()).isEqualTo(DISPLAY_NAME); + assertThat(spanData.getStartTimestamp()).isEqualTo(startTimestamp); + assertThat(spanData.getAttributes().getAttributeMap().isEmpty()).isTrue(); + assertThat(spanData.getAnnotations().getEvents().isEmpty()).isTrue(); + assertThat(spanData.getNetworkEvents().getEvents().isEmpty()).isTrue(); + assertThat(spanData.getLinks().getLinks().isEmpty()).isTrue(); + assertThat(spanData.getStatus()).isEqualTo(status); + assertThat(spanData.getEndTimestamp()).isEqualTo(endTimestamp); + } + + @Test + public void spanDataEquals() { + SpanData allSpanData1 = + SpanData.create( + spanContext, + parentSpanId, + false, + DISPLAY_NAME, + startTimestamp, + attributes, + annotations, + networkEvents, + links, + status, + endTimestamp); + SpanData allSpanData2 = + SpanData.create( + spanContext, + parentSpanId, + false, + DISPLAY_NAME, + startTimestamp, + attributes, + annotations, + networkEvents, + links, + status, + endTimestamp); + SpanData emptySpanData = + SpanData.create( + spanContext, + parentSpanId, + false, + DISPLAY_NAME, + startTimestamp, + Attributes.create(Collections.emptyMap(), 0), + TimedEvents.create(Collections.>emptyList(), 0), + TimedEvents.create(Collections.>emptyList(), 0), + Links.create(Collections.emptyList(), 0), + status, + endTimestamp); + new EqualsTester() + .addEqualityGroup(allSpanData1, allSpanData2) + .addEqualityGroup(emptySpanData) + .testEquals(); + } + + @Test + public void spanData_ToString() { + String spanDataString = + SpanData.create( + spanContext, + parentSpanId, + false, + DISPLAY_NAME, + startTimestamp, + attributes, + annotations, + networkEvents, + links, + status, + endTimestamp) + .toString(); + assertThat(spanDataString).contains(spanContext.toString()); + assertThat(spanDataString).contains(parentSpanId.toString()); + assertThat(spanDataString).contains(DISPLAY_NAME); + assertThat(spanDataString).contains(startTimestamp.toString()); + assertThat(spanDataString).contains(attributes.toString()); + assertThat(spanDataString).contains(annotations.toString()); + assertThat(spanDataString).contains(networkEvents.toString()); + assertThat(spanDataString).contains(links.toString()); + assertThat(spanDataString).contains(status.toString()); + assertThat(spanDataString).contains(endTimestamp.toString()); + } +} -- cgit v1.2.3 From 82bc9cdefb378d80cfe8ad1f1ac8c72978119c66 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Wed, 14 Jun 2017 12:18:58 -0700 Subject: Split InProcessDebuggingHandler into ActiveSpans and SampleStore. (#351) --- .../trace/export/ActiveSpansExporter.java | 159 ++++++++ .../opencensus/trace/export/ExportComponent.java | 30 +- .../trace/export/InProcessDebuggingHandler.java | 416 --------------------- .../opencensus/trace/export/SampledSpanStore.java | 354 ++++++++++++++++++ .../trace/export/ExportComponentTest.java | 8 +- 5 files changed, 541 insertions(+), 426 deletions(-) create mode 100644 api/src/main/java/io/opencensus/trace/export/ActiveSpansExporter.java delete mode 100644 api/src/main/java/io/opencensus/trace/export/InProcessDebuggingHandler.java create mode 100644 api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/export/ActiveSpansExporter.java b/api/src/main/java/io/opencensus/trace/export/ActiveSpansExporter.java new file mode 100644 index 00000000..bb2edb31 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/export/ActiveSpansExporter.java @@ -0,0 +1,159 @@ +/* + * Copyright 2017, Google Inc. + * 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.export; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import io.opencensus.trace.Span; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.concurrent.Immutable; +import javax.annotation.concurrent.ThreadSafe; + +/** + * This class allows users to access in-process information about all active spans. + * + *

The active spans tracking is available for all the spans with the option {@link + * Span.Options#RECORD_EVENTS}. This functionality allows users to debug stuck operations or long + * living operations. + */ +@ThreadSafe +public abstract class ActiveSpansExporter { + + protected ActiveSpansExporter() {} + + /** + * Returns the summary of all available data such, as number of active spans. + * + * @return the summary of all available data. + */ + public abstract Summary getSummary(); + + /** + * Returns the number of active spans for every span name. + * + * @return the number of active spans for every span name. + */ + public abstract Map getNumberOfActiveSpans(); + + /** + * Returns a list of active spans that match the {@code Filter}. + * + * @param filter used to filter the returned spans. + * @return a list of active spans that match the {@code Filter}. + */ + public abstract Collection getActiveSpans(Filter filter); + + /** The summary of all available data. */ + @AutoValue + @Immutable + public abstract static class Summary { + + Summary() {} + + /** + * Returns a new instance of {@code Summary}. + * + * @param perSpanNameSummary a map with summary for each span name. + * @return a new instance of {@code Summary}. + * @throws NullPointerException if {@code perSpanNameSummary} is {@code null}. + */ + public static Summary create(Map perSpanNameSummary) { + return new AutoValue_ActiveSpansExporter_Summary( + Collections.unmodifiableMap( + new HashMap( + checkNotNull(perSpanNameSummary, "perSpanNameSummary")))); + } + + /** + * Returns a map with summary of available data for each span name. + * + * @return a map with all the span names and the summary. + */ + public abstract Map getPerSpanNameSummary(); + } + + /** Summary of all available data for a span name. */ + @AutoValue + @Immutable + public abstract static class PerSpanNameSummary { + + PerSpanNameSummary() {} + + /** + * Returns a new instance of {@code PerSpanNameSummary}. + * + * @param numActiveSpans the number of sampled spans. + * @return a new instance of {@code PerSpanNameSummary}. + * @throws IllegalArgumentException if {@code numActiveSpans} is negative. + */ + public static PerSpanNameSummary create(int numActiveSpans) { + checkArgument(numActiveSpans >= 0, "Negative numActiveSpans."); + return new AutoValue_ActiveSpansExporter_PerSpanNameSummary(numActiveSpans); + } + + /** + * Returns the number of active spans. + * + * @return the number of active spans. + */ + public abstract int getNumActiveSpans(); + } + + /** + * Filter for active spans. Used to filter results returned by the {@link #getActiveSpans(Filter)} + * request. + */ + @AutoValue + @Immutable + public abstract static class Filter { + + Filter() {} + + /** + * Returns a new instance of {@code Filter}. + * + *

Filters all the spans based on {@code spanName} and returns a maximum of {@code + * maxSpansToReturn}. + * + * @param spanName the name of the span. + * @param maxSpansToReturn the maximum number of results to be returned. {@code 0} means all. + * @return a new instance of {@code Filter}. + * @throws NullPointerException if {@code spanName} is {@code null}. + * @throws IllegalArgumentException if {@code maxSpansToReturn} is negative. + */ + public static Filter create(String spanName, int maxSpansToReturn) { + checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); + return new AutoValue_ActiveSpansExporter_Filter(spanName, maxSpansToReturn); + } + + /** + * Returns the span name. + * + * @return the span name. + */ + public abstract String getSpanName(); + + /** + * Returns the maximum number of spans to be returned. {@code 0} means all. + * + * @return the maximum number of spans to be returned. + */ + public abstract int getMaxSpansToReturn(); + } +} diff --git a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java index 03f1cc6c..99e73a6c 100644 --- a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java +++ b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java @@ -17,8 +17,8 @@ import io.opencensus.trace.base.TraceOptions; import javax.annotation.Nullable; /** - * Class that holds the implementation instances for {@link SpanExporter} and {@link - * InProcessDebuggingHandler}. + * Class that holds the implementation instances for {@link SpanExporter}, {@link + * ActiveSpansExporter} and {@link SampledSpanStore}. * *

Unless otherwise noted all methods (on component) results are cacheable. */ @@ -45,14 +45,22 @@ public abstract class ExportComponent { public abstract SpanExporter getSpanExporter(); /** - * Returns the {@link InProcessDebuggingHandler} that can be used to get useful debugging - * information such as (active spans, latency based sampled spans, error based sampled spans). + * Returns the {@link ActiveSpansExporter} that can be used to get useful debugging information + * about all the current active spans. * - * @return the {@code InProcessDebuggingHandler} or {@code null} if in-process debugging is not - * supported. + * @return the {@code ActiveSpansExporter} or {@code null} if not supported. */ @Nullable - public abstract InProcessDebuggingHandler getInProcessDebuggingHandler(); + public abstract ActiveSpansExporter getActiveSpansExporter(); + + /** + * Returns the {@link SampledSpanStore} that can be used to get useful debugging information, such + * as latency based sampled spans, error based sampled spans. + * + * @return the {@code SampledSpanStore} or {@code null} if not supported. + */ + @Nullable + public abstract SampledSpanStore getSampledSpanStore(); private static final class NoopExportComponent extends ExportComponent { @Override @@ -62,7 +70,13 @@ public abstract class ExportComponent { @Nullable @Override - public InProcessDebuggingHandler getInProcessDebuggingHandler() { + public ActiveSpansExporter getActiveSpansExporter() { + return null; + } + + @Nullable + @Override + public SampledSpanStore getSampledSpanStore() { return null; } } diff --git a/api/src/main/java/io/opencensus/trace/export/InProcessDebuggingHandler.java b/api/src/main/java/io/opencensus/trace/export/InProcessDebuggingHandler.java deleted file mode 100644 index c2e7ab1c..00000000 --- a/api/src/main/java/io/opencensus/trace/export/InProcessDebuggingHandler.java +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.export; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.auto.value.AutoValue; -import io.opencensus.trace.Span; -import io.opencensus.trace.base.Status; -import io.opencensus.trace.base.Status.CanonicalCode; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import javax.annotation.concurrent.Immutable; -import javax.annotation.concurrent.ThreadSafe; - -/** - * This class allows users to access in-process debugging information such as (getting access to all - * active spans, support latency based sampled spans and error based sampled spans). - * - *

The active spans tracking is available for all the spans with the option {@link - * Span.Options#RECORD_EVENTS}. This functionality allows users to debug stuck operations or long - * living operations. - * - *

For all completed spans with the option {@link Span.Options#RECORD_EVENTS} the library can - * store samples based on latency for succeeded operations or based on error code for failed - * operations. To activate this, users MUST manually configure all the span names for which samples - * will be collected (see {@link #registerSpanNamesForCollection(Collection)}). - */ -@ThreadSafe -public abstract class InProcessDebuggingHandler { - - InProcessDebuggingHandler() {} - - /** - * Returns the summary of all available in-process debugging data such as number of active spans, - * number of sampled spans in the latency based samples or error based samples. - * - *

Latency based sampled summary buckets and error based sampled summary buckets are available - * only for span names registered using {@link #registerSpanNamesForCollection(Collection)}. - * - * @return the summary of all available in-process debugging data. - */ - public abstract Summary getSummary(); - - /** - * Returns a list of active spans that match the {@code filter}. - * - *

Active spans are available for all the span names. - * - * @param filter used to filter the returned spans. - * @return a list of active spans that match the {@code filter}. - */ - public abstract Collection getActiveSpans(ActiveSpansFilter filter); - - /** - * Returns a list of succeeded spans (spans with {@link Status} equal to {@link Status#OK}) that - * match the {@code filter}. - * - *

Latency based sampled spans are available only for span names registered using {@link - * #registerSpanNamesForCollection(Collection)}. - * - * @param filter used to filter the returned sampled spans. - * @return a list of succeeded spans that match the {@code filter}. - */ - public abstract Collection getLatencyBasedSampledSpans( - LatencyBasedSampledSpansFilter filter); - - /** - * Returns a list of failed spans (spans with {@link Status} other than {@link Status#OK}) that - * match the {@code filter}. - * - *

Error based sampled spans are available only for span names registered using {@link - * #registerSpanNamesForCollection(Collection)}. - * - * @param filter used to filter the returned sampled spans. - * @return a list of failed spans that match the {@code filter}. - */ - public abstract Collection getErrorBasedSampledSpans( - ErrorBasedSampledSpansFilter filter); - - /** - * Appends a list of span names for which the library will collect latency based sampled spans and - * error based sampled spans. - * - *

If called multiple times the library keeps the list of unique span names from all the calls. - * - * @param spanNames list of span names for which the library will collect samples. - */ - public abstract void registerSpanNamesForCollection(Collection spanNames); - - /** - * Removes a list of span names for which the library will collect latency based sampled spans and - * error based sampled spans. - * - *

The library keeps the list of unique registered span names for which samples will be called. - * This method allows users to remove span names from that list. - * - * @param spanNames list of span names for which the library will no longer collect samples. - */ - public abstract void unregisterSpanNamesForCollection(Collection spanNames); - - /** - * The latency buckets boundaries. Samples based on latency for successful spans (the status of - * the span has a canonical code equal to {@link CanonicalCode#OK}) are collected in one of these - * latency buckets. - */ - public enum LatencyBucketBoundaries { - // Stores finished successful requests of duration within the interval [0, 10us) - ZERO_MICROSx10(0, TimeUnit.MICROSECONDS.toNanos(10)), - // Stores finished successful requests of duration within the interval [10us, 100us) - MICROSx10_MICROSx100(TimeUnit.MICROSECONDS.toNanos(10), TimeUnit.MICROSECONDS.toNanos(100)), - // Stores finished successful requests of duration within the interval [100us, 1ms) - MICROSx100_MILLIx1(TimeUnit.MICROSECONDS.toNanos(100), TimeUnit.MILLISECONDS.toNanos(1)), - // Stores finished successful requests of duration within the interval [1ms, 10ms) - MILLIx1_MILLIx10(TimeUnit.MILLISECONDS.toNanos(1), TimeUnit.MILLISECONDS.toNanos(10)), - // Stores finished successful requests of duration within the interval [10ms, 100ms) - MILLIx10_MILLIx100(TimeUnit.MILLISECONDS.toNanos(10), TimeUnit.MILLISECONDS.toNanos(100)), - // Stores finished successful requests of duration within the interval [100ms, 1sec) - MILLIx100_SECONDx1(TimeUnit.MILLISECONDS.toNanos(100), TimeUnit.SECONDS.toNanos(1)), - // Stores finished successful requests of duration within the interval [1sec, 10sec) - SECONDx1_SECONDx10(TimeUnit.SECONDS.toNanos(1), TimeUnit.SECONDS.toNanos(10)), - // Stores finished successful requests of duration within the interval [10sec, 100sec) - SECONDx10_SECONDx100(TimeUnit.SECONDS.toNanos(10), TimeUnit.SECONDS.toNanos(100)), - // Stores finished successful requests of duration >= 100sec - SECONDx100_MAX(TimeUnit.SECONDS.toNanos(100), Long.MAX_VALUE); - - /** - * Constructs a {@code LatencyBucketBoundaries} with the given boundaries and label. - * - * @param latencyLowerNs the latency lower bound of the bucket. - * @param latencyUpperNs the latency upper bound of the bucket. - */ - LatencyBucketBoundaries(long latencyLowerNs, long latencyUpperNs) { - this.latencyLowerNs = latencyLowerNs; - this.latencyUpperNs = latencyUpperNs; - } - - /** - * Returns the latency lower bound of the bucket. - * - * @return the latency lower bound of the bucket. - */ - public long getLatencyLowerNs() { - return latencyLowerNs; - } - - /** - * Returns the latency upper bound of the bucket. - * - * @return the latency upper bound of the bucket. - */ - public long getLatencyUpperNs() { - return latencyUpperNs; - } - - private final long latencyLowerNs; - private final long latencyUpperNs; - } - - /** The summary of all in-process debugging information. */ - @AutoValue - @Immutable - public abstract static class Summary { - - Summary() {} - - /** - * Returns a new instance of {@code Summary}. - * - * @param perSpanNameSummary a map with summary for each different span name. - * @return a new instance of {@code Summary}. - * @throws NullPointerException if {@code perSpanNameSummary} is {@code null}. - */ - public static Summary create(Map perSpanNameSummary) { - return new AutoValue_InProcessDebuggingHandler_Summary( - Collections.unmodifiableMap( - new HashMap( - checkNotNull(perSpanNameSummary, "perSpanNameSummary")))); - } - - /** - * Returns a map with summary of available data for each different span name. - * - * @return a map with all the span names and the summary. - */ - public abstract Map getPerSpanNameSummary(); - - /** Summary of all available data for a span name. */ - @AutoValue - @Immutable - public abstract static class PerSpanNameSummary { - - PerSpanNameSummary() {} - - /** - * Returns a new instance of {@code PerSpanNameSummary}. - * - * @param numActiveSpans the number of sampled spans. - * @param latencyBucketsSummaries the summary for the latency buckets. - * @param errorBucketsSummaries the summary for the error buckets. - * @return a new instance of {@code PerSpanNameSummary}. - * @throws NullPointerException if {@code latencyBucketSummaries} or {@code - * errorBucketSummaries} are {@code null}. - * @throws IllegalArgumentException if {@code numActiveSpans} is negative. - */ - public static Summary.PerSpanNameSummary create( - int numActiveSpans, - Map latencyBucketsSummaries, - Map errorBucketsSummaries) { - checkArgument(numActiveSpans >= 0, "Negative numActiveSpans."); - return new AutoValue_InProcessDebuggingHandler_Summary_PerSpanNameSummary( - numActiveSpans, - Collections.unmodifiableMap( - new HashMap( - checkNotNull(latencyBucketsSummaries, "latencyBucketsSummaries"))), - Collections.unmodifiableMap( - new HashMap( - checkNotNull(errorBucketsSummaries, "errorBucketsSummaries")))); - } - - /** - * Returns the number of active spans. - * - * @return the number of active spans. - */ - public abstract int getNumActiveSpans(); - - /** - * Returns the number of samples for each latency based sampled bucket. - * - * @return the number of samples for each latency based sampled bucket. - */ - public abstract Map getLatencyBucketsSummaries(); - - /** - * Returns the number of samples for each error based sampled bucket. - * - * @return the number of samples for each error based sampled bucket. - */ - public abstract Map getErrorBucketsSummaries(); - } - } - - /** - * Filter for active spans. Used to filter results returned by the {@link - * #getActiveSpans(ActiveSpansFilter)} request. - */ - @AutoValue - @Immutable - public abstract static class ActiveSpansFilter { - - ActiveSpansFilter() {} - - /** - * Returns a new instance of {@code ActiveSpansFilter}. - * - *

Filters all the spans based on {@code spanName} and returns a maximum of {@code - * maxSpansToReturn}. - * - * @param spanName the name of the span. - * @param maxSpansToReturn the maximum number of results to be returned. {@code 0} means all. - * @return a new instance of {@code ActiveSpansFilter}. - * @throws NullPointerException if {@code spanName} is {@code null}. - * @throws IllegalArgumentException if {@code maxSpansToReturn} is negative. - */ - public static ActiveSpansFilter create(String spanName, int maxSpansToReturn) { - checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); - return new AutoValue_InProcessDebuggingHandler_ActiveSpansFilter(spanName, maxSpansToReturn); - } - - /** - * Returns the span name. - * - * @return the span name. - */ - public abstract String getSpanName(); - - /** - * Returns the maximum number of spans to be returned. {@code 0} means all. - * - * @return the maximum number of spans to be returned. - */ - public abstract int getMaxSpansToReturn(); - } - - /** - * Filter for latency based sampled spans. Used to filter results returned by the {@link - * #getLatencyBasedSampledSpans(LatencyBasedSampledSpansFilter)} request. - */ - @AutoValue - @Immutable - public abstract static class LatencyBasedSampledSpansFilter { - - LatencyBasedSampledSpansFilter() {} - - /** - * Returns a new instance of {@code LatencyBasedSampledSpansFilter}. - * - *

Filters all the spans based on {@code spanName} and latency in the interval - * [latencyLowerNs, latencyUpperNs) and returns a maximum of {@code maxSpansToReturn}. - * - * @param spanName the name of the span. - * @param latencyLowerNs the latency lower bound. - * @param latencyUpperNs the latency upper bound. - * @param maxSpansToReturn the maximum number of results to be returned. {@code 0} means all. - * @return a new instance of {@code LatencyBasedSampledSpansFilter}. - * @throws NullPointerException if {@code spanName} is {@code null}. - * @throws IllegalArgumentException if {@code maxSpansToReturn} or {@code latencyLowerNs} or - * {@code latencyUpperNs} are negative. - */ - public static LatencyBasedSampledSpansFilter create( - String spanName, long latencyLowerNs, long latencyUpperNs, int maxSpansToReturn) { - checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); - checkArgument(latencyLowerNs >= 0, "Negative latencyLowerNs"); - checkArgument(latencyUpperNs >= 0, "Negative latencyUpperNs"); - return new AutoValue_InProcessDebuggingHandler_LatencyBasedSampledSpansFilter( - spanName, latencyLowerNs, latencyUpperNs, maxSpansToReturn); - } - - /** - * Returns the span name used by this filter. - * - * @return the span name used by this filter. - */ - public abstract String getSpanName(); - - /** - * Returns the latency lower bound of this bucket (inclusive). - * - * @return the latency lower bound of this bucket. - */ - public abstract long getLatencyLowerNs(); - - /** - * Returns the latency upper bound of this bucket (exclusive). - * - * @return the latency upper bound of this bucket. - */ - public abstract long getLatencyUpperNs(); - - /** - * Returns the maximum number of spans to be returned. {@code 0} means all. - * - * @return the maximum number of spans to be returned. - */ - public abstract int getMaxSpansToReturn(); - } - - /** Filter for error based sampled spans. */ - @AutoValue - @Immutable - public abstract static class ErrorBasedSampledSpansFilter { - - ErrorBasedSampledSpansFilter() {} - - /** - * Returns a new instance of {@code ErrorBasedSampledSpansFilter}. - * - *

Filters all the spans based on {@code spanName} and {@code canonicalCode} and returns a - * maximum of {@code maxSpansToReturn}. - * - * @param spanName the name of the span. - * @param canonicalCode the error code of the span. - * @param maxSpansToReturn the maximum number of results to be returned. {@code 0} means all. - * @return a new instance of {@code ErrorBasedSampledSpansFilter}. - * @throws NullPointerException if {@code spanName} or {@code canonicalCode} are {@code null}. - * @throws IllegalArgumentException if {@code canonicalCode} is {@link CanonicalCode#OK} or - * {@code maxSpansToReturn} is negative. - */ - public static ErrorBasedSampledSpansFilter create( - String spanName, CanonicalCode canonicalCode, int maxSpansToReturn) { - checkArgument(canonicalCode != CanonicalCode.OK, "Invalid canonical code."); - checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); - return new AutoValue_InProcessDebuggingHandler_ErrorBasedSampledSpansFilter( - spanName, canonicalCode, maxSpansToReturn); - } - - /** - * Returns the span name used by this filter. - * - * @return the span name used by this filter. - */ - public abstract String getSpanName(); - - /** - * Returns the canonical code used by this filter. Always different than {@link - * CanonicalCode#OK}. - * - * @return the canonical code used by this filter. - */ - public abstract CanonicalCode getCanonicalCode(); - - /** - * Returns the maximum number of spans to be returned. Used to enforce the number of returned - * {@code SpanData}. {@code 0} means all. - * - * @return the maximum number of spans to be returned. - */ - public abstract int getMaxSpansToReturn(); - } -} diff --git a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java new file mode 100644 index 00000000..1fae1750 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java @@ -0,0 +1,354 @@ +/* + * Copyright 2017, Google Inc. + * 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.export; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import io.opencensus.trace.Span; +import io.opencensus.trace.base.Status; +import io.opencensus.trace.base.Status.CanonicalCode; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import javax.annotation.concurrent.Immutable; +import javax.annotation.concurrent.ThreadSafe; + +/** + * This class allows users to access in-process information such as latency based sampled spans and + * error based sampled spans. + * + *

For all completed spans with the option {@link Span.Options#RECORD_EVENTS} the library can + * store samples based on latency for succeeded operations or based on error code for failed + * operations. To activate this, users MUST manually configure all the span names for which samples + * will be collected (see {@link #registerSpanNamesForCollection(Collection)}). + */ +@ThreadSafe +public abstract class SampledSpanStore { + + protected SampledSpanStore() {} + + /** + * Returns the summary of all available data, such as number of sampled spans in the latency based + * samples or error based samples. + * + *

Data available only for span names registered using {@link + * #registerSpanNamesForCollection(Collection)}. + * + * @return the summary of all available data. + */ + public abstract Summary getSummary(); + + /** + * Returns a list of succeeded spans (spans with {@link Status} equal to {@link Status#OK}) that + * match the {@code filter}. + * + *

Latency based sampled spans are available only for span names registered using {@link + * #registerSpanNamesForCollection(Collection)}. + * + * @param filter used to filter the returned sampled spans. + * @return a list of succeeded spans that match the {@code filter}. + */ + public abstract Collection getLatencySampledSpans(LatencyFilter filter); + + /** + * Returns a list of failed spans (spans with {@link Status} other than {@link Status#OK}) that + * match the {@code filter}. + * + *

Error based sampled spans are available only for span names registered using {@link + * #registerSpanNamesForCollection(Collection)}. + * + * @param filter used to filter the returned sampled spans. + * @return a list of failed spans that match the {@code filter}. + */ + public abstract Collection getErrorSampledSpans(ErrorFilter filter); + + /** + * Appends a list of span names for which the library will collect latency based sampled spans and + * error based sampled spans. + * + *

If called multiple times the library keeps the list of unique span names from all the calls. + * + * @param spanNames list of span names for which the library will collect samples. + */ + public abstract void registerSpanNamesForCollection(Collection spanNames); + + /** + * Removes a list of span names for which the library will collect latency based sampled spans and + * error based sampled spans. + * + *

The library keeps the list of unique registered span names for which samples will be called. + * This method allows users to remove span names from that list. + * + * @param spanNames list of span names for which the library will no longer collect samples. + */ + public abstract void unregisterSpanNamesForCollection(Collection spanNames); + + /** The summary of all available data. */ + @AutoValue + @Immutable + public abstract static class Summary { + + Summary() {} + + /** + * Returns a new instance of {@code Summary}. + * + * @param perSpanNameSummary a map with summary for each span name. + * @return a new instance of {@code Summary}. + * @throws NullPointerException if {@code perSpanNameSummary} is {@code null}. + */ + public static Summary create(Map perSpanNameSummary) { + return new AutoValue_SampledSpanStore_Summary( + Collections.unmodifiableMap( + new HashMap( + checkNotNull(perSpanNameSummary, "perSpanNameSummary")))); + } + + /** + * Returns a map with summary of available data for each span name. + * + * @return a map with all the span names and the summary. + */ + public abstract Map getPerSpanNameSummary(); + } + + /** Summary of all available data for a span name. */ + @AutoValue + @Immutable + public abstract static class PerSpanNameSummary { + + PerSpanNameSummary() {} + + /** + * Returns a new instance of {@code PerSpanNameSummary}. + * + * @param numberOfLatencySampledSpans the summary for the latency buckets. + * @param numberOfErrorSampledSpans the summary for the error buckets. + * @return a new instance of {@code PerSpanNameSummary}. + * @throws NullPointerException if {@code numberOfLatencySampledSpans} or {@code + * numberOfErrorSampledSpans} are {@code null}. + */ + public static PerSpanNameSummary create( + Map numberOfLatencySampledSpans, + Map numberOfErrorSampledSpans) { + return new AutoValue_SampledSpanStore_PerSpanNameSummary( + Collections.unmodifiableMap( + new HashMap( + checkNotNull(numberOfLatencySampledSpans, "numberOfLatencySampledSpans"))), + Collections.unmodifiableMap( + new HashMap( + checkNotNull(numberOfErrorSampledSpans, "numberOfErrorSampledSpans")))); + } + + /** + * Returns the number of sampled spans in all the latency buckets. + * + *

Data available only for span names registered using {@link + * #registerSpanNamesForCollection(Collection)}. + * + * @return the number of sampled spans in all the latency buckets. + */ + public abstract Map getNumberOfLatencySampledSpans(); + + /** + * Returns the number of sampled spans in all the error buckets. + * + *

Data available only for span names registered using {@link + * #registerSpanNamesForCollection(Collection)}. + * + * @return the number of sampled spans in all the error buckets. + */ + public abstract Map getNumberOfErrorSampledSpans(); + } + + /** + * The latency buckets boundaries. Samples based on latency for successful spans (the status of + * the span has a canonical code equal to {@link CanonicalCode#OK}) are collected in one of these + * latency buckets. + */ + public enum LatencyBucketBoundaries { + // Stores finished successful requests of duration within the interval [0, 10us) + ZERO_MICROSx10(0, TimeUnit.MICROSECONDS.toNanos(10)), + // Stores finished successful requests of duration within the interval [10us, 100us) + MICROSx10_MICROSx100(TimeUnit.MICROSECONDS.toNanos(10), TimeUnit.MICROSECONDS.toNanos(100)), + // Stores finished successful requests of duration within the interval [100us, 1ms) + MICROSx100_MILLIx1(TimeUnit.MICROSECONDS.toNanos(100), TimeUnit.MILLISECONDS.toNanos(1)), + // Stores finished successful requests of duration within the interval [1ms, 10ms) + MILLIx1_MILLIx10(TimeUnit.MILLISECONDS.toNanos(1), TimeUnit.MILLISECONDS.toNanos(10)), + // Stores finished successful requests of duration within the interval [10ms, 100ms) + MILLIx10_MILLIx100(TimeUnit.MILLISECONDS.toNanos(10), TimeUnit.MILLISECONDS.toNanos(100)), + // Stores finished successful requests of duration within the interval [100ms, 1sec) + MILLIx100_SECONDx1(TimeUnit.MILLISECONDS.toNanos(100), TimeUnit.SECONDS.toNanos(1)), + // Stores finished successful requests of duration within the interval [1sec, 10sec) + SECONDx1_SECONDx10(TimeUnit.SECONDS.toNanos(1), TimeUnit.SECONDS.toNanos(10)), + // Stores finished successful requests of duration within the interval [10sec, 100sec) + SECONDx10_SECONDx100(TimeUnit.SECONDS.toNanos(10), TimeUnit.SECONDS.toNanos(100)), + // Stores finished successful requests of duration >= 100sec + SECONDx100_MAX(TimeUnit.SECONDS.toNanos(100), Long.MAX_VALUE); + + /** + * Constructs a {@code LatencyBucketBoundaries} with the given boundaries and label. + * + * @param latencyLowerNs the latency lower bound of the bucket. + * @param latencyUpperNs the latency upper bound of the bucket. + */ + LatencyBucketBoundaries(long latencyLowerNs, long latencyUpperNs) { + this.latencyLowerNs = latencyLowerNs; + this.latencyUpperNs = latencyUpperNs; + } + + /** + * Returns the latency lower bound of the bucket. + * + * @return the latency lower bound of the bucket. + */ + public long getLatencyLowerNs() { + return latencyLowerNs; + } + + /** + * Returns the latency upper bound of the bucket. + * + * @return the latency upper bound of the bucket. + */ + public long getLatencyUpperNs() { + return latencyUpperNs; + } + + private final long latencyLowerNs; + private final long latencyUpperNs; + } + + /** + * Filter for latency based sampled spans. Used to filter results returned by the {@link + * #getLatencySampledSpans(LatencyFilter)} request. + */ + @AutoValue + @Immutable + public abstract static class LatencyFilter { + + LatencyFilter() {} + + /** + * Returns a new instance of {@code LatencyFilter}. + * + *

Filters all the spans based on {@code spanName} and latency in the interval + * [latencyLowerNs, latencyUpperNs) and returns a maximum of {@code maxSpansToReturn}. + * + * @param spanName the name of the span. + * @param latencyLowerNs the latency lower bound. + * @param latencyUpperNs the latency upper bound. + * @param maxSpansToReturn the maximum number of results to be returned. {@code 0} means all. + * @return a new instance of {@code LatencyFilter}. + * @throws NullPointerException if {@code spanName} is {@code null}. + * @throws IllegalArgumentException if {@code maxSpansToReturn} or {@code latencyLowerNs} or + * {@code latencyUpperNs} are negative. + */ + public static LatencyFilter create( + String spanName, long latencyLowerNs, long latencyUpperNs, int maxSpansToReturn) { + checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); + checkArgument(latencyLowerNs >= 0, "Negative latencyLowerNs"); + checkArgument(latencyUpperNs >= 0, "Negative latencyUpperNs"); + return new AutoValue_SampledSpanStore_LatencyFilter( + spanName, latencyLowerNs, latencyUpperNs, maxSpansToReturn); + } + + /** + * Returns the span name used by this filter. + * + * @return the span name used by this filter. + */ + public abstract String getSpanName(); + + /** + * Returns the latency lower bound of this bucket (inclusive). + * + * @return the latency lower bound of this bucket. + */ + public abstract long getLatencyLowerNs(); + + /** + * Returns the latency upper bound of this bucket (exclusive). + * + * @return the latency upper bound of this bucket. + */ + public abstract long getLatencyUpperNs(); + + /** + * Returns the maximum number of spans to be returned. {@code 0} means all. + * + * @return the maximum number of spans to be returned. + */ + public abstract int getMaxSpansToReturn(); + } + + /** + * Filter for error based sampled spans. Used to filter results returned by the {@link + * #getErrorSampledSpans(ErrorFilter)} request. + */ + @AutoValue + @Immutable + public abstract static class ErrorFilter { + + ErrorFilter() {} + + /** + * Returns a new instance of {@code ErrorFilter}. + * + *

Filters all the spans based on {@code spanName} and {@code canonicalCode} and returns a + * maximum of {@code maxSpansToReturn}. + * + * @param spanName the name of the span. + * @param canonicalCode the error code of the span. + * @param maxSpansToReturn the maximum number of results to be returned. {@code 0} means all. + * @return a new instance of {@code ErrorFilter}. + * @throws NullPointerException if {@code spanName} or {@code canonicalCode} are {@code null}. + * @throws IllegalArgumentException if {@code canonicalCode} is {@link CanonicalCode#OK} or + * {@code maxSpansToReturn} is negative. + */ + public static ErrorFilter create( + String spanName, CanonicalCode canonicalCode, int maxSpansToReturn) { + checkArgument(canonicalCode != CanonicalCode.OK, "Invalid canonical code."); + checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); + return new AutoValue_SampledSpanStore_ErrorFilter(spanName, canonicalCode, maxSpansToReturn); + } + + /** + * Returns the span name used by this filter. + * + * @return the span name used by this filter. + */ + public abstract String getSpanName(); + + /** + * Returns the canonical code used by this filter. Always different than {@link + * CanonicalCode#OK}. + * + * @return the canonical code used by this filter. + */ + public abstract CanonicalCode getCanonicalCode(); + + /** + * Returns the maximum number of spans to be returned. Used to enforce the number of returned + * {@code SpanData}. {@code 0} means all. + * + * @return the maximum number of spans to be returned. + */ + public abstract int getMaxSpansToReturn(); + } +} diff --git a/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java b/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java index 4125801c..f3a3b137 100644 --- a/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java +++ b/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java @@ -29,8 +29,12 @@ public class ExportComponentTest { assertThat(exportComponent.getSpanExporter()).isEqualTo(SpanExporter.getNoopSpanExporter()); } + public void implementationOfActiveSpans() { + assertThat(exportComponent.getActiveSpansExporter()).isNull(); + } + @Test - public void implementationOfInProcessDebuggingHandler() { - assertThat(exportComponent.getInProcessDebuggingHandler()).isNull(); + public void implementationOfSampledSpanStore() { + assertThat(exportComponent.getSampledSpanStore()).isNull(); } } -- cgit v1.2.3 From 461b4ed4a37e74a42c8ba6264807a15e36ab9dc6 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Wed, 14 Jun 2017 16:25:07 -0700 Subject: Remove method left unintentionally. (#355) --- .../main/java/io/opencensus/trace/export/ActiveSpansExporter.java | 7 ------- 1 file changed, 7 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/export/ActiveSpansExporter.java b/api/src/main/java/io/opencensus/trace/export/ActiveSpansExporter.java index bb2edb31..c6c5b8da 100644 --- a/api/src/main/java/io/opencensus/trace/export/ActiveSpansExporter.java +++ b/api/src/main/java/io/opencensus/trace/export/ActiveSpansExporter.java @@ -44,13 +44,6 @@ public abstract class ActiveSpansExporter { */ public abstract Summary getSummary(); - /** - * Returns the number of active spans for every span name. - * - * @return the number of active spans for every span name. - */ - public abstract Map getNumberOfActiveSpans(); - /** * Returns a list of active spans that match the {@code Filter}. * -- cgit v1.2.3 From 3b74070f74a75e780828370126b713524eece13c Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Thu, 15 Jun 2017 11:29:30 -0700 Subject: Prepare the release of the opencensus library. (#357) --- api/src/main/java/io/opencensus/common/Internal.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Internal.java b/api/src/main/java/io/opencensus/common/Internal.java index 9d540e21..fee892c3 100644 --- a/api/src/main/java/io/opencensus/common/Internal.java +++ b/api/src/main/java/io/opencensus/common/Internal.java @@ -20,8 +20,8 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Annotates a program element (class, method, package etc) which is internal to opencensus, not - * part of the public API, and should not be used by users of the opencensus library. + * Annotates a program element (class, method, package etc) which is internal to OpenCensus, not + * part of the public API, and should not be used by users of the OpenCensus library. */ @Internal @Retention(RetentionPolicy.SOURCE) -- cgit v1.2.3 From 5484bd0904ceb4950ed3ccd3b4c993ed2d4a8813 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Thu, 15 Jun 2017 17:09:30 -0700 Subject: Add support to load lite or full implementations. (#360) --- api/src/main/java/io/opencensus/trace/Tracing.java | 20 ++++++++++++++++++-- .../test/java/io/opencensus/trace/TracingTest.java | 4 ++-- 2 files changed, 20 insertions(+), 4 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/Tracing.java b/api/src/main/java/io/opencensus/trace/Tracing.java index 3a4be463..5255450a 100644 --- a/api/src/main/java/io/opencensus/trace/Tracing.java +++ b/api/src/main/java/io/opencensus/trace/Tracing.java @@ -24,7 +24,7 @@ import java.util.logging.Logger; /** Class that manages a global instance of the {@link TraceComponent}. */ public final class Tracing { - private static final Logger logger = Logger.getLogger(Tracer.class.getName()); + private static final Logger logger = Logger.getLogger(Tracing.class.getName()); private static final TraceComponent traceComponent = loadTraceComponent(Provider.getCorrectClassLoader(TraceComponent.class)); @@ -82,7 +82,23 @@ public final class Tracing { Class.forName("io.opencensus.trace.TraceComponentImpl", true, classLoader), TraceComponent.class); } catch (ClassNotFoundException e) { - logger.log(Level.FINE, "Using default implementation for TraceComponent.", e); + logger.log( + Level.FINE, + "Couldn't load full implementation for TraceComponent, now trying to load lite " + + "implementation.", + e); + } + try { + // Call Class.forName with literal string name of the class to help shading tools. + return Provider.createInstance( + Class.forName("io.opencensus.trace.TraceComponentImplLite", true, classLoader), + TraceComponent.class); + } catch (ClassNotFoundException e) { + logger.log( + Level.FINE, + "Couldn't load lite implementation for TraceComponent, now using " + + "default implementation for TraceComponent.", + e); } return TraceComponent.getNoopTraceComponent(); } diff --git a/api/src/test/java/io/opencensus/trace/TracingTest.java b/api/src/test/java/io/opencensus/trace/TracingTest.java index 33303896..14e2607c 100644 --- a/api/src/test/java/io/opencensus/trace/TracingTest.java +++ b/api/src/test/java/io/opencensus/trace/TracingTest.java @@ -30,7 +30,7 @@ public class TracingTest { @Rule public ExpectedException thrown = ExpectedException.none(); @Test - public void loadTraceService_UsesProvidedClassLoader() { + public void loadTraceComponent_UsesProvidedClassLoader() { final RuntimeException toThrow = new RuntimeException("UseClassLoader"); thrown.expect(RuntimeException.class); thrown.expectMessage("UseClassLoader"); @@ -44,7 +44,7 @@ public class TracingTest { } @Test - public void loadSpanFactory_IgnoresMissingClasses() { + public void loadTraceComponent_IgnoresMissingClasses() { assertThat( Tracing.loadTraceComponent( new ClassLoader() { -- cgit v1.2.3 From e49a8abc653d5a8b2eb0e04ead8cd33a6d727c12 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Fri, 16 Jun 2017 03:53:30 -0700 Subject: Enable checkstyle for all tests in io.opencensus.*. (#361) --- api/build.gradle | 3 ++- .../test/java/io/opencensus/common/DurationTest.java | 13 +++++++++++++ .../test/java/io/opencensus/common/TimestampTest.java | 13 +++++++++++++ .../test/java/io/opencensus/internal/ProviderTest.java | 2 +- api/src/test/java/io/opencensus/trace/TracingTest.java | 18 ++++++++---------- 5 files changed, 37 insertions(+), 12 deletions(-) (limited to 'api') diff --git a/api/build.gradle b/api/build.gradle index 99000c2c..8d2967bc 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -8,4 +8,5 @@ dependencies { signature "org.codehaus.mojo.signature:java16:+@signature" } -javadoc.exclude 'io/opencensus/internal/**' \ No newline at end of file +javadoc.exclude 'io/opencensus/internal/**' +javadoc.exclude 'io/opencensus/trace/internal/**' \ No newline at end of file diff --git a/api/src/test/java/io/opencensus/common/DurationTest.java b/api/src/test/java/io/opencensus/common/DurationTest.java index b9861eea..e0dd7a99 100644 --- a/api/src/test/java/io/opencensus/common/DurationTest.java +++ b/api/src/test/java/io/opencensus/common/DurationTest.java @@ -1,3 +1,16 @@ +/* + * Copyright 2017, Google Inc. + * 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.common; import static com.google.common.truth.Truth.assertThat; diff --git a/api/src/test/java/io/opencensus/common/TimestampTest.java b/api/src/test/java/io/opencensus/common/TimestampTest.java index 5a02264b..263bc66d 100644 --- a/api/src/test/java/io/opencensus/common/TimestampTest.java +++ b/api/src/test/java/io/opencensus/common/TimestampTest.java @@ -1,3 +1,16 @@ +/* + * Copyright 2017, Google Inc. + * 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.common; import static com.google.common.truth.Truth.assertThat; diff --git a/api/src/test/java/io/opencensus/internal/ProviderTest.java b/api/src/test/java/io/opencensus/internal/ProviderTest.java index f6aba5ec..30f5f0e8 100644 --- a/api/src/test/java/io/opencensus/internal/ProviderTest.java +++ b/api/src/test/java/io/opencensus/internal/ProviderTest.java @@ -20,7 +20,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** Tests for {@link Provider} */ +/** Tests for {@link Provider}. */ @RunWith(JUnit4.class) public class ProviderTest { static class GoodClass { diff --git a/api/src/test/java/io/opencensus/trace/TracingTest.java b/api/src/test/java/io/opencensus/trace/TracingTest.java index 14e2607c..be11ff5f 100644 --- a/api/src/test/java/io/opencensus/trace/TracingTest.java +++ b/api/src/test/java/io/opencensus/trace/TracingTest.java @@ -45,16 +45,14 @@ public class TracingTest { @Test public void loadTraceComponent_IgnoresMissingClasses() { - assertThat( - Tracing.loadTraceComponent( - new ClassLoader() { - @Override - public Class loadClass(String name) throws ClassNotFoundException { - throw new ClassNotFoundException(); - } - }) - .getClass() - .getName()) + ClassLoader classLoader = + new ClassLoader() { + @Override + public Class loadClass(String name) throws ClassNotFoundException { + throw new ClassNotFoundException(); + } + }; + assertThat(Tracing.loadTraceComponent(classLoader).getClass().getName()) .isEqualTo("io.opencensus.trace.TraceComponent$NoopTraceComponent"); } -- cgit v1.2.3 From a7e1b0cb733a5c6b7cbe5b90a2ab57507be0c5bd Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Fri, 16 Jun 2017 12:29:28 -0700 Subject: Rename ActiveSpansExporter to RunningSpanStore. (#362) --- .../trace/export/ActiveSpansExporter.java | 152 --------------------- .../opencensus/trace/export/ExportComponent.java | 10 +- .../opencensus/trace/export/RunningSpanStore.java | 152 +++++++++++++++++++++ .../trace/export/ExportComponentTest.java | 2 +- 4 files changed, 158 insertions(+), 158 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/trace/export/ActiveSpansExporter.java create mode 100644 api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/export/ActiveSpansExporter.java b/api/src/main/java/io/opencensus/trace/export/ActiveSpansExporter.java deleted file mode 100644 index c6c5b8da..00000000 --- a/api/src/main/java/io/opencensus/trace/export/ActiveSpansExporter.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.export; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.auto.value.AutoValue; -import io.opencensus.trace.Span; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import javax.annotation.concurrent.Immutable; -import javax.annotation.concurrent.ThreadSafe; - -/** - * This class allows users to access in-process information about all active spans. - * - *

The active spans tracking is available for all the spans with the option {@link - * Span.Options#RECORD_EVENTS}. This functionality allows users to debug stuck operations or long - * living operations. - */ -@ThreadSafe -public abstract class ActiveSpansExporter { - - protected ActiveSpansExporter() {} - - /** - * Returns the summary of all available data such, as number of active spans. - * - * @return the summary of all available data. - */ - public abstract Summary getSummary(); - - /** - * Returns a list of active spans that match the {@code Filter}. - * - * @param filter used to filter the returned spans. - * @return a list of active spans that match the {@code Filter}. - */ - public abstract Collection getActiveSpans(Filter filter); - - /** The summary of all available data. */ - @AutoValue - @Immutable - public abstract static class Summary { - - Summary() {} - - /** - * Returns a new instance of {@code Summary}. - * - * @param perSpanNameSummary a map with summary for each span name. - * @return a new instance of {@code Summary}. - * @throws NullPointerException if {@code perSpanNameSummary} is {@code null}. - */ - public static Summary create(Map perSpanNameSummary) { - return new AutoValue_ActiveSpansExporter_Summary( - Collections.unmodifiableMap( - new HashMap( - checkNotNull(perSpanNameSummary, "perSpanNameSummary")))); - } - - /** - * Returns a map with summary of available data for each span name. - * - * @return a map with all the span names and the summary. - */ - public abstract Map getPerSpanNameSummary(); - } - - /** Summary of all available data for a span name. */ - @AutoValue - @Immutable - public abstract static class PerSpanNameSummary { - - PerSpanNameSummary() {} - - /** - * Returns a new instance of {@code PerSpanNameSummary}. - * - * @param numActiveSpans the number of sampled spans. - * @return a new instance of {@code PerSpanNameSummary}. - * @throws IllegalArgumentException if {@code numActiveSpans} is negative. - */ - public static PerSpanNameSummary create(int numActiveSpans) { - checkArgument(numActiveSpans >= 0, "Negative numActiveSpans."); - return new AutoValue_ActiveSpansExporter_PerSpanNameSummary(numActiveSpans); - } - - /** - * Returns the number of active spans. - * - * @return the number of active spans. - */ - public abstract int getNumActiveSpans(); - } - - /** - * Filter for active spans. Used to filter results returned by the {@link #getActiveSpans(Filter)} - * request. - */ - @AutoValue - @Immutable - public abstract static class Filter { - - Filter() {} - - /** - * Returns a new instance of {@code Filter}. - * - *

Filters all the spans based on {@code spanName} and returns a maximum of {@code - * maxSpansToReturn}. - * - * @param spanName the name of the span. - * @param maxSpansToReturn the maximum number of results to be returned. {@code 0} means all. - * @return a new instance of {@code Filter}. - * @throws NullPointerException if {@code spanName} is {@code null}. - * @throws IllegalArgumentException if {@code maxSpansToReturn} is negative. - */ - public static Filter create(String spanName, int maxSpansToReturn) { - checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); - return new AutoValue_ActiveSpansExporter_Filter(spanName, maxSpansToReturn); - } - - /** - * Returns the span name. - * - * @return the span name. - */ - public abstract String getSpanName(); - - /** - * Returns the maximum number of spans to be returned. {@code 0} means all. - * - * @return the maximum number of spans to be returned. - */ - public abstract int getMaxSpansToReturn(); - } -} diff --git a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java index 99e73a6c..f1199e39 100644 --- a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java +++ b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java @@ -18,7 +18,7 @@ import javax.annotation.Nullable; /** * Class that holds the implementation instances for {@link SpanExporter}, {@link - * ActiveSpansExporter} and {@link SampledSpanStore}. + * RunningSpanStore} and {@link SampledSpanStore}. * *

Unless otherwise noted all methods (on component) results are cacheable. */ @@ -45,13 +45,13 @@ public abstract class ExportComponent { public abstract SpanExporter getSpanExporter(); /** - * Returns the {@link ActiveSpansExporter} that can be used to get useful debugging information + * Returns the {@link RunningSpanStore} that can be used to get useful debugging information * about all the current active spans. * - * @return the {@code ActiveSpansExporter} or {@code null} if not supported. + * @return the {@code RunningSpanStore} or {@code null} if not supported. */ @Nullable - public abstract ActiveSpansExporter getActiveSpansExporter(); + public abstract RunningSpanStore getRunningSpanStore(); /** * Returns the {@link SampledSpanStore} that can be used to get useful debugging information, such @@ -70,7 +70,7 @@ public abstract class ExportComponent { @Nullable @Override - public ActiveSpansExporter getActiveSpansExporter() { + public RunningSpanStore getRunningSpanStore() { return null; } diff --git a/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java b/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java new file mode 100644 index 00000000..19facc8a --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java @@ -0,0 +1,152 @@ +/* + * Copyright 2017, Google Inc. + * 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.export; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import io.opencensus.trace.Span; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.concurrent.Immutable; +import javax.annotation.concurrent.ThreadSafe; + +/** + * This class allows users to access in-process information about all running spans. + * + *

The running spans tracking is available for all the spans with the option {@link + * Span.Options#RECORD_EVENTS}. This functionality allows users to debug stuck operations or long + * living operations. + */ +@ThreadSafe +public abstract class RunningSpanStore { + + protected RunningSpanStore() {} + + /** + * Returns the summary of all available data such, as number of running spans. + * + * @return the summary of all available data. + */ + public abstract Summary getSummary(); + + /** + * Returns a list of running spans that match the {@code Filter}. + * + * @param filter used to filter the returned spans. + * @return a list of running spans that match the {@code Filter}. + */ + public abstract Collection getRunningSpans(Filter filter); + + /** The summary of all available data. */ + @AutoValue + @Immutable + public abstract static class Summary { + + Summary() {} + + /** + * Returns a new instance of {@code Summary}. + * + * @param perSpanNameSummary a map with summary for each span name. + * @return a new instance of {@code Summary}. + * @throws NullPointerException if {@code perSpanNameSummary} is {@code null}. + */ + public static Summary create(Map perSpanNameSummary) { + return new AutoValue_RunningSpanStore_Summary( + Collections.unmodifiableMap( + new HashMap( + checkNotNull(perSpanNameSummary, "perSpanNameSummary")))); + } + + /** + * Returns a map with summary of available data for each span name. + * + * @return a map with all the span names and the summary. + */ + public abstract Map getPerSpanNameSummary(); + } + + /** Summary of all available data for a span name. */ + @AutoValue + @Immutable + public abstract static class PerSpanNameSummary { + + PerSpanNameSummary() {} + + /** + * Returns a new instance of {@code PerSpanNameSummary}. + * + * @param numRunningSpans the number of running spans. + * @return a new instance of {@code PerSpanNameSummary}. + * @throws IllegalArgumentException if {@code numRunningSpans} is negative. + */ + public static PerSpanNameSummary create(int numRunningSpans) { + checkArgument(numRunningSpans >= 0, "Negative numRunningSpans."); + return new AutoValue_RunningSpanStore_PerSpanNameSummary(numRunningSpans); + } + + /** + * Returns the number of running spans. + * + * @return the number of running spans. + */ + public abstract int getNumRunningSpans(); + } + + /** + * Filter for running spans. Used to filter results returned by the + * {@link #getRunningSpans(Filter)} request. + */ + @AutoValue + @Immutable + public abstract static class Filter { + + Filter() {} + + /** + * Returns a new instance of {@code Filter}. + * + *

Filters all the spans based on {@code spanName} and returns a maximum of {@code + * maxSpansToReturn}. + * + * @param spanName the name of the span. + * @param maxSpansToReturn the maximum number of results to be returned. {@code 0} means all. + * @return a new instance of {@code Filter}. + * @throws NullPointerException if {@code spanName} is {@code null}. + * @throws IllegalArgumentException if {@code maxSpansToReturn} is negative. + */ + public static Filter create(String spanName, int maxSpansToReturn) { + checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); + return new AutoValue_RunningSpanStore_Filter(spanName, maxSpansToReturn); + } + + /** + * Returns the span name. + * + * @return the span name. + */ + public abstract String getSpanName(); + + /** + * Returns the maximum number of spans to be returned. {@code 0} means all. + * + * @return the maximum number of spans to be returned. + */ + public abstract int getMaxSpansToReturn(); + } +} diff --git a/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java b/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java index f3a3b137..efff03ba 100644 --- a/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java +++ b/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java @@ -30,7 +30,7 @@ public class ExportComponentTest { } public void implementationOfActiveSpans() { - assertThat(exportComponent.getActiveSpansExporter()).isNull(); + assertThat(exportComponent.getRunningSpanStore()).isNull(); } @Test -- cgit v1.2.3 From 4aa6e80c8efac571e3017b70d599eb52db23a6f3 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Fri, 16 Jun 2017 14:33:42 -0700 Subject: Move TestClock in opencensus-testing package. (#368) --- api/build.gradle | 3 +- .../java/io/opencensus/internal/TestClock.java | 99 ---------------------- .../java/io/opencensus/internal/TestClockTest.java | 62 -------------- 3 files changed, 2 insertions(+), 162 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/internal/TestClock.java delete mode 100644 api/src/test/java/io/opencensus/internal/TestClockTest.java (limited to 'api') diff --git a/api/build.gradle b/api/build.gradle index 8d2967bc..3834f051 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -1,8 +1,9 @@ -description = 'OpenCensus: API' +description = 'OpenCensus API' dependencies { compile libraries.grpc_context, libraries.guava + compileOnly libraries.auto_value signature "org.codehaus.mojo.signature:java16:+@signature" diff --git a/api/src/main/java/io/opencensus/internal/TestClock.java b/api/src/main/java/io/opencensus/internal/TestClock.java deleted file mode 100644 index d181da3a..00000000 --- a/api/src/main/java/io/opencensus/internal/TestClock.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.internal; - -import com.google.common.math.LongMath; -import io.opencensus.common.Clock; -import io.opencensus.common.Duration; -import io.opencensus.common.Timestamp; -import javax.annotation.concurrent.GuardedBy; -import javax.annotation.concurrent.ThreadSafe; - -/** A {@link Clock} that allows the time to be set for testing. */ -@ThreadSafe -public final class TestClock extends Clock { - private static final int NUM_NANOS_PER_SECOND = 1000 * 1000 * 1000; - - @GuardedBy("this") - private Timestamp currentTime = validateNanos(Timestamp.create(1493419949, 223123456)); - - private TestClock() {} - - /** - * Creates a clock initialized to a constant non-zero time. {@code Timestamp.create(0, 0)} is not - * a good default, because it represents an invalid time. - * - * @return a clock initialized to a constant non-zero time. - */ - public static TestClock create() { - return new TestClock(); - } - - /** - * Creates a clock with the given time. - * - * @param time the initial time. - * @return a new {@code TestClock} with the given time. - */ - public static TestClock create(Timestamp time) { - TestClock clock = new TestClock(); - clock.setTime(time); - return clock; - } - - /** - * Sets the time. - * - * @param time the new time. - */ - public synchronized void setTime(Timestamp time) { - currentTime = validateNanos(time); - } - - /** - * Advances the time by a duration. - * - * @param duration the increase in time. - */ - // TODO(sebright): Consider adding an 'addDuration' method to Timestamp. - public synchronized void advanceTime(Duration duration) { - currentTime = - validateNanos( - Timestamp.create( - LongMath.checkedAdd(currentTime.getSeconds(), duration.getSeconds()), - currentTime.getNanos()) - .addNanos(duration.getNanos())); - } - - @Override - public synchronized Timestamp now() { - return currentTime; - } - - @Override - public synchronized long nowNanos() { - return getNanos(currentTime); - } - - private static Timestamp validateNanos(Timestamp time) { - getNanos(time); - return time; - } - - // Converts Timestamp into nanoseconds since time 0 and throws an exception if it overflows. - private static long getNanos(Timestamp time) { - return LongMath.checkedAdd( - LongMath.checkedMultiply(time.getSeconds(), NUM_NANOS_PER_SECOND), time.getNanos()); - } -} diff --git a/api/src/test/java/io/opencensus/internal/TestClockTest.java b/api/src/test/java/io/opencensus/internal/TestClockTest.java deleted file mode 100644 index fe3f80cb..00000000 --- a/api/src/test/java/io/opencensus/internal/TestClockTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.internal; - -import static com.google.common.truth.Truth.assertThat; - -import io.opencensus.common.Duration; -import io.opencensus.common.Timestamp; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Tests for {@link TestClock}. */ -@RunWith(JUnit4.class) -public final class TestClockTest { - private static final int NUM_NANOS_PER_SECOND = 1000 * 1000 * 1000; - - @Test - public void setAndGetTime() { - TestClock clock = TestClock.create(Timestamp.create(1, 2)); - assertThat(clock.now()).isEqualTo(Timestamp.create(1, 2)); - clock.setTime(Timestamp.create(3, 4)); - assertThat(clock.now()).isEqualTo(Timestamp.create(3, 4)); - } - - @Test - public void advanceTime() { - TestClock clock = TestClock.create(Timestamp.create(1, 500 * 1000 * 1000)); - clock.advanceTime(Duration.create(2, 600 * 1000 * 1000)); - assertThat(clock.now()).isEqualTo(Timestamp.create(4, 100 * 1000 * 1000)); - } - - @Test - public void measureElapsedTime() { - TestClock clock = TestClock.create(Timestamp.create(10, 1)); - long nanos1 = clock.nowNanos(); - clock.setTime(Timestamp.create(11, 5)); - long nanos2 = clock.nowNanos(); - assertThat(nanos2 - nanos1).isEqualTo(1000 * 1000 * 1000 + 4); - } - - @Test(expected = ArithmeticException.class) - public void catchOverflow() { - TestClock.create(Timestamp.create(Long.MAX_VALUE / NUM_NANOS_PER_SECOND + 1, 0)); - } - - @Test(expected = ArithmeticException.class) - public void catchNegativeOverflow() { - TestClock.create(Timestamp.create(Long.MIN_VALUE / NUM_NANOS_PER_SECOND - 1, 0)); - } -} -- cgit v1.2.3 From 83d3453503922014fb11632788c190affa532c2c Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Mon, 19 Jun 2017 16:20:07 -0700 Subject: Clean minor things. (#372) --- api/src/main/java/io/opencensus/trace/Span.java | 5 ++--- api/src/main/java/io/opencensus/trace/base/TraceOptions.java | 5 ++--- api/src/main/java/io/opencensus/trace/config/TraceParams.java | 3 +-- .../main/java/io/opencensus/trace/export/RunningSpanStore.java | 9 ++++----- .../java/io/opencensus/trace/export/ExportComponentTest.java | 1 + 5 files changed, 10 insertions(+), 13 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/Span.java b/api/src/main/java/io/opencensus/trace/Span.java index f1661901..af6e3adb 100644 --- a/api/src/main/java/io/opencensus/trace/Span.java +++ b/api/src/main/java/io/opencensus/trace/Span.java @@ -21,7 +21,6 @@ import io.opencensus.trace.base.AttributeValue; import io.opencensus.trace.base.EndSpanOptions; import io.opencensus.trace.base.Link; import io.opencensus.trace.base.NetworkEvent; -import io.opencensus.trace.base.StartSpanOptions; import java.util.Collections; import java.util.EnumSet; import java.util.Map; @@ -51,8 +50,8 @@ public abstract class Span { */ public enum Options { /** - * This option is set if the Span is part of a sampled distributed trace OR the {@link - * StartSpanOptions#getRecordEvents()} is true. + * This option is set if the Span is part of a sampled distributed trace OR {@link + * SpanBuilder#setRecordEvents(boolean)} was called with true. */ RECORD_EVENTS; } diff --git a/api/src/main/java/io/opencensus/trace/base/TraceOptions.java b/api/src/main/java/io/opencensus/trace/base/TraceOptions.java index 57733238..3f20bb99 100644 --- a/api/src/main/java/io/opencensus/trace/base/TraceOptions.java +++ b/api/src/main/java/io/opencensus/trace/base/TraceOptions.java @@ -20,13 +20,12 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; import com.google.common.base.Objects; -import io.opencensus.trace.Span; import javax.annotation.concurrent.Immutable; /** * A class that represents global trace options. These options are propagated to all child {@link - * Span spans}. These determine features such as whether a {@code Span} should be traced. It is - * implemented as a bitmask. + * io.opencensus.trace.Span spans}. These determine features such as whether a {@code Span} should + * be traced. It is implemented as a bitmask. */ @Immutable public final class TraceOptions { diff --git a/api/src/main/java/io/opencensus/trace/config/TraceParams.java b/api/src/main/java/io/opencensus/trace/config/TraceParams.java index 74953cfd..5f1ba3b0 100644 --- a/api/src/main/java/io/opencensus/trace/config/TraceParams.java +++ b/api/src/main/java/io/opencensus/trace/config/TraceParams.java @@ -21,7 +21,6 @@ import io.opencensus.trace.base.Annotation; import io.opencensus.trace.base.Link; import io.opencensus.trace.base.NetworkEvent; import io.opencensus.trace.base.Sampler; -import io.opencensus.trace.base.StartSpanOptions; import io.opencensus.trace.samplers.Samplers; import javax.annotation.concurrent.Immutable; @@ -48,7 +47,7 @@ public abstract class TraceParams { /** * Returns the global default {@code Sampler}. Used if no {@code Sampler} is provided in {@link - * StartSpanOptions}. + * io.opencensus.trace.SpanBuilder#setSampler(Sampler)}. * * @return the global default {@code Sampler}. */ diff --git a/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java b/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java index 19facc8a..e87036c4 100644 --- a/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java @@ -17,7 +17,6 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; -import io.opencensus.trace.Span; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -29,8 +28,8 @@ import javax.annotation.concurrent.ThreadSafe; * This class allows users to access in-process information about all running spans. * *

The running spans tracking is available for all the spans with the option {@link - * Span.Options#RECORD_EVENTS}. This functionality allows users to debug stuck operations or long - * living operations. + * io.opencensus.trace.Span.Options#RECORD_EVENTS}. This functionality allows users to debug stuck + * operations or long living operations. */ @ThreadSafe public abstract class RunningSpanStore { @@ -109,8 +108,8 @@ public abstract class RunningSpanStore { } /** - * Filter for running spans. Used to filter results returned by the - * {@link #getRunningSpans(Filter)} request. + * Filter for running spans. Used to filter results returned by the {@link + * #getRunningSpans(Filter)} request. */ @AutoValue @Immutable diff --git a/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java b/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java index efff03ba..82a29b95 100644 --- a/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java +++ b/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java @@ -29,6 +29,7 @@ public class ExportComponentTest { assertThat(exportComponent.getSpanExporter()).isEqualTo(SpanExporter.getNoopSpanExporter()); } + @Test public void implementationOfActiveSpans() { assertThat(exportComponent.getRunningSpanStore()).isNull(); } -- cgit v1.2.3 From 65f8bda11b6712d42a942bb4d51fd56d618a132b Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Mon, 19 Jun 2017 19:33:35 -0700 Subject: =?UTF-8?q?Refactor=20Timestamp=20class=20to=20be=20safer.=20Add?= =?UTF-8?q?=20methods=20to=20minus=20a=20timestam=E2=80=A6=20(#367)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/io/opencensus/common/Duration.java | 90 +++++-------- .../main/java/io/opencensus/common/TimeUtil.java | 23 ++++ .../main/java/io/opencensus/common/Timestamp.java | 149 ++++++++++++--------- .../java/io/opencensus/common/TimestampTest.java | 53 ++++++++ 4 files changed, 190 insertions(+), 125 deletions(-) create mode 100644 api/src/main/java/io/opencensus/common/TimeUtil.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Duration.java b/api/src/main/java/io/opencensus/common/Duration.java index bf490c39..dad3ccdb 100644 --- a/api/src/main/java/io/opencensus/common/Duration.java +++ b/api/src/main/java/io/opencensus/common/Duration.java @@ -13,12 +13,24 @@ package io.opencensus.common; +import static io.opencensus.common.TimeUtil.MAX_NANOS; +import static io.opencensus.common.TimeUtil.MAX_SECONDS; +import static io.opencensus.common.TimeUtil.MILLIS_PER_SECOND; +import static io.opencensus.common.TimeUtil.NANOS_PER_MILLI; + +import com.google.auto.value.AutoValue; +import javax.annotation.concurrent.Immutable; + /** * Represents a signed, fixed-length span of time represented as a count of seconds and fractions of * seconds at nanosecond resolution. It is independent of any calendar and concepts like "day" or * "month". Range is approximately +-10,000 years. */ -public class Duration { +@Immutable +@AutoValue +public abstract class Duration { + private static final Duration ZERO = create(0, 0); + /** * Creates a new time duration from given seconds and nanoseconds. * @@ -29,88 +41,48 @@ public class Duration { * negative `nanos` field. For durations of one second or more, a non-zero value for the * `nanos` field must be of the same sign as the `seconds` field. Must be from -999,999,999 to * +999,999,999 inclusive. - * @return new {@link Duration} with specified fields. For invalid inputs, a {@link Duration} of + * @return new {@code Duration} with specified fields. For invalid inputs, a {@code Duration} of * zero is returned. */ public static Duration create(long seconds, int nanos) { if (seconds < -MAX_SECONDS || seconds > MAX_SECONDS) { - return new Duration(0, 0); + return ZERO; } if (nanos < -MAX_NANOS || nanos > MAX_NANOS) { - return new Duration(0, 0); + return ZERO; } if ((seconds < 0 && nanos > 0) || (seconds > 0 && nanos < 0)) { - return new Duration(0, 0); + return ZERO; } - return new Duration(seconds, nanos); + return new AutoValue_Duration(seconds, nanos); } /** - * Creates a new {@link Duration} from given milliseconds. + * Creates a new {@code Duration} from given milliseconds. * * @param millis the duration in milliseconds. - * @return a new {@link Duration} from given milliseconds. + * @return a new {@code Duration} from given milliseconds. For invalid inputs, a {@code Duration} + * of zero is returned. */ public static Duration fromMillis(long millis) { - long seconds = millis / NUM_MILLIS_PER_SECOND; - int nanos = (int) (millis % NUM_MILLIS_PER_SECOND) * NUM_NANOS_PER_MILLI; - return new Duration(seconds, nanos); + long seconds = millis / MILLIS_PER_SECOND; + int nanos = (int) (millis % MILLIS_PER_SECOND * NANOS_PER_MILLI); + return Duration.create(seconds, nanos); } /** - * Returns the number of seconds in the {@link Duration}. + * Returns the number of seconds in the {@code Duration}. * - * @return the number of seconds in the {@link Duration}. + * @return the number of seconds in the {@code Duration}. */ - public long getSeconds() { - return seconds; - } + public abstract long getSeconds(); /** - * Returns the number of nanoseconds in the {@link Duration}. + * Returns the number of nanoseconds in the {@code Duration}. * - * @return the number of nanoseconds in the {@link Duration}. + * @return the number of nanoseconds in the {@code Duration}. */ - public int getNanos() { - return nanos; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (!(obj instanceof Duration)) { - return false; - } + public abstract int getNanos(); - Duration that = (Duration) obj; - return seconds == that.seconds && nanos == that.nanos; - } - - @Override - public int hashCode() { - int result = 17; - result = 31 * result + (int) (seconds ^ (seconds >>> 32)); - result = 31 * result + nanos; - return result; - } - - @Override - public String toString() { - return "Duration<" + seconds + "," + nanos + ">"; - } - - private static final long MAX_SECONDS = 315576000000L; - private static final int MAX_NANOS = 999999999; - private static final long NUM_MILLIS_PER_SECOND = 1000L; - private static final int NUM_NANOS_PER_MILLI = 1000000; - private final long seconds; - private final int nanos; - - private Duration(long seconds, int nanos) { - this.seconds = seconds; - this.nanos = nanos; - } + Duration() {} } diff --git a/api/src/main/java/io/opencensus/common/TimeUtil.java b/api/src/main/java/io/opencensus/common/TimeUtil.java new file mode 100644 index 00000000..d3d8e647 --- /dev/null +++ b/api/src/main/java/io/opencensus/common/TimeUtil.java @@ -0,0 +1,23 @@ +/* + * Copyright 2017, Google Inc. + * 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.common; + +/** Created by bdrutu on 6/14/17. */ +final class TimeUtil { + static final long MAX_SECONDS = 315576000000L; + static final int MAX_NANOS = 999999999; + static final long MILLIS_PER_SECOND = 1000L; + static final long NANOS_PER_MILLI = 1000 * 1000; + static final long NANOS_PER_SECOND = NANOS_PER_MILLI * MILLIS_PER_SECOND; +} diff --git a/api/src/main/java/io/opencensus/common/Timestamp.java b/api/src/main/java/io/opencensus/common/Timestamp.java index 9a1dd8bb..68b5efc7 100644 --- a/api/src/main/java/io/opencensus/common/Timestamp.java +++ b/api/src/main/java/io/opencensus/common/Timestamp.java @@ -13,6 +13,15 @@ package io.opencensus.common; +import static io.opencensus.common.TimeUtil.MAX_NANOS; +import static io.opencensus.common.TimeUtil.MAX_SECONDS; +import static io.opencensus.common.TimeUtil.MILLIS_PER_SECOND; +import static io.opencensus.common.TimeUtil.NANOS_PER_MILLI; +import static io.opencensus.common.TimeUtil.NANOS_PER_SECOND; + +import com.google.auto.value.AutoValue; +import com.google.common.math.LongMath; +import java.math.RoundingMode; import javax.annotation.concurrent.Immutable; /** @@ -23,19 +32,11 @@ import javax.annotation.concurrent.Immutable; * (1970-01-01T00:00:00Z). */ @Immutable -public final class Timestamp { - private static final long MAX_SECONDS = 315576000000L; - private static final int MAX_NANOS = 999999999; - private static final long NUM_MILLIS_PER_SECOND = 1000L; - private static final int NUM_NANOS_PER_MILLI = 1000 * 1000; - private static final long NUM_NANOS_PER_SECOND = NUM_NANOS_PER_MILLI * NUM_MILLIS_PER_SECOND; - private final long seconds; - private final int nanos; - - private Timestamp(long seconds, int nanos) { - this.seconds = seconds; - this.nanos = nanos; - } +@AutoValue +public abstract class Timestamp { + private static final Timestamp EPOCH = new AutoValue_Timestamp(0, 0); + + Timestamp() {} /** * Creates a new timestamp from given seconds and nanoseconds. @@ -45,33 +46,30 @@ public final class Timestamp { * @param nanos Non-negative fractions of a second at nanosecond resolution. Negative second * values with fractions must still have non-negative nanos values that count forward in time. * Must be from 0 to 999,999,999 inclusive. - * @return new {@link Timestamp} with specified fields. For invalid inputs, a {@link Timestamp} of + * @return new {@code Timestamp} with specified fields. For invalid inputs, a {@code Timestamp} of * zero is returned. */ public static Timestamp create(long seconds, int nanos) { if (seconds < -MAX_SECONDS || seconds > MAX_SECONDS) { - return new Timestamp(0, 0); + return EPOCH; } if (nanos < 0 || nanos > MAX_NANOS) { - return new Timestamp(0, 0); + return EPOCH; } - return new Timestamp(seconds, nanos); + return new AutoValue_Timestamp(seconds, nanos); } /** * Creates a new timestamp from the given milliseconds. * - * @param millis the timestamp represented in milliseconds since epoch. - * @return a new timestamp from the given milliseconds. + * @param epochMilli the timestamp represented in milliseconds since epoch. + * @return new {@code Timestamp} with specified fields. For invalid inputs, a {@code Timestamp} of + * zero is returned. */ - public static Timestamp fromMillis(long millis) { - long seconds = millis / NUM_MILLIS_PER_SECOND; - int nanos = (int) (millis % NUM_MILLIS_PER_SECOND) * NUM_NANOS_PER_MILLI; - if (nanos < 0) { - return new Timestamp(seconds - 1, (int) (nanos + NUM_NANOS_PER_SECOND)); - } else { - return new Timestamp(seconds, nanos); - } + public static Timestamp fromMillis(long epochMilli) { + long secs = floorDiv(epochMilli, MILLIS_PER_SECOND); + int mos = (int) floorMod(epochMilli, MILLIS_PER_SECOND); + return create(secs, (int) (mos * NANOS_PER_MILLI)); // Safe int * NANOS_PER_MILLI } /** @@ -79,9 +77,7 @@ public final class Timestamp { * * @return the number of seconds since the Unix Epoch. */ - public long getSeconds() { - return seconds; - } + public abstract long getSeconds(); /** * Returns the number of nanoseconds after the number of seconds since the Unix Epoch represented @@ -89,57 +85,78 @@ public final class Timestamp { * * @return the number of nanoseconds after the number of seconds since the Unix Epoch. */ - public int getNanos() { - return nanos; - } + public abstract int getNanos(); /** * Returns a {@code Timestamp} calculated as this {@code Timestamp} plus some number of * nanoseconds. * - * @param nanos the nanoseconds to be added to the current timestamp. - * @return a {@code Timestamp} calculated as this {@code Timestamp} plus some number of - * nanoseconds. + * @param nanosToAdd the nanos to add, positive or negative. + * @return the calculated {@code Timestamp}. For invalid inputs, a {@code Timestamp} of zero is + * returned. + * @throws ArithmeticException if numeric overflow occurs. */ - public Timestamp addNanos(long nanos) { - long newSeconds = seconds + nanos / NUM_NANOS_PER_SECOND; - nanos %= NUM_NANOS_PER_SECOND; - // Cannot overflow because: abs(nanos) < NUM_NANOS_PER_SECOND AND - // this.nanos < NUM_NANOS_PER_SECOND. - long newNanos = nanos + this.nanos; - newSeconds += (newNanos / NUM_NANOS_PER_SECOND); - newNanos %= NUM_NANOS_PER_SECOND; - if (newNanos >= 0) { - return Timestamp.create(newSeconds, (int) newNanos); - } else { - return Timestamp.create(newSeconds - 1, (int) (newNanos + NUM_NANOS_PER_SECOND)); - } + public Timestamp addNanos(long nanosToAdd) { + return plus(0, nanosToAdd); + } + + /** + * Returns a {@code Timestamp} calculated as this {@code Timestamp} plus some {@code Duration}. + * + * @param duration the {@code Duration} to add. + * @return a {@code Timestamp} with the specified {@code Duration} added. + */ + public Timestamp addDuration(Duration duration) { + return plus(duration.getSeconds(), duration.getNanos()); } - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; + /** + * Returns a {@link Duration} calculated as: {@code this - timestamp}. + * + * @param timestamp the {@code Timestamp} to subtract. + * @return the calculated {@code Duration}. For invalid inputs, a {@code Duration} of zero is + * returned. + */ + public Duration subtractTimestamp(Timestamp timestamp) { + long durationSeconds = getSeconds() - timestamp.getSeconds(); + int durationNanos = getNanos() - timestamp.getNanos(); + if (durationSeconds < 0 && durationNanos > 0) { + durationSeconds += 1; + durationNanos -= NANOS_PER_SECOND; + } else if (durationSeconds > 0 && durationNanos < 0) { + durationSeconds -= 1; + durationNanos += NANOS_PER_SECOND; } + return Duration.create(durationSeconds, durationNanos); + } - if (!(obj instanceof Timestamp)) { - return false; + // Returns a Timestamp with the specified duration added. + private Timestamp plus(long secondsToAdd, long nanosToAdd) { + if ((secondsToAdd | nanosToAdd) == 0) { + return this; } + long epochSec = LongMath.checkedAdd(getSeconds(), secondsToAdd); + epochSec = LongMath.checkedAdd(epochSec, nanosToAdd / NANOS_PER_SECOND); + nanosToAdd = nanosToAdd % NANOS_PER_SECOND; + long nanoAdjustment = getNanos() + nanosToAdd; // safe int + NANOS_PER_SECOND + return ofEpochSecond(epochSec, nanoAdjustment); + } - Timestamp that = (Timestamp) obj; - return seconds == that.seconds && nanos == that.nanos; + // Returns a Timestamp calculated using seconds from the epoch and nanosecond fraction of + // second (arbitrary number of nanoseconds). + private static Timestamp ofEpochSecond(long epochSecond, long nanoAdjustment) { + long secs = LongMath.checkedAdd(epochSecond, floorDiv(nanoAdjustment, NANOS_PER_SECOND)); + int nos = (int) floorMod(nanoAdjustment, NANOS_PER_SECOND); + return create(secs, nos); } - @Override - public int hashCode() { - int result = 17; - result = 31 * result + (int) (seconds ^ (seconds >>> 32)); - result = 31 * result + nanos; - return result; + // Returns the result of dividing x by y rounded using floor. + private static long floorDiv(long x, long y) { + return LongMath.divide(x, y, RoundingMode.FLOOR); } - @Override - public String toString() { - return "Timestamp<" + seconds + "," + nanos + ">"; + // Returns the floor modulus "x - (floorDiv(x, y) * y)" + private static long floorMod(long x, long y) { + return x - floorDiv(x, y) * y; } } diff --git a/api/src/test/java/io/opencensus/common/TimestampTest.java b/api/src/test/java/io/opencensus/common/TimestampTest.java index 263bc66d..e384b5ca 100644 --- a/api/src/test/java/io/opencensus/common/TimestampTest.java +++ b/api/src/test/java/io/opencensus/common/TimestampTest.java @@ -80,6 +80,59 @@ public class TimestampTest { assertThat(timestamp.addNanos(Long.MIN_VALUE)) .isEqualTo(Timestamp.create(1234L - 9223372036L - 1, 223 + 145224192)); } + + @Test + public void timestampAddDuration() { + Timestamp timestamp = Timestamp.create(1234, 223); + assertThat(timestamp.addDuration(Duration.create(1, 0))).isEqualTo(Timestamp.create(1235, 223)); + assertThat(timestamp.addDuration(Duration.create(0, 1))).isEqualTo(Timestamp.create(1234, 224)); + assertThat(timestamp.addDuration(Duration.create(1, 1))).isEqualTo(Timestamp.create(1235, 224)); + assertThat(timestamp.addDuration(Duration.create(1, 999999900))) + .isEqualTo(Timestamp.create(1236, 123)); + } + + @Test + public void timestampAddDuration_Negative() { + Timestamp timestamp = Timestamp.create(1234, 223); + assertThat(timestamp.addDuration(Duration.create(-1234, -223))) + .isEqualTo(Timestamp.create(0, 0)); + assertThat(timestamp.addDuration(Duration.create(-1, 0))) + .isEqualTo(Timestamp.create(1233, 223)); + assertThat(timestamp.addDuration(Duration.create(-1, -1))) + .isEqualTo(Timestamp.create(1233, 222)); + assertThat(timestamp.addDuration(Duration.create(-1, -323))) + .isEqualTo(Timestamp.create(1232, 999999900)); + assertThat(timestamp.addDuration(Duration.create(-33, -999999999))) + .isEqualTo(Timestamp.create(1200, 224)); + } + + @Test + public void timestampSubtractTimestamp() { + Timestamp timestamp = Timestamp.create(1234, 223); + assertThat(timestamp.subtractTimestamp(Timestamp.create(0, 0))) + .isEqualTo(Duration.create(1234, 223)); + assertThat(timestamp.subtractTimestamp(Timestamp.create(1233, 223))) + .isEqualTo(Duration.create(1, 0)); + assertThat(timestamp.subtractTimestamp(Timestamp.create(1233, 222))) + .isEqualTo(Duration.create(1, 1)); + assertThat(timestamp.subtractTimestamp(Timestamp.create(1232, 999999900))) + .isEqualTo(Duration.create(1, 323)); + assertThat(timestamp.subtractTimestamp(Timestamp.create(1200, 224))) + .isEqualTo(Duration.create(33, 999999999)); + } + + @Test + public void timestampSubtractTimestamp_NegativeResult() { + Timestamp timestamp = Timestamp.create(1234, 223); + assertThat(timestamp.subtractTimestamp(Timestamp.create(1235, 223))) + .isEqualTo(Duration.create(-1, 0)); + assertThat(timestamp.subtractTimestamp(Timestamp.create(1234, 224))) + .isEqualTo(Duration.create(0, -1)); + assertThat(timestamp.subtractTimestamp(Timestamp.create(1235, 224))) + .isEqualTo(Duration.create(-1, -1)); + assertThat(timestamp.subtractTimestamp(Timestamp.create(1236, 123))) + .isEqualTo(Duration.create(-1, -999999900)); + } @Test public void testTimestampEqual() { -- cgit v1.2.3 From 75291d20f08159c4c426c45d7c7b4657dafc1c15 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Tue, 20 Jun 2017 11:27:04 -0700 Subject: Add initial implementation of the SampleSpanStore. (#358) --- api/src/main/java/io/opencensus/trace/base/Status.java | 9 ++++++++- .../java/io/opencensus/trace/export/SampledSpanStore.java | 15 ++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/base/Status.java b/api/src/main/java/io/opencensus/trace/base/Status.java index 6166c17c..e0ab4904 100644 --- a/api/src/main/java/io/opencensus/trace/base/Status.java +++ b/api/src/main/java/io/opencensus/trace/base/Status.java @@ -15,6 +15,7 @@ package io.opencensus.trace.base; import static com.google.common.base.Preconditions.checkNotNull; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; import com.google.common.base.Objects; import io.opencensus.trace.Span; @@ -164,7 +165,13 @@ public final class Status { return value; } - Status toStatus() { + /** + * Returns the status that has the current {@code CanonicalCode}.. + * + * @return the status that has the current {@code CanonicalCode}. + */ + @VisibleForTesting + public Status toStatus() { return STATUS_LIST.get(value); } } diff --git a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java index 1fae1750..00074a07 100644 --- a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java @@ -25,6 +25,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.ThreadSafe; @@ -314,16 +315,19 @@ public abstract class SampledSpanStore { * maximum of {@code maxSpansToReturn}. * * @param spanName the name of the span. - * @param canonicalCode the error code of the span. + * @param canonicalCode the error code of the span. {@code null} can be used to query all + * error codes. * @param maxSpansToReturn the maximum number of results to be returned. {@code 0} means all. * @return a new instance of {@code ErrorFilter}. - * @throws NullPointerException if {@code spanName} or {@code canonicalCode} are {@code null}. + * @throws NullPointerException if {@code spanName} is {@code null}. * @throws IllegalArgumentException if {@code canonicalCode} is {@link CanonicalCode#OK} or * {@code maxSpansToReturn} is negative. */ public static ErrorFilter create( - String spanName, CanonicalCode canonicalCode, int maxSpansToReturn) { - checkArgument(canonicalCode != CanonicalCode.OK, "Invalid canonical code."); + String spanName, @Nullable CanonicalCode canonicalCode, int maxSpansToReturn) { + if (canonicalCode != null) { + checkArgument(canonicalCode != CanonicalCode.OK, "Invalid canonical code."); + } checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); return new AutoValue_SampledSpanStore_ErrorFilter(spanName, canonicalCode, maxSpansToReturn); } @@ -337,10 +341,11 @@ public abstract class SampledSpanStore { /** * Returns the canonical code used by this filter. Always different than {@link - * CanonicalCode#OK}. + * CanonicalCode#OK}. If {@code null} then all errors match. * * @return the canonical code used by this filter. */ + @Nullable public abstract CanonicalCode getCanonicalCode(); /** -- cgit v1.2.3 From 57bec530f351009a796b579ea69898b890a2fc49 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Tue, 20 Jun 2017 19:18:06 -0700 Subject: Change getNumberOf -> getNumbersOf in SampledSpanStore. (#378) --- .../opencensus/trace/export/SampledSpanStore.java | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java index 00074a07..0a47f4dd 100644 --- a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java @@ -138,22 +138,22 @@ public abstract class SampledSpanStore { /** * Returns a new instance of {@code PerSpanNameSummary}. * - * @param numberOfLatencySampledSpans the summary for the latency buckets. - * @param numberOfErrorSampledSpans the summary for the error buckets. + * @param numbersOfLatencySampledSpans the summary for the latency buckets. + * @param numbersOfErrorSampledSpans the summary for the error buckets. * @return a new instance of {@code PerSpanNameSummary}. - * @throws NullPointerException if {@code numberOfLatencySampledSpans} or {@code - * numberOfErrorSampledSpans} are {@code null}. + * @throws NullPointerException if {@code numbersOfLatencySampledSpans} or {@code + * numbersOfErrorSampledSpans} are {@code null}. */ public static PerSpanNameSummary create( - Map numberOfLatencySampledSpans, - Map numberOfErrorSampledSpans) { + Map numbersOfLatencySampledSpans, + Map numbersOfErrorSampledSpans) { return new AutoValue_SampledSpanStore_PerSpanNameSummary( Collections.unmodifiableMap( new HashMap( - checkNotNull(numberOfLatencySampledSpans, "numberOfLatencySampledSpans"))), + checkNotNull(numbersOfLatencySampledSpans, "numbersOfLatencySampledSpans"))), Collections.unmodifiableMap( new HashMap( - checkNotNull(numberOfErrorSampledSpans, "numberOfErrorSampledSpans")))); + checkNotNull(numbersOfErrorSampledSpans, "numbersOfErrorSampledSpans")))); } /** @@ -164,7 +164,7 @@ public abstract class SampledSpanStore { * * @return the number of sampled spans in all the latency buckets. */ - public abstract Map getNumberOfLatencySampledSpans(); + public abstract Map getNumbersOfLatencySampledSpans(); /** * Returns the number of sampled spans in all the error buckets. @@ -174,7 +174,7 @@ public abstract class SampledSpanStore { * * @return the number of sampled spans in all the error buckets. */ - public abstract Map getNumberOfErrorSampledSpans(); + public abstract Map getNumbersOfErrorSampledSpans(); } /** @@ -315,8 +315,8 @@ public abstract class SampledSpanStore { * maximum of {@code maxSpansToReturn}. * * @param spanName the name of the span. - * @param canonicalCode the error code of the span. {@code null} can be used to query all - * error codes. + * @param canonicalCode the error code of the span. {@code null} can be used to query all error + * codes. * @param maxSpansToReturn the maximum number of results to be returned. {@code 0} means all. * @return a new instance of {@code ErrorFilter}. * @throws NullPointerException if {@code spanName} is {@code null}. -- cgit v1.2.3 From 831b9ce3122268c4f689700b851f1b6d73bcacfe Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Thu, 22 Jun 2017 00:24:00 -0700 Subject: Fix Tracing method name to get ExportComponent (#382) --- api/src/main/java/io/opencensus/trace/Tracing.java | 2 +- api/src/test/java/io/opencensus/trace/TracingTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/Tracing.java b/api/src/main/java/io/opencensus/trace/Tracing.java index 5255450a..869fae48 100644 --- a/api/src/main/java/io/opencensus/trace/Tracing.java +++ b/api/src/main/java/io/opencensus/trace/Tracing.java @@ -60,7 +60,7 @@ public final class Tracing { * * @return the global {@code ExportComponent}. */ - public static ExportComponent getTraceExporter() { + public static ExportComponent getExportComponent() { return traceComponent.getExportComponent(); } diff --git a/api/src/test/java/io/opencensus/trace/TracingTest.java b/api/src/test/java/io/opencensus/trace/TracingTest.java index be11ff5f..10891f2f 100644 --- a/api/src/test/java/io/opencensus/trace/TracingTest.java +++ b/api/src/test/java/io/opencensus/trace/TracingTest.java @@ -69,7 +69,7 @@ public class TracingTest { @Test public void defaultTraceExporter() { - assertThat(Tracing.getTraceExporter()).isSameAs(ExportComponent.getNoopExportComponent()); + assertThat(Tracing.getExportComponent()).isSameAs(ExportComponent.getNoopExportComponent()); } @Test -- cgit v1.2.3 From 286ab5aedb270eb516a2ce761eb6ed956bba1ff8 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Wed, 28 Jun 2017 13:33:44 +0200 Subject: Add compareTo to Timestamp. (#392) * Add compareTo to Timestamp. * Update Timestamp.java Javadoc edits. * Update Timestamp.java Fix the long line that broke the appveyor build. * Fix comments --- .../main/java/io/opencensus/common/Timestamp.java | 23 +++++++++++++++++++++- .../java/io/opencensus/common/TimestampTest.java | 17 +++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Timestamp.java b/api/src/main/java/io/opencensus/common/Timestamp.java index 68b5efc7..5cdfeea0 100644 --- a/api/src/main/java/io/opencensus/common/Timestamp.java +++ b/api/src/main/java/io/opencensus/common/Timestamp.java @@ -33,7 +33,7 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue -public abstract class Timestamp { +public abstract class Timestamp implements Comparable { private static final Timestamp EPOCH = new AutoValue_Timestamp(0, 0); Timestamp() {} @@ -130,6 +130,27 @@ public abstract class Timestamp { return Duration.create(durationSeconds, durationNanos); } + /** + * Compares this {@code Timestamp} to the specified {@code Timestamp}. + * + * @param otherTimestamp the other {@code Timestamp} to compare to, not {@code null}. + * @return the comparator value: zero if equal, negative if this timestamp happens + * before otherTimestamp, positive if after. + * @throws NullPointerException if otherTimestamp is {@code null}. + */ + @Override + public int compareTo(Timestamp otherTimestamp) { + int cmp = compareLong(getSeconds(), otherTimestamp.getSeconds()); + if (cmp != 0) { + return cmp; + } + return compareLong(getNanos(), otherTimestamp.getNanos()); + } + + private static int compareLong(long x, long y) { + return (x < y) ? -1 : ((x == y) ? 0 : 1); + } + // Returns a Timestamp with the specified duration added. private Timestamp plus(long secondsToAdd, long nanosToAdd) { if ((secondsToAdd | nanosToAdd) == 0) { diff --git a/api/src/test/java/io/opencensus/common/TimestampTest.java b/api/src/test/java/io/opencensus/common/TimestampTest.java index e384b5ca..6936247e 100644 --- a/api/src/test/java/io/opencensus/common/TimestampTest.java +++ b/api/src/test/java/io/opencensus/common/TimestampTest.java @@ -135,7 +135,22 @@ public class TimestampTest { } @Test - public void testTimestampEqual() { + public void timestamp_CompareTo() { + assertThat(Timestamp.create(0, 0).compareTo(Timestamp.create(0, 0))).isEqualTo(0); + assertThat(Timestamp.create(24, 42).compareTo(Timestamp.create(24, 42))).isEqualTo(0); + assertThat(Timestamp.create(-24, 42).compareTo(Timestamp.create(-24, 42))).isEqualTo(0); + assertThat(Timestamp.create(25, 42).compareTo(Timestamp.create(24, 42))).isEqualTo(1); + assertThat(Timestamp.create(24, 45).compareTo(Timestamp.create(24, 42))).isEqualTo(1); + assertThat(Timestamp.create(24, 42).compareTo(Timestamp.create(25, 42))).isEqualTo(-1); + assertThat(Timestamp.create(24, 42).compareTo(Timestamp.create(24, 45))).isEqualTo(-1); + assertThat(Timestamp.create(-25, 42).compareTo(Timestamp.create(-24, 42))).isEqualTo(-1); + assertThat(Timestamp.create(-24, 45).compareTo(Timestamp.create(-24, 42))).isEqualTo(1); + assertThat(Timestamp.create(-24, 42).compareTo(Timestamp.create(-25, 42))).isEqualTo(1); + assertThat(Timestamp.create(-24, 42).compareTo(Timestamp.create(-24, 45))).isEqualTo(-1); + } + + @Test + public void timestamp_Equal() { // Positive tests. assertThat(Timestamp.create(0, 0)).isEqualTo(Timestamp.create(0, 0)); assertThat(Timestamp.create(24, 42)).isEqualTo(Timestamp.create(24, 42)); -- cgit v1.2.3 From 07d69996286f6800be2d3977571cac0a80bb4e7c Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Fri, 30 Jun 2017 11:12:56 -0700 Subject: Change API to remove the "Option" logic and keep only Builder. (#380) --- .../main/java/io/opencensus/trace/SpanBuilder.java | 111 +++++-------- api/src/main/java/io/opencensus/trace/Tracer.java | 67 ++++---- .../io/opencensus/trace/base/StartSpanOptions.java | 122 -------------- .../io/opencensus/trace/internal/SpanFactory.java | 47 ------ .../java/io/opencensus/trace/SpanBuilderTest.java | 179 --------------------- .../test/java/io/opencensus/trace/TracerTest.java | 137 +++++----------- .../trace/base/StartSpanOptionsTest.java | 114 ------------- 7 files changed, 105 insertions(+), 672 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/trace/base/StartSpanOptions.java delete mode 100644 api/src/main/java/io/opencensus/trace/internal/SpanFactory.java delete mode 100644 api/src/test/java/io/opencensus/trace/SpanBuilderTest.java delete mode 100644 api/src/test/java/io/opencensus/trace/base/StartSpanOptionsTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java index 782248ba..f573d9a6 100644 --- a/api/src/main/java/io/opencensus/trace/SpanBuilder.java +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -13,11 +13,11 @@ package io.opencensus.trace; +import static com.google.common.base.Preconditions.checkNotNull; + import io.opencensus.common.NonThrowingCloseable; import io.opencensus.trace.base.EndSpanOptions; import io.opencensus.trace.base.Sampler; -import io.opencensus.trace.base.StartSpanOptions; -import io.opencensus.trace.internal.SpanFactory; import java.util.List; import javax.annotation.Nullable; @@ -102,34 +102,15 @@ import javax.annotation.Nullable; *

If your Java version is less than Java SE 7, see {@link SpanBuilder#startSpan} and {@link * SpanBuilder#startScopedSpan} for usage examples. */ -public final class SpanBuilder { - private final SpanFactory spanFactory; - private final String name; - private final StartSpanOptions.Builder startSpanOptionsBuilder = StartSpanOptions.builder(); - private Span parentSpan; - private SpanContext parentSpanContext; - private boolean remoteParent; - - static SpanBuilder builder(SpanFactory spanFactory, Span parentSpan, String name) { - return new SpanBuilder(spanFactory, parentSpan, null, false, name); - } - - static SpanBuilder builderWithRemoteParent( - SpanFactory spanFactory, SpanContext parentSpanContext, String name) { - return new SpanBuilder(spanFactory, null, parentSpanContext, true, name); - } +public abstract class SpanBuilder { /** - * Sets the {@link Sampler} to use. If a {@code null} value is passed, the implementation will - * provide a default. + * Sets the {@link Sampler} to use. If not set, the implementation will provide a default. * * @param sampler The {@code Sampler} to use when determining sampling for a {@code Span}. * @return this. */ - public SpanBuilder setSampler(@Nullable Sampler sampler) { - startSpanOptionsBuilder.setSampler(sampler); - return this; - } + public abstract SpanBuilder setSampler(Sampler sampler); /** * Sets the {@code List} of parent links. Links are used to link {@link Span}s in different @@ -138,11 +119,9 @@ public final class SpanBuilder { * * @param parentLinks New links to be added. * @return this. + * @throws NullPointerException if {@code parentLinks} is {@code null}. */ - public SpanBuilder setParentLinks(@Nullable List parentLinks) { - startSpanOptionsBuilder.setParentLinks(parentLinks); - return this; - } + public abstract SpanBuilder setParentLinks(List parentLinks); /** * Sets the option {@link Span.Options#RECORD_EVENTS} for the newly created {@code Span}. If not @@ -151,27 +130,7 @@ public final class SpanBuilder { * @param recordEvents New value determining if this {@code Span} should have events recorded. * @return this. */ - public SpanBuilder setRecordEvents(boolean recordEvents) { - startSpanOptionsBuilder.setRecordEvents(recordEvents); - return this; - } - - /** - * If called this will force the newly created {@code Span} to be a root span. As a consequence, - * any parent specified (or inherited from the Context) will be ignored (N.B. does not apply to - * linked parents set through {@link #setParentLinks}). - * - *

This is useful when {@link Tracer#spanBuilder(String)} is used and the newly created {@code - * Span} needs to be decoupled from the parent {@code Span}. - * - * @return this. - */ - public SpanBuilder becomeRoot() { - parentSpan = null; - parentSpanContext = null; - remoteParent = false; - return this; - } + public abstract SpanBuilder setRecordEvents(boolean recordEvents); /** * Starts a new {@link Span}. @@ -201,9 +160,7 @@ public final class SpanBuilder { * * @return the newly created {@code Span}. */ - public Span startSpan() { - return start(); - } + public abstract Span startSpan(); // TODO(bdrutu): Add error_prone annotation @MustBeClosed when the 2.0.16 jar is fixed. /** @@ -260,28 +217,38 @@ public final class SpanBuilder { * @return an object that defines a scope where the newly created {@code Span} will be set to the * current Context. */ - public NonThrowingCloseable startScopedSpan() { - return new ScopedSpanHandle(start()); + public final NonThrowingCloseable startScopedSpan() { + return new ScopedSpanHandle(startSpan()); } - private SpanBuilder( - SpanFactory spanFactory, - @Nullable Span parentSpan, - @Nullable SpanContext parentSpanContext, - boolean remoteParent, - String name) { - this.parentSpan = parentSpan; - this.parentSpanContext = parentSpanContext; - this.remoteParent = remoteParent; - this.name = name; - this.spanFactory = spanFactory; - } + static final class NoopSpanBuilder extends SpanBuilder { + NoopSpanBuilder(@Nullable Span parentSpan, String name) { + checkNotNull(name, "name"); + } + + NoopSpanBuilder(SpanContext remoteParentSpanContext, String name) { + checkNotNull(remoteParentSpanContext, "remoteParentSpanContext"); + checkNotNull(name, "name"); + } + + @Override + public Span startSpan() { + return BlankSpan.INSTANCE; + } + + @Override + public SpanBuilder setSampler(@Nullable Sampler sampler) { + return this; + } + + @Override + public SpanBuilder setParentLinks(List parentLinks) { + return this; + } - // Utility method to start a Span. - private Span start() { - return remoteParent - ? spanFactory.startSpanWithRemoteParent( - parentSpanContext, name, startSpanOptionsBuilder.build()) - : spanFactory.startSpan(parentSpan, name, startSpanOptionsBuilder.build()); + @Override + public SpanBuilder setRecordEvents(boolean recordEvents) { + return this; + } } } diff --git a/api/src/main/java/io/opencensus/trace/Tracer.java b/api/src/main/java/io/opencensus/trace/Tracer.java index e6172bed..ef5616a9 100644 --- a/api/src/main/java/io/opencensus/trace/Tracer.java +++ b/api/src/main/java/io/opencensus/trace/Tracer.java @@ -16,8 +16,6 @@ package io.opencensus.trace; import static com.google.common.base.Preconditions.checkNotNull; import io.opencensus.common.NonThrowingCloseable; -import io.opencensus.trace.base.StartSpanOptions; -import io.opencensus.trace.internal.SpanFactory; import javax.annotation.Nullable; /** @@ -67,7 +65,6 @@ import javax.annotation.Nullable; */ public abstract class Tracer { private static final NoopTracer noopTracer = new NoopTracer(); - private final SpanFactory spanFactory; /** * Returns the no-op implementation of the {@code Tracer}. @@ -142,7 +139,7 @@ public abstract class Tracer { * @param span The {@link Span} to be set to the current Context. * @return an object that defines a scope where the given {@link Span} will be set to the current * Context. - * @throws NullPointerException if span is null. + * @throws NullPointerException if {@code span} is null. */ public final NonThrowingCloseable withSpan(Span span) { return ContextUtils.withSpan(checkNotNull(span, "span")); @@ -150,7 +147,7 @@ public abstract class Tracer { /** * Returns a {@link SpanBuilder} to create and start a new child {@link Span} as a child of to the - * current {@code Span} if any, otherwise create a root Span with the default options. + * current {@code Span} if any, otherwise creates a root {@code Span}. * *

See {@link SpanBuilder} for usage examples. * @@ -159,7 +156,7 @@ public abstract class Tracer { * * @param name The name of the returned Span. * @return a {@code SpanBuilder} to create and start a new {@code Span}. - * @throws NullPointerException if name is null. + * @throws NullPointerException if {@code name} is null. */ public final SpanBuilder spanBuilder(String name) { return spanBuilder(ContextUtils.getCurrentSpan(), name); @@ -167,64 +164,60 @@ public abstract class Tracer { /** * Returns a {@link SpanBuilder} to create and start a new child {@link Span} (or root if parent - * is null), with parent being the designated {@code Span}. + * is {@code null} or has an invalid {@link SpanContext}), with parent being the designated {@code + * Span}. * *

See {@link SpanBuilder} for usage examples. * - *

This must be used to create a {@code Span} when manual Context propagation is used. + *

This must be used to create a {@code Span} when manual Context propagation is used + * OR when creating a root {@code Span} with a {@code null} parent. * * @param parent The parent of the returned Span. If null the {@code SpanBuilder} will build a * root {@code Span}. * @param name The name of the returned Span. * @return a {@code SpanBuilder} to create and start a new {@code Span}. - * @throws NullPointerException if name is null. + * @throws NullPointerException if {@code name} is null. */ - public final SpanBuilder spanBuilder(@Nullable Span parent, String name) { - return SpanBuilder.builder(spanFactory, parent, checkNotNull(name, "name")); - } + public abstract SpanBuilder spanBuilder(@Nullable Span parent, String name); /** * Returns a {@link SpanBuilder} to create and start a new child {@link Span} (or root if parent - * is null), with parent being the {@link Span} designated by the {@link SpanContext}. + * is an invalid {@link SpanContext}), with parent being the {@link Span} designated by the {@link + * SpanContext}. * *

See {@link SpanBuilder} for usage examples. * *

This must be used to create a {@code Span} when the parent is in a different process. * This is only intended for use by RPC systems or similar. * - * @param remoteParent The remote parent of the returned Span. + *

If no {@link SpanContext} OR fail to parse the {@link SpanContext} on the server side, + * users must call this method with an {@link SpanContext#INVALID} remote parent {@code + * SpanContext}. + * + * @param remoteParentSpanContext The remote parent of the returned Span. * @param name The name of the returned Span. * @return a {@code SpanBuilder} to create and start a new {@code Span}. - * @throws NullPointerException if name is null. + * @throws NullPointerException if {@code name} or {@code remoteParentSpanContext} are null. */ - public final SpanBuilder spanBuilderWithRemoteParent( - @Nullable SpanContext remoteParent, String name) { - return SpanBuilder.builderWithRemoteParent( - spanFactory, remoteParent, checkNotNull(name, "name")); - } + public abstract SpanBuilder spanBuilderWithRemoteParent( + SpanContext remoteParentSpanContext, String name); // No-Op implementation of the Tracer. private static final class NoopTracer extends Tracer { - private NoopTracer() { - super(new NoopSpanFactory()); - } - // No-op implementation of the SpanFactory - private static final class NoopSpanFactory extends SpanFactory { - @Override - public Span startSpan(@Nullable Span parent, String name, StartSpanOptions options) { - return BlankSpan.INSTANCE; - } + @Override + public SpanBuilder spanBuilder(@Nullable Span parent, String name) { + return new SpanBuilder.NoopSpanBuilder(parent, name); + } - @Override - public Span startSpanWithRemoteParent( - @Nullable SpanContext remoteParent, String name, StartSpanOptions options) { - return BlankSpan.INSTANCE; - } + @Override + public SpanBuilder spanBuilderWithRemoteParent( + SpanContext remoteParentSpanContext, String name) { + return new SpanBuilder.NoopSpanBuilder(remoteParentSpanContext, name); } - } - protected Tracer(SpanFactory spanFactory) { - this.spanFactory = checkNotNull(spanFactory, "spanFactory"); + private NoopTracer() {} } + + protected Tracer() {} } diff --git a/api/src/main/java/io/opencensus/trace/base/StartSpanOptions.java b/api/src/main/java/io/opencensus/trace/base/StartSpanOptions.java deleted file mode 100644 index 518f1e60..00000000 --- a/api/src/main/java/io/opencensus/trace/base/StartSpanOptions.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * 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.base; - -import com.google.auto.value.AutoValue; -import com.google.common.annotations.VisibleForTesting; -import io.opencensus.trace.Span; -import io.opencensus.trace.config.TraceConfig; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; - -/** - * A class that enables overriding the default values used when starting a {@link Span}. Allows - * overriding the {@link Sampler sampler}, the parent links, and option to record all the events - * even if the {@code Span} is not sampled. - */ -@AutoValue -@Immutable -public abstract class StartSpanOptions { - private static final List EMPTY_PARENT_LINKS_LIST = Collections.emptyList(); - - /** The default {@code StartSpanOptions}. */ - @VisibleForTesting public static final StartSpanOptions DEFAULT = builder().build(); - - /** - * Returns the {@link Sampler} to be used, or {@code null} if default. - * - * @return the {@code Sampler} to be used, or {@code null} if default. - */ - @Nullable - public abstract Sampler getSampler(); - - /** - * Returns the parent links to be set for the {@link Span}. - * - * @return the parent links to be set for the {@code Span}. - */ - public abstract List getParentLinks(); - - /** - * Returns the record events option, or {@code null} if default. - * - *

See {@link Span.Options#RECORD_EVENTS} for more details. - * - * @return the record events option, or {@code null} if default. - */ - @Nullable - public abstract Boolean getRecordEvents(); - - /** - * Returns a new {@link Builder} with default options. - * - * @return a new {@code Builder} with default options. - */ - public static Builder builder() { - return new AutoValue_StartSpanOptions.Builder().setParentLinks(EMPTY_PARENT_LINKS_LIST); - } - - /** Builder class for {@link StartSpanOptions}. */ - @AutoValue.Builder - public abstract static class Builder { - - /** - * Sets the {@link Sampler} to be used. If {@code null} the default {@code Sampler} from the - * {@link TraceConfig#getActiveTraceParams()} will be used. - * - * @param sampler the {@link Sampler} to be used. - * @return this. - */ - public abstract Builder setSampler(@Nullable Sampler sampler); - - /** - * Sets the parent links to be set for the {@link Span}. - * - * @param parentLinks the parent links to be set for the {@link Span}. - * @return this. - * @throws NullPointerException if {@code parentLinks} is {@code null}. - */ - public abstract Builder setParentLinks(List parentLinks); - - /** - * Sets the record events option. If {@code null} the default value from the {@link - * TraceConfig#getActiveTraceParams()} will be used. - * - *

See {@link Span.Options#RECORD_EVENTS} for more details. - * - * @param recordEvents the record events option. - * @return this. - */ - public abstract Builder setRecordEvents(@Nullable Boolean recordEvents); - - abstract List getParentLinks(); // not public - - abstract StartSpanOptions autoBuild(); // not public - - /** - * Builds and returns a {@code StartSpanOptions} with the desired settings. - * - * @return a {@code StartSpanOptions} with the desired settings. - */ - public StartSpanOptions build() { - setParentLinks(Collections.unmodifiableList(new ArrayList(getParentLinks()))); - return autoBuild(); - } - } - - StartSpanOptions() {} -} diff --git a/api/src/main/java/io/opencensus/trace/internal/SpanFactory.java b/api/src/main/java/io/opencensus/trace/internal/SpanFactory.java deleted file mode 100644 index a0306152..00000000 --- a/api/src/main/java/io/opencensus/trace/internal/SpanFactory.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.internal; - -import io.opencensus.trace.Span; -import io.opencensus.trace.SpanContext; -import io.opencensus.trace.base.StartSpanOptions; -import javax.annotation.Nullable; - -/** Factory class to create and start a {@link Span}. */ -public abstract class SpanFactory { - /** - * Creates and starts a new child {@link Span} (or root if parent is {@code null}), with parent - * being the designated {@code Span} and the given options. - * - * @param parent The parent of the returned {@code Span}. - * @param name The name of the returned {@code Span}. - * @param options The options for the start of the {@code Span}. - * @return A child {@code Span} that will have the name provided. - */ - public abstract Span startSpan(@Nullable Span parent, String name, StartSpanOptions options); - - /** - * Creates and starts a new child {@link Span} (or root if parent is {@code null}), with parent - * being the {@code Span} designated by the {@link SpanContext} and the given options. - * - *

This must be used to create a {@code Span} when the parent is on a different process. - * - * @param remoteParent The remote parent of the returned {@code Span}. - * @param name The name of the returned {@code Span}. - * @param options The options for the start of the {@code Span}. - * @return A child {@code Span} that will have the name provided. - */ - public abstract Span startSpanWithRemoteParent( - @Nullable SpanContext remoteParent, String name, StartSpanOptions options); -} diff --git a/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java b/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java deleted file mode 100644 index 10eccbe6..00000000 --- a/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isNull; -import static org.mockito.Matchers.same; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import io.opencensus.common.NonThrowingCloseable; -import io.opencensus.trace.base.EndSpanOptions; -import io.opencensus.trace.base.SpanId; -import io.opencensus.trace.base.StartSpanOptions; -import io.opencensus.trace.base.TraceId; -import io.opencensus.trace.base.TraceOptions; -import io.opencensus.trace.internal.SpanFactory; -import io.opencensus.trace.samplers.Samplers; -import java.util.Arrays; -import java.util.List; -import java.util.Random; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** Unit tests for {@link Tracer}. */ -@RunWith(JUnit4.class) -public class SpanBuilderTest { - private static final String SPAN_NAME = "MySpanName"; - private static final Tracer tracer = Tracing.getTracer(); - private final Random random = new Random(1234); - private final SpanContext spanContext = - SpanContext.create( - TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); - @Mock private Span span; - @Mock private SpanFactory spanFactory; - private SpanBuilder spanBuilder; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - spanBuilder = SpanBuilder.builder(spanFactory, BlankSpan.INSTANCE, SPAN_NAME); - } - - @Test - public void startScopedSpanRoot() { - when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) - .thenReturn(span); - NonThrowingCloseable ss = spanBuilder.becomeRoot().startScopedSpan(); - try { - assertThat(tracer.getCurrentSpan()).isSameAs(span); - } finally { - ss.close(); - } - verify(span).end(same(EndSpanOptions.DEFAULT)); - } - - @Test - public void startScopedSpanRootWithOptions() { - StartSpanOptions startSpanOptions = - StartSpanOptions.builder().setSampler(Samplers.neverSample()).build(); - when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(startSpanOptions))) - .thenReturn(span); - NonThrowingCloseable ss = - spanBuilder.becomeRoot().setSampler(Samplers.neverSample()).startScopedSpan(); - try { - assertThat(tracer.getCurrentSpan()).isSameAs(span); - } finally { - ss.close(); - } - verify(span).end(same(EndSpanOptions.DEFAULT)); - } - - @Test - public void startRootSpan() { - when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) - .thenReturn(span); - Span rootSpan = spanBuilder.becomeRoot().startSpan(); - assertThat(rootSpan).isEqualTo(span); - rootSpan.end(); - verify(span).end(same(EndSpanOptions.DEFAULT)); - } - - @Test - public void startSpan_WithNullParent() { - spanBuilder = SpanBuilder.builder(spanFactory, null, SPAN_NAME); - when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) - .thenReturn(span); - Span rootSpan = spanBuilder.startSpan(); - assertThat(rootSpan).isEqualTo(span); - rootSpan.end(); - verify(span).end(same(EndSpanOptions.DEFAULT)); - } - - @Test - public void startRootSpanWithOptions() { - List parentList = Arrays.asList(BlankSpan.INSTANCE); - StartSpanOptions startSpanOptions = - StartSpanOptions.builder() - .setSampler(Samplers.neverSample()) - .setParentLinks(parentList) - .build(); - when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(startSpanOptions))) - .thenReturn(span); - Span rootSpan = - spanBuilder - .becomeRoot() - .setSampler(Samplers.neverSample()) - .setParentLinks(parentList) - .startSpan(); - assertThat(rootSpan).isEqualTo(span); - rootSpan.end(); - verify(span).end(same(EndSpanOptions.DEFAULT)); - } - - @Test - public void startChildSpan() { - when(spanFactory.startSpan( - same(BlankSpan.INSTANCE), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) - .thenReturn(span); - Span childSpan = spanBuilder.startSpan(); - assertThat(childSpan).isEqualTo(span); - childSpan.end(); - verify(span).end(same(EndSpanOptions.DEFAULT)); - } - - @Test - public void startChildSpanWithOptions() { - StartSpanOptions startSpanOptions = - StartSpanOptions.builder().setSampler(Samplers.neverSample()).setRecordEvents(true).build(); - ; - when(spanFactory.startSpan(same(BlankSpan.INSTANCE), same(SPAN_NAME), eq(startSpanOptions))) - .thenReturn(span); - Span childSpan = - spanBuilder.setSampler(Samplers.neverSample()).setRecordEvents(true).startSpan(); - assertThat(childSpan).isEqualTo(span); - childSpan.end(); - verify(span).end(same(EndSpanOptions.DEFAULT)); - } - - @Test - public void startSpanWitRemoteParent() { - spanBuilder = SpanBuilder.builderWithRemoteParent(spanFactory, spanContext, SPAN_NAME); - when(spanFactory.startSpanWithRemoteParent( - same(spanContext), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) - .thenReturn(span); - Span remoteChildSpan = spanBuilder.startSpan(); - assertThat(remoteChildSpan).isEqualTo(span); - remoteChildSpan.end(); - verify(span).end(same(EndSpanOptions.DEFAULT)); - } - - @Test - public void startSpanWitRemoteParent_WithNullParent() { - spanBuilder = SpanBuilder.builderWithRemoteParent(spanFactory, null, SPAN_NAME); - when(spanFactory.startSpanWithRemoteParent( - isNull(SpanContext.class), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) - .thenReturn(span); - Span remoteChildSpan = spanBuilder.startSpan(); - assertThat(remoteChildSpan).isEqualTo(span); - remoteChildSpan.end(); - verify(span).end(same(EndSpanOptions.DEFAULT)); - } -} diff --git a/api/src/test/java/io/opencensus/trace/TracerTest.java b/api/src/test/java/io/opencensus/trace/TracerTest.java index 7339eae2..3c69068b 100644 --- a/api/src/test/java/io/opencensus/trace/TracerTest.java +++ b/api/src/test/java/io/opencensus/trace/TracerTest.java @@ -14,21 +14,11 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isNull; import static org.mockito.Matchers.same; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import io.grpc.Context; import io.opencensus.common.NonThrowingCloseable; -import io.opencensus.trace.base.EndSpanOptions; -import io.opencensus.trace.base.SpanId; -import io.opencensus.trace.base.StartSpanOptions; -import io.opencensus.trace.base.TraceId; -import io.opencensus.trace.base.TraceOptions; -import io.opencensus.trace.internal.SpanFactory; -import java.util.Random; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -41,10 +31,11 @@ import org.mockito.MockitoAnnotations; /** Unit tests for {@link Tracer}. */ @RunWith(JUnit4.class) public class TracerTest { - private static final Tracer tracer = Tracing.getTracer(); + private static final Tracer noopTracer = Tracer.getNoopTracer(); private static final String SPAN_NAME = "MySpanName"; @Rule public ExpectedException thrown = ExpectedException.none(); - @Mock private SpanFactory spanFactory; + @Mock private Tracer tracer; + @Mock private SpanBuilder spanBuilder; @Mock private Span span; @Before @@ -54,163 +45,107 @@ public class TracerTest { @Test public void defaultGetCurrentSpan() { - assertThat(tracer.getCurrentSpan()).isEqualTo(BlankSpan.INSTANCE); + assertThat(noopTracer.getCurrentSpan()).isEqualTo(BlankSpan.INSTANCE); } @Test(expected = NullPointerException.class) public void withSpan_NullSpan() { - tracer.withSpan(null); + noopTracer.withSpan(null); } @Test public void getCurrentSpan_WithSpan() { - assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); - NonThrowingCloseable ws = tracer.withSpan(span); + assertThat(noopTracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + NonThrowingCloseable ws = noopTracer.withSpan(span); try { - assertThat(tracer.getCurrentSpan()).isSameAs(span); + assertThat(noopTracer.getCurrentSpan()).isSameAs(span); } finally { ws.close(); } - assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + assertThat(noopTracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); } @Test public void propagationViaRunnable() { - Runnable runnable = null; - NonThrowingCloseable ws = tracer.withSpan(span); + Runnable runnable; + NonThrowingCloseable ws = noopTracer.withSpan(span); try { - assertThat(tracer.getCurrentSpan()).isSameAs(span); + assertThat(noopTracer.getCurrentSpan()).isSameAs(span); runnable = Context.current() .wrap( new Runnable() { @Override public void run() { - assertThat(tracer.getCurrentSpan()).isSameAs(span); + assertThat(noopTracer.getCurrentSpan()).isSameAs(span); } }); } finally { ws.close(); } - assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + assertThat(noopTracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); // When we run the runnable we will have the span in the current Context. runnable.run(); - assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + assertThat(noopTracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); } @Test(expected = NullPointerException.class) public void spanBuilderWithName_NullName() { - assertThat(tracer.spanBuilder(null).startSpan()).isSameAs(BlankSpan.INSTANCE); + noopTracer.spanBuilder(null); } @Test public void defaultSpanBuilderWithName() { - assertThat(tracer.spanBuilder(SPAN_NAME).startSpan()).isSameAs(BlankSpan.INSTANCE); + assertThat(noopTracer.spanBuilder(SPAN_NAME).startSpan()).isSameAs(BlankSpan.INSTANCE); } @Test(expected = NullPointerException.class) public void spanBuilderWithParentAndName_NullName() { - assertThat(tracer.spanBuilder(null, null).startSpan()).isSameAs(BlankSpan.INSTANCE); + noopTracer.spanBuilder(null, null); } @Test public void defaultSpanBuilderWithParentAndName() { - assertThat(tracer.spanBuilder(null, SPAN_NAME).startSpan()).isSameAs(BlankSpan.INSTANCE); + assertThat(noopTracer.spanBuilder(null, SPAN_NAME).startSpan()).isSameAs(BlankSpan.INSTANCE); } @Test(expected = NullPointerException.class) public void spanBuilderWithRemoteParent_NullName() { - assertThat(tracer.spanBuilderWithRemoteParent(null, null).startSpan()) - .isSameAs(BlankSpan.INSTANCE); + noopTracer.spanBuilderWithRemoteParent(null, null); + } + + @Test(expected = NullPointerException.class) + public void defaultSpanBuilderWitRemoteParent_NullParent() { + noopTracer.spanBuilderWithRemoteParent(null, SPAN_NAME); } @Test - public void defaultSpanBuilderWitRemoteParent() { - assertThat(tracer.spanBuilderWithRemoteParent(null, SPAN_NAME).startSpan()) + public void defaultSpanBuilderWithRemoteParent() { + assertThat(noopTracer.spanBuilderWithRemoteParent(SpanContext.INVALID, SPAN_NAME).startSpan()) .isSameAs(BlankSpan.INSTANCE); } @Test - public void startScopedSpanRoot() { - Tracer mockTracer = new MockTracer(spanFactory); - when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) - .thenReturn(span); - NonThrowingCloseable ss = mockTracer.spanBuilder(SPAN_NAME).becomeRoot().startScopedSpan(); + public void startSpanWithParentFromContext() { + NonThrowingCloseable ws = tracer.withSpan(span); try { assertThat(tracer.getCurrentSpan()).isSameAs(span); + when(tracer.spanBuilder(same(span), same(SPAN_NAME))).thenReturn(spanBuilder); + assertThat(tracer.spanBuilder(SPAN_NAME)).isSameAs(spanBuilder); } finally { - ss.close(); + ws.close(); } - verify(span).end(same(EndSpanOptions.DEFAULT)); } @Test - public void startScopedSpanChild() { - Tracer mockTracer = new MockTracer(spanFactory); - NonThrowingCloseable ws = mockTracer.withSpan(BlankSpan.INSTANCE); + public void startSpanWithInvalidParentFromContext() { + NonThrowingCloseable ws = tracer.withSpan(BlankSpan.INSTANCE); try { assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); - when(spanFactory.startSpan( - same(BlankSpan.INSTANCE), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) - .thenReturn(span); - NonThrowingCloseable ss = mockTracer.spanBuilder(SPAN_NAME).startScopedSpan(); - try { - assertThat(tracer.getCurrentSpan()).isSameAs(span); - } finally { - ss.close(); - } - assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + when(tracer.spanBuilder(same(BlankSpan.INSTANCE), same(SPAN_NAME))).thenReturn(spanBuilder); + assertThat(tracer.spanBuilder(SPAN_NAME)).isSameAs(spanBuilder); } finally { ws.close(); } - verify(span).end(same(EndSpanOptions.DEFAULT)); - } - - @Test - public void startRootSpan() { - Tracer mockTracer = new MockTracer(spanFactory); - when(spanFactory.startSpan(isNull(Span.class), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) - .thenReturn(span); - Span rootSpan = mockTracer.spanBuilder(BlankSpan.INSTANCE, SPAN_NAME).becomeRoot().startSpan(); - assertThat(rootSpan).isEqualTo(span); - rootSpan.end(); - verify(span).end(same(EndSpanOptions.DEFAULT)); - } - - @Test - public void startChildSpan() { - Tracer mockTracer = new MockTracer(spanFactory); - when(spanFactory.startSpan( - same(BlankSpan.INSTANCE), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) - .thenReturn(span); - Span childSpan = mockTracer.spanBuilder(BlankSpan.INSTANCE, SPAN_NAME).startSpan(); - assertThat(childSpan).isEqualTo(span); - childSpan.end(); - verify(span).end(same(EndSpanOptions.DEFAULT)); - } - - @Test - public void startSpanWitRemoteParent() { - Random random = new Random(1234); - Tracer mockTracer = new MockTracer(spanFactory); - SpanContext spanContext = - SpanContext.create( - TraceId.generateRandomId(random), - SpanId.generateRandomId(random), - TraceOptions.DEFAULT); - when(spanFactory.startSpanWithRemoteParent( - same(spanContext), same(SPAN_NAME), eq(StartSpanOptions.DEFAULT))) - .thenReturn(span); - Span remoteChildSpan = - mockTracer.spanBuilderWithRemoteParent(spanContext, SPAN_NAME).startSpan(); - assertThat(remoteChildSpan).isEqualTo(span); - remoteChildSpan.end(); - verify(span).end(same(EndSpanOptions.DEFAULT)); - } - - private static final class MockTracer extends Tracer { - private MockTracer(SpanFactory spanFactory) { - super(spanFactory); - } } } diff --git a/api/src/test/java/io/opencensus/trace/base/StartSpanOptionsTest.java b/api/src/test/java/io/opencensus/trace/base/StartSpanOptionsTest.java deleted file mode 100644 index 1a983b73..00000000 --- a/api/src/test/java/io/opencensus/trace/base/StartSpanOptionsTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.base; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import io.opencensus.trace.BlankSpan; -import io.opencensus.trace.Span; -import io.opencensus.trace.samplers.Samplers; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link StartSpanOptions}. */ -@RunWith(JUnit4.class) -public class StartSpanOptionsTest { - private final List singleParentList = Arrays.asList(BlankSpan.INSTANCE); - - @Test - public void defaultOptions() { - StartSpanOptions defaultOptions = StartSpanOptions.builder().build(); - assertThat(defaultOptions.getSampler()).isNull(); - assertThat(defaultOptions.getParentLinks().isEmpty()).isTrue(); - assertThat(defaultOptions.getRecordEvents()).isNull(); - } - - @Test - public void setSampler() { - StartSpanOptions options = - StartSpanOptions.builder().setSampler(Samplers.neverSample()).build(); - assertThat(options.getSampler()).isEqualTo(Samplers.neverSample()); - assertThat(options.getParentLinks().isEmpty()).isTrue(); - assertThat(options.getRecordEvents()).isNull(); - } - - @Test - public void setParentLinks() { - StartSpanOptions options = StartSpanOptions.builder().setParentLinks(singleParentList).build(); - assertThat(options.getSampler()).isNull(); - assertThat(options.getParentLinks()).isEqualTo(singleParentList); - assertThat(options.getRecordEvents()).isNull(); - } - - @Test - public void setParentLinks_EmptyList() { - StartSpanOptions options = - StartSpanOptions.builder().setParentLinks(new LinkedList()).build(); - assertThat(options.getSampler()).isNull(); - assertThat(options.getParentLinks().size()).isEqualTo(0); - assertThat(options.getRecordEvents()).isNull(); - } - - @Test - public void setParentLinks_MultipleParents() { - StartSpanOptions options = - StartSpanOptions.builder() - .setParentLinks(Arrays.asList(BlankSpan.INSTANCE, BlankSpan.INSTANCE)) - .build(); - assertThat(options.getSampler()).isNull(); - assertThat(options.getParentLinks().size()).isEqualTo(2); - assertThat(options.getRecordEvents()).isNull(); - } - - @Test - public void setRecordEvents() { - StartSpanOptions options = StartSpanOptions.builder().setRecordEvents(true).build(); - assertThat(options.getSampler()).isNull(); - assertThat(options.getParentLinks().isEmpty()).isTrue(); - assertThat(options.getRecordEvents()).isTrue(); - } - - @Test - public void setAllProperties() { - StartSpanOptions options = - StartSpanOptions.builder() - .setSampler(Samplers.alwaysSample()) - .setRecordEvents(true) - .setParentLinks(singleParentList) - .build(); - assertThat(options.getSampler()).isEqualTo(Samplers.alwaysSample()); - assertThat(options.getParentLinks()).isEqualTo(singleParentList); - assertThat(options.getRecordEvents()).isTrue(); - } - - @Test - public void startSpanOptions_EqualsAndHashCode() { - EqualsTester tester = new EqualsTester(); - StartSpanOptions optionsWithAlwaysSampler1 = - StartSpanOptions.builder().setSampler(Samplers.alwaysSample()).build(); - StartSpanOptions optionsWithAlwaysSampler2 = - StartSpanOptions.builder().setSampler(Samplers.alwaysSample()).build(); - tester.addEqualityGroup(optionsWithAlwaysSampler1, optionsWithAlwaysSampler2); - StartSpanOptions optionsWithNeverSampler = - StartSpanOptions.builder().setSampler(Samplers.neverSample()).build(); - tester.addEqualityGroup(optionsWithNeverSampler); - tester.addEqualityGroup(StartSpanOptions.DEFAULT); - tester.testEquals(); - } -} -- cgit v1.2.3 From f93d676f532e1a351eb8028bf8441b9e2cb165d9 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Mon, 3 Jul 2017 15:28:24 -0700 Subject: Change tracer API names to create a SpanBuilder. (#407) --- .../main/java/io/opencensus/trace/SpanBuilder.java | 34 ++++++----- api/src/main/java/io/opencensus/trace/Tracer.java | 65 ++++++++++++---------- .../opencensus/trace/propagation/BinaryFormat.java | 2 +- .../test/java/io/opencensus/trace/TracerTest.java | 20 ++++--- 4 files changed, 67 insertions(+), 54 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java index f573d9a6..be55906f 100644 --- a/api/src/main/java/io/opencensus/trace/SpanBuilder.java +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -86,14 +86,14 @@ import javax.annotation.Nullable; *

{@code
  * class MyClass {
  *   private static final Tracer tracer = Tracing.getTracer();
- *   void DoWork() {
- *     Span span = tracer.spanBuilder(null, "MyRootSpan").startSpan();
- *     span.addAnnotation("my annotation");
+ *   void DoWork(Span parent) {
+ *     Span childSpan = tracer.spanBuilderWithExplicitParent("MyChildSpan", parent).startSpan();
+ *     childSpan.addAnnotation("my annotation");
  *     try {
- *       doSomeWork(span); // Manually propagate the new span down the stack.
+ *       doSomeWork(childSpan); // Manually propagate the new span down the stack.
  *     } finally {
  *       // To make sure we end the span even in case of an exception.
- *       span.end();  // Manually end the span.
+ *       childSpan.end();  // Manually end the span.
  *     }
  *   }
  * }
@@ -145,14 +145,14 @@ public abstract class SpanBuilder {
    * 
{@code
    * class MyClass {
    *   private static final Tracer tracer = Tracing.getTracer();
-   *   void DoWork() {
-   *     Span span = tracer.spanBuilder(null, "MyRootSpan").startSpan();
-   *     span.addAnnotation("my annotation");
+   *   void DoWork(Span parent) {
+   *     Span childSpan = tracer.spanBuilderWithExplicitParent("MyChildSpan", parent).startSpan();
+   *     childSpan.addAnnotation("my annotation");
    *     try {
-   *       doSomeWork(span); // Manually propagate the new span down the stack.
+   *       doSomeWork(childSpan); // Manually propagate the new span down the stack.
    *     } finally {
    *       // To make sure we end the span even in case of an exception.
-   *       span.end();  // Manually end the span.
+   *       childSpan.end();  // Manually end the span.
    *     }
    *   }
    * }
@@ -222,13 +222,13 @@ public abstract class SpanBuilder {
   }
 
   static final class NoopSpanBuilder extends SpanBuilder {
-    NoopSpanBuilder(@Nullable Span parentSpan, String name) {
-      checkNotNull(name, "name");
+    static NoopSpanBuilder createWithParent(String spanName, @Nullable Span parent) {
+      return new NoopSpanBuilder(spanName);
     }
 
-    NoopSpanBuilder(SpanContext remoteParentSpanContext, String name) {
-      checkNotNull(remoteParentSpanContext, "remoteParentSpanContext");
-      checkNotNull(name, "name");
+    static NoopSpanBuilder createWithRemoteParent(
+        String spanName, @Nullable SpanContext remoteParentSpanContext) {
+      return new NoopSpanBuilder(spanName);
     }
 
     @Override
@@ -250,5 +250,9 @@ public abstract class SpanBuilder {
     public SpanBuilder setRecordEvents(boolean recordEvents) {
       return this;
     }
+
+    private NoopSpanBuilder(String name) {
+      checkNotNull(name, "name");
+    }
   }
 }
diff --git a/api/src/main/java/io/opencensus/trace/Tracer.java b/api/src/main/java/io/opencensus/trace/Tracer.java
index ef5616a9..97cd0998 100644
--- a/api/src/main/java/io/opencensus/trace/Tracer.java
+++ b/api/src/main/java/io/opencensus/trace/Tracer.java
@@ -16,6 +16,7 @@ package io.opencensus.trace;
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import io.opencensus.common.NonThrowingCloseable;
+import io.opencensus.trace.SpanBuilder.NoopSpanBuilder;
 import javax.annotation.Nullable;
 
 /**
@@ -49,15 +50,14 @@ import javax.annotation.Nullable;
  * 
{@code
  * class MyClass {
  *   private static final Tracer tracer = Tracing.getTracer();
- *   void doWork() {
- *     Span span = tracer.spanBuilder(null, "MyRootSpan").startSpan();
- *     span.addAnnotation("Starting the work.");
+ *   void doWork(Span parent) {
+ *     Span childSpan = tracer.spanBuilderWithExplicitParent("MyChildSpan", parent).startSpan();
+ *     childSpan.addAnnotation("Starting the work.");
  *     try {
- *       doSomeWork(span); // Manually propagate the new span down the stack.
+ *       doSomeWork(childSpan); // Manually propagate the new span down the stack.
  *     } finally {
- *       span.addAnnotation("Finished working.");
  *       // To make sure we end the span even in case of an exception.
- *       span.end();  // Manually end the span.
+ *       childSpan.end();  // Manually end the span.
  *     }
  *   }
  * }
@@ -139,7 +139,7 @@ public abstract class Tracer {
    * @param span The {@link Span} to be set to the current Context.
    * @return an object that defines a scope where the given {@link Span} will be set to the current
    *     Context.
-   * @throws NullPointerException if {@code span} is null.
+   * @throws NullPointerException if {@code span} is {@code null}.
    */
   public final NonThrowingCloseable withSpan(Span span) {
     return ContextUtils.withSpan(checkNotNull(span, "span"));
@@ -154,12 +154,18 @@ public abstract class Tracer {
    * 

This must be used to create a {@code Span} when automatic Context propagation is * used. * - * @param name The name of the returned Span. + *

This is equivalent with: + * + *

{@code
+   * tracer.spanBuilderWithExplicitParent("MySpanName",tracer.getCurrentSpan());
+   * }
+ * + * @param spanName The name of the returned Span. * @return a {@code SpanBuilder} to create and start a new {@code Span}. - * @throws NullPointerException if {@code name} is null. + * @throws NullPointerException if {@code spanName} is {@code null}. */ - public final SpanBuilder spanBuilder(String name) { - return spanBuilder(ContextUtils.getCurrentSpan(), name); + public final SpanBuilder spanBuilder(String spanName) { + return spanBuilderWithExplicitParent(spanName, ContextUtils.getCurrentSpan()); } /** @@ -169,51 +175,50 @@ public abstract class Tracer { * *

See {@link SpanBuilder} for usage examples. * - *

This must be used to create a {@code Span} when manual Context propagation is used - * OR when creating a root {@code Span} with a {@code null} parent. + *

This must be used to create a {@code Span} when manual Context propagation is used OR + * when creating a root {@code Span} with a {@code null} parent. * - * @param parent The parent of the returned Span. If null the {@code SpanBuilder} will build a - * root {@code Span}. - * @param name The name of the returned Span. + * @param spanName The name of the returned Span. + * @param parent The parent of the returned Span. If {@code null} the {@code SpanBuilder} will + * build a root {@code Span}. * @return a {@code SpanBuilder} to create and start a new {@code Span}. - * @throws NullPointerException if {@code name} is null. + * @throws NullPointerException if {@code spanName} is {@code null}. */ - public abstract SpanBuilder spanBuilder(@Nullable Span parent, String name); + public abstract SpanBuilder spanBuilderWithExplicitParent(String spanName, @Nullable Span parent); /** * Returns a {@link SpanBuilder} to create and start a new child {@link Span} (or root if parent - * is an invalid {@link SpanContext}), with parent being the {@link Span} designated by the {@link - * SpanContext}. + * is {@link SpanContext#INVALID} or {@code null}), with parent being the remote {@link Span} + * designated by the {@link SpanContext}. * *

See {@link SpanBuilder} for usage examples. * *

This must be used to create a {@code Span} when the parent is in a different process. * This is only intended for use by RPC systems or similar. * - *

If no {@link SpanContext} OR fail to parse the {@link SpanContext} on the server side, - * users must call this method with an {@link SpanContext#INVALID} remote parent {@code - * SpanContext}. + *

If no {@link SpanContext} OR fail to parse the {@link SpanContext} on the server side, users + * must call this method with a {@code null} remote parent {@code SpanContext}. * + * @param spanName The name of the returned Span. * @param remoteParentSpanContext The remote parent of the returned Span. - * @param name The name of the returned Span. * @return a {@code SpanBuilder} to create and start a new {@code Span}. - * @throws NullPointerException if {@code name} or {@code remoteParentSpanContext} are null. + * @throws NullPointerException if {@code spanName} is {@code null}. */ public abstract SpanBuilder spanBuilderWithRemoteParent( - SpanContext remoteParentSpanContext, String name); + String spanName, @Nullable SpanContext remoteParentSpanContext); // No-Op implementation of the Tracer. private static final class NoopTracer extends Tracer { @Override - public SpanBuilder spanBuilder(@Nullable Span parent, String name) { - return new SpanBuilder.NoopSpanBuilder(parent, name); + public SpanBuilder spanBuilderWithExplicitParent(String spanName, @Nullable Span parent) { + return NoopSpanBuilder.createWithParent(spanName, parent); } @Override public SpanBuilder spanBuilderWithRemoteParent( - SpanContext remoteParentSpanContext, String name) { - return new SpanBuilder.NoopSpanBuilder(remoteParentSpanContext, name); + String spanName, @Nullable SpanContext remoteParentSpanContext) { + return NoopSpanBuilder.createWithRemoteParent(spanName, remoteParentSpanContext); } private NoopTracer() {} diff --git a/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java b/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java index d34f69f9..284576ec 100644 --- a/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java +++ b/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java @@ -52,7 +52,7 @@ import java.text.ParseException; * // Maybe log the exception. * } * try (NonThrowingCloseable ss = - * tracer.spanBuilderWithRemoteParent(spanContext, "Recv.MyRequest").startScopedSpan()) { + * tracer.spanBuilderWithRemoteParent("Recv.MyRequest", spanContext).startScopedSpan()) { * // Handle request and send response back. * } * } diff --git a/api/src/test/java/io/opencensus/trace/TracerTest.java b/api/src/test/java/io/opencensus/trace/TracerTest.java index 3c69068b..a0830428 100644 --- a/api/src/test/java/io/opencensus/trace/TracerTest.java +++ b/api/src/test/java/io/opencensus/trace/TracerTest.java @@ -101,12 +101,13 @@ public class TracerTest { @Test(expected = NullPointerException.class) public void spanBuilderWithParentAndName_NullName() { - noopTracer.spanBuilder(null, null); + noopTracer.spanBuilderWithExplicitParent(null, null); } @Test public void defaultSpanBuilderWithParentAndName() { - assertThat(noopTracer.spanBuilder(null, SPAN_NAME).startSpan()).isSameAs(BlankSpan.INSTANCE); + assertThat(noopTracer.spanBuilderWithExplicitParent(SPAN_NAME, null).startSpan()) + .isSameAs(BlankSpan.INSTANCE); } @Test(expected = NullPointerException.class) @@ -114,14 +115,15 @@ public class TracerTest { noopTracer.spanBuilderWithRemoteParent(null, null); } - @Test(expected = NullPointerException.class) - public void defaultSpanBuilderWitRemoteParent_NullParent() { - noopTracer.spanBuilderWithRemoteParent(null, SPAN_NAME); + @Test + public void defaultSpanBuilderWithRemoteParent_NullParent() { + assertThat(noopTracer.spanBuilderWithRemoteParent(SPAN_NAME, null).startSpan()) + .isSameAs(BlankSpan.INSTANCE); } @Test public void defaultSpanBuilderWithRemoteParent() { - assertThat(noopTracer.spanBuilderWithRemoteParent(SpanContext.INVALID, SPAN_NAME).startSpan()) + assertThat(noopTracer.spanBuilderWithRemoteParent(SPAN_NAME, SpanContext.INVALID).startSpan()) .isSameAs(BlankSpan.INSTANCE); } @@ -130,7 +132,8 @@ public class TracerTest { NonThrowingCloseable ws = tracer.withSpan(span); try { assertThat(tracer.getCurrentSpan()).isSameAs(span); - when(tracer.spanBuilder(same(span), same(SPAN_NAME))).thenReturn(spanBuilder); + when(tracer.spanBuilderWithExplicitParent(same(SPAN_NAME), same(span))) + .thenReturn(spanBuilder); assertThat(tracer.spanBuilder(SPAN_NAME)).isSameAs(spanBuilder); } finally { ws.close(); @@ -142,7 +145,8 @@ public class TracerTest { NonThrowingCloseable ws = tracer.withSpan(BlankSpan.INSTANCE); try { assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); - when(tracer.spanBuilder(same(BlankSpan.INSTANCE), same(SPAN_NAME))).thenReturn(spanBuilder); + when(tracer.spanBuilderWithExplicitParent(same(SPAN_NAME), same(BlankSpan.INSTANCE))) + .thenReturn(spanBuilder); assertThat(tracer.spanBuilder(SPAN_NAME)).isSameAs(spanBuilder); } finally { ws.close(); -- cgit v1.2.3 From 8d05cb32b05e39cd803637094be8ad95c29fbd6e Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Tue, 4 Jul 2017 15:59:08 -0700 Subject: Move Sampler abstract class and EndSpanOptions to the main package. (#412) --- .../main/java/io/opencensus/trace/BlankSpan.java | 1 - .../java/io/opencensus/trace/EndSpanOptions.java | 79 ++++++++++++++++++++++ api/src/main/java/io/opencensus/trace/Sampler.java | 43 ++++++++++++ api/src/main/java/io/opencensus/trace/Span.java | 1 - .../main/java/io/opencensus/trace/SpanBuilder.java | 2 - .../io/opencensus/trace/base/EndSpanOptions.java | 79 ---------------------- .../java/io/opencensus/trace/base/Sampler.java | 44 ------------ .../io/opencensus/trace/config/TraceParams.java | 2 +- .../trace/samplers/AlwaysSampleSampler.java | 9 +-- .../trace/samplers/NeverSampleSampler.java | 9 +-- .../trace/samplers/ProbabilitySampler.java | 13 ++-- .../io/opencensus/trace/samplers/Samplers.java | 2 +- .../java/io/opencensus/trace/BlankSpanTest.java | 1 - .../io/opencensus/trace/EndSpanOptionsTest.java | 69 +++++++++++++++++++ .../io/opencensus/trace/ScopedSpanHandleTest.java | 1 - .../test/java/io/opencensus/trace/SpanTest.java | 1 - .../opencensus/trace/base/EndSpanOptionsTest.java | 68 ------------------- .../io/opencensus/trace/samplers/SamplersTest.java | 2 +- 18 files changed, 206 insertions(+), 220 deletions(-) create mode 100644 api/src/main/java/io/opencensus/trace/EndSpanOptions.java create mode 100644 api/src/main/java/io/opencensus/trace/Sampler.java delete mode 100644 api/src/main/java/io/opencensus/trace/base/EndSpanOptions.java delete mode 100644 api/src/main/java/io/opencensus/trace/base/Sampler.java create mode 100644 api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java delete mode 100644 api/src/test/java/io/opencensus/trace/base/EndSpanOptionsTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/BlankSpan.java b/api/src/main/java/io/opencensus/trace/BlankSpan.java index f78c3907..b4e11217 100644 --- a/api/src/main/java/io/opencensus/trace/BlankSpan.java +++ b/api/src/main/java/io/opencensus/trace/BlankSpan.java @@ -15,7 +15,6 @@ package io.opencensus.trace; import io.opencensus.trace.base.Annotation; import io.opencensus.trace.base.AttributeValue; -import io.opencensus.trace.base.EndSpanOptions; import io.opencensus.trace.base.Link; import io.opencensus.trace.base.NetworkEvent; import java.util.Map; diff --git a/api/src/main/java/io/opencensus/trace/EndSpanOptions.java b/api/src/main/java/io/opencensus/trace/EndSpanOptions.java new file mode 100644 index 00000000..37d08ede --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/EndSpanOptions.java @@ -0,0 +1,79 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import io.opencensus.trace.base.Status; +import javax.annotation.concurrent.Immutable; + +/** + * A class that enables overriding the default values used when ending a {@link Span}. Allows + * overriding the {@link Status status}. + */ +@Immutable +@AutoValue +public abstract class EndSpanOptions { + /** The default {@code EndSpanOptions}. */ + public static final EndSpanOptions DEFAULT = builder().build(); + + /** + * Returns a new {@link Builder} with default options. + * + * @return a new {@code Builder} with default options. + */ + public static Builder builder() { + return new AutoValue_EndSpanOptions.Builder().setStatus(Status.OK); + } + + /** + * Returns the status. + * + * @return the status. + */ + public abstract Status getStatus(); + + /** Builder class for {@link EndSpanOptions}. */ + @AutoValue.Builder + public abstract static class Builder { + /** + * Sets the status for the {@link Span}. + * + *

If set, this will override the default {@code Span} status. Default is {@link Status#OK}. + * + * @param status the status. + * @return this. + */ + public abstract Builder setStatus(Status status); + + abstract EndSpanOptions autoBuild(); // not public + + /** + * Builds and returns a {@code EndSpanOptions} with the desired settings. + * + * @return a {@code EndSpanOptions} with the desired settings. + * @throws NullPointerException if {@code status} is {@code null}. + */ + public EndSpanOptions build() { + EndSpanOptions endSpanOptions = autoBuild(); + checkNotNull(endSpanOptions.getStatus(), "status"); + return endSpanOptions; + } + + Builder() {} + } + + EndSpanOptions() {} +} diff --git a/api/src/main/java/io/opencensus/trace/Sampler.java b/api/src/main/java/io/opencensus/trace/Sampler.java new file mode 100644 index 00000000..29f70c6d --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/Sampler.java @@ -0,0 +1,43 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import io.opencensus.trace.base.SpanId; +import io.opencensus.trace.base.TraceId; +import java.util.List; +import javax.annotation.Nullable; + +/** Sampler is used to make decisions on {@link Span} sampling. */ +public abstract class Sampler { + /** + * Called during {@link Span} creation to make a sampling decision. + * + * @param parentContext The parent {@code Span} {@link SpanContext}. May be {@code null} if this + * is a root span. + * @param remoteParent true if the parentContext is remote. + * @param traceId The {@link TraceId} for the new {@code Span}. This will be identical to that in + * the parentContext, unless this is a root span. + * @param spanId The span ID for the new {@code Span}. + * @param name The name of the new {@code Span}. + * @param parentLinks The parentLinks associated with the new {@code Span}. + * @return {@code true} if the {@code Span} is sampled. + */ + public abstract boolean shouldSample( + @Nullable SpanContext parentContext, + boolean remoteParent, + TraceId traceId, + SpanId spanId, + String name, + List parentLinks); +} diff --git a/api/src/main/java/io/opencensus/trace/Span.java b/api/src/main/java/io/opencensus/trace/Span.java index af6e3adb..15689057 100644 --- a/api/src/main/java/io/opencensus/trace/Span.java +++ b/api/src/main/java/io/opencensus/trace/Span.java @@ -18,7 +18,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import io.opencensus.trace.base.Annotation; import io.opencensus.trace.base.AttributeValue; -import io.opencensus.trace.base.EndSpanOptions; import io.opencensus.trace.base.Link; import io.opencensus.trace.base.NetworkEvent; import java.util.Collections; diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java index be55906f..e61318ea 100644 --- a/api/src/main/java/io/opencensus/trace/SpanBuilder.java +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -16,8 +16,6 @@ package io.opencensus.trace; import static com.google.common.base.Preconditions.checkNotNull; import io.opencensus.common.NonThrowingCloseable; -import io.opencensus.trace.base.EndSpanOptions; -import io.opencensus.trace.base.Sampler; import java.util.List; import javax.annotation.Nullable; diff --git a/api/src/main/java/io/opencensus/trace/base/EndSpanOptions.java b/api/src/main/java/io/opencensus/trace/base/EndSpanOptions.java deleted file mode 100644 index 00cd8ffb..00000000 --- a/api/src/main/java/io/opencensus/trace/base/EndSpanOptions.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.base; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.auto.value.AutoValue; -import io.opencensus.trace.Span; -import javax.annotation.concurrent.Immutable; - -/** - * A class that enables overriding the default values used when ending a {@link Span}. Allows - * overriding the {@link Status status}. - */ -@Immutable -@AutoValue -public abstract class EndSpanOptions { - /** The default {@code EndSpanOptions}. */ - public static final EndSpanOptions DEFAULT = builder().build(); - - /** - * Returns a new {@link Builder} with default options. - * - * @return a new {@code Builder} with default options. - */ - public static Builder builder() { - return new AutoValue_EndSpanOptions.Builder().setStatus(Status.OK); - } - - /** - * Returns the status. - * - * @return the status. - */ - public abstract Status getStatus(); - - /** Builder class for {@link EndSpanOptions}. */ - @AutoValue.Builder - public abstract static class Builder { - /** - * Sets the status for the {@link Span}. - * - *

If set, this will override the default {@code Span} status. Default is {@link Status#OK}. - * - * @param status the status. - * @return this. - */ - public abstract Builder setStatus(Status status); - - abstract EndSpanOptions autoBuild(); // not public - - /** - * Builds and returns a {@code EndSpanOptions} with the desired settings. - * - * @return a {@code EndSpanOptions} with the desired settings. - * @throws NullPointerException if {@code status} is {@code null}. - */ - public EndSpanOptions build() { - EndSpanOptions endSpanOptions = autoBuild(); - checkNotNull(endSpanOptions.getStatus(), "status"); - return endSpanOptions; - } - - Builder() {} - } - - EndSpanOptions() {} -} diff --git a/api/src/main/java/io/opencensus/trace/base/Sampler.java b/api/src/main/java/io/opencensus/trace/base/Sampler.java deleted file mode 100644 index 94bd2966..00000000 --- a/api/src/main/java/io/opencensus/trace/base/Sampler.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.base; - -import io.opencensus.trace.Span; -import io.opencensus.trace.SpanContext; - -import java.util.List; -import javax.annotation.Nullable; - -/** Sampler is used to make decisions on {@link Span} sampling. */ -public abstract class Sampler { - /** - * Called during {@link Span} creation to make a sampling decision. - * - * @param parentContext The parent {@code Span} {@link SpanContext}. May be {@code null} if this - * is a root span. - * @param remoteParent true if the parentContext is remote. - * @param traceId The {@link TraceId} for the new {@code Span}. This will be identical to that in - * the parentContext, unless this is a root span. - * @param spanId The span ID for the new {@code Span}. - * @param name The name of the new {@code Span}. - * @param parentLinks The parentLinks associated with the new {@code Span}. - * @return {@code true} if the {@code Span} is sampled. - */ - public abstract boolean shouldSample( - @Nullable SpanContext parentContext, - boolean remoteParent, - TraceId traceId, - SpanId spanId, - String name, - List parentLinks); -} diff --git a/api/src/main/java/io/opencensus/trace/config/TraceParams.java b/api/src/main/java/io/opencensus/trace/config/TraceParams.java index 5f1ba3b0..d07ae043 100644 --- a/api/src/main/java/io/opencensus/trace/config/TraceParams.java +++ b/api/src/main/java/io/opencensus/trace/config/TraceParams.java @@ -16,11 +16,11 @@ package io.opencensus.trace.config; import static com.google.common.base.Preconditions.checkArgument; import com.google.auto.value.AutoValue; +import io.opencensus.trace.Sampler; import io.opencensus.trace.Span; import io.opencensus.trace.base.Annotation; import io.opencensus.trace.base.Link; import io.opencensus.trace.base.NetworkEvent; -import io.opencensus.trace.base.Sampler; import io.opencensus.trace.samplers.Samplers; import javax.annotation.concurrent.Immutable; diff --git a/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java b/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java index f3daed4b..f78fcd18 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java +++ b/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java @@ -13,23 +13,20 @@ package io.opencensus.trace.samplers; +import io.opencensus.trace.Sampler; import io.opencensus.trace.Span; import io.opencensus.trace.SpanContext; -import io.opencensus.trace.base.Sampler; import io.opencensus.trace.base.SpanId; import io.opencensus.trace.base.TraceId; import java.util.List; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; -/** - * Sampler that always makes a "yes" decision on {@link Span} sampling. - */ +/** Sampler that always makes a "yes" decision on {@link Span} sampling. */ @Immutable final class AlwaysSampleSampler extends Sampler { - AlwaysSampleSampler() { - } + AlwaysSampleSampler() {} // Returns always makes a "yes" decision on {@link Span} sampling. @Override diff --git a/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java b/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java index bca64df4..9fa8ea7b 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java +++ b/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java @@ -13,23 +13,20 @@ package io.opencensus.trace.samplers; +import io.opencensus.trace.Sampler; import io.opencensus.trace.Span; import io.opencensus.trace.SpanContext; -import io.opencensus.trace.base.Sampler; import io.opencensus.trace.base.SpanId; import io.opencensus.trace.base.TraceId; import java.util.List; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; -/** - * Sampler that always makes a "no" decision on {@link Span} sampling. - */ +/** Sampler that always makes a "no" decision on {@link Span} sampling. */ @Immutable final class NeverSampleSampler extends Sampler { - NeverSampleSampler() { - } + NeverSampleSampler() {} // Returns always makes a "no" decision on {@link Span} sampling. @Override diff --git a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java index c5c9c002..11735629 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java +++ b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java @@ -16,9 +16,9 @@ package io.opencensus.trace.samplers; import static com.google.common.base.Preconditions.checkArgument; import com.google.auto.value.AutoValue; +import io.opencensus.trace.Sampler; import io.opencensus.trace.Span; import io.opencensus.trace.SpanContext; -import io.opencensus.trace.base.Sampler; import io.opencensus.trace.base.SpanId; import io.opencensus.trace.base.TraceId; import java.util.List; @@ -29,23 +29,22 @@ import javax.annotation.concurrent.Immutable; * We assume the lower 64 bits of the traceId's are randomly distributed around the whole (long) * range. We convert an incoming probability into an upper bound on that value, such that we can * just compare the absolute value of the id and the bound to see if we are within the desired - * probability range. Using the low bits of the traceId also ensures that systems that only use - * 64 bit ID's will also work with this sampler. + * probability range. Using the low bits of the traceId also ensures that systems that only use 64 + * bit ID's will also work with this sampler. */ @AutoValue @Immutable abstract class ProbabilitySampler extends Sampler { - ProbabilitySampler() { - } + ProbabilitySampler() {} abstract double getProbability(); abstract long getIdUpperBound(); /** - * Returns a new {@link ProbabilitySampler}. The probability of sampling a trace is equal to - * that of the specified probability. + * Returns a new {@link ProbabilitySampler}. The probability of sampling a trace is equal to that + * of the specified probability. * * @param probability The desired probability of sampling. Must be within [0.0, 1.0]. * @return a new {@link ProbabilitySampler}. diff --git a/api/src/main/java/io/opencensus/trace/samplers/Samplers.java b/api/src/main/java/io/opencensus/trace/samplers/Samplers.java index 40d72931..f5ff4531 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/Samplers.java +++ b/api/src/main/java/io/opencensus/trace/samplers/Samplers.java @@ -13,8 +13,8 @@ package io.opencensus.trace.samplers; +import io.opencensus.trace.Sampler; import io.opencensus.trace.Span; -import io.opencensus.trace.base.Sampler; /** Static class to access a set of pre-defined {@link Sampler Samplers}. */ public final class Samplers { diff --git a/api/src/test/java/io/opencensus/trace/BlankSpanTest.java b/api/src/test/java/io/opencensus/trace/BlankSpanTest.java index c2f4c35d..c62b5bf6 100644 --- a/api/src/test/java/io/opencensus/trace/BlankSpanTest.java +++ b/api/src/test/java/io/opencensus/trace/BlankSpanTest.java @@ -17,7 +17,6 @@ import static com.google.common.truth.Truth.assertThat; import io.opencensus.trace.base.Annotation; import io.opencensus.trace.base.AttributeValue; -import io.opencensus.trace.base.EndSpanOptions; import io.opencensus.trace.base.Link; import io.opencensus.trace.base.NetworkEvent; import java.util.HashMap; diff --git a/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java b/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java new file mode 100644 index 00000000..5fc50b7b --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java @@ -0,0 +1,69 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.trace.base.Status; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link EndSpanOptions}. */ +@RunWith(JUnit4.class) +public class EndSpanOptionsTest { + @Test(expected = NullPointerException.class) + public void setNullStatus() { + EndSpanOptions.builder().setStatus(null).build(); + } + + @Test + public void endSpanOptions_DefaultOptions() { + assertThat(EndSpanOptions.DEFAULT.getStatus()).isEqualTo(Status.OK); + } + + @Test + public void setStatus() { + EndSpanOptions endSpanOptions = + EndSpanOptions.builder() + .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) + .build(); + assertThat(endSpanOptions.getStatus()) + .isEqualTo(Status.CANCELLED.withDescription("ThisIsAnError")); + } + + @Test + public void endSpanOptions_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup( + EndSpanOptions.builder() + .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) + .build(), + EndSpanOptions.builder() + .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) + .build()); + tester.addEqualityGroup(EndSpanOptions.builder().build(), EndSpanOptions.DEFAULT); + tester.testEquals(); + } + + @Test + public void endSpanOptions_ToString() { + EndSpanOptions endSpanOptions = + EndSpanOptions.builder() + .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) + .build(); + assertThat(endSpanOptions.toString()).contains("ThisIsAnError"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java b/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java index cf043d09..8922f4c2 100644 --- a/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java +++ b/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java @@ -18,7 +18,6 @@ import static org.mockito.Matchers.same; import static org.mockito.Mockito.verify; import io.opencensus.common.NonThrowingCloseable; -import io.opencensus.trace.base.EndSpanOptions; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/api/src/test/java/io/opencensus/trace/SpanTest.java b/api/src/test/java/io/opencensus/trace/SpanTest.java index 0ab481d9..186e6b1b 100644 --- a/api/src/test/java/io/opencensus/trace/SpanTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanTest.java @@ -19,7 +19,6 @@ import static org.mockito.Mockito.verify; import io.opencensus.trace.base.Annotation; import io.opencensus.trace.base.AttributeValue; -import io.opencensus.trace.base.EndSpanOptions; import io.opencensus.trace.base.Link; import io.opencensus.trace.base.NetworkEvent; import io.opencensus.trace.base.SpanId; diff --git a/api/src/test/java/io/opencensus/trace/base/EndSpanOptionsTest.java b/api/src/test/java/io/opencensus/trace/base/EndSpanOptionsTest.java deleted file mode 100644 index 87ff8df8..00000000 --- a/api/src/test/java/io/opencensus/trace/base/EndSpanOptionsTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.base; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link EndSpanOptions}. */ -@RunWith(JUnit4.class) -public class EndSpanOptionsTest { - @Test(expected = NullPointerException.class) - public void setNullStatus() { - EndSpanOptions.builder().setStatus(null).build(); - } - - @Test - public void endSpanOptions_DefaultOptions() { - assertThat(EndSpanOptions.DEFAULT.getStatus()).isEqualTo(Status.OK); - } - - @Test - public void setStatus() { - EndSpanOptions endSpanOptions = - EndSpanOptions.builder() - .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) - .build(); - assertThat(endSpanOptions.getStatus()) - .isEqualTo(Status.CANCELLED.withDescription("ThisIsAnError")); - } - - @Test - public void endSpanOptions_EqualsAndHashCode() { - EqualsTester tester = new EqualsTester(); - tester.addEqualityGroup( - EndSpanOptions.builder() - .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) - .build(), - EndSpanOptions.builder() - .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) - .build()); - tester.addEqualityGroup(EndSpanOptions.builder().build(), EndSpanOptions.DEFAULT); - tester.testEquals(); - } - - @Test - public void endSpanOptions_ToString() { - EndSpanOptions endSpanOptions = - EndSpanOptions.builder() - .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) - .build(); - assertThat(endSpanOptions.toString()).contains("ThisIsAnError"); - } -} diff --git a/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java b/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java index 5e996835..12ec7548 100644 --- a/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java +++ b/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java @@ -15,9 +15,9 @@ package io.opencensus.trace.samplers; import static com.google.common.truth.Truth.assertThat; +import io.opencensus.trace.Sampler; import io.opencensus.trace.Span; import io.opencensus.trace.SpanContext; -import io.opencensus.trace.base.Sampler; import io.opencensus.trace.base.SpanId; import io.opencensus.trace.base.TraceId; import io.opencensus.trace.base.TraceOptions; -- cgit v1.2.3 From 9676a3f7b66021d846f5ca92dca69bd122e501d5 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Wed, 5 Jul 2017 10:21:28 -0700 Subject: Clarify the nature of the Link.Type enum (#413) --- .../main/java/io/opencensus/trace/base/Link.java | 4 ++-- .../java/io/opencensus/trace/BlankSpanTest.java | 3 ++- .../java/io/opencensus/trace/base/LinkTest.java | 28 +++++++++++----------- .../io/opencensus/trace/export/SpanDataTest.java | 2 +- 4 files changed, 19 insertions(+), 18 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/base/Link.java b/api/src/main/java/io/opencensus/trace/base/Link.java index 363bd212..3f8b93f8 100644 --- a/api/src/main/java/io/opencensus/trace/base/Link.java +++ b/api/src/main/java/io/opencensus/trace/base/Link.java @@ -33,9 +33,9 @@ public abstract class Link { /** The relationship with the linked {@code Span} relative to the current {@code Span}. */ public enum Type { /** When the linked {@code Span} is a child of the current {@code Span}. */ - CHILD, + CHILD_LINKED_SPAN, /** When the linked {@code Span} is a parent of the current {@code Span}. */ - PARENT + PARENT_LINKED_SPAN } /** diff --git a/api/src/test/java/io/opencensus/trace/BlankSpanTest.java b/api/src/test/java/io/opencensus/trace/BlankSpanTest.java index c62b5bf6..f9690321 100644 --- a/api/src/test/java/io/opencensus/trace/BlankSpanTest.java +++ b/api/src/test/java/io/opencensus/trace/BlankSpanTest.java @@ -52,7 +52,8 @@ public class BlankSpanTest { BlankSpan.INSTANCE.addAnnotation("MyAnnotation", multipleAttributes); BlankSpan.INSTANCE.addAnnotation(Annotation.fromDescription("MyAnnotation")); BlankSpan.INSTANCE.addNetworkEvent(NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).build()); - BlankSpan.INSTANCE.addLink(Link.fromSpanContext(SpanContext.INVALID, Link.Type.CHILD)); + BlankSpan.INSTANCE.addLink( + Link.fromSpanContext(SpanContext.INVALID, Link.Type.CHILD_LINKED_SPAN)); BlankSpan.INSTANCE.end(EndSpanOptions.DEFAULT); BlankSpan.INSTANCE.end(); } diff --git a/api/src/test/java/io/opencensus/trace/base/LinkTest.java b/api/src/test/java/io/opencensus/trace/base/LinkTest.java index 4fafa02a..d0bfc46e 100644 --- a/api/src/test/java/io/opencensus/trace/base/LinkTest.java +++ b/api/src/test/java/io/opencensus/trace/base/LinkTest.java @@ -33,18 +33,18 @@ public class LinkTest { @Test public void fromSpanContext_ChildLink() { - Link link = Link.fromSpanContext(spanContext, Type.CHILD); + Link link = Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN); assertThat(link.getTraceId()).isEqualTo(spanContext.getTraceId()); assertThat(link.getSpanId()).isEqualTo(spanContext.getSpanId()); - assertThat(link.getType()).isEqualTo(Type.CHILD); + assertThat(link.getType()).isEqualTo(Type.CHILD_LINKED_SPAN); } @Test public void fromSpanContext_ParentLink() { - Link link = Link.fromSpanContext(spanContext, Type.PARENT); + Link link = Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN); assertThat(link.getTraceId()).isEqualTo(spanContext.getTraceId()); assertThat(link.getSpanId()).isEqualTo(spanContext.getSpanId()); - assertThat(link.getType()).isEqualTo(Type.PARENT); + assertThat(link.getType()).isEqualTo(Type.PARENT_LINKED_SPAN); } @Test @@ -52,25 +52,25 @@ public class LinkTest { EqualsTester tester = new EqualsTester(); tester .addEqualityGroup( - Link.fromSpanContext(spanContext, Type.PARENT), - Link.fromSpanContext(spanContext, Type.PARENT)) + Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN), + Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN)) .addEqualityGroup( - Link.fromSpanContext(spanContext, Type.CHILD), - Link.fromSpanContext(spanContext, Type.CHILD)) - .addEqualityGroup(Link.fromSpanContext(SpanContext.INVALID, Type.CHILD)) - .addEqualityGroup(Link.fromSpanContext(SpanContext.INVALID, Type.PARENT)); + Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN), + Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN)) + .addEqualityGroup(Link.fromSpanContext(SpanContext.INVALID, Type.CHILD_LINKED_SPAN)) + .addEqualityGroup(Link.fromSpanContext(SpanContext.INVALID, Type.PARENT_LINKED_SPAN)); tester.testEquals(); } @Test public void link_ToString() { - Link link = Link.fromSpanContext(spanContext, Type.CHILD); + Link link = Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN); assertThat(link.toString()).contains(spanContext.getTraceId().toString()); assertThat(link.toString()).contains(spanContext.getSpanId().toString()); - assertThat(link.toString()).contains("CHILD"); - link = Link.fromSpanContext(spanContext, Type.PARENT); + assertThat(link.toString()).contains("CHILD_LINKED_SPAN"); + link = Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN); assertThat(link.toString()).contains(spanContext.getTraceId().toString()); assertThat(link.toString()).contains(spanContext.getSpanId().toString()); - assertThat(link.toString()).contains("PARENT"); + assertThat(link.toString()).contains("PARENT_LINKED_SPAN"); } } diff --git a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java index 1a92b0e6..6ea20fcc 100644 --- a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java +++ b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java @@ -85,7 +85,7 @@ public class SpanDataTest { networkEventsList.add(SpanData.TimedEvent.create(eventTimestamp1, recvNetworkEvent)); networkEventsList.add(SpanData.TimedEvent.create(eventTimestamp2, sentNetworkEvent)); networkEvents = TimedEvents.create(networkEventsList, 3); - linksList.add(Link.fromSpanContext(spanContext, Type.CHILD)); + linksList.add(Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN)); links = Links.create(linksList, 0); } -- cgit v1.2.3 From 6bf1e1d397a20cd1a1f6c80da8b7f1d07357852c Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Wed, 5 Jul 2017 20:37:10 -0700 Subject: Move logging exporter into an independent package. (#416) * Move logging exporter into an independent package. * Change package to opencensus-trace-logging-exporter --- .../io/opencensus/trace/export/SpanExporter.java | 41 ------------------ .../opencensus/trace/export/SpanExporterTest.java | 49 ---------------------- 2 files changed, 90 deletions(-) delete mode 100644 api/src/test/java/io/opencensus/trace/export/SpanExporterTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/export/SpanExporter.java b/api/src/main/java/io/opencensus/trace/export/SpanExporter.java index 39e0a583..bfae4bad 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanExporter.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanExporter.java @@ -16,8 +16,6 @@ package io.opencensus.trace.export; import io.opencensus.trace.Span; import io.opencensus.trace.base.TraceOptions; import java.util.Collection; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.annotation.concurrent.ThreadSafe; /** @@ -84,43 +82,4 @@ public abstract class SpanExporter { @Override public void unregisterHandler(String name) {} } - - /** Implementation of the {@link Handler} which logs all the exported {@link SpanData}. */ - @ThreadSafe - public static final class LoggingHandler extends Handler { - - private static final Logger logger = Logger.getLogger(LoggingHandler.class.getName()); - private static final String REGISTER_NAME = - "io.opencensus.trace.export.SpanExporter$LoggingHandler"; - private static final LoggingHandler INSTANCE = new LoggingHandler(); - - private LoggingHandler() {} - - /** - * Registers the {@code LoggingHandler} to the {@code ExportComponent}. - * - * @param spanExporter the instance of the {@code SpanExporter} where this service is - * registered. - */ - public static void register(SpanExporter spanExporter) { - spanExporter.registerHandler(REGISTER_NAME, INSTANCE); - } - - /** - * Unregisters the {@code LoggingHandler} from the {@code ExportComponent}. - * - * @param spanExporter the instance of the {@code SpanExporter} from where this service is - * unregistered. - */ - public static void unregister(SpanExporter spanExporter) { - spanExporter.unregisterHandler(REGISTER_NAME); - } - - @Override - public void export(Collection spanDataList) { - for (SpanData spanData : spanDataList) { - logger.log(Level.INFO, spanData.toString()); - } - } - } } diff --git a/api/src/test/java/io/opencensus/trace/export/SpanExporterTest.java b/api/src/test/java/io/opencensus/trace/export/SpanExporterTest.java deleted file mode 100644 index 46480688..00000000 --- a/api/src/test/java/io/opencensus/trace/export/SpanExporterTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.export; - -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.verify; - -import io.opencensus.trace.export.SpanExporter.LoggingHandler; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** Unit tests for {@link ExportComponent}. */ -@RunWith(JUnit4.class) -public class SpanExporterTest { - @Mock private SpanExporter spanExporter; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void registerUnregisterLoggingService() { - LoggingHandler.register(spanExporter); - verify(spanExporter) - .registerHandler( - eq("io.opencensus.trace.export.SpanExporter$LoggingHandler"), - any(LoggingHandler.class)); - LoggingHandler.unregister(spanExporter); - verify(spanExporter) - .unregisterHandler(eq("io.opencensus.trace.export.SpanExporter$LoggingHandler")); - } -} -- cgit v1.2.3 From d51699ee80ba3d19cda27ce269c56b486e795521 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Thu, 6 Jul 2017 08:12:08 -0700 Subject: Get rid of base directory and move everything on level up. (#417) * Get rid of base directory and move everything on level up. * Remove unused imports in tests. --- .../main/java/io/opencensus/trace/Annotation.java | 73 +++++ .../java/io/opencensus/trace/AttributeValue.java | 91 ++++++ .../main/java/io/opencensus/trace/BlankSpan.java | 4 - .../java/io/opencensus/trace/EndSpanOptions.java | 1 - api/src/main/java/io/opencensus/trace/Link.java | 72 +++++ .../java/io/opencensus/trace/NetworkEvent.java | 124 ++++++++ api/src/main/java/io/opencensus/trace/Sampler.java | 2 - api/src/main/java/io/opencensus/trace/Span.java | 4 - .../main/java/io/opencensus/trace/SpanContext.java | 3 - api/src/main/java/io/opencensus/trace/SpanId.java | 171 +++++++++++ api/src/main/java/io/opencensus/trace/Status.java | 334 ++++++++++++++++++++ api/src/main/java/io/opencensus/trace/TraceId.java | 193 ++++++++++++ .../java/io/opencensus/trace/TraceOptions.java | 210 +++++++++++++ .../java/io/opencensus/trace/base/Annotation.java | 73 ----- .../io/opencensus/trace/base/AttributeValue.java | 91 ------ .../main/java/io/opencensus/trace/base/Link.java | 74 ----- .../io/opencensus/trace/base/NetworkEvent.java | 124 -------- .../main/java/io/opencensus/trace/base/SpanId.java | 171 ----------- .../main/java/io/opencensus/trace/base/Status.java | 335 --------------------- .../java/io/opencensus/trace/base/TraceId.java | 193 ------------ .../io/opencensus/trace/base/TraceOptions.java | 210 ------------- .../io/opencensus/trace/config/TraceParams.java | 6 +- .../opencensus/trace/export/ExportComponent.java | 2 +- .../opencensus/trace/export/SampledSpanStore.java | 4 +- .../java/io/opencensus/trace/export/SpanData.java | 12 +- .../io/opencensus/trace/export/SpanExporter.java | 2 +- .../trace/samplers/AlwaysSampleSampler.java | 4 +- .../trace/samplers/NeverSampleSampler.java | 4 +- .../trace/samplers/ProbabilitySampler.java | 4 +- .../java/io/opencensus/trace/AnnotationTest.java | 99 ++++++ .../io/opencensus/trace/AttributeValueTest.java | 75 +++++ .../java/io/opencensus/trace/BlankSpanTest.java | 4 - .../io/opencensus/trace/EndSpanOptionsTest.java | 1 - .../test/java/io/opencensus/trace/LinkTest.java | 75 +++++ .../java/io/opencensus/trace/NetworkEventTest.java | 87 ++++++ .../java/io/opencensus/trace/SpanContextTest.java | 3 - .../test/java/io/opencensus/trace/SpanIdTest.java | 73 +++++ .../test/java/io/opencensus/trace/SpanTest.java | 7 - .../test/java/io/opencensus/trace/StatusTest.java | 51 ++++ .../test/java/io/opencensus/trace/TraceIdTest.java | 75 +++++ .../java/io/opencensus/trace/TraceOptionsTest.java | 77 +++++ .../io/opencensus/trace/base/AnnotationTest.java | 99 ------ .../opencensus/trace/base/AttributeValueTest.java | 75 ----- .../java/io/opencensus/trace/base/LinkTest.java | 76 ----- .../io/opencensus/trace/base/NetworkEventTest.java | 87 ------ .../java/io/opencensus/trace/base/SpanIdTest.java | 73 ----- .../java/io/opencensus/trace/base/StatusTest.java | 51 ---- .../java/io/opencensus/trace/base/TraceIdTest.java | 75 ----- .../io/opencensus/trace/base/TraceOptionsTest.java | 77 ----- .../io/opencensus/trace/export/SpanDataTest.java | 18 +- .../io/opencensus/trace/samplers/SamplersTest.java | 6 +- 51 files changed, 1911 insertions(+), 1944 deletions(-) create mode 100644 api/src/main/java/io/opencensus/trace/Annotation.java create mode 100644 api/src/main/java/io/opencensus/trace/AttributeValue.java create mode 100644 api/src/main/java/io/opencensus/trace/Link.java create mode 100644 api/src/main/java/io/opencensus/trace/NetworkEvent.java create mode 100644 api/src/main/java/io/opencensus/trace/SpanId.java create mode 100644 api/src/main/java/io/opencensus/trace/Status.java create mode 100644 api/src/main/java/io/opencensus/trace/TraceId.java create mode 100644 api/src/main/java/io/opencensus/trace/TraceOptions.java delete mode 100644 api/src/main/java/io/opencensus/trace/base/Annotation.java delete mode 100644 api/src/main/java/io/opencensus/trace/base/AttributeValue.java delete mode 100644 api/src/main/java/io/opencensus/trace/base/Link.java delete mode 100644 api/src/main/java/io/opencensus/trace/base/NetworkEvent.java delete mode 100644 api/src/main/java/io/opencensus/trace/base/SpanId.java delete mode 100644 api/src/main/java/io/opencensus/trace/base/Status.java delete mode 100644 api/src/main/java/io/opencensus/trace/base/TraceId.java delete mode 100644 api/src/main/java/io/opencensus/trace/base/TraceOptions.java create mode 100644 api/src/test/java/io/opencensus/trace/AnnotationTest.java create mode 100644 api/src/test/java/io/opencensus/trace/AttributeValueTest.java create mode 100644 api/src/test/java/io/opencensus/trace/LinkTest.java create mode 100644 api/src/test/java/io/opencensus/trace/NetworkEventTest.java create mode 100644 api/src/test/java/io/opencensus/trace/SpanIdTest.java create mode 100644 api/src/test/java/io/opencensus/trace/StatusTest.java create mode 100644 api/src/test/java/io/opencensus/trace/TraceIdTest.java create mode 100644 api/src/test/java/io/opencensus/trace/TraceOptionsTest.java delete mode 100644 api/src/test/java/io/opencensus/trace/base/AnnotationTest.java delete mode 100644 api/src/test/java/io/opencensus/trace/base/AttributeValueTest.java delete mode 100644 api/src/test/java/io/opencensus/trace/base/LinkTest.java delete mode 100644 api/src/test/java/io/opencensus/trace/base/NetworkEventTest.java delete mode 100644 api/src/test/java/io/opencensus/trace/base/SpanIdTest.java delete mode 100644 api/src/test/java/io/opencensus/trace/base/StatusTest.java delete mode 100644 api/src/test/java/io/opencensus/trace/base/TraceIdTest.java delete mode 100644 api/src/test/java/io/opencensus/trace/base/TraceOptionsTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/Annotation.java b/api/src/main/java/io/opencensus/trace/Annotation.java new file mode 100644 index 00000000..f72070e8 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/Annotation.java @@ -0,0 +1,73 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.concurrent.Immutable; + +/** A text annotation with a set of attributes. */ +@Immutable +@AutoValue +public abstract class Annotation { + private static final Map EMPTY_ATTRIBUTES = + Collections.unmodifiableMap(Collections.emptyMap()); + + /** + * Returns a new {@code Annotation} with the given description. + * + * @param description the text description of the {@code Annotation}. + * @return a new {@code Annotation} with the given description. + * @throws NullPointerException if {@code description} is {@code null}. + */ + public static Annotation fromDescription(String description) { + return new AutoValue_Annotation(description, EMPTY_ATTRIBUTES); + } + + /** + * Returns a new {@code Annotation} with the given description and set of attributes. + * + * @param description the text description of the {@code Annotation}. + * @param attributes the attributes of the {@code Annotation}. + * @return a new {@code Annotation} with the given description and set of attributes. + * @throws NullPointerException if {@code description} or {@code attributes} are {@code null}. + */ + public static Annotation fromDescriptionAndAttributes( + String description, Map attributes) { + return new AutoValue_Annotation( + description, + Collections.unmodifiableMap( + new HashMap(checkNotNull(attributes, "attributes")))); + } + + /** + * Return the description of the {@code Annotation}. + * + * @return the description of the {@code Annotation}. + */ + public abstract String getDescription(); + + /** + * Return the attributes of the {@code Annotation}. + * + * @return the attributes of the {@code Annotation}. + */ + public abstract Map getAttributes(); + + Annotation() {} +} diff --git a/api/src/main/java/io/opencensus/trace/AttributeValue.java b/api/src/main/java/io/opencensus/trace/AttributeValue.java new file mode 100644 index 00000000..f66fd425 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/AttributeValue.java @@ -0,0 +1,91 @@ +/* + * Copyright 2016, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * A class that represents all the possible values for an attribute. An attribute can have 3 types + * of values: {@code String}, {@code Boolean} or {@code Long}. + */ +@Immutable +@AutoValue +public abstract class AttributeValue { + /** + * Returns an {@code AttributeValue} with a string value. + * + * @param stringValue The new value. + * @return an {@code AttributeValue} with a string value. + * @throws NullPointerException if {@code stringValue} is {@code null}. + */ + public static AttributeValue stringAttributeValue(String stringValue) { + return new AutoValue_AttributeValue(checkNotNull(stringValue, "stringValue"), null, null); + } + + /** + * Returns an {@code AttributeValue} with a boolean value. + * + * @param booleanValue The new value. + * @return an {@code AttributeValue} with a boolean value. + */ + public static AttributeValue booleanAttributeValue(boolean booleanValue) { + return new AutoValue_AttributeValue(null, booleanValue, null); + } + + /** + * Returns an {@code AttributeValue} with a long value. + * + * @param longValue The new value. + * @return an {@code AttributeValue} with a long value. + */ + public static AttributeValue longAttributeValue(long longValue) { + return new AutoValue_AttributeValue(null, null, longValue); + } + + AttributeValue() {} + + /** + * Returns the {@code String} value if this is a string {@code AttributeValue}, otherwise {@code + * null}. + * + * @return the {@code String} value if this is a string {@code AttributeValue}, otherwise {@code + * null}. + */ + @Nullable + public abstract String getStringValue(); + + /** + * Returns the {@code Boolean} value if this is a boolean {@code AttributeValue}, otherwise {@code + * null}. + * + * @return the {@code Boolean} value if this is a boolean {@code AttributeValue}, otherwise {@code + * null}. + */ + @Nullable + public abstract Boolean getBooleanValue(); + + /** + * Returns the {@code Long} value if this is a long {@code AttributeValue}, otherwise {@code + * null}. + * + * @return the {@code Long} value if this is a long {@code AttributeValue}, otherwise {@code + * null}. + */ + @Nullable + public abstract Long getLongValue(); +} diff --git a/api/src/main/java/io/opencensus/trace/BlankSpan.java b/api/src/main/java/io/opencensus/trace/BlankSpan.java index b4e11217..40e49551 100644 --- a/api/src/main/java/io/opencensus/trace/BlankSpan.java +++ b/api/src/main/java/io/opencensus/trace/BlankSpan.java @@ -13,10 +13,6 @@ package io.opencensus.trace; -import io.opencensus.trace.base.Annotation; -import io.opencensus.trace.base.AttributeValue; -import io.opencensus.trace.base.Link; -import io.opencensus.trace.base.NetworkEvent; import java.util.Map; import javax.annotation.concurrent.Immutable; diff --git a/api/src/main/java/io/opencensus/trace/EndSpanOptions.java b/api/src/main/java/io/opencensus/trace/EndSpanOptions.java index 37d08ede..e58a06c3 100644 --- a/api/src/main/java/io/opencensus/trace/EndSpanOptions.java +++ b/api/src/main/java/io/opencensus/trace/EndSpanOptions.java @@ -16,7 +16,6 @@ package io.opencensus.trace; import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; -import io.opencensus.trace.base.Status; import javax.annotation.concurrent.Immutable; /** diff --git a/api/src/main/java/io/opencensus/trace/Link.java b/api/src/main/java/io/opencensus/trace/Link.java new file mode 100644 index 00000000..058bd8a9 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/Link.java @@ -0,0 +1,72 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import com.google.auto.value.AutoValue; +import javax.annotation.concurrent.Immutable; + +/** + * A link to a {@link Span} from a different trace. + * + *

It requires a {@link Type} which describes the relationship with the linked {@code Span} and + * the identifiers of the linked {@code Span}. + * + *

Used (for example) in batching operations, where a single batch handler processes multiple + * requests from different traces. + */ +@Immutable +@AutoValue +public abstract class Link { + /** The relationship with the linked {@code Span} relative to the current {@code Span}. */ + public enum Type { + /** When the linked {@code Span} is a child of the current {@code Span}. */ + CHILD_LINKED_SPAN, + /** When the linked {@code Span} is a parent of the current {@code Span}. */ + PARENT_LINKED_SPAN + } + + /** + * Returns a new {@code Link}. + * + * @param context the context of the linked {@code Span}. + * @param type the type of the relationship with the linked {@code Span}. + * @return a new {@code Link}. + */ + public static Link fromSpanContext(SpanContext context, Type type) { + return new AutoValue_Link(context.getTraceId(), context.getSpanId(), type); + } + + /** + * Returns the {@code TraceId}. + * + * @return the {@code TraceId}. + */ + public abstract TraceId getTraceId(); + + /** + * Returns the {@code SpanId}. + * + * @return the {@code SpanId} + */ + public abstract SpanId getSpanId(); + + /** + * Returns the {@code Type}. + * + * @return the {@code Type}. + */ + public abstract Type getType(); + + Link() {} +} diff --git a/api/src/main/java/io/opencensus/trace/NetworkEvent.java b/api/src/main/java/io/opencensus/trace/NetworkEvent.java new file mode 100644 index 00000000..10687074 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/NetworkEvent.java @@ -0,0 +1,124 @@ +/* + * Copyright 2016, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.Timestamp; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * A class that represents a network event. It requires a {@link Type type} and a message id that + * serves to uniquely identify each network message. It can optionally can have information about + * the kernel time and message size. + */ +@Immutable +@AutoValue +public abstract class NetworkEvent { + /** Available types for a {@code NetworkEvent}. */ + public enum Type { + /** When the message was sent. */ + SENT, + /** When the message was received. */ + RECV, + } + + /** + * Returns a new {@link Builder} with default values. + * + * @param type designates whether this is a network send or receive message. + * @param messageId serves to uniquely identify each network message. + * @return a new {@code Builder} with default values. + * @throws NullPointerException if {@code type} is {@code null}. + */ + public static Builder builder(Type type, long messageId) { + return new AutoValue_NetworkEvent.Builder() + .setType(checkNotNull(type, "type")) + .setMessageId(messageId) + // We need to set a value for the message size because the autovalue requires all + // primitives to be initialized. + // TODO(bdrutu): Consider to change the API to require message size. + .setMessageSize(0); + } + + /** + * Returns the kernel timestamp associated with the {@code NetworkEvent} or {@code null} if not + * set. + * + * @return the kernel timestamp associated with the {@code NetworkEvent} or {@code null} if not + * set. + */ + @Nullable + public abstract Timestamp getKernelTimestamp(); + + /** + * Returns the type of the {@code NetworkEvent}. + * + * @return the type of the {@code NetworkEvent}. + */ + public abstract Type getType(); + + /** + * Returns the message id argument that serves to uniquely identify each network message. + * + * @return The message id of the {@code NetworkEvent}. + */ + public abstract long getMessageId(); + + /** + * Returns The message size in bytes of the {@code NetworkEvent}. + * + * @return The message size in bytes of the {@code NetworkEvent}. + */ + public abstract long getMessageSize(); + + /** Builder class for {@link NetworkEvent}. */ + @AutoValue.Builder + public abstract static class Builder { + // Package protected methods because these values are mandatory and set only in the + // NetworkEvent#builder() function. + abstract Builder setType(Type type); + + abstract Builder setMessageId(long messageId); + + /** + * Sets the kernel timestamp. + * + * @param kernelTimestamp The kernel timestamp of the event. + * @return this. + */ + public abstract Builder setKernelTimestamp(@Nullable Timestamp kernelTimestamp); + + /** + * Sets the message size. + * + * @param messageSize represents the size in bytes of this network message. + * @return this. + */ + public abstract Builder setMessageSize(long messageSize); + + /** + * Builds and returns a {@code NetworkEvent} with the desired values. + * + * @return a {@code NetworkEvent} with the desired values. + */ + public abstract NetworkEvent build(); + + Builder() {} + } + + NetworkEvent() {} +} diff --git a/api/src/main/java/io/opencensus/trace/Sampler.java b/api/src/main/java/io/opencensus/trace/Sampler.java index 29f70c6d..327bfa42 100644 --- a/api/src/main/java/io/opencensus/trace/Sampler.java +++ b/api/src/main/java/io/opencensus/trace/Sampler.java @@ -13,8 +13,6 @@ package io.opencensus.trace; -import io.opencensus.trace.base.SpanId; -import io.opencensus.trace.base.TraceId; import java.util.List; import javax.annotation.Nullable; diff --git a/api/src/main/java/io/opencensus/trace/Span.java b/api/src/main/java/io/opencensus/trace/Span.java index 15689057..428f0201 100644 --- a/api/src/main/java/io/opencensus/trace/Span.java +++ b/api/src/main/java/io/opencensus/trace/Span.java @@ -16,10 +16,6 @@ package io.opencensus.trace; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -import io.opencensus.trace.base.Annotation; -import io.opencensus.trace.base.AttributeValue; -import io.opencensus.trace.base.Link; -import io.opencensus.trace.base.NetworkEvent; import java.util.Collections; import java.util.EnumSet; import java.util.Map; diff --git a/api/src/main/java/io/opencensus/trace/SpanContext.java b/api/src/main/java/io/opencensus/trace/SpanContext.java index 8847a3ce..56a046f1 100644 --- a/api/src/main/java/io/opencensus/trace/SpanContext.java +++ b/api/src/main/java/io/opencensus/trace/SpanContext.java @@ -15,9 +15,6 @@ package io.opencensus.trace; import com.google.common.base.MoreObjects; import com.google.common.base.Objects; -import io.opencensus.trace.base.SpanId; -import io.opencensus.trace.base.TraceId; -import io.opencensus.trace.base.TraceOptions; import javax.annotation.concurrent.Immutable; /** diff --git a/api/src/main/java/io/opencensus/trace/SpanId.java b/api/src/main/java/io/opencensus/trace/SpanId.java new file mode 100644 index 00000000..8128c9d7 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/SpanId.java @@ -0,0 +1,171 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.MoreObjects; +import com.google.common.io.BaseEncoding; +import java.util.Arrays; +import java.util.Random; +import javax.annotation.concurrent.Immutable; + +/** + * A class that represents a span identifier. A valid span identifier is an 8-byte array with at + * least one non-zero byte. + */ +@Immutable +public final class SpanId implements Comparable { + /** The size in bytes of the {@code SpanId}. */ + public static final int SIZE = 8; + + /** The invalid {@code SpanId}. All bytes are 0. */ + public static final SpanId INVALID = new SpanId(new byte[SIZE]); + + // The internal representation of the SpanId. + private final byte[] bytes; + + private SpanId(byte[] bytes) { + this.bytes = bytes; + } + + /** + * Returns a {@code SpanId} built from a byte representation. + * + *

Equivalent with: + * + *

{@code
+   * SpanId.fromBytes(buffer, 0);
+   * }
+ * + * @param buffer the representation of the {@code SpanId}. + * @return a {@code SpanId} whose representation is given by the {@code buffer} parameter. + * @throws NullPointerException if {@code buffer} is null. + * @throws IllegalArgumentException if {@code buffer.length} is not {@link SpanId#SIZE}. + */ + public static SpanId fromBytes(byte[] buffer) { + checkNotNull(buffer, "buffer"); + checkArgument(buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); + byte[] bytesCopied = Arrays.copyOf(buffer, SIZE); + return new SpanId(bytesCopied); + } + + /** + * Returns a {@code SpanId} whose representation is copied from the {@code src} beginning at the + * {@code srcOffset} offset. + * + * @param src the buffer where the representation of the {@code SpanId} is copied. + * @param srcOffset the offset in the buffer where the representation of the {@code SpanId} + * begins. + * @return a {@code SpanId} whose representation is copied from the buffer. + * @throws NullPointerException if {@code src} is null. + * @throws IndexOutOfBoundsException if {@code srcOffset+SpanId.SIZE} is greater than {@code + * src.length}. + */ + public static SpanId fromBytes(byte[] src, int srcOffset) { + byte[] bytes = new byte[SIZE]; + System.arraycopy(src, srcOffset, bytes, 0, SIZE); + return new SpanId(bytes); + } + + /** + * Generates a new random {@code SpanId}. + * + * @param random The random number generator. + * @return a valid new {@code SpanId}. + */ + public static SpanId generateRandomId(Random random) { + byte[] bytes = new byte[SIZE]; + do { + random.nextBytes(bytes); + } while (Arrays.equals(bytes, INVALID.bytes)); + return new SpanId(bytes); + } + + /** + * Returns the byte representation of the {@code SpanId}. + * + * @return the byte representation of the {@code SpanId}. + */ + public byte[] getBytes() { + return Arrays.copyOf(bytes, SIZE); + } + + /** + * Copies the byte array representations of the {@code SpanId} into the {@code dest} beginning at + * the {@code destOffset} offset. + * + *

Equivalent with (but faster because it avoids any new allocations): + * + *

{@code
+   * System.arraycopy(getBytes(), 0, dest, destOffset, SpanId.SIZE);
+   * }
+ * + * @param dest the destination buffer. + * @param destOffset the starting offset in the destination buffer. + * @throws NullPointerException if {@code dest} is null. + * @throws IndexOutOfBoundsException if {@code destOffset+SpanId.SIZE} is greater than {@code + * dest.length}. + */ + public void copyBytesTo(byte[] dest, int destOffset) { + System.arraycopy(bytes, 0, dest, destOffset, SIZE); + } + + /** + * Returns whether the span identifier is valid. A valid span identifier is an 8-byte array with + * at least one non-zero byte. + * + * @return {@code true} if the span identifier is valid. + */ + public boolean isValid() { + return !Arrays.equals(bytes, INVALID.bytes); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof SpanId)) { + return false; + } + + SpanId that = (SpanId) obj; + return Arrays.equals(bytes, that.bytes); + } + + @Override + public int hashCode() { + return Arrays.hashCode(bytes); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("spanId", BaseEncoding.base16().lowerCase().encode(bytes)) + .toString(); + } + + @Override + public int compareTo(SpanId that) { + for (int i = 0; i < SIZE; i++) { + if (bytes[i] != that.bytes[i]) { + return bytes[i] < that.bytes[i] ? -1 : 1; + } + } + return 0; + } +} diff --git a/api/src/main/java/io/opencensus/trace/Status.java b/api/src/main/java/io/opencensus/trace/Status.java new file mode 100644 index 00000000..fab8a833 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/Status.java @@ -0,0 +1,334 @@ +/* + * Copyright 2016, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.MoreObjects; +import com.google.common.base.Objects; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.TreeMap; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * Defines the status of a {@link Span} by providing a standard {@link CanonicalCode} in conjunction + * with an optional descriptive message. Instances of {@code Status} are created by starting with + * the template for the appropriate {@link Status.CanonicalCode} and supplementing it with + * additional information: {@code Status.NOT_FOUND.withDescription("Could not find + * 'important_file.txt'");} + */ +@Immutable +public final class Status { + /** + * The set of canonical status codes. If new codes are added over time they must choose a + * numerical value that does not collide with any previously used value. + */ + public enum CanonicalCode { + /** The operation completed successfully. */ + OK(0), + + /** The operation was cancelled (typically by the caller). */ + CANCELLED(1), + + /** + * Unknown error. An example of where this error may be returned is if a Status value received + * from another address space belongs to an error-space that is not known in this address space. + * Also errors raised by APIs that do not return enough error information may be converted to + * this error. + */ + UNKNOWN(2), + + /** + * Client specified an invalid argument. Note that this differs from FAILED_PRECONDITION. + * INVALID_ARGUMENT indicates arguments that are problematic regardless of the state of the + * system (e.g., a malformed file name). + */ + INVALID_ARGUMENT(3), + + /** + * Deadline expired before operation could complete. For operations that change the state of the + * system, this error may be returned even if the operation has completed successfully. For + * example, a successful response from a server could have been delayed long enough for the + * deadline to expire. + */ + DEADLINE_EXCEEDED(4), + + /** Some requested entity (e.g., file or directory) was not found. */ + NOT_FOUND(5), + + /** Some entity that we attempted to create (e.g., file or directory) already exists. */ + ALREADY_EXISTS(6), + + /** + * The caller does not have permission to execute the specified operation. PERMISSION_DENIED + * must not be used for rejections caused by exhausting some resource (use RESOURCE_EXHAUSTED + * instead for those errors). PERMISSION_DENIED must not be used if the caller cannot be + * identified (use UNAUTHENTICATED instead for those errors). + */ + PERMISSION_DENIED(7), + + /** + * Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system + * is out of space. + */ + RESOURCE_EXHAUSTED(8), + + /** + * Operation was rejected because the system is not in a state required for the operation's + * execution. For example, directory to be deleted may be non-empty, an rmdir operation is + * applied to a non-directory, etc. + * + *

A litmus test that may help a service implementor in deciding between FAILED_PRECONDITION, + * ABORTED, and UNAVAILABLE: (a) Use UNAVAILABLE if the client can retry just the failing call. + * (b) Use ABORTED if the client should retry at a higher-level (e.g., restarting a + * read-modify-write sequence). (c) Use FAILED_PRECONDITION if the client should not retry until + * the system state has been explicitly fixed. E.g., if an "rmdir" fails because the directory + * is non-empty, FAILED_PRECONDITION should be returned since the client should not retry unless + * they have first fixed up the directory by deleting files from it. + */ + FAILED_PRECONDITION(9), + + /** + * The operation was aborted, typically due to a concurrency issue like sequencer check + * failures, transaction aborts, etc. + * + *

See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE. + */ + ABORTED(10), + + /** + * Operation was attempted past the valid range. E.g., seeking or reading past end of file. + * + *

Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed if the system + * state changes. For example, a 32-bit file system will generate INVALID_ARGUMENT if asked to + * read at an offset that is not in the range [0,2^32-1], but it will generate OUT_OF_RANGE if + * asked to read from an offset past the current file size. + * + *

There is a fair bit of overlap between FAILED_PRECONDITION and OUT_OF_RANGE. We recommend + * using OUT_OF_RANGE (the more specific error) when it applies so that callers who are + * iterating through a space can easily look for an OUT_OF_RANGE error to detect when they are + * done. + */ + OUT_OF_RANGE(11), + + /** Operation is not implemented or not supported/enabled in this service. */ + UNIMPLEMENTED(12), + + /** + * Internal errors. Means some invariants expected by underlying system has been broken. If you + * see one of these errors, something is very broken. + */ + INTERNAL(13), + + /** + * The service is currently unavailable. This is a most likely a transient condition and may be + * corrected by retrying with a backoff. + * + *

See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE. + */ + UNAVAILABLE(14), + + /** Unrecoverable data loss or corruption. */ + DATA_LOSS(15), + + /** The request does not have valid authentication credentials for the operation. */ + UNAUTHENTICATED(16); + + private final int value; + + private CanonicalCode(int value) { + this.value = value; + } + + /** + * Returns the numerical value of the code. + * + * @return the numerical value of the code. + */ + public int value() { + return value; + } + + /** + * Returns the status that has the current {@code CanonicalCode}.. + * + * @return the status that has the current {@code CanonicalCode}. + */ + @VisibleForTesting + public Status toStatus() { + return STATUS_LIST.get(value); + } + } + + // Create the canonical list of Status instances indexed by their code values. + private static final List STATUS_LIST = buildStatusList(); + + private static List buildStatusList() { + TreeMap canonicalizer = new TreeMap(); + for (CanonicalCode code : CanonicalCode.values()) { + Status replaced = canonicalizer.put(code.value(), new Status(code, null)); + if (replaced != null) { + throw new IllegalStateException( + "Code value duplication between " + + replaced.getCanonicalCode().name() + + " & " + + code.name()); + } + } + return Collections.unmodifiableList(new ArrayList(canonicalizer.values())); + } + + // A pseudo-enum of Status instances mapped 1:1 with values in CanonicalCode. This simplifies + // construction patterns for derived instances of Status. + /** The operation completed successfully. */ + public static final Status OK = CanonicalCode.OK.toStatus(); + /** The operation was cancelled (typically by the caller). */ + public static final Status CANCELLED = CanonicalCode.CANCELLED.toStatus(); + /** Unknown error. See {@link CanonicalCode#UNKNOWN}. */ + public static final Status UNKNOWN = CanonicalCode.UNKNOWN.toStatus(); + /** Client specified an invalid argument. See {@link CanonicalCode#INVALID_ARGUMENT}. */ + public static final Status INVALID_ARGUMENT = CanonicalCode.INVALID_ARGUMENT.toStatus(); + /** + * Deadline expired before operation could complete. See {@link CanonicalCode#DEADLINE_EXCEEDED}. + */ + public static final Status DEADLINE_EXCEEDED = CanonicalCode.DEADLINE_EXCEEDED.toStatus(); + /** Some requested entity (e.g., file or directory) was not found. */ + public static final Status NOT_FOUND = CanonicalCode.NOT_FOUND.toStatus(); + /** Some entity that we attempted to create (e.g., file or directory) already exists. */ + public static final Status ALREADY_EXISTS = CanonicalCode.ALREADY_EXISTS.toStatus(); + /** + * The caller does not have permission to execute the specified operation. See {@link + * CanonicalCode#PERMISSION_DENIED}. + */ + public static final Status PERMISSION_DENIED = CanonicalCode.PERMISSION_DENIED.toStatus(); + /** The request does not have valid authentication credentials for the operation. */ + public static final Status UNAUTHENTICATED = CanonicalCode.UNAUTHENTICATED.toStatus(); + /** + * Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system + * is out of space. + */ + public static final Status RESOURCE_EXHAUSTED = CanonicalCode.RESOURCE_EXHAUSTED.toStatus(); + /** + * Operation was rejected because the system is not in a state required for the operation's + * execution. See {@link CanonicalCode#FAILED_PRECONDITION}. + */ + public static final Status FAILED_PRECONDITION = CanonicalCode.FAILED_PRECONDITION.toStatus(); + /** + * The operation was aborted, typically due to a concurrency issue like sequencer check failures, + * transaction aborts, etc. See {@link CanonicalCode#ABORTED}. + */ + public static final Status ABORTED = CanonicalCode.ABORTED.toStatus(); + /** Operation was attempted past the valid range. See {@link CanonicalCode#OUT_OF_RANGE}. */ + public static final Status OUT_OF_RANGE = CanonicalCode.OUT_OF_RANGE.toStatus(); + /** Operation is not implemented or not supported/enabled in this service. */ + public static final Status UNIMPLEMENTED = CanonicalCode.UNIMPLEMENTED.toStatus(); + /** Internal errors. See {@link CanonicalCode#INTERNAL}. */ + public static final Status INTERNAL = CanonicalCode.INTERNAL.toStatus(); + /** The service is currently unavailable. See {@link CanonicalCode#UNAVAILABLE}. */ + public static final Status UNAVAILABLE = CanonicalCode.UNAVAILABLE.toStatus(); + /** Unrecoverable data loss or corruption. */ + public static final Status DATA_LOSS = CanonicalCode.DATA_LOSS.toStatus(); + + // The canonical code of this message. + private final CanonicalCode canonicalCode; + // An additional error message. + private final String description; + + private Status(CanonicalCode canonicalCode, @Nullable String description) { + this.canonicalCode = checkNotNull(canonicalCode, "canonicalCode"); + this.description = description; + } + + /** + * Creates a derived instance of {@code Status} with the given description. + * + * @param description the new description of the {@code Status}. + * @return The newly created {@code Status} with the given description. + */ + public Status withDescription(String description) { + if (Objects.equal(this.description, description)) { + return this; + } + return new Status(this.canonicalCode, description); + } + + /** + * Returns the canonical status code. + * + * @return the canonical status code. + */ + public CanonicalCode getCanonicalCode() { + return canonicalCode; + } + + /** + * Returns the description of this {@code Status} for human consumption. + * + * @return the description of this {@code Status}. + */ + @Nullable + public String getDescription() { + return description; + } + + /** + * Returns {@code true} if this {@code Status} is OK, i.e., not an error. + * + * @return {@code true} if this {@code Status} is OK. + */ + public boolean isOk() { + return CanonicalCode.OK == canonicalCode; + } + + /** + * Equality on Statuses is not well defined. Instead, do comparison based on their CanonicalCode + * with {@link #getCanonicalCode}. The description of the Status is unlikely to be stable, and + * additional fields may be added to Status in the future. + */ + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof Status)) { + return false; + } + + Status that = (Status) obj; + return canonicalCode == that.canonicalCode && Objects.equal(description, that.description); + } + + /** + * Hash codes on Statuses are not well defined. + * + * @see #equals + */ + @Override + public int hashCode() { + return Objects.hashCode(canonicalCode, description); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("canonicalCode", canonicalCode) + .add("description", description) + .toString(); + } +} diff --git a/api/src/main/java/io/opencensus/trace/TraceId.java b/api/src/main/java/io/opencensus/trace/TraceId.java new file mode 100644 index 00000000..191f593f --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/TraceId.java @@ -0,0 +1,193 @@ +/* + * Copyright 2016, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.MoreObjects; +import com.google.common.io.BaseEncoding; +import io.opencensus.common.Internal; +import java.util.Arrays; +import java.util.Random; +import javax.annotation.concurrent.Immutable; + +/** + * A class that represents a trace identifier. A valid trace identifier is a 16-byte array with at + * least one non-zero byte. + */ +@Immutable +public final class TraceId implements Comparable { + /** The size in bytes of the {@code TraceId}. */ + public static final int SIZE = 16; + + /** The invalid {@code TraceId}. All bytes are '\0'. */ + public static final TraceId INVALID = new TraceId(new byte[SIZE]); + + // The internal representation of the TraceId. + private final byte[] bytes; + + private TraceId(byte[] bytes) { + this.bytes = bytes; + } + + /** + * Returns a {@code TraceId} built from a byte representation. + * + *

Equivalent with: + * + *

{@code
+   * TraceId.fromBytes(buffer, 0);
+   * }
+ * + * @param buffer the representation of the {@code TraceId}. + * @return a {@code TraceId} whose representation is given by the {@code buffer} parameter. + * @throws NullPointerException if {@code buffer} is null. + * @throws IllegalArgumentException if {@code buffer.length} is not {@link TraceId#SIZE}. + */ + public static TraceId fromBytes(byte[] buffer) { + checkNotNull(buffer, "buffer"); + checkArgument(buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); + byte[] bytesCopied = Arrays.copyOf(buffer, SIZE); + return new TraceId(bytesCopied); + } + + /** + * Returns a {@code TraceId} whose representation is copied from the {@code src} beginning at the + * {@code srcOffset} offset. + * + * @param src the buffer where the representation of the {@code TraceId} is copied. + * @param srcOffset the offset in the buffer where the representation of the {@code TraceId} + * begins. + * @return a {@code TraceId} whose representation is copied from the buffer. + * @throws NullPointerException if {@code src} is null. + * @throws IndexOutOfBoundsException if {@code srcOffset+TraceId.SIZE} is greater than {@code + * src.length}. + */ + public static TraceId fromBytes(byte[] src, int srcOffset) { + byte[] bytes = new byte[SIZE]; + System.arraycopy(src, srcOffset, bytes, 0, SIZE); + return new TraceId(bytes); + } + + /** + * Generates a new random {@code TraceId}. + * + * @param random the random number generator. + * @return a new valid {@code TraceId}. + */ + public static TraceId generateRandomId(Random random) { + byte[] bytes = new byte[SIZE]; + do { + random.nextBytes(bytes); + } while (Arrays.equals(bytes, INVALID.bytes)); + return new TraceId(bytes); + } + + /** + * Returns the 16-bytes array representation of the {@code TraceId}. + * + * @return the 16-bytes array representation of the {@code TraceId}. + */ + public byte[] getBytes() { + return Arrays.copyOf(bytes, SIZE); + } + + /** + * Copies the byte array representations of the {@code TraceId} into the {@code dest} beginning at + * the {@code destOffset} offset. + * + *

Equivalent with (but faster because it avoids any new allocations): + * + *

{@code
+   * System.arraycopy(getBytes(), 0, dest, destOffset, TraceId.SIZE);
+   * }
+ * + * @param dest the destination buffer. + * @param destOffset the starting offset in the destination buffer. + * @throws NullPointerException if {@code dest} is null. + * @throws IndexOutOfBoundsException if {@code destOffset+TraceId.SIZE} is greater than {@code + * dest.length}. + */ + public void copyBytesTo(byte[] dest, int destOffset) { + System.arraycopy(bytes, 0, dest, destOffset, SIZE); + } + + /** + * Returns whether the {@code TraceId} is valid. A valid trace identifier is a 16-byte array with + * at least one non-zero byte. + * + * @return {@code true} if the {@code TraceId} is valid. + */ + public boolean isValid() { + return !Arrays.equals(bytes, INVALID.bytes); + } + + /** + * Returns the lower 8 bytes of the trace-id as a long value, assuming little-endian order. This + * is used in ProbabilitySampler. + * + *

This method is marked as internal and subject to change. + * + * @return the lower 8 bytes of the trace-id as a long value, assuming little-endian order. + */ + @Internal + public long getLowerLong() { + long result = 0; + for (int i = 0; i < Long.SIZE / Byte.SIZE; i++) { + result <<= Byte.SIZE; + result |= (bytes[i] & 0xff); + } + if (result < 0) { + return -result; + } + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof TraceId)) { + return false; + } + + TraceId that = (TraceId) obj; + return Arrays.equals(bytes, that.bytes); + } + + @Override + public int hashCode() { + return Arrays.hashCode(bytes); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("traceId", BaseEncoding.base16().lowerCase().encode(bytes)) + .toString(); + } + + @Override + public int compareTo(TraceId that) { + for (int i = 0; i < SIZE; i++) { + if (bytes[i] != that.bytes[i]) { + return bytes[i] < that.bytes[i] ? -1 : 1; + } + } + return 0; + } +} diff --git a/api/src/main/java/io/opencensus/trace/TraceOptions.java b/api/src/main/java/io/opencensus/trace/TraceOptions.java new file mode 100644 index 00000000..d41737fa --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/TraceOptions.java @@ -0,0 +1,210 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkElementIndex; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.MoreObjects; +import com.google.common.base.Objects; +import javax.annotation.concurrent.Immutable; + +/** + * A class that represents global trace options. These options are propagated to all child {@link + * io.opencensus.trace.Span spans}. These determine features such as whether a {@code Span} should + * be traced. It is implemented as a bitmask. + */ +@Immutable +public final class TraceOptions { + // Default options. Nothing set. + private static final byte DEFAULT_OPTIONS = 0; + // Bit to represent whether trace is sampled or not. + private static final byte IS_SAMPLED = 0x1; + + /** The size in bytes of the {@code TraceOptions}. */ + public static final int SIZE = 1; + + /** The default {@code TraceOptions}. */ + public static final TraceOptions DEFAULT = new TraceOptions(DEFAULT_OPTIONS); + + // The set of enabled features is determined by all the enabled bits. + private final byte options; + + // Creates a new {@code TraceOptions} with the given options. + private TraceOptions(byte options) { + this.options = options; + } + + /** + * Returns a {@code TraceOptions} built from a byte representation. + * + *

Equivalent with: + * + *

{@code
+   * TraceOptions.fromBytes(buffer, 0);
+   * }
+ * + * @param buffer the representation of the {@code TraceOptions}. + * @return a {@code TraceOptions} whose representation is given by the {@code buffer} parameter. + * @throws NullPointerException if {@code buffer} is null. + * @throws IllegalArgumentException if {@code buffer.length} is not {@link TraceOptions#SIZE}. + */ + public static TraceOptions fromBytes(byte[] buffer) { + checkNotNull(buffer, "buffer"); + checkArgument(buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); + return new TraceOptions(buffer[0]); + } + + /** + * Returns a {@code TraceOptions} whose representation is copied from the {@code src} beginning at + * the {@code srcOffset} offset. + * + * @param src the buffer where the representation of the {@code TraceOptions} is copied. + * @param srcOffset the offset in the buffer where the representation of the {@code TraceOptions} + * begins. + * @return a {@code TraceOptions} whose representation is copied from the buffer. + * @throws NullPointerException if {@code src} is null. + * @throws IndexOutOfBoundsException if {@code srcOffset+TraceOptions.SIZE} is greater than {@code + * src.length}. + */ + public static TraceOptions fromBytes(byte[] src, int srcOffset) { + checkElementIndex(srcOffset, src.length); + return new TraceOptions(src[srcOffset]); + } + + /** + * Returns the 1-byte array representation of the {@code TraceOptions}. + * + * @return the 1-byte array representation of the {@code TraceOptions}. + */ + public byte[] getBytes() { + byte[] bytes = new byte[SIZE]; + bytes[0] = options; + return bytes; + } + + /** + * Copies the byte representations of the {@code TraceOptions} into the {@code dest} beginning at + * the {@code destOffset} offset. + * + *

Equivalent with (but faster because it avoids any new allocations): + * + *

{@code
+   * System.arraycopy(getBytes(), 0, dest, destOffset, TraceOptions.SIZE);
+   * }
+ * + * @param dest the destination buffer. + * @param destOffset the starting offset in the destination buffer. + * @throws NullPointerException if {@code dest} is null. + * @throws IndexOutOfBoundsException if {@code destOffset+TraceOptions.SIZE} is greater than + * {@code dest.length}. + */ + public void copyBytesTo(byte[] dest, int destOffset) { + checkElementIndex(destOffset, dest.length); + dest[destOffset] = options; + } + + /** + * Returns a new {@link Builder} with default options. + * + * @return a new {@code Builder} with default options. + */ + public static Builder builder() { + return new Builder(DEFAULT_OPTIONS); + } + + /** + * Returns a new {@link Builder} with all given options set. + * + * @param traceOptions the given options set. + * @return a new {@code Builder} with all given options set. + */ + public static Builder builder(TraceOptions traceOptions) { + return new Builder(traceOptions.options); + } + + /** + * Returns a boolean indicating whether this {@code Span} is part of a sampled trace and data + * should be exported to a persistent store. + * + * @return a boolean indicating whether the trace is sampled. + */ + public boolean isSampled() { + return hasOption(IS_SAMPLED); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof TraceOptions)) { + return false; + } + + TraceOptions that = (TraceOptions) obj; + return options == that.options; + } + + @Override + public int hashCode() { + return Objects.hashCode(options); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this).add("sampled", isSampled()).toString(); + } + + /** Builder class for {@link TraceOptions}. */ + public static final class Builder { + private byte options; + + private Builder(byte options) { + this.options = options; + } + + /** + * Marks this trace as sampled. + * + * @return this. + */ + public Builder setIsSampled() { + options |= IS_SAMPLED; + return this; + } + + /** + * Builds and returns a {@code TraceOptions} with the desired options. + * + * @return a {@code TraceOptions} with the desired options. + */ + public TraceOptions build() { + return new TraceOptions(options); + } + } + + // Returns the current set of options bitmask. + @VisibleForTesting + byte getOptions() { + return options; + } + + private boolean hasOption(int mask) { + return (this.options & mask) != 0; + } +} diff --git a/api/src/main/java/io/opencensus/trace/base/Annotation.java b/api/src/main/java/io/opencensus/trace/base/Annotation.java deleted file mode 100644 index b86b93d8..00000000 --- a/api/src/main/java/io/opencensus/trace/base/Annotation.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.base; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.auto.value.AutoValue; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import javax.annotation.concurrent.Immutable; - -/** A text annotation with a set of attributes. */ -@Immutable -@AutoValue -public abstract class Annotation { - private static final Map EMPTY_ATTRIBUTES = - Collections.unmodifiableMap(Collections.emptyMap()); - - /** - * Returns a new {@code Annotation} with the given description. - * - * @param description the text description of the {@code Annotation}. - * @return a new {@code Annotation} with the given description. - * @throws NullPointerException if {@code description} is {@code null}. - */ - public static Annotation fromDescription(String description) { - return new AutoValue_Annotation(description, EMPTY_ATTRIBUTES); - } - - /** - * Returns a new {@code Annotation} with the given description and set of attributes. - * - * @param description the text description of the {@code Annotation}. - * @param attributes the attributes of the {@code Annotation}. - * @return a new {@code Annotation} with the given description and set of attributes. - * @throws NullPointerException if {@code description} or {@code attributes} are {@code null}. - */ - public static Annotation fromDescriptionAndAttributes( - String description, Map attributes) { - return new AutoValue_Annotation( - description, - Collections.unmodifiableMap( - new HashMap(checkNotNull(attributes, "attributes")))); - } - - /** - * Return the description of the {@code Annotation}. - * - * @return the description of the {@code Annotation}. - */ - public abstract String getDescription(); - - /** - * Return the attributes of the {@code Annotation}. - * - * @return the attributes of the {@code Annotation}. - */ - public abstract Map getAttributes(); - - Annotation() {} -} diff --git a/api/src/main/java/io/opencensus/trace/base/AttributeValue.java b/api/src/main/java/io/opencensus/trace/base/AttributeValue.java deleted file mode 100644 index 86f0c84a..00000000 --- a/api/src/main/java/io/opencensus/trace/base/AttributeValue.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * 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.base; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.auto.value.AutoValue; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; - -/** - * A class that represents all the possible values for an attribute. An attribute can have 3 types - * of values: {@code String}, {@code Boolean} or {@code Long}. - */ -@Immutable -@AutoValue -public abstract class AttributeValue { - /** - * Returns an {@code AttributeValue} with a string value. - * - * @param stringValue The new value. - * @return an {@code AttributeValue} with a string value. - * @throws NullPointerException if {@code stringValue} is {@code null}. - */ - public static AttributeValue stringAttributeValue(String stringValue) { - return new AutoValue_AttributeValue(checkNotNull(stringValue, "stringValue"), null, null); - } - - /** - * Returns an {@code AttributeValue} with a boolean value. - * - * @param booleanValue The new value. - * @return an {@code AttributeValue} with a boolean value. - */ - public static AttributeValue booleanAttributeValue(boolean booleanValue) { - return new AutoValue_AttributeValue(null, booleanValue, null); - } - - /** - * Returns an {@code AttributeValue} with a long value. - * - * @param longValue The new value. - * @return an {@code AttributeValue} with a long value. - */ - public static AttributeValue longAttributeValue(long longValue) { - return new AutoValue_AttributeValue(null, null, longValue); - } - - AttributeValue() {} - - /** - * Returns the {@code String} value if this is a string {@code AttributeValue}, otherwise {@code - * null}. - * - * @return the {@code String} value if this is a string {@code AttributeValue}, otherwise {@code - * null}. - */ - @Nullable - public abstract String getStringValue(); - - /** - * Returns the {@code Boolean} value if this is a boolean {@code AttributeValue}, otherwise {@code - * null}. - * - * @return the {@code Boolean} value if this is a boolean {@code AttributeValue}, otherwise {@code - * null}. - */ - @Nullable - public abstract Boolean getBooleanValue(); - - /** - * Returns the {@code Long} value if this is a long {@code AttributeValue}, otherwise {@code - * null}. - * - * @return the {@code Long} value if this is a long {@code AttributeValue}, otherwise {@code - * null}. - */ - @Nullable - public abstract Long getLongValue(); -} diff --git a/api/src/main/java/io/opencensus/trace/base/Link.java b/api/src/main/java/io/opencensus/trace/base/Link.java deleted file mode 100644 index 3f8b93f8..00000000 --- a/api/src/main/java/io/opencensus/trace/base/Link.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.base; - -import com.google.auto.value.AutoValue; -import io.opencensus.trace.Span; -import io.opencensus.trace.SpanContext; -import javax.annotation.concurrent.Immutable; - -/** - * A link to a {@link Span} from a different trace. - * - *

It requires a {@link Type} which describes the relationship with the linked {@code Span} and - * the identifiers of the linked {@code Span}. - * - *

Used (for example) in batching operations, where a single batch handler processes multiple - * requests from different traces. - */ -@Immutable -@AutoValue -public abstract class Link { - /** The relationship with the linked {@code Span} relative to the current {@code Span}. */ - public enum Type { - /** When the linked {@code Span} is a child of the current {@code Span}. */ - CHILD_LINKED_SPAN, - /** When the linked {@code Span} is a parent of the current {@code Span}. */ - PARENT_LINKED_SPAN - } - - /** - * Returns a new {@code Link}. - * - * @param context the context of the linked {@code Span}. - * @param type the type of the relationship with the linked {@code Span}. - * @return a new {@code Link}. - */ - public static Link fromSpanContext(SpanContext context, Type type) { - return new AutoValue_Link(context.getTraceId(), context.getSpanId(), type); - } - - /** - * Returns the {@code TraceId}. - * - * @return the {@code TraceId}. - */ - public abstract TraceId getTraceId(); - - /** - * Returns the {@code SpanId}. - * - * @return the {@code SpanId} - */ - public abstract SpanId getSpanId(); - - /** - * Returns the {@code Type}. - * - * @return the {@code Type}. - */ - public abstract Type getType(); - - Link() {} -} diff --git a/api/src/main/java/io/opencensus/trace/base/NetworkEvent.java b/api/src/main/java/io/opencensus/trace/base/NetworkEvent.java deleted file mode 100644 index 9edc6f25..00000000 --- a/api/src/main/java/io/opencensus/trace/base/NetworkEvent.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * 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.base; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.auto.value.AutoValue; -import io.opencensus.common.Timestamp; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; - -/** - * A class that represents a network event. It requires a {@link Type type} and a message id that - * serves to uniquely identify each network message. It can optionally can have information about - * the kernel time and message size. - */ -@Immutable -@AutoValue -public abstract class NetworkEvent { - /** Available types for a {@code NetworkEvent}. */ - public enum Type { - /** When the message was sent. */ - SENT, - /** When the message was received. */ - RECV, - } - - /** - * Returns a new {@link Builder} with default values. - * - * @param type designates whether this is a network send or receive message. - * @param messageId serves to uniquely identify each network message. - * @return a new {@code Builder} with default values. - * @throws NullPointerException if {@code type} is {@code null}. - */ - public static Builder builder(Type type, long messageId) { - return new AutoValue_NetworkEvent.Builder() - .setType(checkNotNull(type, "type")) - .setMessageId(messageId) - // We need to set a value for the message size because the autovalue requires all - // primitives to be initialized. - // TODO(bdrutu): Consider to change the API to require message size. - .setMessageSize(0); - } - - /** - * Returns the kernel timestamp associated with the {@code NetworkEvent} or {@code null} if not - * set. - * - * @return the kernel timestamp associated with the {@code NetworkEvent} or {@code null} if not - * set. - */ - @Nullable - public abstract Timestamp getKernelTimestamp(); - - /** - * Returns the type of the {@code NetworkEvent}. - * - * @return the type of the {@code NetworkEvent}. - */ - public abstract Type getType(); - - /** - * Returns the message id argument that serves to uniquely identify each network message. - * - * @return The message id of the {@code NetworkEvent}. - */ - public abstract long getMessageId(); - - /** - * Returns The message size in bytes of the {@code NetworkEvent}. - * - * @return The message size in bytes of the {@code NetworkEvent}. - */ - public abstract long getMessageSize(); - - /** Builder class for {@link NetworkEvent}. */ - @AutoValue.Builder - public abstract static class Builder { - // Package protected methods because these values are mandatory and set only in the - // NetworkEvent#builder() function. - abstract Builder setType(Type type); - - abstract Builder setMessageId(long messageId); - - /** - * Sets the kernel timestamp. - * - * @param kernelTimestamp The kernel timestamp of the event. - * @return this. - */ - public abstract Builder setKernelTimestamp(@Nullable Timestamp kernelTimestamp); - - /** - * Sets the message size. - * - * @param messageSize represents the size in bytes of this network message. - * @return this. - */ - public abstract Builder setMessageSize(long messageSize); - - /** - * Builds and returns a {@code NetworkEvent} with the desired values. - * - * @return a {@code NetworkEvent} with the desired values. - */ - public abstract NetworkEvent build(); - - Builder() {} - } - - NetworkEvent() {} -} diff --git a/api/src/main/java/io/opencensus/trace/base/SpanId.java b/api/src/main/java/io/opencensus/trace/base/SpanId.java deleted file mode 100644 index 4e0b1bed..00000000 --- a/api/src/main/java/io/opencensus/trace/base/SpanId.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.base; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.base.MoreObjects; -import com.google.common.io.BaseEncoding; -import java.util.Arrays; -import java.util.Random; -import javax.annotation.concurrent.Immutable; - -/** - * A class that represents a span identifier. A valid span identifier is an 8-byte array with at - * least one non-zero byte. - */ -@Immutable -public final class SpanId implements Comparable { - /** The size in bytes of the {@code SpanId}. */ - public static final int SIZE = 8; - - /** The invalid {@code SpanId}. All bytes are 0. */ - public static final SpanId INVALID = new SpanId(new byte[SIZE]); - - // The internal representation of the SpanId. - private final byte[] bytes; - - private SpanId(byte[] bytes) { - this.bytes = bytes; - } - - /** - * Returns a {@code SpanId} built from a byte representation. - * - *

Equivalent with: - * - *

{@code
-   * SpanId.fromBytes(buffer, 0);
-   * }
- * - * @param buffer the representation of the {@code SpanId}. - * @return a {@code SpanId} whose representation is given by the {@code buffer} parameter. - * @throws NullPointerException if {@code buffer} is null. - * @throws IllegalArgumentException if {@code buffer.length} is not {@link SpanId#SIZE}. - */ - public static SpanId fromBytes(byte[] buffer) { - checkNotNull(buffer, "buffer"); - checkArgument(buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); - byte[] bytesCopied = Arrays.copyOf(buffer, SIZE); - return new SpanId(bytesCopied); - } - - /** - * Returns a {@code SpanId} whose representation is copied from the {@code src} beginning at the - * {@code srcOffset} offset. - * - * @param src the buffer where the representation of the {@code SpanId} is copied. - * @param srcOffset the offset in the buffer where the representation of the {@code SpanId} - * begins. - * @return a {@code SpanId} whose representation is copied from the buffer. - * @throws NullPointerException if {@code src} is null. - * @throws IndexOutOfBoundsException if {@code srcOffset+SpanId.SIZE} is greater than {@code - * src.length}. - */ - public static SpanId fromBytes(byte[] src, int srcOffset) { - byte[] bytes = new byte[SIZE]; - System.arraycopy(src, srcOffset, bytes, 0, SIZE); - return new SpanId(bytes); - } - - /** - * Generates a new random {@code SpanId}. - * - * @param random The random number generator. - * @return a valid new {@code SpanId}. - */ - public static SpanId generateRandomId(Random random) { - byte[] bytes = new byte[SIZE]; - do { - random.nextBytes(bytes); - } while (Arrays.equals(bytes, INVALID.bytes)); - return new SpanId(bytes); - } - - /** - * Returns the byte representation of the {@code SpanId}. - * - * @return the byte representation of the {@code SpanId}. - */ - public byte[] getBytes() { - return Arrays.copyOf(bytes, SIZE); - } - - /** - * Copies the byte array representations of the {@code SpanId} into the {@code dest} beginning at - * the {@code destOffset} offset. - * - *

Equivalent with (but faster because it avoids any new allocations): - * - *

{@code
-   * System.arraycopy(getBytes(), 0, dest, destOffset, SpanId.SIZE);
-   * }
- * - * @param dest the destination buffer. - * @param destOffset the starting offset in the destination buffer. - * @throws NullPointerException if {@code dest} is null. - * @throws IndexOutOfBoundsException if {@code destOffset+SpanId.SIZE} is greater than {@code - * dest.length}. - */ - public void copyBytesTo(byte[] dest, int destOffset) { - System.arraycopy(bytes, 0, dest, destOffset, SIZE); - } - - /** - * Returns whether the span identifier is valid. A valid span identifier is an 8-byte array with - * at least one non-zero byte. - * - * @return {@code true} if the span identifier is valid. - */ - public boolean isValid() { - return !Arrays.equals(bytes, INVALID.bytes); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (!(obj instanceof SpanId)) { - return false; - } - - SpanId that = (SpanId) obj; - return Arrays.equals(bytes, that.bytes); - } - - @Override - public int hashCode() { - return Arrays.hashCode(bytes); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("spanId", BaseEncoding.base16().lowerCase().encode(bytes)) - .toString(); - } - - @Override - public int compareTo(SpanId that) { - for (int i = 0; i < SIZE; i++) { - if (bytes[i] != that.bytes[i]) { - return bytes[i] < that.bytes[i] ? -1 : 1; - } - } - return 0; - } -} diff --git a/api/src/main/java/io/opencensus/trace/base/Status.java b/api/src/main/java/io/opencensus/trace/base/Status.java deleted file mode 100644 index e0ab4904..00000000 --- a/api/src/main/java/io/opencensus/trace/base/Status.java +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * 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.base; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.MoreObjects; -import com.google.common.base.Objects; -import io.opencensus.trace.Span; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.TreeMap; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; - -/** - * Defines the status of a {@link Span} by providing a standard {@link CanonicalCode} in conjunction - * with an optional descriptive message. Instances of {@code Status} are created by starting with - * the template for the appropriate {@link Status.CanonicalCode} and supplementing it with - * additional information: {@code Status.NOT_FOUND.withDescription("Could not find - * 'important_file.txt'");} - */ -@Immutable -public final class Status { - /** - * The set of canonical status codes. If new codes are added over time they must choose a - * numerical value that does not collide with any previously used value. - */ - public enum CanonicalCode { - /** The operation completed successfully. */ - OK(0), - - /** The operation was cancelled (typically by the caller). */ - CANCELLED(1), - - /** - * Unknown error. An example of where this error may be returned is if a Status value received - * from another address space belongs to an error-space that is not known in this address space. - * Also errors raised by APIs that do not return enough error information may be converted to - * this error. - */ - UNKNOWN(2), - - /** - * Client specified an invalid argument. Note that this differs from FAILED_PRECONDITION. - * INVALID_ARGUMENT indicates arguments that are problematic regardless of the state of the - * system (e.g., a malformed file name). - */ - INVALID_ARGUMENT(3), - - /** - * Deadline expired before operation could complete. For operations that change the state of the - * system, this error may be returned even if the operation has completed successfully. For - * example, a successful response from a server could have been delayed long enough for the - * deadline to expire. - */ - DEADLINE_EXCEEDED(4), - - /** Some requested entity (e.g., file or directory) was not found. */ - NOT_FOUND(5), - - /** Some entity that we attempted to create (e.g., file or directory) already exists. */ - ALREADY_EXISTS(6), - - /** - * The caller does not have permission to execute the specified operation. PERMISSION_DENIED - * must not be used for rejections caused by exhausting some resource (use RESOURCE_EXHAUSTED - * instead for those errors). PERMISSION_DENIED must not be used if the caller cannot be - * identified (use UNAUTHENTICATED instead for those errors). - */ - PERMISSION_DENIED(7), - - /** - * Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system - * is out of space. - */ - RESOURCE_EXHAUSTED(8), - - /** - * Operation was rejected because the system is not in a state required for the operation's - * execution. For example, directory to be deleted may be non-empty, an rmdir operation is - * applied to a non-directory, etc. - * - *

A litmus test that may help a service implementor in deciding between FAILED_PRECONDITION, - * ABORTED, and UNAVAILABLE: (a) Use UNAVAILABLE if the client can retry just the failing call. - * (b) Use ABORTED if the client should retry at a higher-level (e.g., restarting a - * read-modify-write sequence). (c) Use FAILED_PRECONDITION if the client should not retry until - * the system state has been explicitly fixed. E.g., if an "rmdir" fails because the directory - * is non-empty, FAILED_PRECONDITION should be returned since the client should not retry unless - * they have first fixed up the directory by deleting files from it. - */ - FAILED_PRECONDITION(9), - - /** - * The operation was aborted, typically due to a concurrency issue like sequencer check - * failures, transaction aborts, etc. - * - *

See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE. - */ - ABORTED(10), - - /** - * Operation was attempted past the valid range. E.g., seeking or reading past end of file. - * - *

Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed if the system - * state changes. For example, a 32-bit file system will generate INVALID_ARGUMENT if asked to - * read at an offset that is not in the range [0,2^32-1], but it will generate OUT_OF_RANGE if - * asked to read from an offset past the current file size. - * - *

There is a fair bit of overlap between FAILED_PRECONDITION and OUT_OF_RANGE. We recommend - * using OUT_OF_RANGE (the more specific error) when it applies so that callers who are - * iterating through a space can easily look for an OUT_OF_RANGE error to detect when they are - * done. - */ - OUT_OF_RANGE(11), - - /** Operation is not implemented or not supported/enabled in this service. */ - UNIMPLEMENTED(12), - - /** - * Internal errors. Means some invariants expected by underlying system has been broken. If you - * see one of these errors, something is very broken. - */ - INTERNAL(13), - - /** - * The service is currently unavailable. This is a most likely a transient condition and may be - * corrected by retrying with a backoff. - * - *

See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE. - */ - UNAVAILABLE(14), - - /** Unrecoverable data loss or corruption. */ - DATA_LOSS(15), - - /** The request does not have valid authentication credentials for the operation. */ - UNAUTHENTICATED(16); - - private final int value; - - private CanonicalCode(int value) { - this.value = value; - } - - /** - * Returns the numerical value of the code. - * - * @return the numerical value of the code. - */ - public int value() { - return value; - } - - /** - * Returns the status that has the current {@code CanonicalCode}.. - * - * @return the status that has the current {@code CanonicalCode}. - */ - @VisibleForTesting - public Status toStatus() { - return STATUS_LIST.get(value); - } - } - - // Create the canonical list of Status instances indexed by their code values. - private static final List STATUS_LIST = buildStatusList(); - - private static List buildStatusList() { - TreeMap canonicalizer = new TreeMap(); - for (CanonicalCode code : CanonicalCode.values()) { - Status replaced = canonicalizer.put(code.value(), new Status(code, null)); - if (replaced != null) { - throw new IllegalStateException( - "Code value duplication between " - + replaced.getCanonicalCode().name() - + " & " - + code.name()); - } - } - return Collections.unmodifiableList(new ArrayList(canonicalizer.values())); - } - - // A pseudo-enum of Status instances mapped 1:1 with values in CanonicalCode. This simplifies - // construction patterns for derived instances of Status. - /** The operation completed successfully. */ - public static final Status OK = CanonicalCode.OK.toStatus(); - /** The operation was cancelled (typically by the caller). */ - public static final Status CANCELLED = CanonicalCode.CANCELLED.toStatus(); - /** Unknown error. See {@link CanonicalCode#UNKNOWN}. */ - public static final Status UNKNOWN = CanonicalCode.UNKNOWN.toStatus(); - /** Client specified an invalid argument. See {@link CanonicalCode#INVALID_ARGUMENT}. */ - public static final Status INVALID_ARGUMENT = CanonicalCode.INVALID_ARGUMENT.toStatus(); - /** - * Deadline expired before operation could complete. See {@link CanonicalCode#DEADLINE_EXCEEDED}. - */ - public static final Status DEADLINE_EXCEEDED = CanonicalCode.DEADLINE_EXCEEDED.toStatus(); - /** Some requested entity (e.g., file or directory) was not found. */ - public static final Status NOT_FOUND = CanonicalCode.NOT_FOUND.toStatus(); - /** Some entity that we attempted to create (e.g., file or directory) already exists. */ - public static final Status ALREADY_EXISTS = CanonicalCode.ALREADY_EXISTS.toStatus(); - /** - * The caller does not have permission to execute the specified operation. See {@link - * CanonicalCode#PERMISSION_DENIED}. - */ - public static final Status PERMISSION_DENIED = CanonicalCode.PERMISSION_DENIED.toStatus(); - /** The request does not have valid authentication credentials for the operation. */ - public static final Status UNAUTHENTICATED = CanonicalCode.UNAUTHENTICATED.toStatus(); - /** - * Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system - * is out of space. - */ - public static final Status RESOURCE_EXHAUSTED = CanonicalCode.RESOURCE_EXHAUSTED.toStatus(); - /** - * Operation was rejected because the system is not in a state required for the operation's - * execution. See {@link CanonicalCode#FAILED_PRECONDITION}. - */ - public static final Status FAILED_PRECONDITION = CanonicalCode.FAILED_PRECONDITION.toStatus(); - /** - * The operation was aborted, typically due to a concurrency issue like sequencer check failures, - * transaction aborts, etc. See {@link CanonicalCode#ABORTED}. - */ - public static final Status ABORTED = CanonicalCode.ABORTED.toStatus(); - /** Operation was attempted past the valid range. See {@link CanonicalCode#OUT_OF_RANGE}. */ - public static final Status OUT_OF_RANGE = CanonicalCode.OUT_OF_RANGE.toStatus(); - /** Operation is not implemented or not supported/enabled in this service. */ - public static final Status UNIMPLEMENTED = CanonicalCode.UNIMPLEMENTED.toStatus(); - /** Internal errors. See {@link CanonicalCode#INTERNAL}. */ - public static final Status INTERNAL = CanonicalCode.INTERNAL.toStatus(); - /** The service is currently unavailable. See {@link CanonicalCode#UNAVAILABLE}. */ - public static final Status UNAVAILABLE = CanonicalCode.UNAVAILABLE.toStatus(); - /** Unrecoverable data loss or corruption. */ - public static final Status DATA_LOSS = CanonicalCode.DATA_LOSS.toStatus(); - - // The canonical code of this message. - private final CanonicalCode canonicalCode; - // An additional error message. - private final String description; - - private Status(CanonicalCode canonicalCode, @Nullable String description) { - this.canonicalCode = checkNotNull(canonicalCode, "canonicalCode"); - this.description = description; - } - - /** - * Creates a derived instance of {@code Status} with the given description. - * - * @param description the new description of the {@code Status}. - * @return The newly created {@code Status} with the given description. - */ - public Status withDescription(String description) { - if (Objects.equal(this.description, description)) { - return this; - } - return new Status(this.canonicalCode, description); - } - - /** - * Returns the canonical status code. - * - * @return the canonical status code. - */ - public CanonicalCode getCanonicalCode() { - return canonicalCode; - } - - /** - * Returns the description of this {@code Status} for human consumption. - * - * @return the description of this {@code Status}. - */ - @Nullable - public String getDescription() { - return description; - } - - /** - * Returns {@code true} if this {@code Status} is OK, i.e., not an error. - * - * @return {@code true} if this {@code Status} is OK. - */ - public boolean isOk() { - return CanonicalCode.OK == canonicalCode; - } - - /** - * Equality on Statuses is not well defined. Instead, do comparison based on their CanonicalCode - * with {@link #getCanonicalCode}. The description of the Status is unlikely to be stable, and - * additional fields may be added to Status in the future. - */ - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (!(obj instanceof Status)) { - return false; - } - - Status that = (Status) obj; - return canonicalCode == that.canonicalCode && Objects.equal(description, that.description); - } - - /** - * Hash codes on Statuses are not well defined. - * - * @see #equals - */ - @Override - public int hashCode() { - return Objects.hashCode(canonicalCode, description); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("canonicalCode", canonicalCode) - .add("description", description) - .toString(); - } -} diff --git a/api/src/main/java/io/opencensus/trace/base/TraceId.java b/api/src/main/java/io/opencensus/trace/base/TraceId.java deleted file mode 100644 index 293e2a72..00000000 --- a/api/src/main/java/io/opencensus/trace/base/TraceId.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * 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.base; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.base.MoreObjects; -import com.google.common.io.BaseEncoding; -import io.opencensus.common.Internal; -import java.util.Arrays; -import java.util.Random; -import javax.annotation.concurrent.Immutable; - -/** - * A class that represents a trace identifier. A valid trace identifier is a 16-byte array with at - * least one non-zero byte. - */ -@Immutable -public final class TraceId implements Comparable { - /** The size in bytes of the {@code TraceId}. */ - public static final int SIZE = 16; - - /** The invalid {@code TraceId}. All bytes are '\0'. */ - public static final TraceId INVALID = new TraceId(new byte[SIZE]); - - // The internal representation of the TraceId. - private final byte[] bytes; - - private TraceId(byte[] bytes) { - this.bytes = bytes; - } - - /** - * Returns a {@code TraceId} built from a byte representation. - * - *

Equivalent with: - * - *

{@code
-   * TraceId.fromBytes(buffer, 0);
-   * }
- * - * @param buffer the representation of the {@code TraceId}. - * @return a {@code TraceId} whose representation is given by the {@code buffer} parameter. - * @throws NullPointerException if {@code buffer} is null. - * @throws IllegalArgumentException if {@code buffer.length} is not {@link TraceId#SIZE}. - */ - public static TraceId fromBytes(byte[] buffer) { - checkNotNull(buffer, "buffer"); - checkArgument(buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); - byte[] bytesCopied = Arrays.copyOf(buffer, SIZE); - return new TraceId(bytesCopied); - } - - /** - * Returns a {@code TraceId} whose representation is copied from the {@code src} beginning at the - * {@code srcOffset} offset. - * - * @param src the buffer where the representation of the {@code TraceId} is copied. - * @param srcOffset the offset in the buffer where the representation of the {@code TraceId} - * begins. - * @return a {@code TraceId} whose representation is copied from the buffer. - * @throws NullPointerException if {@code src} is null. - * @throws IndexOutOfBoundsException if {@code srcOffset+TraceId.SIZE} is greater than {@code - * src.length}. - */ - public static TraceId fromBytes(byte[] src, int srcOffset) { - byte[] bytes = new byte[SIZE]; - System.arraycopy(src, srcOffset, bytes, 0, SIZE); - return new TraceId(bytes); - } - - /** - * Generates a new random {@code TraceId}. - * - * @param random the random number generator. - * @return a new valid {@code TraceId}. - */ - public static TraceId generateRandomId(Random random) { - byte[] bytes = new byte[SIZE]; - do { - random.nextBytes(bytes); - } while (Arrays.equals(bytes, INVALID.bytes)); - return new TraceId(bytes); - } - - /** - * Returns the 16-bytes array representation of the {@code TraceId}. - * - * @return the 16-bytes array representation of the {@code TraceId}. - */ - public byte[] getBytes() { - return Arrays.copyOf(bytes, SIZE); - } - - /** - * Copies the byte array representations of the {@code TraceId} into the {@code dest} beginning at - * the {@code destOffset} offset. - * - *

Equivalent with (but faster because it avoids any new allocations): - * - *

{@code
-   * System.arraycopy(getBytes(), 0, dest, destOffset, TraceId.SIZE);
-   * }
- * - * @param dest the destination buffer. - * @param destOffset the starting offset in the destination buffer. - * @throws NullPointerException if {@code dest} is null. - * @throws IndexOutOfBoundsException if {@code destOffset+TraceId.SIZE} is greater than {@code - * dest.length}. - */ - public void copyBytesTo(byte[] dest, int destOffset) { - System.arraycopy(bytes, 0, dest, destOffset, SIZE); - } - - /** - * Returns whether the {@code TraceId} is valid. A valid trace identifier is a 16-byte array with - * at least one non-zero byte. - * - * @return {@code true} if the {@code TraceId} is valid. - */ - public boolean isValid() { - return !Arrays.equals(bytes, INVALID.bytes); - } - - /** - * Returns the lower 8 bytes of the trace-id as a long value, assuming little-endian order. This - * is used in ProbabilitySampler. - * - *

This method is marked as internal and subject to change. - * - * @return the lower 8 bytes of the trace-id as a long value, assuming little-endian order. - */ - @Internal - public long getLowerLong() { - long result = 0; - for (int i = 0; i < Long.SIZE / Byte.SIZE; i++) { - result <<= Byte.SIZE; - result |= (bytes[i] & 0xff); - } - if (result < 0) { - return -result; - } - return result; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (!(obj instanceof TraceId)) { - return false; - } - - TraceId that = (TraceId) obj; - return Arrays.equals(bytes, that.bytes); - } - - @Override - public int hashCode() { - return Arrays.hashCode(bytes); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("traceId", BaseEncoding.base16().lowerCase().encode(bytes)) - .toString(); - } - - @Override - public int compareTo(TraceId that) { - for (int i = 0; i < SIZE; i++) { - if (bytes[i] != that.bytes[i]) { - return bytes[i] < that.bytes[i] ? -1 : 1; - } - } - return 0; - } -} diff --git a/api/src/main/java/io/opencensus/trace/base/TraceOptions.java b/api/src/main/java/io/opencensus/trace/base/TraceOptions.java deleted file mode 100644 index 3f20bb99..00000000 --- a/api/src/main/java/io/opencensus/trace/base/TraceOptions.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.base; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkElementIndex; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.MoreObjects; -import com.google.common.base.Objects; -import javax.annotation.concurrent.Immutable; - -/** - * A class that represents global trace options. These options are propagated to all child {@link - * io.opencensus.trace.Span spans}. These determine features such as whether a {@code Span} should - * be traced. It is implemented as a bitmask. - */ -@Immutable -public final class TraceOptions { - // Default options. Nothing set. - private static final byte DEFAULT_OPTIONS = 0; - // Bit to represent whether trace is sampled or not. - private static final byte IS_SAMPLED = 0x1; - - /** The size in bytes of the {@code TraceOptions}. */ - public static final int SIZE = 1; - - /** The default {@code TraceOptions}. */ - public static final TraceOptions DEFAULT = new TraceOptions(DEFAULT_OPTIONS); - - // The set of enabled features is determined by all the enabled bits. - private final byte options; - - // Creates a new {@code TraceOptions} with the given options. - private TraceOptions(byte options) { - this.options = options; - } - - /** - * Returns a {@code TraceOptions} built from a byte representation. - * - *

Equivalent with: - * - *

{@code
-   * TraceOptions.fromBytes(buffer, 0);
-   * }
- * - * @param buffer the representation of the {@code TraceOptions}. - * @return a {@code TraceOptions} whose representation is given by the {@code buffer} parameter. - * @throws NullPointerException if {@code buffer} is null. - * @throws IllegalArgumentException if {@code buffer.length} is not {@link TraceOptions#SIZE}. - */ - public static TraceOptions fromBytes(byte[] buffer) { - checkNotNull(buffer, "buffer"); - checkArgument(buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); - return new TraceOptions(buffer[0]); - } - - /** - * Returns a {@code TraceOptions} whose representation is copied from the {@code src} beginning at - * the {@code srcOffset} offset. - * - * @param src the buffer where the representation of the {@code TraceOptions} is copied. - * @param srcOffset the offset in the buffer where the representation of the {@code TraceOptions} - * begins. - * @return a {@code TraceOptions} whose representation is copied from the buffer. - * @throws NullPointerException if {@code src} is null. - * @throws IndexOutOfBoundsException if {@code srcOffset+TraceOptions.SIZE} is greater than {@code - * src.length}. - */ - public static TraceOptions fromBytes(byte[] src, int srcOffset) { - checkElementIndex(srcOffset, src.length); - return new TraceOptions(src[srcOffset]); - } - - /** - * Returns the 1-byte array representation of the {@code TraceOptions}. - * - * @return the 1-byte array representation of the {@code TraceOptions}. - */ - public byte[] getBytes() { - byte[] bytes = new byte[SIZE]; - bytes[0] = options; - return bytes; - } - - /** - * Copies the byte representations of the {@code TraceOptions} into the {@code dest} beginning at - * the {@code destOffset} offset. - * - *

Equivalent with (but faster because it avoids any new allocations): - * - *

{@code
-   * System.arraycopy(getBytes(), 0, dest, destOffset, TraceOptions.SIZE);
-   * }
- * - * @param dest the destination buffer. - * @param destOffset the starting offset in the destination buffer. - * @throws NullPointerException if {@code dest} is null. - * @throws IndexOutOfBoundsException if {@code destOffset+TraceOptions.SIZE} is greater than - * {@code dest.length}. - */ - public void copyBytesTo(byte[] dest, int destOffset) { - checkElementIndex(destOffset, dest.length); - dest[destOffset] = options; - } - - /** - * Returns a new {@link Builder} with default options. - * - * @return a new {@code Builder} with default options. - */ - public static Builder builder() { - return new Builder(DEFAULT_OPTIONS); - } - - /** - * Returns a new {@link Builder} with all given options set. - * - * @param traceOptions the given options set. - * @return a new {@code Builder} with all given options set. - */ - public static Builder builder(TraceOptions traceOptions) { - return new Builder(traceOptions.options); - } - - /** - * Returns a boolean indicating whether this {@code Span} is part of a sampled trace and data - * should be exported to a persistent store. - * - * @return a boolean indicating whether the trace is sampled. - */ - public boolean isSampled() { - return hasOption(IS_SAMPLED); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (!(obj instanceof TraceOptions)) { - return false; - } - - TraceOptions that = (TraceOptions) obj; - return options == that.options; - } - - @Override - public int hashCode() { - return Objects.hashCode(options); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this).add("sampled", isSampled()).toString(); - } - - /** Builder class for {@link TraceOptions}. */ - public static final class Builder { - private byte options; - - private Builder(byte options) { - this.options = options; - } - - /** - * Marks this trace as sampled. - * - * @return this. - */ - public Builder setIsSampled() { - options |= IS_SAMPLED; - return this; - } - - /** - * Builds and returns a {@code TraceOptions} with the desired options. - * - * @return a {@code TraceOptions} with the desired options. - */ - public TraceOptions build() { - return new TraceOptions(options); - } - } - - // Returns the current set of options bitmask. - @VisibleForTesting - byte getOptions() { - return options; - } - - private boolean hasOption(int mask) { - return (this.options & mask) != 0; - } -} diff --git a/api/src/main/java/io/opencensus/trace/config/TraceParams.java b/api/src/main/java/io/opencensus/trace/config/TraceParams.java index d07ae043..73192348 100644 --- a/api/src/main/java/io/opencensus/trace/config/TraceParams.java +++ b/api/src/main/java/io/opencensus/trace/config/TraceParams.java @@ -16,11 +16,11 @@ package io.opencensus.trace.config; import static com.google.common.base.Preconditions.checkArgument; import com.google.auto.value.AutoValue; +import io.opencensus.trace.Annotation; +import io.opencensus.trace.Link; +import io.opencensus.trace.NetworkEvent; import io.opencensus.trace.Sampler; import io.opencensus.trace.Span; -import io.opencensus.trace.base.Annotation; -import io.opencensus.trace.base.Link; -import io.opencensus.trace.base.NetworkEvent; import io.opencensus.trace.samplers.Samplers; import javax.annotation.concurrent.Immutable; diff --git a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java index f1199e39..be5cad47 100644 --- a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java +++ b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java @@ -13,7 +13,7 @@ package io.opencensus.trace.export; -import io.opencensus.trace.base.TraceOptions; +import io.opencensus.trace.TraceOptions; import javax.annotation.Nullable; /** diff --git a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java index 0a47f4dd..316cc36b 100644 --- a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java @@ -18,8 +18,8 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; import io.opencensus.trace.Span; -import io.opencensus.trace.base.Status; -import io.opencensus.trace.base.Status.CanonicalCode; +import io.opencensus.trace.Status; +import io.opencensus.trace.Status.CanonicalCode; import java.util.Collection; import java.util.Collections; import java.util.HashMap; diff --git a/api/src/main/java/io/opencensus/trace/export/SpanData.java b/api/src/main/java/io/opencensus/trace/export/SpanData.java index 73e03f46..762335af 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanData.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanData.java @@ -17,14 +17,14 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; import io.opencensus.common.Timestamp; +import io.opencensus.trace.Annotation; +import io.opencensus.trace.AttributeValue; +import io.opencensus.trace.Link; +import io.opencensus.trace.NetworkEvent; import io.opencensus.trace.Span; import io.opencensus.trace.SpanContext; -import io.opencensus.trace.base.Annotation; -import io.opencensus.trace.base.AttributeValue; -import io.opencensus.trace.base.Link; -import io.opencensus.trace.base.NetworkEvent; -import io.opencensus.trace.base.SpanId; -import io.opencensus.trace.base.Status; +import io.opencensus.trace.SpanId; +import io.opencensus.trace.Status; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; diff --git a/api/src/main/java/io/opencensus/trace/export/SpanExporter.java b/api/src/main/java/io/opencensus/trace/export/SpanExporter.java index bfae4bad..44b95488 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanExporter.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanExporter.java @@ -14,7 +14,7 @@ package io.opencensus.trace.export; import io.opencensus.trace.Span; -import io.opencensus.trace.base.TraceOptions; +import io.opencensus.trace.TraceOptions; import java.util.Collection; import javax.annotation.concurrent.ThreadSafe; diff --git a/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java b/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java index f78fcd18..e20265d9 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java +++ b/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java @@ -16,8 +16,8 @@ package io.opencensus.trace.samplers; import io.opencensus.trace.Sampler; import io.opencensus.trace.Span; import io.opencensus.trace.SpanContext; -import io.opencensus.trace.base.SpanId; -import io.opencensus.trace.base.TraceId; +import io.opencensus.trace.SpanId; +import io.opencensus.trace.TraceId; import java.util.List; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; diff --git a/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java b/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java index 9fa8ea7b..f773f3a7 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java +++ b/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java @@ -16,8 +16,8 @@ package io.opencensus.trace.samplers; import io.opencensus.trace.Sampler; import io.opencensus.trace.Span; import io.opencensus.trace.SpanContext; -import io.opencensus.trace.base.SpanId; -import io.opencensus.trace.base.TraceId; +import io.opencensus.trace.SpanId; +import io.opencensus.trace.TraceId; import java.util.List; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; diff --git a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java index 11735629..7a4029e5 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java +++ b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java @@ -19,8 +19,8 @@ import com.google.auto.value.AutoValue; import io.opencensus.trace.Sampler; import io.opencensus.trace.Span; import io.opencensus.trace.SpanContext; -import io.opencensus.trace.base.SpanId; -import io.opencensus.trace.base.TraceId; +import io.opencensus.trace.SpanId; +import io.opencensus.trace.TraceId; import java.util.List; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; diff --git a/api/src/test/java/io/opencensus/trace/AnnotationTest.java b/api/src/test/java/io/opencensus/trace/AnnotationTest.java new file mode 100644 index 00000000..fbfe5fd3 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/AnnotationTest.java @@ -0,0 +1,99 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Link}. */ +@RunWith(JUnit4.class) +public class AnnotationTest { + @Test(expected = NullPointerException.class) + public void fromDescription_NullDescription() { + Annotation.fromDescription(null); + } + + @Test + public void fromDescription() { + Annotation annotation = Annotation.fromDescription("MyAnnotationText"); + assertThat(annotation.getDescription()).isEqualTo("MyAnnotationText"); + assertThat(annotation.getAttributes().size()).isEqualTo(0); + } + + @Test(expected = NullPointerException.class) + public void fromDescriptionAndAttributes_NullDescription() { + Annotation.fromDescriptionAndAttributes(null, Collections.emptyMap()); + } + + @Test(expected = NullPointerException.class) + public void fromDescriptionAndAttributes_NullAttributes() { + Annotation.fromDescriptionAndAttributes("", null); + } + + @Test + public void fromDescriptionAndAttributes() { + Map attributes = new HashMap(); + attributes.put( + "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); + Annotation annotation = Annotation.fromDescriptionAndAttributes("MyAnnotationText", attributes); + assertThat(annotation.getDescription()).isEqualTo("MyAnnotationText"); + assertThat(annotation.getAttributes()).isEqualTo(attributes); + } + + @Test + public void fromDescriptionAndAttributes_EmptyAttributes() { + Annotation annotation = + Annotation.fromDescriptionAndAttributes( + "MyAnnotationText", Collections.emptyMap()); + assertThat(annotation.getDescription()).isEqualTo("MyAnnotationText"); + assertThat(annotation.getAttributes().size()).isEqualTo(0); + } + + @Test + public void annotation_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + Map attributes = new HashMap(); + attributes.put( + "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); + tester + .addEqualityGroup( + Annotation.fromDescription("MyAnnotationText"), + Annotation.fromDescriptionAndAttributes( + "MyAnnotationText", Collections.emptyMap())) + .addEqualityGroup( + Annotation.fromDescriptionAndAttributes("MyAnnotationText", attributes), + Annotation.fromDescriptionAndAttributes("MyAnnotationText", attributes)) + .addEqualityGroup(Annotation.fromDescription("MyAnnotationText2")); + tester.testEquals(); + } + + @Test + public void annotation_ToString() { + Annotation annotation = Annotation.fromDescription("MyAnnotationText"); + assertThat(annotation.toString()).contains("MyAnnotationText"); + Map attributes = new HashMap(); + attributes.put( + "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); + annotation = Annotation.fromDescriptionAndAttributes("MyAnnotationText2", attributes); + assertThat(annotation.toString()).contains("MyAnnotationText2"); + assertThat(annotation.toString()).contains(attributes.toString()); + } +} diff --git a/api/src/test/java/io/opencensus/trace/AttributeValueTest.java b/api/src/test/java/io/opencensus/trace/AttributeValueTest.java new file mode 100644 index 00000000..7a999604 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/AttributeValueTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link AttributeValue}. */ +@RunWith(JUnit4.class) +public class AttributeValueTest { + @Test + public void stringAttributeValue() { + AttributeValue attribute = AttributeValue.stringAttributeValue("MyStringAttributeValue"); + assertThat(attribute.getStringValue()).isEqualTo("MyStringAttributeValue"); + assertThat(attribute.getBooleanValue()).isNull(); + assertThat(attribute.getLongValue()).isNull(); + } + + @Test + public void booleanAttributeValue() { + AttributeValue attribute = AttributeValue.booleanAttributeValue(true); + assertThat(attribute.getStringValue()).isNull(); + assertThat(attribute.getBooleanValue()).isTrue(); + assertThat(attribute.getLongValue()).isNull(); + } + + @Test + public void longAttributeValue() { + AttributeValue attribute = AttributeValue.longAttributeValue(123456L); + assertThat(attribute.getStringValue()).isNull(); + assertThat(attribute.getBooleanValue()).isNull(); + assertThat(attribute.getLongValue()).isEqualTo(123456L); + } + + @Test + public void attributeValue_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup( + AttributeValue.stringAttributeValue("MyStringAttributeValue"), + AttributeValue.stringAttributeValue("MyStringAttributeValue")); + tester.addEqualityGroup(AttributeValue.stringAttributeValue("MyStringAttributeDiffValue")); + tester.addEqualityGroup( + AttributeValue.booleanAttributeValue(true), AttributeValue.booleanAttributeValue(true)); + tester.addEqualityGroup(AttributeValue.booleanAttributeValue(false)); + tester.addEqualityGroup( + AttributeValue.longAttributeValue(123456L), AttributeValue.longAttributeValue(123456L)); + tester.addEqualityGroup(AttributeValue.longAttributeValue(1234567L)); + tester.testEquals(); + } + + @Test + public void attributeValue_ToString() { + AttributeValue attribute = AttributeValue.stringAttributeValue("MyStringAttributeValue"); + assertThat(attribute.toString()).contains("MyStringAttributeValue"); + attribute = AttributeValue.booleanAttributeValue(true); + assertThat(attribute.toString()).contains("true"); + attribute = AttributeValue.longAttributeValue(123456L); + assertThat(attribute.toString()).contains("123456"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/BlankSpanTest.java b/api/src/test/java/io/opencensus/trace/BlankSpanTest.java index f9690321..ad1eea8b 100644 --- a/api/src/test/java/io/opencensus/trace/BlankSpanTest.java +++ b/api/src/test/java/io/opencensus/trace/BlankSpanTest.java @@ -15,10 +15,6 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; -import io.opencensus.trace.base.Annotation; -import io.opencensus.trace.base.AttributeValue; -import io.opencensus.trace.base.Link; -import io.opencensus.trace.base.NetworkEvent; import java.util.HashMap; import java.util.Map; import org.junit.Test; diff --git a/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java b/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java index 5fc50b7b..d531fba5 100644 --- a/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java +++ b/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java @@ -16,7 +16,6 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; import com.google.common.testing.EqualsTester; -import io.opencensus.trace.base.Status; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; diff --git a/api/src/test/java/io/opencensus/trace/LinkTest.java b/api/src/test/java/io/opencensus/trace/LinkTest.java new file mode 100644 index 00000000..e6b4afe5 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/LinkTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.trace.Link.Type; +import java.util.Random; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Link}. */ +@RunWith(JUnit4.class) +public class LinkTest { + private final Random random = new Random(1234); + private final SpanContext spanContext = + SpanContext.create( + TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); + + @Test + public void fromSpanContext_ChildLink() { + Link link = Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN); + assertThat(link.getTraceId()).isEqualTo(spanContext.getTraceId()); + assertThat(link.getSpanId()).isEqualTo(spanContext.getSpanId()); + assertThat(link.getType()).isEqualTo(Type.CHILD_LINKED_SPAN); + } + + @Test + public void fromSpanContext_ParentLink() { + Link link = Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN); + assertThat(link.getTraceId()).isEqualTo(spanContext.getTraceId()); + assertThat(link.getSpanId()).isEqualTo(spanContext.getSpanId()); + assertThat(link.getType()).isEqualTo(Type.PARENT_LINKED_SPAN); + } + + @Test + public void link_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester + .addEqualityGroup( + Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN), + Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN)) + .addEqualityGroup( + Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN), + Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN)) + .addEqualityGroup(Link.fromSpanContext(SpanContext.INVALID, Type.CHILD_LINKED_SPAN)) + .addEqualityGroup(Link.fromSpanContext(SpanContext.INVALID, Type.PARENT_LINKED_SPAN)); + tester.testEquals(); + } + + @Test + public void link_ToString() { + Link link = Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN); + assertThat(link.toString()).contains(spanContext.getTraceId().toString()); + assertThat(link.toString()).contains(spanContext.getSpanId().toString()); + assertThat(link.toString()).contains("CHILD_LINKED_SPAN"); + link = Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN); + assertThat(link.toString()).contains(spanContext.getTraceId().toString()); + assertThat(link.toString()).contains(spanContext.getSpanId().toString()); + assertThat(link.toString()).contains("PARENT_LINKED_SPAN"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/NetworkEventTest.java b/api/src/test/java/io/opencensus/trace/NetworkEventTest.java new file mode 100644 index 00000000..946e8ce1 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/NetworkEventTest.java @@ -0,0 +1,87 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.common.Timestamp; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link NetworkEvent}. */ +@RunWith(JUnit4.class) +public class NetworkEventTest { + @Test(expected = NullPointerException.class) + public void buildNetworkEvent_NullType() { + NetworkEvent.builder(null, 1L).build(); + } + + @Test + public void buildNetworkEvent_WithRequiredFields() { + NetworkEvent networkEvent = NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).build(); + assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); + assertThat(networkEvent.getMessageId()).isEqualTo(1L); + assertThat(networkEvent.getKernelTimestamp()).isNull(); + assertThat(networkEvent.getMessageSize()).isEqualTo(0L); + } + + @Test + public void buildNetworkEvent_WithTimestamp() { + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.SENT, 1L) + .setKernelTimestamp(Timestamp.fromMillis(123456L)) + .build(); + assertThat(networkEvent.getKernelTimestamp()).isEqualTo(Timestamp.fromMillis(123456L)); + assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); + assertThat(networkEvent.getMessageId()).isEqualTo(1L); + assertThat(networkEvent.getMessageSize()).isEqualTo(0L); + } + + @Test + public void buildNetworkEvent_WithMessageSize() { + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).setMessageSize(123L).build(); + assertThat(networkEvent.getKernelTimestamp()).isNull(); + assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); + assertThat(networkEvent.getMessageId()).isEqualTo(1L); + assertThat(networkEvent.getMessageSize()).isEqualTo(123L); + } + + @Test + public void buildNetworkEvent_WithAllValues() { + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.RECV, 1L) + .setKernelTimestamp(Timestamp.fromMillis(123456L)) + .setMessageSize(123L) + .build(); + assertThat(networkEvent.getKernelTimestamp()).isEqualTo(Timestamp.fromMillis(123456L)); + assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.RECV); + assertThat(networkEvent.getMessageId()).isEqualTo(1L); + assertThat(networkEvent.getMessageSize()).isEqualTo(123L); + } + + @Test + public void networkEvent_ToString() { + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.SENT, 1L) + .setKernelTimestamp(Timestamp.fromMillis(123456L)) + .setMessageSize(123L) + .build(); + assertThat(networkEvent.toString()).contains(Timestamp.fromMillis(123456L).toString()); + assertThat(networkEvent.toString()).contains("type=SENT"); + assertThat(networkEvent.toString()).contains("messageId=1"); + assertThat(networkEvent.toString()).contains("messageSize=123"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/SpanContextTest.java b/api/src/test/java/io/opencensus/trace/SpanContextTest.java index eaa5bfc9..c0eb5d40 100644 --- a/api/src/test/java/io/opencensus/trace/SpanContextTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanContextTest.java @@ -16,9 +16,6 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; import com.google.common.testing.EqualsTester; -import io.opencensus.trace.base.SpanId; -import io.opencensus.trace.base.TraceId; -import io.opencensus.trace.base.TraceOptions; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; diff --git a/api/src/test/java/io/opencensus/trace/SpanIdTest.java b/api/src/test/java/io/opencensus/trace/SpanIdTest.java new file mode 100644 index 00000000..a35fddce --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/SpanIdTest.java @@ -0,0 +1,73 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import java.util.Arrays; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link SpanId}. */ +@RunWith(JUnit4.class) +public class SpanIdTest { + private static final byte[] firstBytes = new byte[] {0, 0, 0, 0, 0, 0, 0, 'a'}; + private static final byte[] secondBytes = new byte[] {(byte) 0xFF, 0, 0, 0, 0, 0, 0, 0}; + private static final SpanId first = SpanId.fromBytes(firstBytes); + private static final SpanId second = SpanId.fromBytes(secondBytes); + + @Test + public void invalidSpanId() { + assertThat(SpanId.INVALID.getBytes()).isEqualTo(new byte[8]); + } + + @Test + public void isValid() { + assertThat(SpanId.INVALID.isValid()).isFalse(); + assertThat(first.isValid()).isTrue(); + assertThat(second.isValid()).isTrue(); + } + + @Test + public void getBytes() { + assertThat(first.getBytes()).isEqualTo(firstBytes); + assertThat(second.getBytes()).isEqualTo(secondBytes); + } + + @Test + public void traceId_CompareTo() { + assertThat(first.compareTo(second)).isGreaterThan(0); + assertThat(second.compareTo(first)).isLessThan(0); + assertThat(first.compareTo(SpanId.fromBytes(firstBytes))).isEqualTo(0); + } + + @Test + public void traceId_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup(SpanId.INVALID, SpanId.INVALID); + tester.addEqualityGroup(first, SpanId.fromBytes(Arrays.copyOf(firstBytes, firstBytes.length))); + tester.addEqualityGroup( + second, SpanId.fromBytes(Arrays.copyOf(secondBytes, secondBytes.length))); + tester.testEquals(); + } + + @Test + public void traceId_ToString() { + assertThat(SpanId.INVALID.toString()).contains("0000000000000000"); + assertThat(first.toString()).contains("0000000000000061"); + assertThat(second.toString()).contains("ff00000000000000"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/SpanTest.java b/api/src/test/java/io/opencensus/trace/SpanTest.java index 186e6b1b..c8f7cb50 100644 --- a/api/src/test/java/io/opencensus/trace/SpanTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanTest.java @@ -17,13 +17,6 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Matchers.same; import static org.mockito.Mockito.verify; -import io.opencensus.trace.base.Annotation; -import io.opencensus.trace.base.AttributeValue; -import io.opencensus.trace.base.Link; -import io.opencensus.trace.base.NetworkEvent; -import io.opencensus.trace.base.SpanId; -import io.opencensus.trace.base.TraceId; -import io.opencensus.trace.base.TraceOptions; import java.util.EnumSet; import java.util.Map; import java.util.Random; diff --git a/api/src/test/java/io/opencensus/trace/StatusTest.java b/api/src/test/java/io/opencensus/trace/StatusTest.java new file mode 100644 index 00000000..c66a3428 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/StatusTest.java @@ -0,0 +1,51 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Status}. */ +@RunWith(JUnit4.class) +public class StatusTest { + @Test + public void status_Ok() { + assertThat(Status.OK.getCanonicalCode()).isEqualTo(Status.CanonicalCode.OK); + assertThat(Status.OK.getDescription()).isNull(); + assertThat(Status.OK.isOk()).isTrue(); + } + + @Test + public void createStatus_WithDescription() { + Status status = Status.UNKNOWN.withDescription("This is an error."); + assertThat(status.getCanonicalCode()).isEqualTo(Status.CanonicalCode.UNKNOWN); + assertThat(status.getDescription()).isEqualTo("This is an error."); + assertThat(status.isOk()).isFalse(); + } + + @Test + public void status_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup(Status.OK, Status.OK.withDescription(null)); + tester.addEqualityGroup( + Status.CANCELLED.withDescription("ThisIsAnError"), + Status.CANCELLED.withDescription("ThisIsAnError")); + tester.addEqualityGroup(Status.UNKNOWN.withDescription("This is an error.")); + tester.testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/trace/TraceIdTest.java b/api/src/test/java/io/opencensus/trace/TraceIdTest.java new file mode 100644 index 00000000..cd1b7c24 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/TraceIdTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 2016, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import java.util.Arrays; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TraceId}. */ +@RunWith(JUnit4.class) +public class TraceIdTest { + private static final byte[] firstBytes = + new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'a'}; + private static final byte[] secondBytes = + new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'A'}; + private static final TraceId first = TraceId.fromBytes(firstBytes); + private static final TraceId second = TraceId.fromBytes(secondBytes); + + @Test + public void invalidTraceId() { + assertThat(TraceId.INVALID.getBytes()).isEqualTo(new byte[16]); + } + + @Test + public void isValid() { + assertThat(TraceId.INVALID.isValid()).isFalse(); + assertThat(first.isValid()).isTrue(); + assertThat(second.isValid()).isTrue(); + } + + @Test + public void getBytes() { + assertThat(first.getBytes()).isEqualTo(firstBytes); + assertThat(second.getBytes()).isEqualTo(secondBytes); + } + + @Test + public void traceId_CompareTo() { + assertThat(first.compareTo(second)).isGreaterThan(0); + assertThat(second.compareTo(first)).isLessThan(0); + assertThat(first.compareTo(TraceId.fromBytes(firstBytes))).isEqualTo(0); + } + + @Test + public void traceId_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup(TraceId.INVALID, TraceId.INVALID); + tester.addEqualityGroup(first, TraceId.fromBytes(Arrays.copyOf(firstBytes, firstBytes.length))); + tester.addEqualityGroup( + second, TraceId.fromBytes(Arrays.copyOf(secondBytes, secondBytes.length))); + tester.testEquals(); + } + + @Test + public void traceId_ToString() { + assertThat(TraceId.INVALID.toString()).contains("00000000000000000000000000000000"); + assertThat(first.toString()).contains("00000000000000000000000000000061"); + assertThat(second.toString()).contains("00000000000000000000000000000041"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java b/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java new file mode 100644 index 00000000..fb240646 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java @@ -0,0 +1,77 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TraceOptions}. */ +@RunWith(JUnit4.class) +public class TraceOptionsTest { + private static final byte[] firstBytes = {(byte) 0xff}; + private static final byte[] secondBytes = {1}; + private static final byte[] thirdBytes = {6}; + + @Test + public void getOptions() { + assertThat(TraceOptions.DEFAULT.getOptions()).isEqualTo(0); + assertThat(TraceOptions.builder().setIsSampled().build().getOptions()).isEqualTo(1); + assertThat(TraceOptions.fromBytes(firstBytes).getOptions()).isEqualTo(-1); + assertThat(TraceOptions.fromBytes(secondBytes).getOptions()).isEqualTo(1); + assertThat(TraceOptions.fromBytes(thirdBytes).getOptions()).isEqualTo(6); + } + + @Test + public void isSampled() { + assertThat(TraceOptions.DEFAULT.isSampled()).isFalse(); + assertThat(TraceOptions.builder().setIsSampled().build().isSampled()).isTrue(); + } + + @Test + public void toFromBytes() { + assertThat(TraceOptions.fromBytes(firstBytes).getBytes()).isEqualTo(firstBytes); + assertThat(TraceOptions.fromBytes(secondBytes).getBytes()).isEqualTo(secondBytes); + assertThat(TraceOptions.fromBytes(thirdBytes).getBytes()).isEqualTo(thirdBytes); + } + + @Test + public void builder_FromOptions() { + assertThat( + TraceOptions.builder(TraceOptions.fromBytes(thirdBytes)) + .setIsSampled() + .build() + .getOptions()) + .isEqualTo(6 | 1); + } + + @Test + public void traceOptions_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup(TraceOptions.DEFAULT); + tester.addEqualityGroup( + TraceOptions.fromBytes(secondBytes), TraceOptions.builder().setIsSampled().build()); + tester.addEqualityGroup(TraceOptions.fromBytes(firstBytes)); + tester.testEquals(); + } + + @Test + public void traceOptions_ToString() { + assertThat(TraceOptions.DEFAULT.toString()).contains("sampled=false"); + assertThat(TraceOptions.builder().setIsSampled().build().toString()).contains("sampled=true"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/base/AnnotationTest.java b/api/src/test/java/io/opencensus/trace/base/AnnotationTest.java deleted file mode 100644 index c6e0c2ce..00000000 --- a/api/src/test/java/io/opencensus/trace/base/AnnotationTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.base; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link Link}. */ -@RunWith(JUnit4.class) -public class AnnotationTest { - @Test(expected = NullPointerException.class) - public void fromDescription_NullDescription() { - Annotation.fromDescription(null); - } - - @Test - public void fromDescription() { - Annotation annotation = Annotation.fromDescription("MyAnnotationText"); - assertThat(annotation.getDescription()).isEqualTo("MyAnnotationText"); - assertThat(annotation.getAttributes().size()).isEqualTo(0); - } - - @Test(expected = NullPointerException.class) - public void fromDescriptionAndAttributes_NullDescription() { - Annotation.fromDescriptionAndAttributes(null, Collections.emptyMap()); - } - - @Test(expected = NullPointerException.class) - public void fromDescriptionAndAttributes_NullAttributes() { - Annotation.fromDescriptionAndAttributes("", null); - } - - @Test - public void fromDescriptionAndAttributes() { - Map attributes = new HashMap(); - attributes.put( - "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); - Annotation annotation = Annotation.fromDescriptionAndAttributes("MyAnnotationText", attributes); - assertThat(annotation.getDescription()).isEqualTo("MyAnnotationText"); - assertThat(annotation.getAttributes()).isEqualTo(attributes); - } - - @Test - public void fromDescriptionAndAttributes_EmptyAttributes() { - Annotation annotation = - Annotation.fromDescriptionAndAttributes( - "MyAnnotationText", Collections.emptyMap()); - assertThat(annotation.getDescription()).isEqualTo("MyAnnotationText"); - assertThat(annotation.getAttributes().size()).isEqualTo(0); - } - - @Test - public void annotation_EqualsAndHashCode() { - EqualsTester tester = new EqualsTester(); - Map attributes = new HashMap(); - attributes.put( - "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); - tester - .addEqualityGroup( - Annotation.fromDescription("MyAnnotationText"), - Annotation.fromDescriptionAndAttributes( - "MyAnnotationText", Collections.emptyMap())) - .addEqualityGroup( - Annotation.fromDescriptionAndAttributes("MyAnnotationText", attributes), - Annotation.fromDescriptionAndAttributes("MyAnnotationText", attributes)) - .addEqualityGroup(Annotation.fromDescription("MyAnnotationText2")); - tester.testEquals(); - } - - @Test - public void annotation_ToString() { - Annotation annotation = Annotation.fromDescription("MyAnnotationText"); - assertThat(annotation.toString()).contains("MyAnnotationText"); - Map attributes = new HashMap(); - attributes.put( - "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); - annotation = Annotation.fromDescriptionAndAttributes("MyAnnotationText2", attributes); - assertThat(annotation.toString()).contains("MyAnnotationText2"); - assertThat(annotation.toString()).contains(attributes.toString()); - } -} diff --git a/api/src/test/java/io/opencensus/trace/base/AttributeValueTest.java b/api/src/test/java/io/opencensus/trace/base/AttributeValueTest.java deleted file mode 100644 index 43f85aa4..00000000 --- a/api/src/test/java/io/opencensus/trace/base/AttributeValueTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.base; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link AttributeValue}. */ -@RunWith(JUnit4.class) -public class AttributeValueTest { - @Test - public void stringAttributeValue() { - AttributeValue attribute = AttributeValue.stringAttributeValue("MyStringAttributeValue"); - assertThat(attribute.getStringValue()).isEqualTo("MyStringAttributeValue"); - assertThat(attribute.getBooleanValue()).isNull(); - assertThat(attribute.getLongValue()).isNull(); - } - - @Test - public void booleanAttributeValue() { - AttributeValue attribute = AttributeValue.booleanAttributeValue(true); - assertThat(attribute.getStringValue()).isNull(); - assertThat(attribute.getBooleanValue()).isTrue(); - assertThat(attribute.getLongValue()).isNull(); - } - - @Test - public void longAttributeValue() { - AttributeValue attribute = AttributeValue.longAttributeValue(123456L); - assertThat(attribute.getStringValue()).isNull(); - assertThat(attribute.getBooleanValue()).isNull(); - assertThat(attribute.getLongValue()).isEqualTo(123456L); - } - - @Test - public void attributeValue_EqualsAndHashCode() { - EqualsTester tester = new EqualsTester(); - tester.addEqualityGroup( - AttributeValue.stringAttributeValue("MyStringAttributeValue"), - AttributeValue.stringAttributeValue("MyStringAttributeValue")); - tester.addEqualityGroup(AttributeValue.stringAttributeValue("MyStringAttributeDiffValue")); - tester.addEqualityGroup( - AttributeValue.booleanAttributeValue(true), AttributeValue.booleanAttributeValue(true)); - tester.addEqualityGroup(AttributeValue.booleanAttributeValue(false)); - tester.addEqualityGroup( - AttributeValue.longAttributeValue(123456L), AttributeValue.longAttributeValue(123456L)); - tester.addEqualityGroup(AttributeValue.longAttributeValue(1234567L)); - tester.testEquals(); - } - - @Test - public void attributeValue_ToString() { - AttributeValue attribute = AttributeValue.stringAttributeValue("MyStringAttributeValue"); - assertThat(attribute.toString()).contains("MyStringAttributeValue"); - attribute = AttributeValue.booleanAttributeValue(true); - assertThat(attribute.toString()).contains("true"); - attribute = AttributeValue.longAttributeValue(123456L); - assertThat(attribute.toString()).contains("123456"); - } -} diff --git a/api/src/test/java/io/opencensus/trace/base/LinkTest.java b/api/src/test/java/io/opencensus/trace/base/LinkTest.java deleted file mode 100644 index d0bfc46e..00000000 --- a/api/src/test/java/io/opencensus/trace/base/LinkTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.base; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import io.opencensus.trace.SpanContext; -import io.opencensus.trace.base.Link.Type; -import java.util.Random; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link Link}. */ -@RunWith(JUnit4.class) -public class LinkTest { - private final Random random = new Random(1234); - private final SpanContext spanContext = - SpanContext.create( - TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); - - @Test - public void fromSpanContext_ChildLink() { - Link link = Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN); - assertThat(link.getTraceId()).isEqualTo(spanContext.getTraceId()); - assertThat(link.getSpanId()).isEqualTo(spanContext.getSpanId()); - assertThat(link.getType()).isEqualTo(Type.CHILD_LINKED_SPAN); - } - - @Test - public void fromSpanContext_ParentLink() { - Link link = Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN); - assertThat(link.getTraceId()).isEqualTo(spanContext.getTraceId()); - assertThat(link.getSpanId()).isEqualTo(spanContext.getSpanId()); - assertThat(link.getType()).isEqualTo(Type.PARENT_LINKED_SPAN); - } - - @Test - public void link_EqualsAndHashCode() { - EqualsTester tester = new EqualsTester(); - tester - .addEqualityGroup( - Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN), - Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN)) - .addEqualityGroup( - Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN), - Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN)) - .addEqualityGroup(Link.fromSpanContext(SpanContext.INVALID, Type.CHILD_LINKED_SPAN)) - .addEqualityGroup(Link.fromSpanContext(SpanContext.INVALID, Type.PARENT_LINKED_SPAN)); - tester.testEquals(); - } - - @Test - public void link_ToString() { - Link link = Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN); - assertThat(link.toString()).contains(spanContext.getTraceId().toString()); - assertThat(link.toString()).contains(spanContext.getSpanId().toString()); - assertThat(link.toString()).contains("CHILD_LINKED_SPAN"); - link = Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN); - assertThat(link.toString()).contains(spanContext.getTraceId().toString()); - assertThat(link.toString()).contains(spanContext.getSpanId().toString()); - assertThat(link.toString()).contains("PARENT_LINKED_SPAN"); - } -} diff --git a/api/src/test/java/io/opencensus/trace/base/NetworkEventTest.java b/api/src/test/java/io/opencensus/trace/base/NetworkEventTest.java deleted file mode 100644 index 09d796ee..00000000 --- a/api/src/test/java/io/opencensus/trace/base/NetworkEventTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.base; - -import static com.google.common.truth.Truth.assertThat; - -import io.opencensus.common.Timestamp; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link NetworkEvent}. */ -@RunWith(JUnit4.class) -public class NetworkEventTest { - @Test(expected = NullPointerException.class) - public void buildNetworkEvent_NullType() { - NetworkEvent.builder(null, 1L).build(); - } - - @Test - public void buildNetworkEvent_WithRequiredFields() { - NetworkEvent networkEvent = NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).build(); - assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); - assertThat(networkEvent.getMessageId()).isEqualTo(1L); - assertThat(networkEvent.getKernelTimestamp()).isNull(); - assertThat(networkEvent.getMessageSize()).isEqualTo(0L); - } - - @Test - public void buildNetworkEvent_WithTimestamp() { - NetworkEvent networkEvent = - NetworkEvent.builder(NetworkEvent.Type.SENT, 1L) - .setKernelTimestamp(Timestamp.fromMillis(123456L)) - .build(); - assertThat(networkEvent.getKernelTimestamp()).isEqualTo(Timestamp.fromMillis(123456L)); - assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); - assertThat(networkEvent.getMessageId()).isEqualTo(1L); - assertThat(networkEvent.getMessageSize()).isEqualTo(0L); - } - - @Test - public void buildNetworkEvent_WithMessageSize() { - NetworkEvent networkEvent = - NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).setMessageSize(123L).build(); - assertThat(networkEvent.getKernelTimestamp()).isNull(); - assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); - assertThat(networkEvent.getMessageId()).isEqualTo(1L); - assertThat(networkEvent.getMessageSize()).isEqualTo(123L); - } - - @Test - public void buildNetworkEvent_WithAllValues() { - NetworkEvent networkEvent = - NetworkEvent.builder(NetworkEvent.Type.RECV, 1L) - .setKernelTimestamp(Timestamp.fromMillis(123456L)) - .setMessageSize(123L) - .build(); - assertThat(networkEvent.getKernelTimestamp()).isEqualTo(Timestamp.fromMillis(123456L)); - assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.RECV); - assertThat(networkEvent.getMessageId()).isEqualTo(1L); - assertThat(networkEvent.getMessageSize()).isEqualTo(123L); - } - - @Test - public void networkEvent_ToString() { - NetworkEvent networkEvent = - NetworkEvent.builder(NetworkEvent.Type.SENT, 1L) - .setKernelTimestamp(Timestamp.fromMillis(123456L)) - .setMessageSize(123L) - .build(); - assertThat(networkEvent.toString()).contains(Timestamp.fromMillis(123456L).toString()); - assertThat(networkEvent.toString()).contains("type=SENT"); - assertThat(networkEvent.toString()).contains("messageId=1"); - assertThat(networkEvent.toString()).contains("messageSize=123"); - } -} diff --git a/api/src/test/java/io/opencensus/trace/base/SpanIdTest.java b/api/src/test/java/io/opencensus/trace/base/SpanIdTest.java deleted file mode 100644 index 6db2dc81..00000000 --- a/api/src/test/java/io/opencensus/trace/base/SpanIdTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.base; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import java.util.Arrays; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link SpanId}. */ -@RunWith(JUnit4.class) -public class SpanIdTest { - private static final byte[] firstBytes = new byte[] {0, 0, 0, 0, 0, 0, 0, 'a'}; - private static final byte[] secondBytes = new byte[] {(byte) 0xFF, 0, 0, 0, 0, 0, 0, 0}; - private static final SpanId first = SpanId.fromBytes(firstBytes); - private static final SpanId second = SpanId.fromBytes(secondBytes); - - @Test - public void invalidSpanId() { - assertThat(SpanId.INVALID.getBytes()).isEqualTo(new byte[8]); - } - - @Test - public void isValid() { - assertThat(SpanId.INVALID.isValid()).isFalse(); - assertThat(first.isValid()).isTrue(); - assertThat(second.isValid()).isTrue(); - } - - @Test - public void getBytes() { - assertThat(first.getBytes()).isEqualTo(firstBytes); - assertThat(second.getBytes()).isEqualTo(secondBytes); - } - - @Test - public void traceId_CompareTo() { - assertThat(first.compareTo(second)).isGreaterThan(0); - assertThat(second.compareTo(first)).isLessThan(0); - assertThat(first.compareTo(SpanId.fromBytes(firstBytes))).isEqualTo(0); - } - - @Test - public void traceId_EqualsAndHashCode() { - EqualsTester tester = new EqualsTester(); - tester.addEqualityGroup(SpanId.INVALID, SpanId.INVALID); - tester.addEqualityGroup(first, SpanId.fromBytes(Arrays.copyOf(firstBytes, firstBytes.length))); - tester.addEqualityGroup( - second, SpanId.fromBytes(Arrays.copyOf(secondBytes, secondBytes.length))); - tester.testEquals(); - } - - @Test - public void traceId_ToString() { - assertThat(SpanId.INVALID.toString()).contains("0000000000000000"); - assertThat(first.toString()).contains("0000000000000061"); - assertThat(second.toString()).contains("ff00000000000000"); - } -} diff --git a/api/src/test/java/io/opencensus/trace/base/StatusTest.java b/api/src/test/java/io/opencensus/trace/base/StatusTest.java deleted file mode 100644 index b8c2e19b..00000000 --- a/api/src/test/java/io/opencensus/trace/base/StatusTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.base; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link Status}. */ -@RunWith(JUnit4.class) -public class StatusTest { - @Test - public void status_Ok() { - assertThat(Status.OK.getCanonicalCode()).isEqualTo(Status.CanonicalCode.OK); - assertThat(Status.OK.getDescription()).isNull(); - assertThat(Status.OK.isOk()).isTrue(); - } - - @Test - public void createStatus_WithDescription() { - Status status = Status.UNKNOWN.withDescription("This is an error."); - assertThat(status.getCanonicalCode()).isEqualTo(Status.CanonicalCode.UNKNOWN); - assertThat(status.getDescription()).isEqualTo("This is an error."); - assertThat(status.isOk()).isFalse(); - } - - @Test - public void status_EqualsAndHashCode() { - EqualsTester tester = new EqualsTester(); - tester.addEqualityGroup(Status.OK, Status.OK.withDescription(null)); - tester.addEqualityGroup( - Status.CANCELLED.withDescription("ThisIsAnError"), - Status.CANCELLED.withDescription("ThisIsAnError")); - tester.addEqualityGroup(Status.UNKNOWN.withDescription("This is an error.")); - tester.testEquals(); - } -} diff --git a/api/src/test/java/io/opencensus/trace/base/TraceIdTest.java b/api/src/test/java/io/opencensus/trace/base/TraceIdTest.java deleted file mode 100644 index dd87d40d..00000000 --- a/api/src/test/java/io/opencensus/trace/base/TraceIdTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2016, Google Inc. - * 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.base; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import java.util.Arrays; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link TraceId}. */ -@RunWith(JUnit4.class) -public class TraceIdTest { - private static final byte[] firstBytes = - new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'a'}; - private static final byte[] secondBytes = - new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'A'}; - private static final TraceId first = TraceId.fromBytes(firstBytes); - private static final TraceId second = TraceId.fromBytes(secondBytes); - - @Test - public void invalidTraceId() { - assertThat(TraceId.INVALID.getBytes()).isEqualTo(new byte[16]); - } - - @Test - public void isValid() { - assertThat(TraceId.INVALID.isValid()).isFalse(); - assertThat(first.isValid()).isTrue(); - assertThat(second.isValid()).isTrue(); - } - - @Test - public void getBytes() { - assertThat(first.getBytes()).isEqualTo(firstBytes); - assertThat(second.getBytes()).isEqualTo(secondBytes); - } - - @Test - public void traceId_CompareTo() { - assertThat(first.compareTo(second)).isGreaterThan(0); - assertThat(second.compareTo(first)).isLessThan(0); - assertThat(first.compareTo(TraceId.fromBytes(firstBytes))).isEqualTo(0); - } - - @Test - public void traceId_EqualsAndHashCode() { - EqualsTester tester = new EqualsTester(); - tester.addEqualityGroup(TraceId.INVALID, TraceId.INVALID); - tester.addEqualityGroup(first, TraceId.fromBytes(Arrays.copyOf(firstBytes, firstBytes.length))); - tester.addEqualityGroup( - second, TraceId.fromBytes(Arrays.copyOf(secondBytes, secondBytes.length))); - tester.testEquals(); - } - - @Test - public void traceId_ToString() { - assertThat(TraceId.INVALID.toString()).contains("00000000000000000000000000000000"); - assertThat(first.toString()).contains("00000000000000000000000000000061"); - assertThat(second.toString()).contains("00000000000000000000000000000041"); - } -} diff --git a/api/src/test/java/io/opencensus/trace/base/TraceOptionsTest.java b/api/src/test/java/io/opencensus/trace/base/TraceOptionsTest.java deleted file mode 100644 index 0d247347..00000000 --- a/api/src/test/java/io/opencensus/trace/base/TraceOptionsTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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.base; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link TraceOptions}. */ -@RunWith(JUnit4.class) -public class TraceOptionsTest { - private static final byte[] firstBytes = {(byte) 0xff}; - private static final byte[] secondBytes = {1}; - private static final byte[] thirdBytes = {6}; - - @Test - public void getOptions() { - assertThat(TraceOptions.DEFAULT.getOptions()).isEqualTo(0); - assertThat(TraceOptions.builder().setIsSampled().build().getOptions()).isEqualTo(1); - assertThat(TraceOptions.fromBytes(firstBytes).getOptions()).isEqualTo(-1); - assertThat(TraceOptions.fromBytes(secondBytes).getOptions()).isEqualTo(1); - assertThat(TraceOptions.fromBytes(thirdBytes).getOptions()).isEqualTo(6); - } - - @Test - public void isSampled() { - assertThat(TraceOptions.DEFAULT.isSampled()).isFalse(); - assertThat(TraceOptions.builder().setIsSampled().build().isSampled()).isTrue(); - } - - @Test - public void toFromBytes() { - assertThat(TraceOptions.fromBytes(firstBytes).getBytes()).isEqualTo(firstBytes); - assertThat(TraceOptions.fromBytes(secondBytes).getBytes()).isEqualTo(secondBytes); - assertThat(TraceOptions.fromBytes(thirdBytes).getBytes()).isEqualTo(thirdBytes); - } - - @Test - public void builder_FromOptions() { - assertThat( - TraceOptions.builder(TraceOptions.fromBytes(thirdBytes)) - .setIsSampled() - .build() - .getOptions()) - .isEqualTo(6 | 1); - } - - @Test - public void traceOptions_EqualsAndHashCode() { - EqualsTester tester = new EqualsTester(); - tester.addEqualityGroup(TraceOptions.DEFAULT); - tester.addEqualityGroup( - TraceOptions.fromBytes(secondBytes), TraceOptions.builder().setIsSampled().build()); - tester.addEqualityGroup(TraceOptions.fromBytes(firstBytes)); - tester.testEquals(); - } - - @Test - public void traceOptions_ToString() { - assertThat(TraceOptions.DEFAULT.toString()).contains("sampled=false"); - assertThat(TraceOptions.builder().setIsSampled().build().toString()).contains("sampled=true"); - } -} diff --git a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java index 6ea20fcc..aeb99abf 100644 --- a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java +++ b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java @@ -17,16 +17,16 @@ import static com.google.common.truth.Truth.assertThat; import com.google.common.testing.EqualsTester; import io.opencensus.common.Timestamp; +import io.opencensus.trace.Annotation; +import io.opencensus.trace.AttributeValue; +import io.opencensus.trace.Link; +import io.opencensus.trace.Link.Type; +import io.opencensus.trace.NetworkEvent; import io.opencensus.trace.SpanContext; -import io.opencensus.trace.base.Annotation; -import io.opencensus.trace.base.AttributeValue; -import io.opencensus.trace.base.Link; -import io.opencensus.trace.base.Link.Type; -import io.opencensus.trace.base.NetworkEvent; -import io.opencensus.trace.base.SpanId; -import io.opencensus.trace.base.Status; -import io.opencensus.trace.base.TraceId; -import io.opencensus.trace.base.TraceOptions; +import io.opencensus.trace.SpanId; +import io.opencensus.trace.Status; +import io.opencensus.trace.TraceId; +import io.opencensus.trace.TraceOptions; import io.opencensus.trace.export.SpanData.Attributes; import io.opencensus.trace.export.SpanData.Links; import io.opencensus.trace.export.SpanData.TimedEvent; diff --git a/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java b/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java index 12ec7548..8b9d782a 100644 --- a/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java +++ b/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java @@ -18,9 +18,9 @@ import static com.google.common.truth.Truth.assertThat; import io.opencensus.trace.Sampler; import io.opencensus.trace.Span; import io.opencensus.trace.SpanContext; -import io.opencensus.trace.base.SpanId; -import io.opencensus.trace.base.TraceId; -import io.opencensus.trace.base.TraceOptions; +import io.opencensus.trace.SpanId; +import io.opencensus.trace.TraceId; +import io.opencensus.trace.TraceOptions; import java.util.Collections; import java.util.Random; import org.junit.Test; -- cgit v1.2.3 From e21fe9dab5847f91a1bf2a7d2dbac239636e4741 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Thu, 6 Jul 2017 11:28:04 -0700 Subject: Move ContextUtils to io.opencensus.trace.unsafe package. --- .../java/io/opencensus/trace/ContextUtils.java | 75 --------------------- .../java/io/opencensus/trace/ScopedSpanHandle.java | 1 + api/src/main/java/io/opencensus/trace/Tracer.java | 1 + .../io/opencensus/trace/unsafe/ContextUtils.java | 77 ++++++++++++++++++++++ .../java/io/opencensus/trace/ContextUtilsTest.java | 1 + 5 files changed, 80 insertions(+), 75 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/trace/ContextUtils.java create mode 100644 api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/ContextUtils.java b/api/src/main/java/io/opencensus/trace/ContextUtils.java deleted file mode 100644 index c5331563..00000000 --- a/api/src/main/java/io/opencensus/trace/ContextUtils.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import io.grpc.Context; -import io.opencensus.common.NonThrowingCloseable; - -/** - * Util methods/functionality to interact with the {@link io.grpc.Context}. - * - *

Users must interact with the current Context via the public APIs in {@link Tracer} and avoid - * usages of the {@link #CONTEXT_SPAN_KEY} directly. - */ -public final class ContextUtils { - /** The {@link io.grpc.Context.Key} used to interact with {@link io.grpc.Context}. */ - public static final Context.Key CONTEXT_SPAN_KEY = Context.key("instrumentation-trace-key"); - - // No instance of this class. - private ContextUtils() {} - - /** - * Returns The {@link Span} from the current context. - * - * @return The {@code Span} from the current context. - */ - static Span getCurrentSpan() { - return CONTEXT_SPAN_KEY.get(Context.current()); - } - - /** - * Enters the scope of code where the given {@link Span} is in the current context, and returns an - * object that represents that scope. The scope is exited when the returned object is closed. - * - *

Supports try-with-resource idiom. - * - * @param span The {@code Span} to be set to the current context. - * @return An object that defines a scope where the given {@code Span} is set to the current - * context. - */ - static NonThrowingCloseable withSpan(Span span) { - return new WithSpan(span, CONTEXT_SPAN_KEY); - } - - // Defines an arbitrary scope of code as a traceable operation. Supports try-with-resources idiom. - private static final class WithSpan implements NonThrowingCloseable { - private final Context origContext; - - /** - * Constructs a new {@link WithSpan}. - * - * @param span is the {@code Span} to be added to the current {@code io.grpc.Context}. - * @param contextKey is the {@code Context.Key} used to set/get {@code Span} from the {@code - * Context}. - */ - WithSpan(Span span, Context.Key contextKey) { - origContext = Context.current().withValue(contextKey, span).attach(); - } - - @Override - public void close() { - Context.current().detach(origContext); - } - } -} diff --git a/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java b/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java index 965c4d98..93ff8454 100644 --- a/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java +++ b/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java @@ -14,6 +14,7 @@ package io.opencensus.trace; import io.opencensus.common.NonThrowingCloseable; +import io.opencensus.trace.unsafe.ContextUtils; /** * Defines a scope of code where the given {@link Span} is in the current context. The scope is diff --git a/api/src/main/java/io/opencensus/trace/Tracer.java b/api/src/main/java/io/opencensus/trace/Tracer.java index 97cd0998..98e63672 100644 --- a/api/src/main/java/io/opencensus/trace/Tracer.java +++ b/api/src/main/java/io/opencensus/trace/Tracer.java @@ -17,6 +17,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import io.opencensus.common.NonThrowingCloseable; import io.opencensus.trace.SpanBuilder.NoopSpanBuilder; +import io.opencensus.trace.unsafe.ContextUtils; import javax.annotation.Nullable; /** diff --git a/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java b/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java new file mode 100644 index 00000000..9d885886 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java @@ -0,0 +1,77 @@ +/* + * Copyright 2017, Google Inc. + * 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.unsafe; + +import io.grpc.Context; +import io.opencensus.common.NonThrowingCloseable; +import io.opencensus.trace.Span; +import io.opencensus.trace.Tracer; + +/** + * Util methods/functionality to interact with the {@link io.grpc.Context}. + * + *

Users must interact with the current Context via the public APIs in {@link Tracer} and avoid + * usages of the {@link #CONTEXT_SPAN_KEY} directly. + */ +public final class ContextUtils { + /** The {@link io.grpc.Context.Key} used to interact with {@link io.grpc.Context}. */ + public static final Context.Key CONTEXT_SPAN_KEY = Context.key("instrumentation-trace-key"); + + // No instance of this class. + private ContextUtils() {} + + /** + * Returns The {@link Span} from the current context. + * + * @return The {@code Span} from the current context. + */ + static Span getCurrentSpan() { + return CONTEXT_SPAN_KEY.get(Context.current()); + } + + /** + * Enters the scope of code where the given {@link Span} is in the current context, and returns an + * object that represents that scope. The scope is exited when the returned object is closed. + * + *

Supports try-with-resource idiom. + * + * @param span The {@code Span} to be set to the current context. + * @return An object that defines a scope where the given {@code Span} is set to the current + * context. + */ + static NonThrowingCloseable withSpan(Span span) { + return new WithSpan(span, CONTEXT_SPAN_KEY); + } + + // Defines an arbitrary scope of code as a traceable operation. Supports try-with-resources idiom. + private static final class WithSpan implements NonThrowingCloseable { + private final Context origContext; + + /** + * Constructs a new {@link WithSpan}. + * + * @param span is the {@code Span} to be added to the current {@code io.grpc.Context}. + * @param contextKey is the {@code Context.Key} used to set/get {@code Span} from the {@code + * Context}. + */ + WithSpan(Span span, Context.Key contextKey) { + origContext = Context.current().withValue(contextKey, span).attach(); + } + + @Override + public void close() { + Context.current().detach(origContext); + } + } +} diff --git a/api/src/test/java/io/opencensus/trace/ContextUtilsTest.java b/api/src/test/java/io/opencensus/trace/ContextUtilsTest.java index e4513d74..fff71d07 100644 --- a/api/src/test/java/io/opencensus/trace/ContextUtilsTest.java +++ b/api/src/test/java/io/opencensus/trace/ContextUtilsTest.java @@ -17,6 +17,7 @@ import static com.google.common.truth.Truth.assertThat; import io.grpc.Context; import io.opencensus.common.NonThrowingCloseable; +import io.opencensus.trace.unsafe.ContextUtils; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -- cgit v1.2.3 From d31ce61746bdeb5890852de6ba0c8e51ecaef268 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Thu, 6 Jul 2017 11:52:58 -0700 Subject: Put CONTEXT_SPAN_KEY in a separate class, to avoid exposing methods in ContextUtils. After this commit, ContextUtils is split into two classes, io.opencensus.trace.unsafe.ContextUtils and io.opencensus.trace.CurrentSpanUtils. ContextUtils has one public member, CONTEXT_SPAN_KEY. CurrentSpanUtils has internal methods for working with the current Span, and it is package-private. --- .../java/io/opencensus/trace/CurrentSpanUtils.java | 70 +++++++++++++++++ .../java/io/opencensus/trace/ScopedSpanHandle.java | 3 +- api/src/main/java/io/opencensus/trace/Tracer.java | 7 +- .../io/opencensus/trace/unsafe/ContextUtils.java | 49 +----------- .../java/io/opencensus/trace/ContextUtilsTest.java | 91 ---------------------- .../io/opencensus/trace/CurrentSpanUtilsTest.java | 91 ++++++++++++++++++++++ 6 files changed, 167 insertions(+), 144 deletions(-) create mode 100644 api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java delete mode 100644 api/src/test/java/io/opencensus/trace/ContextUtilsTest.java create mode 100644 api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java new file mode 100644 index 00000000..884fd636 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java @@ -0,0 +1,70 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import io.grpc.Context; +import io.opencensus.common.NonThrowingCloseable; +import io.opencensus.trace.unsafe.ContextUtils; + +/** + * Util methods/functionality to interact with the {@link Span} in the {@link io.grpc.Context}. + */ +final class CurrentSpanUtils { + // No instance of this class. + private CurrentSpanUtils() {} + + /** + * Returns The {@link Span} from the current context. + * + * @return The {@code Span} from the current context. + */ + static Span getCurrentSpan() { + return ContextUtils.CONTEXT_SPAN_KEY.get(Context.current()); + } + + /** + * Enters the scope of code where the given {@link Span} is in the current context, and returns an + * object that represents that scope. The scope is exited when the returned object is closed. + * + *

Supports try-with-resource idiom. + * + * @param span The {@code Span} to be set to the current context. + * @return An object that defines a scope where the given {@code Span} is set to the current + * context. + */ + static NonThrowingCloseable withSpan(Span span) { + return new WithSpan(span, ContextUtils.CONTEXT_SPAN_KEY); + } + + // Defines an arbitrary scope of code as a traceable operation. Supports try-with-resources idiom. + private static final class WithSpan implements NonThrowingCloseable { + private final Context origContext; + + /** + * Constructs a new {@link WithSpan}. + * + * @param span is the {@code Span} to be added to the current {@code io.grpc.Context}. + * @param contextKey is the {@code Context.Key} used to set/get {@code Span} from the {@code + * Context}. + */ + WithSpan(Span span, Context.Key contextKey) { + origContext = Context.current().withValue(contextKey, span).attach(); + } + + @Override + public void close() { + Context.current().detach(origContext); + } + } +} diff --git a/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java b/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java index 93ff8454..e2cf1710 100644 --- a/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java +++ b/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java @@ -14,7 +14,6 @@ package io.opencensus.trace; import io.opencensus.common.NonThrowingCloseable; -import io.opencensus.trace.unsafe.ContextUtils; /** * Defines a scope of code where the given {@link Span} is in the current context. The scope is @@ -34,7 +33,7 @@ final class ScopedSpanHandle implements NonThrowingCloseable { */ ScopedSpanHandle(Span span) { this.span = span; - this.withSpan = ContextUtils.withSpan(span); + this.withSpan = CurrentSpanUtils.withSpan(span); } /** diff --git a/api/src/main/java/io/opencensus/trace/Tracer.java b/api/src/main/java/io/opencensus/trace/Tracer.java index 98e63672..b9f7b67b 100644 --- a/api/src/main/java/io/opencensus/trace/Tracer.java +++ b/api/src/main/java/io/opencensus/trace/Tracer.java @@ -17,7 +17,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import io.opencensus.common.NonThrowingCloseable; import io.opencensus.trace.SpanBuilder.NoopSpanBuilder; -import io.opencensus.trace.unsafe.ContextUtils; import javax.annotation.Nullable; /** @@ -89,7 +88,7 @@ public abstract class Tracer { * from the Context. */ public final Span getCurrentSpan() { - Span currentSpan = ContextUtils.getCurrentSpan(); + Span currentSpan = CurrentSpanUtils.getCurrentSpan(); return currentSpan != null ? currentSpan : BlankSpan.INSTANCE; } @@ -143,7 +142,7 @@ public abstract class Tracer { * @throws NullPointerException if {@code span} is {@code null}. */ public final NonThrowingCloseable withSpan(Span span) { - return ContextUtils.withSpan(checkNotNull(span, "span")); + return CurrentSpanUtils.withSpan(checkNotNull(span, "span")); } /** @@ -166,7 +165,7 @@ public abstract class Tracer { * @throws NullPointerException if {@code spanName} is {@code null}. */ public final SpanBuilder spanBuilder(String spanName) { - return spanBuilderWithExplicitParent(spanName, ContextUtils.getCurrentSpan()); + return spanBuilderWithExplicitParent(spanName, CurrentSpanUtils.getCurrentSpan()); } /** diff --git a/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java b/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java index 9d885886..26ff5c2c 100644 --- a/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java +++ b/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java @@ -14,7 +14,6 @@ package io.opencensus.trace.unsafe; import io.grpc.Context; -import io.opencensus.common.NonThrowingCloseable; import io.opencensus.trace.Span; import io.opencensus.trace.Tracer; @@ -25,53 +24,9 @@ import io.opencensus.trace.Tracer; * usages of the {@link #CONTEXT_SPAN_KEY} directly. */ public final class ContextUtils { - /** The {@link io.grpc.Context.Key} used to interact with {@link io.grpc.Context}. */ - public static final Context.Key CONTEXT_SPAN_KEY = Context.key("instrumentation-trace-key"); - // No instance of this class. private ContextUtils() {} - /** - * Returns The {@link Span} from the current context. - * - * @return The {@code Span} from the current context. - */ - static Span getCurrentSpan() { - return CONTEXT_SPAN_KEY.get(Context.current()); - } - - /** - * Enters the scope of code where the given {@link Span} is in the current context, and returns an - * object that represents that scope. The scope is exited when the returned object is closed. - * - *

Supports try-with-resource idiom. - * - * @param span The {@code Span} to be set to the current context. - * @return An object that defines a scope where the given {@code Span} is set to the current - * context. - */ - static NonThrowingCloseable withSpan(Span span) { - return new WithSpan(span, CONTEXT_SPAN_KEY); - } - - // Defines an arbitrary scope of code as a traceable operation. Supports try-with-resources idiom. - private static final class WithSpan implements NonThrowingCloseable { - private final Context origContext; - - /** - * Constructs a new {@link WithSpan}. - * - * @param span is the {@code Span} to be added to the current {@code io.grpc.Context}. - * @param contextKey is the {@code Context.Key} used to set/get {@code Span} from the {@code - * Context}. - */ - WithSpan(Span span, Context.Key contextKey) { - origContext = Context.current().withValue(contextKey, span).attach(); - } - - @Override - public void close() { - Context.current().detach(origContext); - } - } + /** The {@link io.grpc.Context.Key} used to interact with {@link io.grpc.Context}. */ + public static final Context.Key CONTEXT_SPAN_KEY = Context.key("instrumentation-trace-key"); } diff --git a/api/src/test/java/io/opencensus/trace/ContextUtilsTest.java b/api/src/test/java/io/opencensus/trace/ContextUtilsTest.java deleted file mode 100644 index fff71d07..00000000 --- a/api/src/test/java/io/opencensus/trace/ContextUtilsTest.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2017, Google Inc. - * 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; - -import static com.google.common.truth.Truth.assertThat; - -import io.grpc.Context; -import io.opencensus.common.NonThrowingCloseable; -import io.opencensus.trace.unsafe.ContextUtils; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** Unit tests for {@link ContextUtils}. */ -@RunWith(JUnit4.class) -public class ContextUtilsTest { - @Mock private Span span; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void getCurrentSpan_WhenNoContext() { - assertThat(ContextUtils.getCurrentSpan()).isNull(); - } - - @Test - public void getCurrentSpan() { - assertThat(ContextUtils.getCurrentSpan()).isNull(); - Context origContext = Context.current().withValue(ContextUtils.CONTEXT_SPAN_KEY, span).attach(); - // Make sure context is detached even if test fails. - try { - assertThat(ContextUtils.getCurrentSpan()).isSameAs(span); - } finally { - Context.current().detach(origContext); - } - assertThat(ContextUtils.getCurrentSpan()).isNull(); - } - - @Test - public void withSpan() { - assertThat(ContextUtils.getCurrentSpan()).isNull(); - NonThrowingCloseable ws = ContextUtils.withSpan(span); - try { - assertThat(ContextUtils.getCurrentSpan()).isSameAs(span); - } finally { - ws.close(); - } - assertThat(ContextUtils.getCurrentSpan()).isNull(); - ; - } - - @Test - public void propagationViaRunnable() { - Runnable runnable = null; - NonThrowingCloseable ws = ContextUtils.withSpan(span); - try { - assertThat(ContextUtils.getCurrentSpan()).isSameAs(span); - runnable = - Context.current() - .wrap( - new Runnable() { - @Override - public void run() { - assertThat(ContextUtils.getCurrentSpan()).isSameAs(span); - } - }); - } finally { - ws.close(); - } - assertThat(ContextUtils.getCurrentSpan()).isNotSameAs(span); - // When we run the runnable we will have the span in the current Context. - runnable.run(); - } -} diff --git a/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java b/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java new file mode 100644 index 00000000..22b351a8 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java @@ -0,0 +1,91 @@ +/* + * Copyright 2017, Google Inc. + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import io.grpc.Context; +import io.opencensus.common.NonThrowingCloseable; +import io.opencensus.trace.unsafe.ContextUtils; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** Unit tests for {@link CurrentSpanUtils}. */ +@RunWith(JUnit4.class) +public class CurrentSpanUtilsTest { + @Mock private Span span; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void getCurrentSpan_WhenNoContext() { + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void getCurrentSpan() { + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Context origContext = Context.current().withValue(ContextUtils.CONTEXT_SPAN_KEY, span).attach(); + // Make sure context is detached even if test fails. + try { + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + } finally { + Context.current().detach(origContext); + } + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void withSpan() { + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + NonThrowingCloseable ws = CurrentSpanUtils.withSpan(span); + try { + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + } finally { + ws.close(); + } + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + ; + } + + @Test + public void propagationViaRunnable() { + Runnable runnable = null; + NonThrowingCloseable ws = CurrentSpanUtils.withSpan(span); + try { + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + runnable = + Context.current() + .wrap( + new Runnable() { + @Override + public void run() { + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + } + }); + } finally { + ws.close(); + } + assertThat(CurrentSpanUtils.getCurrentSpan()).isNotSameAs(span); + // When we run the runnable we will have the span in the current Context. + runnable.run(); + } +} -- cgit v1.2.3 From 17e9f4e174391f68d3ca05f39ef48437903f9d14 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Thu, 6 Jul 2017 12:16:53 -0700 Subject: Avoid importing Tracer for Javadoc reference. --- api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java b/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java index 26ff5c2c..c8bf0eb4 100644 --- a/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java +++ b/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java @@ -15,13 +15,12 @@ package io.opencensus.trace.unsafe; import io.grpc.Context; import io.opencensus.trace.Span; -import io.opencensus.trace.Tracer; /** * Util methods/functionality to interact with the {@link io.grpc.Context}. * - *

Users must interact with the current Context via the public APIs in {@link Tracer} and avoid - * usages of the {@link #CONTEXT_SPAN_KEY} directly. + *

Users must interact with the current Context via the public APIs in {@link + * io.opencensus.trace.Tracer} and avoid usages of the {@link #CONTEXT_SPAN_KEY} directly. */ public final class ContextUtils { // No instance of this class. -- cgit v1.2.3 From 83bc424dcc72ea3dc3f1641233d1eaeed923fe2b Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Thu, 6 Jul 2017 12:17:06 -0700 Subject: Delete extra semicolon. --- api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java | 1 - 1 file changed, 1 deletion(-) (limited to 'api') diff --git a/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java b/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java index 22b351a8..9d82bd2c 100644 --- a/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java +++ b/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java @@ -63,7 +63,6 @@ public class CurrentSpanUtilsTest { ws.close(); } assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); - ; } @Test -- cgit v1.2.3 From 1b3a5d60a50914f9574f4dd12a7dd7a187e932d1 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Thu, 6 Jul 2017 12:26:21 -0700 Subject: Rename trace io.grpc.Context key to opencensus-trace-span-key. --- api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java b/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java index c8bf0eb4..b18f663f 100644 --- a/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java +++ b/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java @@ -27,5 +27,5 @@ public final class ContextUtils { private ContextUtils() {} /** The {@link io.grpc.Context.Key} used to interact with {@link io.grpc.Context}. */ - public static final Context.Key CONTEXT_SPAN_KEY = Context.key("instrumentation-trace-key"); + public static final Context.Key CONTEXT_SPAN_KEY = Context.key("opencensus-trace-span-key"); } -- cgit v1.2.3 From 50e3c586da0ae4f4a4333c9b9e5ceab701c44e3e Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Thu, 6 Jul 2017 13:45:46 -0700 Subject: Add convenience functions for handling default case in "match" methods. --- .../main/java/io/opencensus/common/Functions.java | 75 ++++++++++++++++++++++ .../java/io/opencensus/common/FunctionsTest.java | 42 ++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 api/src/main/java/io/opencensus/common/Functions.java create mode 100644 api/src/test/java/io/opencensus/common/FunctionsTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Functions.java b/api/src/main/java/io/opencensus/common/Functions.java new file mode 100644 index 00000000..60bb8885 --- /dev/null +++ b/api/src/main/java/io/opencensus/common/Functions.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017, Google Inc. + * 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.common; + +/** Commonly used {@link Function} instances. */ +public final class Functions { + private Functions() {} + + private static final Function RETURN_NULL = + new Function() { + @Override + public Void apply(Object ignored) { + return null; + } + }; + + private static final Function THROW_ILLEGAL_ARGUMENT_EXCEPTION = + new Function() { + @Override + public Void apply(Object ignored) { + throw new IllegalArgumentException(); + } + }; + + /** + * A {@code Function} that always ignores its argument and returns {@code null}. + * + * @return a {@code Function} that always ignores its argument and returns {@code null}. + */ + public static Function returnNull() { + // It is safe to cast a producer of Void to anything, because Void is always null. + @SuppressWarnings("unchecked") + Function function = (Function) RETURN_NULL; + return function; + } + + /** + * A {@code Function} that always ignores its argument and returns a constant value. + * + * @return a {@code Function} that always ignores its argument and returns a constant value. + */ + public static Function returnConstant(final T constant) { + return new Function() { + @Override + public T apply(Object ignored) { + return constant; + } + }; + } + + /** + * A {@code Function} that always ignores its argument and throws an {@link + * IllegalArgumentException}. + * + * @return a {@code Function} that always ignores its argument and throws an {@link + * IllegalArgumentException}. + */ + public static Function throwIllegalArgumentException() { + // It is safe to cast a producer of Void to anything, because Void is always null. + @SuppressWarnings("unchecked") + Function function = (Function) THROW_ILLEGAL_ARGUMENT_EXCEPTION; + return function; + } +} diff --git a/api/src/test/java/io/opencensus/common/FunctionsTest.java b/api/src/test/java/io/opencensus/common/FunctionsTest.java new file mode 100644 index 00000000..1c8df819 --- /dev/null +++ b/api/src/test/java/io/opencensus/common/FunctionsTest.java @@ -0,0 +1,42 @@ +/* + * Copyright 2017, Google Inc. + * 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.common; + +import static com.google.common.truth.Truth.assertThat; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +/** Tests for {@link Functions}. */ +public class FunctionsTest { + @Rule public ExpectedException thrown = ExpectedException.none(); + + @Test + public void testReturnNull() { + assertThat(Functions.returnNull().apply("ignored")).isNull(); + } + + @Test + public void testReturnConstant() { + assertThat(Functions.returnConstant(123).apply("ignored")).isEqualTo(123); + } + + @Test + public void testThrowIllegalArgumentException() { + Function f = Functions.throwIllegalArgumentException(); + thrown.expect(IllegalArgumentException.class); + f.apply("ignored"); + } +} -- cgit v1.2.3 From 72c82e53c4c1e93ab5216402dea56dffaee467a8 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Thu, 6 Jul 2017 13:47:30 -0700 Subject: Refactor AttributeValue to use a "match" method. AttributeValue.match takes four function arguments: functions for handling String, Long, and Boolean values, and a function for handling any new types that could be added in the future. --- .../main/java/io/opencensus/common/Function.java | 5 +- .../java/io/opencensus/trace/AttributeValue.java | 115 +++++++++++++++------ .../io/opencensus/trace/AttributeValueTest.java | 78 ++++++++++++-- 3 files changed, 157 insertions(+), 41 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Function.java b/api/src/main/java/io/opencensus/common/Function.java index 6105c3e6..035a2363 100644 --- a/api/src/main/java/io/opencensus/common/Function.java +++ b/api/src/main/java/io/opencensus/common/Function.java @@ -14,13 +14,12 @@ package io.opencensus.common; /** - * Used to specify matching functions for use encoding tagged unions (i.e. sum types) in Java. + * Used to specify matching functions for use encoding tagged unions (i.e. sum types) in Java. See + * {@link io.opencensus.trace.AttributeValue#match} for an example of its use. * *

Note: This class is based on the java.util.Function class added in Java 1.8. We cannot use the * Function from Java 1.8 because this library is Java 1.6 compatible. */ -// TODO(bdrutu): Add back "See {@link io.opencensus.stats.ViewDescriptor} for an example of its -// use." public interface Function { B apply(A arg); } diff --git a/api/src/main/java/io/opencensus/trace/AttributeValue.java b/api/src/main/java/io/opencensus/trace/AttributeValue.java index f66fd425..ed314583 100644 --- a/api/src/main/java/io/opencensus/trace/AttributeValue.java +++ b/api/src/main/java/io/opencensus/trace/AttributeValue.java @@ -16,7 +16,7 @@ package io.opencensus.trace; import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; -import javax.annotation.Nullable; +import io.opencensus.common.Function; import javax.annotation.concurrent.Immutable; /** @@ -24,7 +24,6 @@ import javax.annotation.concurrent.Immutable; * of values: {@code String}, {@code Boolean} or {@code Long}. */ @Immutable -@AutoValue public abstract class AttributeValue { /** * Returns an {@code AttributeValue} with a string value. @@ -34,7 +33,7 @@ public abstract class AttributeValue { * @throws NullPointerException if {@code stringValue} is {@code null}. */ public static AttributeValue stringAttributeValue(String stringValue) { - return new AutoValue_AttributeValue(checkNotNull(stringValue, "stringValue"), null, null); + return AttributeValueString.create(stringValue); } /** @@ -44,7 +43,7 @@ public abstract class AttributeValue { * @return an {@code AttributeValue} with a boolean value. */ public static AttributeValue booleanAttributeValue(boolean booleanValue) { - return new AutoValue_AttributeValue(null, booleanValue, null); + return AttributeValueBoolean.create(booleanValue); } /** @@ -54,38 +53,96 @@ public abstract class AttributeValue { * @return an {@code AttributeValue} with a long value. */ public static AttributeValue longAttributeValue(long longValue) { - return new AutoValue_AttributeValue(null, null, longValue); + return AttributeValueLong.create(longValue); } AttributeValue() {} /** - * Returns the {@code String} value if this is a string {@code AttributeValue}, otherwise {@code - * null}. + * Applies a function to the underlying value. The function that is called depends on the value's + * type, which can be {@code String}, {@code Long}, or {@code Boolean}. * - * @return the {@code String} value if this is a string {@code AttributeValue}, otherwise {@code - * null}. + * @param stringFunction the function that should be applied if the value has type {@code String}. + * @param longFunction the function that should be applied if the value has type {@code Long}. + * @param booleanFunction the function that should be applied if the value has type {@code + * Boolean}. + * @param defaultFunction the function that should be applied if the value has a type that was + * added after this {@code match} method was added to the API. See {@link + * io.opencensus.common.Functions} for some common functions for handling unknown types. + * @return the result of the function applied to the underlying value. */ - @Nullable - public abstract String getStringValue(); + public abstract T match( + Function stringFunction, + Function booleanFunction, + Function longFunction, + Function defaultFunction); - /** - * Returns the {@code Boolean} value if this is a boolean {@code AttributeValue}, otherwise {@code - * null}. - * - * @return the {@code Boolean} value if this is a boolean {@code AttributeValue}, otherwise {@code - * null}. - */ - @Nullable - public abstract Boolean getBooleanValue(); + @Immutable + @AutoValue + abstract static class AttributeValueString extends AttributeValue { - /** - * Returns the {@code Long} value if this is a long {@code AttributeValue}, otherwise {@code - * null}. - * - * @return the {@code Long} value if this is a long {@code AttributeValue}, otherwise {@code - * null}. - */ - @Nullable - public abstract Long getLongValue(); + AttributeValueString() {} + + static AttributeValue create(String stringValue) { + return new AutoValue_AttributeValue_AttributeValueString( + checkNotNull(stringValue, "stringValue")); + } + + @Override + public final T match( + Function stringFunction, + Function booleanFunction, + Function longFunction, + Function defaultFunction) { + return stringFunction.apply(getStringValue()); + } + + abstract String getStringValue(); + } + + @Immutable + @AutoValue + abstract static class AttributeValueBoolean extends AttributeValue { + + AttributeValueBoolean() {} + + static AttributeValue create(Boolean stringValue) { + return new AutoValue_AttributeValue_AttributeValueBoolean( + checkNotNull(stringValue, "stringValue")); + } + + @Override + public final T match( + Function stringFunction, + Function booleanFunction, + Function longFunction, + Function defaultFunction) { + return booleanFunction.apply(getBooleanValue()); + } + + abstract Boolean getBooleanValue(); + } + + @Immutable + @AutoValue + abstract static class AttributeValueLong extends AttributeValue { + + AttributeValueLong() {} + + static AttributeValue create(Long stringValue) { + return new AutoValue_AttributeValue_AttributeValueLong( + checkNotNull(stringValue, "stringValue")); + } + + @Override + public final T match( + Function stringFunction, + Function booleanFunction, + Function longFunction, + Function defaultFunction) { + return longFunction.apply(getLongValue()); + } + + abstract Long getLongValue(); + } } diff --git a/api/src/test/java/io/opencensus/trace/AttributeValueTest.java b/api/src/test/java/io/opencensus/trace/AttributeValueTest.java index 7a999604..e078c4ef 100644 --- a/api/src/test/java/io/opencensus/trace/AttributeValueTest.java +++ b/api/src/test/java/io/opencensus/trace/AttributeValueTest.java @@ -14,8 +14,11 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.fail; import com.google.common.testing.EqualsTester; +import io.opencensus.common.Function; +import io.opencensus.common.Functions; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -26,25 +29,82 @@ public class AttributeValueTest { @Test public void stringAttributeValue() { AttributeValue attribute = AttributeValue.stringAttributeValue("MyStringAttributeValue"); - assertThat(attribute.getStringValue()).isEqualTo("MyStringAttributeValue"); - assertThat(attribute.getBooleanValue()).isNull(); - assertThat(attribute.getLongValue()).isNull(); + attribute.match( + new Function() { + @Override + public Object apply(String stringValue) { + assertThat(stringValue).isEqualTo("MyStringAttributeValue"); + return null; + } + }, + new Function() { + @Override + public Object apply(Boolean booleanValue) { + fail("Expected a String"); + return null; + } + }, + new Function() { + @Override + public Object apply(Long longValue) { + fail("Expected a String"); + return null; + } + }, Functions.throwIllegalArgumentException()); } @Test public void booleanAttributeValue() { AttributeValue attribute = AttributeValue.booleanAttributeValue(true); - assertThat(attribute.getStringValue()).isNull(); - assertThat(attribute.getBooleanValue()).isTrue(); - assertThat(attribute.getLongValue()).isNull(); + attribute.match( + new Function() { + @Override + public Object apply(String stringValue) { + fail("Expected a Boolean"); + return null; + } + }, + new Function() { + @Override + public Object apply(Boolean booleanValue) { + assertThat(booleanValue).isTrue(); + return null; + } + }, + new Function() { + @Override + public Object apply(Long longValue) { + fail("Expected a Boolean"); + return null; + } + }, Functions.throwIllegalArgumentException()); } @Test public void longAttributeValue() { AttributeValue attribute = AttributeValue.longAttributeValue(123456L); - assertThat(attribute.getStringValue()).isNull(); - assertThat(attribute.getBooleanValue()).isNull(); - assertThat(attribute.getLongValue()).isEqualTo(123456L); + attribute.match( + new Function() { + @Override + public Object apply(String stringValue) { + fail("Expected a Long"); + return null; + } + }, + new Function() { + @Override + public Object apply(Boolean booleanValue) { + fail("Expected a Long"); + return null; + } + }, + new Function() { + @Override + public Object apply(Long longValue) { + assertThat(longValue).isEqualTo(123456L); + return null; + } + }, Functions.throwIllegalArgumentException()); } @Test -- cgit v1.2.3 From 37d9bd8f9a46666b19533e11e706a64316e7ca8e Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Thu, 6 Jul 2017 15:23:41 -0700 Subject: Change SpanData to use span name instead of display name. (#423) --- .../java/io/opencensus/trace/export/SpanData.java | 12 +++++------ .../io/opencensus/trace/export/SpanDataTest.java | 24 +++++++++++----------- 2 files changed, 18 insertions(+), 18 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/export/SpanData.java b/api/src/main/java/io/opencensus/trace/export/SpanData.java index 762335af..3bcf9e72 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanData.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanData.java @@ -45,7 +45,7 @@ public abstract class SpanData { * @param parentSpanId the parent {@code SpanId} of the {@code Span}. {@code null} if the {@code * Span} is a root. * @param hasRemoteParent {@code true} if the parent is on a different process. - * @param displayName the name of the {@code Span}. + * @param name the name of the {@code Span}. * @param startTimestamp the start {@code Timestamp} of the {@code Span}. * @param attributes the attributes associated with the {@code Span}. * @param annotations the annotations associated with the {@code Span}. @@ -61,7 +61,7 @@ public abstract class SpanData { SpanContext context, @Nullable SpanId parentSpanId, boolean hasRemoteParent, - String displayName, + String name, Timestamp startTimestamp, Attributes attributes, TimedEvents annotations, @@ -73,7 +73,7 @@ public abstract class SpanData { context, parentSpanId, hasRemoteParent, - displayName, + name, startTimestamp, attributes, annotations, @@ -106,11 +106,11 @@ public abstract class SpanData { public abstract boolean getHasRemoteParent(); /** - * Returns the display name of this {@code Span}. + * Returns the name of this {@code Span}. * - * @return the display name of this {@code Span}. + * @return the name of this {@code Span}. */ - public abstract String getDisplayName(); + public abstract String getName(); /** * Returns the start {@code Timestamp} of this {@code Span}. diff --git a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java index aeb99abf..9af46446 100644 --- a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java +++ b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java @@ -50,7 +50,7 @@ public class SpanDataTest { private static final Timestamp eventTimestamp2 = Timestamp.create(123, 458); private static final Timestamp eventTimestamp3 = Timestamp.create(123, 459); private static final Timestamp endTimestamp = Timestamp.create(123, 460); - private static final String DISPLAY_NAME = "MySpanDisplayName"; + private static final String SPAN_NAME = "MySpanName"; private static final String ANNOTATION_TEXT = "MyAnnotationText"; private static final Annotation annotation = Annotation.fromDescription(ANNOTATION_TEXT); private static final NetworkEvent recvNetworkEvent = @@ -96,7 +96,7 @@ public class SpanDataTest { spanContext, parentSpanId, true, - DISPLAY_NAME, + SPAN_NAME, startTimestamp, attributes, annotations, @@ -107,7 +107,7 @@ public class SpanDataTest { assertThat(spanData.getContext()).isEqualTo(spanContext); assertThat(spanData.getParentSpanId()).isEqualTo(parentSpanId); assertThat(spanData.getHasRemoteParent()).isTrue(); - assertThat(spanData.getDisplayName()).isEqualTo(DISPLAY_NAME); + assertThat(spanData.getName()).isEqualTo(SPAN_NAME); assertThat(spanData.getStartTimestamp()).isEqualTo(startTimestamp); assertThat(spanData.getAttributes()).isEqualTo(attributes); assertThat(spanData.getAnnotations()).isEqualTo(annotations); @@ -124,7 +124,7 @@ public class SpanDataTest { spanContext, null, false, - DISPLAY_NAME, + SPAN_NAME, startTimestamp, attributes, annotations, @@ -135,7 +135,7 @@ public class SpanDataTest { assertThat(spanData.getContext()).isEqualTo(spanContext); assertThat(spanData.getParentSpanId()).isNull(); assertThat(spanData.getHasRemoteParent()).isFalse(); - assertThat(spanData.getDisplayName()).isEqualTo(DISPLAY_NAME); + assertThat(spanData.getName()).isEqualTo(SPAN_NAME); assertThat(spanData.getStartTimestamp()).isEqualTo(startTimestamp); assertThat(spanData.getAttributes()).isEqualTo(attributes); assertThat(spanData.getAnnotations()).isEqualTo(annotations); @@ -152,7 +152,7 @@ public class SpanDataTest { spanContext, parentSpanId, false, - DISPLAY_NAME, + SPAN_NAME, startTimestamp, Attributes.create(Collections.emptyMap(), 0), TimedEvents.create(Collections.>emptyList(), 0), @@ -163,7 +163,7 @@ public class SpanDataTest { assertThat(spanData.getContext()).isEqualTo(spanContext); assertThat(spanData.getParentSpanId()).isEqualTo(parentSpanId); assertThat(spanData.getHasRemoteParent()).isFalse(); - assertThat(spanData.getDisplayName()).isEqualTo(DISPLAY_NAME); + assertThat(spanData.getName()).isEqualTo(SPAN_NAME); assertThat(spanData.getStartTimestamp()).isEqualTo(startTimestamp); assertThat(spanData.getAttributes().getAttributeMap().isEmpty()).isTrue(); assertThat(spanData.getAnnotations().getEvents().isEmpty()).isTrue(); @@ -180,7 +180,7 @@ public class SpanDataTest { spanContext, parentSpanId, false, - DISPLAY_NAME, + SPAN_NAME, startTimestamp, attributes, annotations, @@ -193,7 +193,7 @@ public class SpanDataTest { spanContext, parentSpanId, false, - DISPLAY_NAME, + SPAN_NAME, startTimestamp, attributes, annotations, @@ -206,7 +206,7 @@ public class SpanDataTest { spanContext, parentSpanId, false, - DISPLAY_NAME, + SPAN_NAME, startTimestamp, Attributes.create(Collections.emptyMap(), 0), TimedEvents.create(Collections.>emptyList(), 0), @@ -227,7 +227,7 @@ public class SpanDataTest { spanContext, parentSpanId, false, - DISPLAY_NAME, + SPAN_NAME, startTimestamp, attributes, annotations, @@ -238,7 +238,7 @@ public class SpanDataTest { .toString(); assertThat(spanDataString).contains(spanContext.toString()); assertThat(spanDataString).contains(parentSpanId.toString()); - assertThat(spanDataString).contains(DISPLAY_NAME); + assertThat(spanDataString).contains(SPAN_NAME); assertThat(spanDataString).contains(startTimestamp.toString()); assertThat(spanDataString).contains(attributes.toString()); assertThat(spanDataString).contains(annotations.toString()); -- cgit v1.2.3 From 7b804712286908bf61f35e82da33dda17e01483f Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Thu, 6 Jul 2017 16:26:22 -0700 Subject: Add attributes to the Link to match with the data model. (#425) --- api/src/main/java/io/opencensus/trace/Link.java | 31 ++++++++++++++++- .../test/java/io/opencensus/trace/LinkTest.java | 40 ++++++++++++++++++++-- 2 files changed, 67 insertions(+), 4 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/Link.java b/api/src/main/java/io/opencensus/trace/Link.java index 058bd8a9..deea40c1 100644 --- a/api/src/main/java/io/opencensus/trace/Link.java +++ b/api/src/main/java/io/opencensus/trace/Link.java @@ -14,6 +14,9 @@ package io.opencensus.trace; import com.google.auto.value.AutoValue; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import javax.annotation.concurrent.Immutable; /** @@ -28,6 +31,8 @@ import javax.annotation.concurrent.Immutable; @Immutable @AutoValue public abstract class Link { + private static final Map EMPTY_ATTRIBUTES = Collections.emptyMap(); + /** The relationship with the linked {@code Span} relative to the current {@code Span}. */ public enum Type { /** When the linked {@code Span} is a child of the current {@code Span}. */ @@ -44,7 +49,24 @@ public abstract class Link { * @return a new {@code Link}. */ public static Link fromSpanContext(SpanContext context, Type type) { - return new AutoValue_Link(context.getTraceId(), context.getSpanId(), type); + return new AutoValue_Link(context.getTraceId(), context.getSpanId(), type, EMPTY_ATTRIBUTES); + } + + /** + * Returns a new {@code Link}. + * + * @param context the context of the linked {@code Span}. + * @param type the type of the relationship with the linked {@code Span}. + * @param attributes the attributes of the {@code Link}. + * @return a new {@code Link}. + */ + public static Link fromSpanContext( + SpanContext context, Type type, Map attributes) { + return new AutoValue_Link( + context.getTraceId(), + context.getSpanId(), + type, + Collections.unmodifiableMap(new HashMap(attributes))); } /** @@ -68,5 +90,12 @@ public abstract class Link { */ public abstract Type getType(); + /** + * Returns the set of attributes. + * + * @return the set of attributes. + */ + public abstract Map getAttributes(); + Link() {} } diff --git a/api/src/test/java/io/opencensus/trace/LinkTest.java b/api/src/test/java/io/opencensus/trace/LinkTest.java index e6b4afe5..d0d7a147 100644 --- a/api/src/test/java/io/opencensus/trace/LinkTest.java +++ b/api/src/test/java/io/opencensus/trace/LinkTest.java @@ -17,7 +17,10 @@ import static com.google.common.truth.Truth.assertThat; import com.google.common.testing.EqualsTester; import io.opencensus.trace.Link.Type; +import java.util.HashMap; +import java.util.Map; import java.util.Random; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -25,11 +28,19 @@ import org.junit.runners.JUnit4; /** Unit tests for {@link Link}. */ @RunWith(JUnit4.class) public class LinkTest { + private final Map attributesMap = new HashMap(); private final Random random = new Random(1234); private final SpanContext spanContext = SpanContext.create( TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); + @Before + public void setUp() { + attributesMap.put("MyAttributeKey0", AttributeValue.stringAttributeValue("MyStringAttribute")); + attributesMap.put("MyAttributeKey1", AttributeValue.longAttributeValue(10)); + attributesMap.put("MyAttributeKey2", AttributeValue.booleanAttributeValue(true)); + } + @Test public void fromSpanContext_ChildLink() { Link link = Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN); @@ -38,6 +49,15 @@ public class LinkTest { assertThat(link.getType()).isEqualTo(Type.CHILD_LINKED_SPAN); } + @Test + public void fromSpanContext_ChildLink_WithAttributes() { + Link link = Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN, attributesMap); + assertThat(link.getTraceId()).isEqualTo(spanContext.getTraceId()); + assertThat(link.getSpanId()).isEqualTo(spanContext.getSpanId()); + assertThat(link.getType()).isEqualTo(Type.CHILD_LINKED_SPAN); + assertThat(link.getAttributes()).isEqualTo(attributesMap); + } + @Test public void fromSpanContext_ParentLink() { Link link = Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN); @@ -46,6 +66,15 @@ public class LinkTest { assertThat(link.getType()).isEqualTo(Type.PARENT_LINKED_SPAN); } + @Test + public void fromSpanContext_ParentLink_WithAttributes() { + Link link = Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN, attributesMap); + assertThat(link.getTraceId()).isEqualTo(spanContext.getTraceId()); + assertThat(link.getSpanId()).isEqualTo(spanContext.getSpanId()); + assertThat(link.getType()).isEqualTo(Type.PARENT_LINKED_SPAN); + assertThat(link.getAttributes()).isEqualTo(attributesMap); + } + @Test public void link_EqualsAndHashCode() { EqualsTester tester = new EqualsTester(); @@ -57,19 +86,24 @@ public class LinkTest { Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN), Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN)) .addEqualityGroup(Link.fromSpanContext(SpanContext.INVALID, Type.CHILD_LINKED_SPAN)) - .addEqualityGroup(Link.fromSpanContext(SpanContext.INVALID, Type.PARENT_LINKED_SPAN)); + .addEqualityGroup(Link.fromSpanContext(SpanContext.INVALID, Type.PARENT_LINKED_SPAN)) + .addEqualityGroup( + Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN, attributesMap), + Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN, attributesMap)); tester.testEquals(); } @Test public void link_ToString() { - Link link = Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN); + Link link = Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN, attributesMap); assertThat(link.toString()).contains(spanContext.getTraceId().toString()); assertThat(link.toString()).contains(spanContext.getSpanId().toString()); assertThat(link.toString()).contains("CHILD_LINKED_SPAN"); - link = Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN); + assertThat(link.toString()).contains(attributesMap.toString()); + link = Link.fromSpanContext(spanContext, Type.PARENT_LINKED_SPAN, attributesMap); assertThat(link.toString()).contains(spanContext.getTraceId().toString()); assertThat(link.toString()).contains(spanContext.getSpanId().toString()); assertThat(link.toString()).contains("PARENT_LINKED_SPAN"); + assertThat(link.toString()).contains(attributesMap.toString()); } } -- cgit v1.2.3 From 185230ae8051ee82b0ee273a53d065980e7ba341 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Thu, 6 Jul 2017 18:02:35 -0700 Subject: Add an optional number of child spans that were generated while this span was running. (#426) --- api/src/main/java/io/opencensus/trace/export/SpanData.java | 14 ++++++++++++++ .../test/java/io/opencensus/trace/export/SpanDataTest.java | 13 ++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/export/SpanData.java b/api/src/main/java/io/opencensus/trace/export/SpanData.java index 3bcf9e72..b4d5d5c7 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanData.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanData.java @@ -51,6 +51,7 @@ public abstract class SpanData { * @param annotations the annotations associated with the {@code Span}. * @param networkEvents the network events associated with the {@code Span}. * @param links the links associated with the {@code Span}. + * @param childSpanCount the number of child spans that were generated while the span was active. * @param status the {@code Status} of the {@code Span}. {@code null} if the {@code Span} is still * active. * @param endTimestamp the end {@code Timestamp} of the {@code Span}. {@code null} if the {@code @@ -67,6 +68,7 @@ public abstract class SpanData { TimedEvents annotations, TimedEvents networkEvents, Links links, + @Nullable Integer childSpanCount, @Nullable Status status, @Nullable Timestamp endTimestamp) { return new AutoValue_SpanData( @@ -79,6 +81,7 @@ public abstract class SpanData { annotations, networkEvents, links, + childSpanCount, status, endTimestamp); } @@ -147,6 +150,17 @@ public abstract class SpanData { */ public abstract Links getLinks(); + /** + * Returns the number of child spans that were generated while the {@code Span} was running. If + * not {@code null} allows service implementations to detect missing child spans. + * + *

This information is not always available. + * + * @return the number of child spans that were generated while the {@code Span} was running. + */ + @Nullable + public abstract Integer getChildSpanCount(); + /** * Returns the {@code Status} or {@code null} if {@code Span} is still active. * diff --git a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java index 9af46446..8212d4b9 100644 --- a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java +++ b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java @@ -58,6 +58,7 @@ public class SpanDataTest { private static final NetworkEvent sentNetworkEvent = NetworkEvent.builder(NetworkEvent.Type.SENT, 1).build(); private static final Status status = Status.DEADLINE_EXCEEDED.withDescription("TooSlow"); + private static final int CHILD_SPAN_COUNT = 13; private final Random random = new Random(1234); private final SpanContext spanContext = SpanContext.create( @@ -102,6 +103,7 @@ public class SpanDataTest { annotations, networkEvents, links, + CHILD_SPAN_COUNT, status, endTimestamp); assertThat(spanData.getContext()).isEqualTo(spanContext); @@ -113,6 +115,7 @@ public class SpanDataTest { assertThat(spanData.getAnnotations()).isEqualTo(annotations); assertThat(spanData.getNetworkEvents()).isEqualTo(networkEvents); assertThat(spanData.getLinks()).isEqualTo(links); + assertThat(spanData.getChildSpanCount()).isEqualTo(CHILD_SPAN_COUNT); assertThat(spanData.getStatus()).isEqualTo(status); assertThat(spanData.getEndTimestamp()).isEqualTo(endTimestamp); } @@ -131,6 +134,7 @@ public class SpanDataTest { networkEvents, links, null, + null, null); assertThat(spanData.getContext()).isEqualTo(spanContext); assertThat(spanData.getParentSpanId()).isNull(); @@ -141,6 +145,7 @@ public class SpanDataTest { assertThat(spanData.getAnnotations()).isEqualTo(annotations); assertThat(spanData.getNetworkEvents()).isEqualTo(networkEvents); assertThat(spanData.getLinks()).isEqualTo(links); + assertThat(spanData.getChildSpanCount()).isNull(); assertThat(spanData.getStatus()).isNull(); assertThat(spanData.getEndTimestamp()).isNull(); } @@ -158,6 +163,7 @@ public class SpanDataTest { TimedEvents.create(Collections.>emptyList(), 0), TimedEvents.create(Collections.>emptyList(), 0), Links.create(Collections.emptyList(), 0), + 0, status, endTimestamp); assertThat(spanData.getContext()).isEqualTo(spanContext); @@ -169,6 +175,7 @@ public class SpanDataTest { assertThat(spanData.getAnnotations().getEvents().isEmpty()).isTrue(); assertThat(spanData.getNetworkEvents().getEvents().isEmpty()).isTrue(); assertThat(spanData.getLinks().getLinks().isEmpty()).isTrue(); + assertThat(spanData.getChildSpanCount()).isEqualTo(0); assertThat(spanData.getStatus()).isEqualTo(status); assertThat(spanData.getEndTimestamp()).isEqualTo(endTimestamp); } @@ -186,6 +193,7 @@ public class SpanDataTest { annotations, networkEvents, links, + CHILD_SPAN_COUNT, status, endTimestamp); SpanData allSpanData2 = @@ -199,6 +207,7 @@ public class SpanDataTest { annotations, networkEvents, links, + CHILD_SPAN_COUNT, status, endTimestamp); SpanData emptySpanData = @@ -212,6 +221,7 @@ public class SpanDataTest { TimedEvents.create(Collections.>emptyList(), 0), TimedEvents.create(Collections.>emptyList(), 0), Links.create(Collections.emptyList(), 0), + 0, status, endTimestamp); new EqualsTester() @@ -227,12 +237,13 @@ public class SpanDataTest { spanContext, parentSpanId, false, - SPAN_NAME, + SPAN_NAME, startTimestamp, attributes, annotations, networkEvents, links, + CHILD_SPAN_COUNT, status, endTimestamp) .toString(); -- cgit v1.2.3 From 945236db8bd03b1761fa4d287d0f134894a30782 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Thu, 6 Jul 2017 23:00:34 -0700 Subject: Change hasRemoteParent to be Boolean where null means root Span. (#427) --- api/src/main/java/io/opencensus/trace/Sampler.java | 15 ++++++++------- .../main/java/io/opencensus/trace/export/SpanData.java | 14 +++++++++----- .../io/opencensus/trace/samplers/AlwaysSampleSampler.java | 2 +- .../io/opencensus/trace/samplers/NeverSampleSampler.java | 2 +- .../io/opencensus/trace/samplers/ProbabilitySampler.java | 2 +- .../java/io/opencensus/trace/export/SpanDataTest.java | 4 ++-- 6 files changed, 22 insertions(+), 17 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/Sampler.java b/api/src/main/java/io/opencensus/trace/Sampler.java index 327bfa42..3277a4ea 100644 --- a/api/src/main/java/io/opencensus/trace/Sampler.java +++ b/api/src/main/java/io/opencensus/trace/Sampler.java @@ -21,19 +21,20 @@ public abstract class Sampler { /** * Called during {@link Span} creation to make a sampling decision. * - * @param parentContext The parent {@code Span} {@link SpanContext}. May be {@code null} if this + * @param parentContext the parent span's {@link SpanContext}. {@code null} if this is a root + * span. + * @param hasRemoteParent {@code true} if the parent {@code Span} is remote. {@code null} if this * is a root span. - * @param remoteParent true if the parentContext is remote. - * @param traceId The {@link TraceId} for the new {@code Span}. This will be identical to that in + * @param traceId the {@link TraceId} for the new {@code Span}. This will be identical to that in * the parentContext, unless this is a root span. - * @param spanId The span ID for the new {@code Span}. - * @param name The name of the new {@code Span}. - * @param parentLinks The parentLinks associated with the new {@code Span}. + * @param spanId the span ID for the new {@code Span}. + * @param name the name of the new {@code Span}. + * @param parentLinks the parentLinks associated with the new {@code Span}. * @return {@code true} if the {@code Span} is sampled. */ public abstract boolean shouldSample( @Nullable SpanContext parentContext, - boolean remoteParent, + @Nullable Boolean hasRemoteParent, TraceId traceId, SpanId spanId, String name, diff --git a/api/src/main/java/io/opencensus/trace/export/SpanData.java b/api/src/main/java/io/opencensus/trace/export/SpanData.java index b4d5d5c7..bd4daa86 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanData.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanData.java @@ -44,7 +44,8 @@ public abstract class SpanData { * @param context the {@code SpanContext} of the {@code Span}. * @param parentSpanId the parent {@code SpanId} of the {@code Span}. {@code null} if the {@code * Span} is a root. - * @param hasRemoteParent {@code true} if the parent is on a different process. + * @param hasRemoteParent {@code true} if the parent {@code Span} is remote. {@code null} if this + * is a root span. * @param name the name of the {@code Span}. * @param startTimestamp the start {@code Timestamp} of the {@code Span}. * @param attributes the attributes associated with the {@code Span}. @@ -61,7 +62,7 @@ public abstract class SpanData { public static SpanData create( SpanContext context, @Nullable SpanId parentSpanId, - boolean hasRemoteParent, + @Nullable Boolean hasRemoteParent, String name, Timestamp startTimestamp, Attributes attributes, @@ -102,11 +103,14 @@ public abstract class SpanData { public abstract SpanId getParentSpanId(); /** - * Returns {@code true} if the parent is on a different process. + * Returns {@code true} if the parent is on a different process. {@code null} if this is a root + * span. * - * @return {@code true} if the parent is on a different process. + * @return {@code true} if the parent is on a different process. {@code null} if this is a root + * span. */ - public abstract boolean getHasRemoteParent(); + @Nullable + public abstract Boolean getHasRemoteParent(); /** * Returns the name of this {@code Span}. diff --git a/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java b/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java index e20265d9..b8a2c750 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java +++ b/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java @@ -32,7 +32,7 @@ final class AlwaysSampleSampler extends Sampler { @Override public boolean shouldSample( @Nullable SpanContext parentContext, - boolean remoteParent, + @Nullable Boolean hasRemoteParent, TraceId traceId, SpanId spanId, String name, diff --git a/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java b/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java index f773f3a7..f40a9475 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java +++ b/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java @@ -32,7 +32,7 @@ final class NeverSampleSampler extends Sampler { @Override public boolean shouldSample( @Nullable SpanContext parentContext, - boolean remoteParent, + @Nullable Boolean hasRemoteParent, TraceId traceId, SpanId spanId, String name, diff --git a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java index 7a4029e5..f76c498f 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java +++ b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java @@ -71,7 +71,7 @@ abstract class ProbabilitySampler extends Sampler { @Override public final boolean shouldSample( @Nullable SpanContext parentContext, - boolean remoteParent, + @Nullable Boolean hasRemoteParent, TraceId traceId, SpanId spanId, String name, diff --git a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java index 8212d4b9..21fc7945 100644 --- a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java +++ b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java @@ -126,7 +126,7 @@ public class SpanDataTest { SpanData.create( spanContext, null, - false, + null, SPAN_NAME, startTimestamp, attributes, @@ -138,7 +138,7 @@ public class SpanDataTest { null); assertThat(spanData.getContext()).isEqualTo(spanContext); assertThat(spanData.getParentSpanId()).isNull(); - assertThat(spanData.getHasRemoteParent()).isFalse(); + assertThat(spanData.getHasRemoteParent()).isNull(); assertThat(spanData.getName()).isEqualTo(SPAN_NAME); assertThat(spanData.getStartTimestamp()).isEqualTo(startTimestamp); assertThat(spanData.getAttributes()).isEqualTo(attributes); -- cgit v1.2.3 From ee9518de734fcc04270e83045554316361a6f7f0 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Fri, 7 Jul 2017 16:35:08 -0700 Subject: Fix Functions tests. (#437) --- api/src/test/java/io/opencensus/common/FunctionsTest.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'api') diff --git a/api/src/test/java/io/opencensus/common/FunctionsTest.java b/api/src/test/java/io/opencensus/common/FunctionsTest.java index 1c8df819..2ab1ebca 100644 --- a/api/src/test/java/io/opencensus/common/FunctionsTest.java +++ b/api/src/test/java/io/opencensus/common/FunctionsTest.java @@ -18,8 +18,11 @@ import static com.google.common.truth.Truth.assertThat; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; /** Tests for {@link Functions}. */ +@RunWith(JUnit4.class) public class FunctionsTest { @Rule public ExpectedException thrown = ExpectedException.none(); -- cgit v1.2.3 From 4a90bd0a421b1b4f4a509bec586ab9dba1c95020 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Mon, 10 Jul 2017 17:26:13 -0700 Subject: Add Scope as interface for NonThrowingCloseables that work with current context. This interface allows users to write a shorter, more descriptive type name when using scoped tags or spans. --- api/src/main/java/io/opencensus/common/Scope.java | 20 ++++++++++++++++++++ .../java/io/opencensus/trace/CurrentSpanUtils.java | 6 +++--- .../java/io/opencensus/trace/ScopedSpanHandle.java | 6 +++--- .../main/java/io/opencensus/trace/SpanBuilder.java | 12 ++++++------ api/src/main/java/io/opencensus/trace/Tracer.java | 10 +++++----- .../opencensus/trace/propagation/BinaryFormat.java | 4 ++-- .../io/opencensus/trace/CurrentSpanUtilsTest.java | 6 +++--- .../io/opencensus/trace/ScopedSpanHandleTest.java | 4 ++-- .../test/java/io/opencensus/trace/TracerTest.java | 10 +++++----- 9 files changed, 49 insertions(+), 29 deletions(-) create mode 100644 api/src/main/java/io/opencensus/common/Scope.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Scope.java b/api/src/main/java/io/opencensus/common/Scope.java new file mode 100644 index 00000000..929fbd23 --- /dev/null +++ b/api/src/main/java/io/opencensus/common/Scope.java @@ -0,0 +1,20 @@ +/* + * Copyright 2017, Google Inc. + * 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.common; + +/** + * A {@link NonThrowingCloseable} that represents a change to the current context over a scope of + * code. + */ +public interface Scope extends NonThrowingCloseable {} diff --git a/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java index 884fd636..57909f37 100644 --- a/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java +++ b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java @@ -14,7 +14,7 @@ package io.opencensus.trace; import io.grpc.Context; -import io.opencensus.common.NonThrowingCloseable; +import io.opencensus.common.Scope; import io.opencensus.trace.unsafe.ContextUtils; /** @@ -43,12 +43,12 @@ final class CurrentSpanUtils { * @return An object that defines a scope where the given {@code Span} is set to the current * context. */ - static NonThrowingCloseable withSpan(Span span) { + static Scope withSpan(Span span) { return new WithSpan(span, ContextUtils.CONTEXT_SPAN_KEY); } // Defines an arbitrary scope of code as a traceable operation. Supports try-with-resources idiom. - private static final class WithSpan implements NonThrowingCloseable { + private static final class WithSpan implements Scope { private final Context origContext; /** diff --git a/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java b/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java index e2cf1710..81493a2e 100644 --- a/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java +++ b/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java @@ -13,7 +13,7 @@ package io.opencensus.trace; -import io.opencensus.common.NonThrowingCloseable; +import io.opencensus.common.Scope; /** * Defines a scope of code where the given {@link Span} is in the current context. The scope is @@ -22,9 +22,9 @@ import io.opencensus.common.NonThrowingCloseable; * *

Supports try-with-resource idiom. */ -final class ScopedSpanHandle implements NonThrowingCloseable { +final class ScopedSpanHandle implements Scope { private final Span span; - private final NonThrowingCloseable withSpan; + private final Scope withSpan; /** * Creates a {@code ScopedSpanHandle} diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java index e61318ea..1d427b9c 100644 --- a/api/src/main/java/io/opencensus/trace/SpanBuilder.java +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -15,7 +15,7 @@ package io.opencensus.trace; import static com.google.common.base.Preconditions.checkNotNull; -import io.opencensus.common.NonThrowingCloseable; +import io.opencensus.common.Scope; import java.util.List; import javax.annotation.Nullable; @@ -31,7 +31,7 @@ import javax.annotation.Nullable; * private static final Tracer tracer = Tracing.getTracer(); * void doWork { * // Create a Span as a child of the current Span. - * try (NonThrowingCloseable ss = tracer.spanBuilder("MyChildSpan").startScopedSpan()) { + * try (Scope ss = tracer.spanBuilder("MyChildSpan").startScopedSpan()) { * tracer.getCurrentSpan().addAnnotation("my annotation"); * doSomeWork(); // Here the new span is in the current Context, so it can be used * // implicitly anywhere down the stack. @@ -57,7 +57,7 @@ import javax.annotation.Nullable; * } * * public void onExecuteHandler(ServerCallHandler serverCallHandler) { - * try (NonThrowingCloseable ws = tracer.withSpan(mySpan)) { + * try (Scope ws = tracer.withSpan(mySpan)) { * tracer.getCurrentSpan().addAnnotation("Start rpc execution."); * serverCallHandler.run(); // Here the new span is in the current Context, so it can be * // used implicitly anywhere down the stack. @@ -178,7 +178,7 @@ public abstract class SpanBuilder { * private static final Tracer tracer = Tracing.getTracer(); * void doWork { * // Create a Span as a child of the current Span. - * try (NonThrowingCloseable ss = tracer.spanBuilder("MyChildSpan").startScopedSpan()) { + * try (Scope ss = tracer.spanBuilder("MyChildSpan").startScopedSpan()) { * tracer.getCurrentSpan().addAnnotation("my annotation"); * doSomeWork(); // Here the new span is in the current Context, so it can be used * // implicitly anywhere down the stack. Anytime in this closure the span @@ -199,7 +199,7 @@ public abstract class SpanBuilder { * private static Tracer tracer = Tracing.getTracer(); * void doWork { * // Create a Span as a child of the current Span. - * NonThrowingCloseable ss = tracer.spanBuilder("MyChildSpan").startScopedSpan(); + * Scope ss = tracer.spanBuilder("MyChildSpan").startScopedSpan(); * try { * tracer.getCurrentSpan().addAnnotation("my annotation"); * doSomeWork(); // Here the new span is in the current Context, so it can be used @@ -215,7 +215,7 @@ public abstract class SpanBuilder { * @return an object that defines a scope where the newly created {@code Span} will be set to the * current Context. */ - public final NonThrowingCloseable startScopedSpan() { + public final Scope startScopedSpan() { return new ScopedSpanHandle(startSpan()); } diff --git a/api/src/main/java/io/opencensus/trace/Tracer.java b/api/src/main/java/io/opencensus/trace/Tracer.java index b9f7b67b..55a48aa0 100644 --- a/api/src/main/java/io/opencensus/trace/Tracer.java +++ b/api/src/main/java/io/opencensus/trace/Tracer.java @@ -15,7 +15,7 @@ package io.opencensus.trace; import static com.google.common.base.Preconditions.checkNotNull; -import io.opencensus.common.NonThrowingCloseable; +import io.opencensus.common.Scope; import io.opencensus.trace.SpanBuilder.NoopSpanBuilder; import javax.annotation.Nullable; @@ -36,7 +36,7 @@ import javax.annotation.Nullable; * class MyClass { * private static final Tracer tracer = Tracing.getTracer(); * void doWork() { - * try(NonThrowingCloseable ss = tracer.spanBuilder("MyClass.DoWork").startScopedSpan) { + * try(Scope ss = tracer.spanBuilder("MyClass.DoWork").startScopedSpan) { * tracer.getCurrentSpan().addAnnotation("Starting the work."); * doWorkInternal(); * tracer.getCurrentSpan().addAnnotation("Finished working."); @@ -107,7 +107,7 @@ public abstract class Tracer { * void doWork() { * // Create a Span as a child of the current Span. * Span span = tracer.spanBuilder("my span").startSpan(); - * try (NonThrowingCloseable ws = tracer.withSpan(span)) { + * try (Scope ws = tracer.withSpan(span)) { * tracer.getCurrentSpan().addAnnotation("my annotation"); * doSomeOtherWork(); // Here "span" is the current Span. * } @@ -125,7 +125,7 @@ public abstract class Tracer { * void doWork() { * // Create a Span as a child of the current Span. * Span span = tracer.spanBuilder("my span").startSpan(); - * NonThrowingCloseable ws = tracer.withSpan(span); + * Scope ws = tracer.withSpan(span); * try { * tracer.getCurrentSpan().addAnnotation("my annotation"); * doSomeOtherWork(); // Here "span" is the current Span. @@ -141,7 +141,7 @@ public abstract class Tracer { * Context. * @throws NullPointerException if {@code span} is {@code null}. */ - public final NonThrowingCloseable withSpan(Span span) { + public final Scope withSpan(Span span) { return CurrentSpanUtils.withSpan(checkNotNull(span, "span")); } diff --git a/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java b/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java index 284576ec..ab3ad5f2 100644 --- a/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java +++ b/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java @@ -28,7 +28,7 @@ import java.text.ParseException; * private static final BinaryFormat binaryFormat = * Tracing.getPropagationComponent().getBinaryFormat(); * void onSendRequest() { - * try (NonThrowingCloseable ss = tracer.spanBuilder("Sent.MyRequest").startScopedSpan()) { + * try (Scope ss = tracer.spanBuilder("Sent.MyRequest").startScopedSpan()) { * byte[] binaryValue = binaryFormat.toBinaryValue(tracer.getCurrentContext().context()); * // Send the request including the binaryValue and wait for the response. * } @@ -51,7 +51,7 @@ import java.text.ParseException; * } catch (ParseException e) { * // Maybe log the exception. * } - * try (NonThrowingCloseable ss = + * try (Scope ss = * tracer.spanBuilderWithRemoteParent("Recv.MyRequest", spanContext).startScopedSpan()) { * // Handle request and send response back. * } diff --git a/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java b/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java index 9d82bd2c..9b8f6328 100644 --- a/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java +++ b/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java @@ -16,7 +16,7 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; import io.grpc.Context; -import io.opencensus.common.NonThrowingCloseable; +import io.opencensus.common.Scope; import io.opencensus.trace.unsafe.ContextUtils; import org.junit.Before; import org.junit.Test; @@ -56,7 +56,7 @@ public class CurrentSpanUtilsTest { @Test public void withSpan() { assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); - NonThrowingCloseable ws = CurrentSpanUtils.withSpan(span); + Scope ws = CurrentSpanUtils.withSpan(span); try { assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); } finally { @@ -68,7 +68,7 @@ public class CurrentSpanUtilsTest { @Test public void propagationViaRunnable() { Runnable runnable = null; - NonThrowingCloseable ws = CurrentSpanUtils.withSpan(span); + Scope ws = CurrentSpanUtils.withSpan(span); try { assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); runnable = diff --git a/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java b/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java index 8922f4c2..72999115 100644 --- a/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java +++ b/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java @@ -17,7 +17,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Matchers.same; import static org.mockito.Mockito.verify; -import io.opencensus.common.NonThrowingCloseable; +import io.opencensus.common.Scope; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -39,7 +39,7 @@ public class ScopedSpanHandleTest { @Test public void initAttachesSpan_CloseDetachesAndEndsSpan() { assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); - NonThrowingCloseable ss = new ScopedSpanHandle(span); + Scope ss = new ScopedSpanHandle(span); try { assertThat(tracer.getCurrentSpan()).isSameAs(span); } finally { diff --git a/api/src/test/java/io/opencensus/trace/TracerTest.java b/api/src/test/java/io/opencensus/trace/TracerTest.java index a0830428..96116bc2 100644 --- a/api/src/test/java/io/opencensus/trace/TracerTest.java +++ b/api/src/test/java/io/opencensus/trace/TracerTest.java @@ -18,7 +18,7 @@ import static org.mockito.Matchers.same; import static org.mockito.Mockito.when; import io.grpc.Context; -import io.opencensus.common.NonThrowingCloseable; +import io.opencensus.common.Scope; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -56,7 +56,7 @@ public class TracerTest { @Test public void getCurrentSpan_WithSpan() { assertThat(noopTracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); - NonThrowingCloseable ws = noopTracer.withSpan(span); + Scope ws = noopTracer.withSpan(span); try { assertThat(noopTracer.getCurrentSpan()).isSameAs(span); } finally { @@ -68,7 +68,7 @@ public class TracerTest { @Test public void propagationViaRunnable() { Runnable runnable; - NonThrowingCloseable ws = noopTracer.withSpan(span); + Scope ws = noopTracer.withSpan(span); try { assertThat(noopTracer.getCurrentSpan()).isSameAs(span); runnable = @@ -129,7 +129,7 @@ public class TracerTest { @Test public void startSpanWithParentFromContext() { - NonThrowingCloseable ws = tracer.withSpan(span); + Scope ws = tracer.withSpan(span); try { assertThat(tracer.getCurrentSpan()).isSameAs(span); when(tracer.spanBuilderWithExplicitParent(same(SPAN_NAME), same(span))) @@ -142,7 +142,7 @@ public class TracerTest { @Test public void startSpanWithInvalidParentFromContext() { - NonThrowingCloseable ws = tracer.withSpan(BlankSpan.INSTANCE); + Scope ws = tracer.withSpan(BlankSpan.INSTANCE); try { assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); when(tracer.spanBuilderWithExplicitParent(same(SPAN_NAME), same(BlankSpan.INSTANCE))) -- cgit v1.2.3 From 19a146d219c7e1aca0a48cfcc0c79181f24473c6 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Mon, 10 Jul 2017 17:55:16 -0700 Subject: Deprecate NonThrowingCloseable in favor of Scope. --- .../io/opencensus/common/NonThrowingCloseable.java | 3 +++ api/src/main/java/io/opencensus/common/Scope.java | 18 +++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/NonThrowingCloseable.java b/api/src/main/java/io/opencensus/common/NonThrowingCloseable.java index 1dac89f8..81d1166c 100644 --- a/api/src/main/java/io/opencensus/common/NonThrowingCloseable.java +++ b/api/src/main/java/io/opencensus/common/NonThrowingCloseable.java @@ -28,7 +28,10 @@ import java.io.Closeable; * ... * } *

+ * + * @deprecated {@link Scope} is a better match for operations involving the current context. */ +@Deprecated public interface NonThrowingCloseable extends Closeable { @Override void close(); diff --git a/api/src/main/java/io/opencensus/common/Scope.java b/api/src/main/java/io/opencensus/common/Scope.java index 929fbd23..edcc6b9c 100644 --- a/api/src/main/java/io/opencensus/common/Scope.java +++ b/api/src/main/java/io/opencensus/common/Scope.java @@ -14,7 +14,19 @@ package io.opencensus.common; /** - * A {@link NonThrowingCloseable} that represents a change to the current context over a scope of - * code. + * A {@link java.io.Closeable} that represents a change to the current context over a scope of code. + * {@link Scope#close} cannot throw a checked exception. + * + *

Example of usage: + * + *

+ *   try (Scope ctx = tryEnter()) {
+ *     ...
+ *   }
+ * 
*/ -public interface Scope extends NonThrowingCloseable {} +@SuppressWarnings("deprecation") +public interface Scope extends NonThrowingCloseable { + @Override + void close(); +} -- cgit v1.2.3 From 969f95088a3a1e490460ad53931b24e46e6ca907 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 11 Jul 2017 11:14:25 -0700 Subject: Remove Scope.close() method. --- api/src/main/java/io/opencensus/common/Scope.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Scope.java b/api/src/main/java/io/opencensus/common/Scope.java index edcc6b9c..5c069748 100644 --- a/api/src/main/java/io/opencensus/common/Scope.java +++ b/api/src/main/java/io/opencensus/common/Scope.java @@ -26,7 +26,4 @@ package io.opencensus.common; *
*/ @SuppressWarnings("deprecation") -public interface Scope extends NonThrowingCloseable { - @Override - void close(); -} +public interface Scope extends NonThrowingCloseable {} -- cgit v1.2.3 From a112d081d9bccc93ebf524d3eb8689012ae5ecf2 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 11 Jul 2017 12:53:21 -0700 Subject: Revert "Remove Scope.close() method." This reverts commit 969f95088a3a1e490460ad53931b24e46e6ca907. The close() override is necessary to suppress a deprecation warning from NonThrowingCloseable.close(). --- api/src/main/java/io/opencensus/common/Scope.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Scope.java b/api/src/main/java/io/opencensus/common/Scope.java index 5c069748..edcc6b9c 100644 --- a/api/src/main/java/io/opencensus/common/Scope.java +++ b/api/src/main/java/io/opencensus/common/Scope.java @@ -26,4 +26,7 @@ package io.opencensus.common; *
*/ @SuppressWarnings("deprecation") -public interface Scope extends NonThrowingCloseable {} +public interface Scope extends NonThrowingCloseable { + @Override + void close(); +} -- cgit v1.2.3 From 5ac2617a8e715cc318d5fc37a4a95899d967a3e5 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Mon, 24 Jul 2017 13:52:47 -0700 Subject: Add a function that always throws an AssertionError. The function can be used for all default cases in calls to "match" functions in the API library, since a version mismatch isn't possible, and the default case cannot occur in "match" functions that take all subclasses. --- .../main/java/io/opencensus/common/Functions.java | 21 +++++++++++++++++++++ .../java/io/opencensus/common/FunctionsTest.java | 8 ++++++++ 2 files changed, 29 insertions(+) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Functions.java b/api/src/main/java/io/opencensus/common/Functions.java index 60bb8885..dcc1dab5 100644 --- a/api/src/main/java/io/opencensus/common/Functions.java +++ b/api/src/main/java/io/opencensus/common/Functions.java @@ -33,6 +33,14 @@ public final class Functions { } }; + private static final Function THROW_ASSERTION_ERROR = + new Function() { + @Override + public Void apply(Object ignored) { + throw new AssertionError(); + } + }; + /** * A {@code Function} that always ignores its argument and returns {@code null}. * @@ -72,4 +80,17 @@ public final class Functions { Function function = (Function) THROW_ILLEGAL_ARGUMENT_EXCEPTION; return function; } + + /** + * A {@code Function} that always ignores its argument and throws an {@link AssertionError}. + * + * @return a {@code Function} that always ignores its argument and throws an {@code + * AssertionError}. + */ + public static Function throwAssertionError() { + // It is safe to cast a producer of Void to anything, because Void is always null. + @SuppressWarnings("unchecked") + Function function = (Function) THROW_ASSERTION_ERROR; + return function; + } } diff --git a/api/src/test/java/io/opencensus/common/FunctionsTest.java b/api/src/test/java/io/opencensus/common/FunctionsTest.java index 2ab1ebca..6479ad86 100644 --- a/api/src/test/java/io/opencensus/common/FunctionsTest.java +++ b/api/src/test/java/io/opencensus/common/FunctionsTest.java @@ -42,4 +42,12 @@ public class FunctionsTest { thrown.expect(IllegalArgumentException.class); f.apply("ignored"); } + + @Test + public void testThrowAssertionError() { + Function f = Functions.throwAssertionError(); + thrown.handleAssertionErrors(); + thrown.expect(AssertionError.class); + f.apply("ignored"); + } } -- cgit v1.2.3 From 35b8fef45a1d2f1babcd19a8cc239028208859fe Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 25 Jul 2017 09:21:15 -0700 Subject: Improve comments about suppressed "unchecked" warnings. --- api/src/main/java/io/opencensus/common/Functions.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Functions.java b/api/src/main/java/io/opencensus/common/Functions.java index dcc1dab5..67d1f9aa 100644 --- a/api/src/main/java/io/opencensus/common/Functions.java +++ b/api/src/main/java/io/opencensus/common/Functions.java @@ -75,7 +75,7 @@ public final class Functions { * IllegalArgumentException}. */ public static Function throwIllegalArgumentException() { - // It is safe to cast a producer of Void to anything, because Void is always null. + // It is safe to cast this function to have any return type, since it never returns a result. @SuppressWarnings("unchecked") Function function = (Function) THROW_ILLEGAL_ARGUMENT_EXCEPTION; return function; @@ -88,7 +88,7 @@ public final class Functions { * AssertionError}. */ public static Function throwAssertionError() { - // It is safe to cast a producer of Void to anything, because Void is always null. + // It is safe to cast this function to have any return type, since it never returns a result. @SuppressWarnings("unchecked") Function function = (Function) THROW_ASSERTION_ERROR; return function; -- cgit v1.2.3 From f793449e47e58e8cbf3e1fb2c28c95f13bff7833 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Wed, 26 Jul 2017 10:17:29 -0700 Subject: Remove Provider.newInstance(...). newInstance was replaced by Provider.createInstance, which was designed to work with shading and Android. This is part of https://github.com/census-instrumentation/opencensus-java/issues/151 . --- .../main/java/io/opencensus/internal/Provider.java | 29 ---------------------- .../java/io/opencensus/internal/ProviderTest.java | 14 ----------- 2 files changed, 43 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/Provider.java b/api/src/main/java/io/opencensus/internal/Provider.java index 148b6c38..224d92cf 100644 --- a/api/src/main/java/io/opencensus/internal/Provider.java +++ b/api/src/main/java/io/opencensus/internal/Provider.java @@ -14,9 +14,6 @@ package io.opencensus.internal; import java.util.ServiceConfigurationError; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.annotation.Nullable; /** * Instrumentation specific service provider mechanism. @@ -27,32 +24,6 @@ import javax.annotation.Nullable; * } */ public final class Provider { - private static final Logger logger = Logger.getLogger(Provider.class.getName()); - - /** - * Returns a new instance of the class specified with {@code name} by invoking the empty-argument - * constructor via reflections. If the specified class is not found, the {@code defaultValue} is - * returned. - */ - @SuppressWarnings("unchecked") - @Nullable - public static T newInstance(String name, @Nullable T defaultValue) { - try { - Class provider = Class.forName(name); - T result = (T) provider.getConstructor().newInstance(); - logger.fine("Loaded: " + name); - return result; - } catch (ClassNotFoundException e) { - logger.log(Level.FINE, "Falling back to " + defaultValue, e); - return defaultValue; - } catch (Exception e) { - if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } else { - throw new RuntimeException(e); - } - } - } /** * Tries to create an instance of the given rawClass as a subclass of the given superclass. diff --git a/api/src/test/java/io/opencensus/internal/ProviderTest.java b/api/src/test/java/io/opencensus/internal/ProviderTest.java index 30f5f0e8..3ca13b72 100644 --- a/api/src/test/java/io/opencensus/internal/ProviderTest.java +++ b/api/src/test/java/io/opencensus/internal/ProviderTest.java @@ -43,20 +43,6 @@ public class ProviderTest { public MyInterfaceImpl() {} } - @Test - public void testGoodClass() { - assertThat( - Provider.newInstance("io.opencensus.internal.ProviderTest$GoodClass", null)) - .isNotNull(); - } - - @Test - public void testBadClass() { - assertThat( - Provider.newInstance("io.opencensus.internal.ProviderTest$BadClass", null)) - .isNull(); - } - @Test(expected = ServiceConfigurationError.class) public void createInstance_ThrowsErrorWhenClassIsPrivate() throws ClassNotFoundException { Provider.createInstance( -- cgit v1.2.3 From d779d0008dbf6c6094b09c8bea5fb1d284a3c4eb Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Wed, 26 Jul 2017 10:30:27 -0700 Subject: Update Javadoc. --- api/src/main/java/io/opencensus/internal/Provider.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/Provider.java b/api/src/main/java/io/opencensus/internal/Provider.java index 224d92cf..05e36d09 100644 --- a/api/src/main/java/io/opencensus/internal/Provider.java +++ b/api/src/main/java/io/opencensus/internal/Provider.java @@ -16,11 +16,12 @@ package io.opencensus.internal; import java.util.ServiceConfigurationError; /** - * Instrumentation specific service provider mechanism. + * OpenCensus service provider mechanism. * *
{@code
- * // Initialize a static variable using reflection.
- * static final Foo foo = Provider.newInstance("Foo", new NoopFoo());
+ * // Initialize a variable using reflection.
+ * foo = Provider.createInstance(
+ *     Class.forName("FooImpl", true, classLoader), Foo.class);
  * }
*/ public final class Provider { -- cgit v1.2.3 From 199be03c07ab5b57869a19a51aee67ce645efd3a Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Fri, 11 Aug 2017 19:00:06 +0300 Subject: Stop using context ClassLoader in Provider (#502) --- .../main/java/io/opencensus/internal/Provider.java | 26 ---------------------- api/src/main/java/io/opencensus/trace/Tracing.java | 2 +- .../java/io/opencensus/internal/ProviderTest.java | 12 +++++----- 3 files changed, 7 insertions(+), 33 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/Provider.java b/api/src/main/java/io/opencensus/internal/Provider.java index 05e36d09..43cd40f6 100644 --- a/api/src/main/java/io/opencensus/internal/Provider.java +++ b/api/src/main/java/io/opencensus/internal/Provider.java @@ -42,30 +42,4 @@ public final class Provider { "Provider " + rawClass.getName() + " could not be instantiated.", e); } } - - /** - * Get the correct {@link ClassLoader} that must be used when loading using reflection. - * - * @return The correct {@code ClassLoader} that must be used when loading using reflection. - */ - public static ClassLoader getCorrectClassLoader(Class superClass) { - if (isAndroid()) { - // When android:sharedUserId or android:process is used, Android will setup a dummy - // ClassLoader for the thread context (http://stackoverflow.com/questions/13407006), - // instead of letting users to manually set context class loader, we choose the - // correct class loader here. - return superClass.getClassLoader(); - } - return Thread.currentThread().getContextClassLoader(); - } - - private static boolean isAndroid() { - try { - Class.forName("android.app.Application", /*initialize=*/ false, null); - return true; - } catch (Exception e) { - // If Application isn't loaded, it might as well not be Android. - return false; - } - } } diff --git a/api/src/main/java/io/opencensus/trace/Tracing.java b/api/src/main/java/io/opencensus/trace/Tracing.java index 869fae48..70b0a70e 100644 --- a/api/src/main/java/io/opencensus/trace/Tracing.java +++ b/api/src/main/java/io/opencensus/trace/Tracing.java @@ -26,7 +26,7 @@ import java.util.logging.Logger; public final class Tracing { private static final Logger logger = Logger.getLogger(Tracing.class.getName()); private static final TraceComponent traceComponent = - loadTraceComponent(Provider.getCorrectClassLoader(TraceComponent.class)); + loadTraceComponent(TraceComponent.class.getClassLoader()); /** * Returns the global {@link Tracer}. diff --git a/api/src/test/java/io/opencensus/internal/ProviderTest.java b/api/src/test/java/io/opencensus/internal/ProviderTest.java index 3ca13b72..ed6e8a02 100644 --- a/api/src/test/java/io/opencensus/internal/ProviderTest.java +++ b/api/src/test/java/io/opencensus/internal/ProviderTest.java @@ -49,7 +49,7 @@ public class ProviderTest { Class.forName( "io.opencensus.internal.ProviderTest$PrivateClass", true, - Provider.getCorrectClassLoader(ProviderTest.class)), + ProviderTest.class.getClassLoader()), PrivateClass.class); } @@ -60,7 +60,7 @@ public class ProviderTest { Class.forName( "io.opencensus.internal.ProviderTest$PrivateConstructorClass", true, - Provider.getCorrectClassLoader(ProviderTest.class)), + ProviderTest.class.getClassLoader()), PrivateConstructorClass.class); } @@ -71,7 +71,7 @@ public class ProviderTest { Class.forName( "io.opencensus.internal.ProviderTest$NoDefaultConstructorClass", true, - Provider.getCorrectClassLoader(ProviderTest.class)), + ProviderTest.class.getClassLoader()), NoDefaultConstructorClass.class); } @@ -81,7 +81,7 @@ public class ProviderTest { Class.forName( "io.opencensus.internal.ProviderTest$GoodClass", true, - Provider.getCorrectClassLoader(ProviderTest.class)), + ProviderTest.class.getClassLoader()), MyInterface.class); } @@ -92,7 +92,7 @@ public class ProviderTest { Class.forName( "io.opencensus.internal.ProviderTest$GoodClass", true, - Provider.getCorrectClassLoader(ProviderTest.class)), + ProviderTest.class.getClassLoader()), GoodClass.class)) .isNotNull(); } @@ -104,7 +104,7 @@ public class ProviderTest { Class.forName( "io.opencensus.internal.ProviderTest$MyInterfaceImpl", true, - Provider.getCorrectClassLoader(ProviderTest.class)), + ProviderTest.class.getClassLoader()), MyInterface.class)) .isNotNull(); } -- cgit v1.2.3 From 0318bc5a0ba6742273551068b3cdd900364be37e Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Mon, 14 Aug 2017 11:28:40 -0700 Subject: Refactor tag validation code. This commit splits tag validation into separate methods for handling tag keys and values, since keys and values may need different restrictions on their input Strings. There should be no change in behavior. --- api/src/main/java/io/opencensus/internal/StringUtil.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/StringUtil.java b/api/src/main/java/io/opencensus/internal/StringUtil.java index 48992ebd..2d17cb34 100644 --- a/api/src/main/java/io/opencensus/internal/StringUtil.java +++ b/api/src/main/java/io/opencensus/internal/StringUtil.java @@ -44,17 +44,12 @@ public final class StringUtil { } /** - * Determines whether the {@code String} is a valid tag key, tag value, or metric name. + * Determines whether the {@code String} contains only printable characters. * - * @param string the {@code String} to be validated. - * @return whether the {@code String} is valid. - * @see #sanitize(String) + * @param str the {@code String} to be validated. + * @return whether the {@code String} contains only printable characters. */ - public static boolean isValid(String string) { - return string.length() <= MAX_LENGTH && isPrintableString(string); - } - - private static boolean isPrintableString(String str) { + public static boolean isPrintableString(String str) { for (int i = 0; i < str.length(); i++) { if (!isPrintableChar(str.charAt(i))) { return false; -- cgit v1.2.3 From 3b5ec6e482575bd6be1572c7ef65c7b7ab832320 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 15 Aug 2017 13:45:20 -0700 Subject: Move tracing implementation classes to io.opencensus.impl.trace. This is part of #379. The package name may still need to be changed again, but this commit includes all of the changes necessary to put the API and implementation in separate packages. Other changes in this commit: - Make TraceComponent's constructor public. - Leave deprecated copies of the TraceComponent subclasses in the io.opencensus.trace package so that they can be loaded by opencensus-api 0.5. - Move internal classes to io.opencensus.impl.internal. - Make TraceComponentImplBase and BinaryFormatImpl public. --- api/src/main/java/io/opencensus/trace/TraceComponent.java | 3 --- api/src/main/java/io/opencensus/trace/Tracing.java | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/TraceComponent.java b/api/src/main/java/io/opencensus/trace/TraceComponent.java index 276999cc..033de24d 100644 --- a/api/src/main/java/io/opencensus/trace/TraceComponent.java +++ b/api/src/main/java/io/opencensus/trace/TraceComponent.java @@ -67,9 +67,6 @@ public abstract class TraceComponent { */ public abstract TraceConfig getTraceConfig(); - // Disallow external overrides until we define the final API. - TraceComponent() {} - /** * Returns an instance that contains no-op implementations for all the instances. * diff --git a/api/src/main/java/io/opencensus/trace/Tracing.java b/api/src/main/java/io/opencensus/trace/Tracing.java index 70b0a70e..316368a5 100644 --- a/api/src/main/java/io/opencensus/trace/Tracing.java +++ b/api/src/main/java/io/opencensus/trace/Tracing.java @@ -79,7 +79,7 @@ public final class Tracing { try { // Call Class.forName with literal string name of the class to help shading tools. return Provider.createInstance( - Class.forName("io.opencensus.trace.TraceComponentImpl", true, classLoader), + Class.forName("io.opencensus.impl.trace.TraceComponentImpl", true, classLoader), TraceComponent.class); } catch (ClassNotFoundException e) { logger.log( @@ -91,7 +91,7 @@ public final class Tracing { try { // Call Class.forName with literal string name of the class to help shading tools. return Provider.createInstance( - Class.forName("io.opencensus.trace.TraceComponentImplLite", true, classLoader), + Class.forName("io.opencensus.impl.trace.TraceComponentImplLite", true, classLoader), TraceComponent.class); } catch (ClassNotFoundException e) { logger.log( -- cgit v1.2.3 From 59990408b1c2c43862a999f902bfef5661743cea Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Thu, 17 Aug 2017 17:31:41 -0700 Subject: Add @MustBeClosed annotations to the Scoped objects. (#527) --- api/src/main/java/io/opencensus/trace/SpanBuilder.java | 3 ++- api/src/main/java/io/opencensus/trace/Tracer.java | 2 ++ api/src/test/java/io/opencensus/trace/TracerTest.java | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java index 1d427b9c..259a5f29 100644 --- a/api/src/main/java/io/opencensus/trace/SpanBuilder.java +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -15,6 +15,7 @@ package io.opencensus.trace; import static com.google.common.base.Preconditions.checkNotNull; +import com.google.errorprone.annotations.MustBeClosed; import io.opencensus.common.Scope; import java.util.List; import javax.annotation.Nullable; @@ -160,7 +161,6 @@ public abstract class SpanBuilder { */ public abstract Span startSpan(); - // TODO(bdrutu): Add error_prone annotation @MustBeClosed when the 2.0.16 jar is fixed. /** * Starts a new new span and sets it as the {@link Tracer#getCurrentSpan current span}. * @@ -215,6 +215,7 @@ public abstract class SpanBuilder { * @return an object that defines a scope where the newly created {@code Span} will be set to the * current Context. */ + @MustBeClosed public final Scope startScopedSpan() { return new ScopedSpanHandle(startSpan()); } diff --git a/api/src/main/java/io/opencensus/trace/Tracer.java b/api/src/main/java/io/opencensus/trace/Tracer.java index 55a48aa0..a76719f7 100644 --- a/api/src/main/java/io/opencensus/trace/Tracer.java +++ b/api/src/main/java/io/opencensus/trace/Tracer.java @@ -15,6 +15,7 @@ package io.opencensus.trace; import static com.google.common.base.Preconditions.checkNotNull; +import com.google.errorprone.annotations.MustBeClosed; import io.opencensus.common.Scope; import io.opencensus.trace.SpanBuilder.NoopSpanBuilder; import javax.annotation.Nullable; @@ -141,6 +142,7 @@ public abstract class Tracer { * Context. * @throws NullPointerException if {@code span} is {@code null}. */ + @MustBeClosed public final Scope withSpan(Span span) { return CurrentSpanUtils.withSpan(checkNotNull(span, "span")); } diff --git a/api/src/test/java/io/opencensus/trace/TracerTest.java b/api/src/test/java/io/opencensus/trace/TracerTest.java index 96116bc2..04816cc2 100644 --- a/api/src/test/java/io/opencensus/trace/TracerTest.java +++ b/api/src/test/java/io/opencensus/trace/TracerTest.java @@ -30,6 +30,8 @@ import org.mockito.MockitoAnnotations; /** Unit tests for {@link Tracer}. */ @RunWith(JUnit4.class) +// Need to suppress warnings for MustBeClosed because Java-6 does not support try-with-resources. +@SuppressWarnings("MustBeClosedChecker") public class TracerTest { private static final Tracer noopTracer = Tracer.getNoopTracer(); private static final String SPAN_NAME = "MySpanName"; -- cgit v1.2.3 From 7edf0c605414a38f14d719747235d3993791136e Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Thu, 17 Aug 2017 12:00:51 -0700 Subject: Use different package names in each artifact. (fixes #379) This commit uses the following package name prefixes in each artifact, in order to ensure that no package is split across artifacts: opencensus-api: io.opencensus opencensus-impl-core: io.opencensus.implcore opencensus-impl: io.opencensus.impl opencensus-impl-lite: io.opencensus.impllite --- api/src/main/java/io/opencensus/trace/Tracing.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/Tracing.java b/api/src/main/java/io/opencensus/trace/Tracing.java index 316368a5..2f6c891e 100644 --- a/api/src/main/java/io/opencensus/trace/Tracing.java +++ b/api/src/main/java/io/opencensus/trace/Tracing.java @@ -91,7 +91,7 @@ public final class Tracing { try { // Call Class.forName with literal string name of the class to help shading tools. return Provider.createInstance( - Class.forName("io.opencensus.impl.trace.TraceComponentImplLite", true, classLoader), + Class.forName("io.opencensus.impllite.trace.TraceComponentImplLite", true, classLoader), TraceComponent.class); } catch (ClassNotFoundException e) { logger.log( -- cgit v1.2.3 From b2f48c5d608c154d75ae7616c660e053f6e5c5f7 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Wed, 23 Aug 2017 09:52:48 -0700 Subject: Change the licence to OpenCensus authors. (#539) --- api/src/main/java/io/opencensus/common/Clock.java | 5 ++++- api/src/main/java/io/opencensus/common/Duration.java | 5 ++++- api/src/main/java/io/opencensus/common/Function.java | 5 ++++- api/src/main/java/io/opencensus/common/Functions.java | 5 ++++- api/src/main/java/io/opencensus/common/Internal.java | 5 ++++- api/src/main/java/io/opencensus/common/NonThrowingCloseable.java | 5 ++++- api/src/main/java/io/opencensus/common/Scope.java | 5 ++++- api/src/main/java/io/opencensus/common/TimeUtil.java | 5 ++++- api/src/main/java/io/opencensus/common/Timestamp.java | 5 ++++- api/src/main/java/io/opencensus/internal/Provider.java | 5 ++++- api/src/main/java/io/opencensus/internal/StringUtil.java | 5 ++++- api/src/main/java/io/opencensus/internal/ZeroTimeClock.java | 5 ++++- api/src/main/java/io/opencensus/internal/package-info.java | 5 ++++- api/src/main/java/io/opencensus/trace/Annotation.java | 5 ++++- api/src/main/java/io/opencensus/trace/AttributeValue.java | 5 ++++- api/src/main/java/io/opencensus/trace/BlankSpan.java | 5 ++++- api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java | 5 ++++- api/src/main/java/io/opencensus/trace/EndSpanOptions.java | 5 ++++- api/src/main/java/io/opencensus/trace/Link.java | 5 ++++- api/src/main/java/io/opencensus/trace/NetworkEvent.java | 5 ++++- api/src/main/java/io/opencensus/trace/Sampler.java | 5 ++++- api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java | 5 ++++- api/src/main/java/io/opencensus/trace/Span.java | 5 ++++- api/src/main/java/io/opencensus/trace/SpanBuilder.java | 5 ++++- api/src/main/java/io/opencensus/trace/SpanContext.java | 5 ++++- api/src/main/java/io/opencensus/trace/SpanId.java | 5 ++++- api/src/main/java/io/opencensus/trace/Status.java | 5 ++++- api/src/main/java/io/opencensus/trace/TraceComponent.java | 5 ++++- api/src/main/java/io/opencensus/trace/TraceId.java | 5 ++++- api/src/main/java/io/opencensus/trace/TraceOptions.java | 5 ++++- api/src/main/java/io/opencensus/trace/Tracer.java | 5 ++++- api/src/main/java/io/opencensus/trace/Tracing.java | 5 ++++- api/src/main/java/io/opencensus/trace/config/TraceConfig.java | 5 ++++- api/src/main/java/io/opencensus/trace/config/TraceParams.java | 5 ++++- api/src/main/java/io/opencensus/trace/export/ExportComponent.java | 5 ++++- api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java | 5 ++++- api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java | 5 ++++- api/src/main/java/io/opencensus/trace/export/SpanData.java | 5 ++++- api/src/main/java/io/opencensus/trace/export/SpanExporter.java | 5 ++++- api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java | 5 ++++- .../java/io/opencensus/trace/propagation/PropagationComponent.java | 5 ++++- .../main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java | 5 ++++- .../main/java/io/opencensus/trace/samplers/NeverSampleSampler.java | 5 ++++- .../main/java/io/opencensus/trace/samplers/ProbabilitySampler.java | 5 ++++- api/src/main/java/io/opencensus/trace/samplers/Samplers.java | 5 ++++- api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java | 5 ++++- api/src/test/java/io/opencensus/common/DurationTest.java | 5 ++++- api/src/test/java/io/opencensus/common/FunctionsTest.java | 5 ++++- api/src/test/java/io/opencensus/common/TimestampTest.java | 5 ++++- api/src/test/java/io/opencensus/internal/ProviderTest.java | 5 ++++- api/src/test/java/io/opencensus/internal/StringUtilTest.java | 5 ++++- api/src/test/java/io/opencensus/trace/AnnotationTest.java | 5 ++++- api/src/test/java/io/opencensus/trace/AttributeValueTest.java | 5 ++++- api/src/test/java/io/opencensus/trace/BlankSpanTest.java | 5 ++++- api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java | 5 ++++- api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java | 5 ++++- api/src/test/java/io/opencensus/trace/LinkTest.java | 5 ++++- api/src/test/java/io/opencensus/trace/NetworkEventTest.java | 5 ++++- api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java | 5 ++++- api/src/test/java/io/opencensus/trace/SpanContextTest.java | 5 ++++- api/src/test/java/io/opencensus/trace/SpanIdTest.java | 5 ++++- api/src/test/java/io/opencensus/trace/SpanTest.java | 5 ++++- api/src/test/java/io/opencensus/trace/StatusTest.java | 5 ++++- api/src/test/java/io/opencensus/trace/TraceComponentTest.java | 5 ++++- api/src/test/java/io/opencensus/trace/TraceIdTest.java | 5 ++++- api/src/test/java/io/opencensus/trace/TraceOptionsTest.java | 5 ++++- api/src/test/java/io/opencensus/trace/TracerTest.java | 5 ++++- api/src/test/java/io/opencensus/trace/TracingTest.java | 5 ++++- api/src/test/java/io/opencensus/trace/config/TraceConfigTest.java | 5 ++++- api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java | 5 ++++- .../test/java/io/opencensus/trace/export/ExportComponentTest.java | 5 ++++- api/src/test/java/io/opencensus/trace/export/SpanDataTest.java | 5 ++++- .../test/java/io/opencensus/trace/propagation/BinaryFormatTest.java | 5 ++++- .../io/opencensus/trace/propagation/PropagationComponentTest.java | 5 ++++- api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java | 5 ++++- 75 files changed, 300 insertions(+), 75 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Clock.java b/api/src/main/java/io/opencensus/common/Clock.java index 420c5191..f359f49a 100644 --- a/api/src/main/java/io/opencensus/common/Clock.java +++ b/api/src/main/java/io/opencensus/common/Clock.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/common/Duration.java b/api/src/main/java/io/opencensus/common/Duration.java index dad3ccdb..e355d7ed 100644 --- a/api/src/main/java/io/opencensus/common/Duration.java +++ b/api/src/main/java/io/opencensus/common/Duration.java @@ -1,9 +1,12 @@ /* - * Copyright 2016, Google Inc. + * Copyright 2016-17, 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. diff --git a/api/src/main/java/io/opencensus/common/Function.java b/api/src/main/java/io/opencensus/common/Function.java index 035a2363..f790485c 100644 --- a/api/src/main/java/io/opencensus/common/Function.java +++ b/api/src/main/java/io/opencensus/common/Function.java @@ -1,9 +1,12 @@ /* - * Copyright 2016, Google Inc. + * Copyright 2016-17, 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. diff --git a/api/src/main/java/io/opencensus/common/Functions.java b/api/src/main/java/io/opencensus/common/Functions.java index 67d1f9aa..b952a697 100644 --- a/api/src/main/java/io/opencensus/common/Functions.java +++ b/api/src/main/java/io/opencensus/common/Functions.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/common/Internal.java b/api/src/main/java/io/opencensus/common/Internal.java index fee892c3..c0952353 100644 --- a/api/src/main/java/io/opencensus/common/Internal.java +++ b/api/src/main/java/io/opencensus/common/Internal.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/common/NonThrowingCloseable.java b/api/src/main/java/io/opencensus/common/NonThrowingCloseable.java index 81d1166c..de47f4dc 100644 --- a/api/src/main/java/io/opencensus/common/NonThrowingCloseable.java +++ b/api/src/main/java/io/opencensus/common/NonThrowingCloseable.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/common/Scope.java b/api/src/main/java/io/opencensus/common/Scope.java index edcc6b9c..3893fad4 100644 --- a/api/src/main/java/io/opencensus/common/Scope.java +++ b/api/src/main/java/io/opencensus/common/Scope.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/common/TimeUtil.java b/api/src/main/java/io/opencensus/common/TimeUtil.java index d3d8e647..be6b2627 100644 --- a/api/src/main/java/io/opencensus/common/TimeUtil.java +++ b/api/src/main/java/io/opencensus/common/TimeUtil.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/common/Timestamp.java b/api/src/main/java/io/opencensus/common/Timestamp.java index 5cdfeea0..e15ae349 100644 --- a/api/src/main/java/io/opencensus/common/Timestamp.java +++ b/api/src/main/java/io/opencensus/common/Timestamp.java @@ -1,9 +1,12 @@ /* - * Copyright 2016, Google Inc. + * Copyright 2016-17, 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. diff --git a/api/src/main/java/io/opencensus/internal/Provider.java b/api/src/main/java/io/opencensus/internal/Provider.java index 43cd40f6..25cb82b0 100644 --- a/api/src/main/java/io/opencensus/internal/Provider.java +++ b/api/src/main/java/io/opencensus/internal/Provider.java @@ -1,9 +1,12 @@ /* - * Copyright 2016, Google Inc. + * Copyright 2016-17, 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. diff --git a/api/src/main/java/io/opencensus/internal/StringUtil.java b/api/src/main/java/io/opencensus/internal/StringUtil.java index 2d17cb34..6f9ff807 100644 --- a/api/src/main/java/io/opencensus/internal/StringUtil.java +++ b/api/src/main/java/io/opencensus/internal/StringUtil.java @@ -1,9 +1,12 @@ /* - * Copyright 2016, Google Inc. + * Copyright 2016-17, 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. diff --git a/api/src/main/java/io/opencensus/internal/ZeroTimeClock.java b/api/src/main/java/io/opencensus/internal/ZeroTimeClock.java index 022f02fe..fda13e9e 100644 --- a/api/src/main/java/io/opencensus/internal/ZeroTimeClock.java +++ b/api/src/main/java/io/opencensus/internal/ZeroTimeClock.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/internal/package-info.java b/api/src/main/java/io/opencensus/internal/package-info.java index a9f94864..5dd35b23 100644 --- a/api/src/main/java/io/opencensus/internal/package-info.java +++ b/api/src/main/java/io/opencensus/internal/package-info.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/Annotation.java b/api/src/main/java/io/opencensus/trace/Annotation.java index f72070e8..f6482bd0 100644 --- a/api/src/main/java/io/opencensus/trace/Annotation.java +++ b/api/src/main/java/io/opencensus/trace/Annotation.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/AttributeValue.java b/api/src/main/java/io/opencensus/trace/AttributeValue.java index ed314583..ef0d37ed 100644 --- a/api/src/main/java/io/opencensus/trace/AttributeValue.java +++ b/api/src/main/java/io/opencensus/trace/AttributeValue.java @@ -1,9 +1,12 @@ /* - * Copyright 2016, Google Inc. + * Copyright 2016-17, 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. diff --git a/api/src/main/java/io/opencensus/trace/BlankSpan.java b/api/src/main/java/io/opencensus/trace/BlankSpan.java index 40e49551..05087983 100644 --- a/api/src/main/java/io/opencensus/trace/BlankSpan.java +++ b/api/src/main/java/io/opencensus/trace/BlankSpan.java @@ -1,9 +1,12 @@ /* - * Copyright 2016, Google Inc. + * Copyright 2016-17, 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. diff --git a/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java index 57909f37..ab8282de 100644 --- a/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java +++ b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/EndSpanOptions.java b/api/src/main/java/io/opencensus/trace/EndSpanOptions.java index e58a06c3..8711517b 100644 --- a/api/src/main/java/io/opencensus/trace/EndSpanOptions.java +++ b/api/src/main/java/io/opencensus/trace/EndSpanOptions.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/Link.java b/api/src/main/java/io/opencensus/trace/Link.java index deea40c1..716c2d72 100644 --- a/api/src/main/java/io/opencensus/trace/Link.java +++ b/api/src/main/java/io/opencensus/trace/Link.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/NetworkEvent.java b/api/src/main/java/io/opencensus/trace/NetworkEvent.java index 10687074..c933d62b 100644 --- a/api/src/main/java/io/opencensus/trace/NetworkEvent.java +++ b/api/src/main/java/io/opencensus/trace/NetworkEvent.java @@ -1,9 +1,12 @@ /* - * Copyright 2016, Google Inc. + * Copyright 2016-17, 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. diff --git a/api/src/main/java/io/opencensus/trace/Sampler.java b/api/src/main/java/io/opencensus/trace/Sampler.java index 3277a4ea..f56a0deb 100644 --- a/api/src/main/java/io/opencensus/trace/Sampler.java +++ b/api/src/main/java/io/opencensus/trace/Sampler.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java b/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java index 81493a2e..b5beb4aa 100644 --- a/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java +++ b/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/Span.java b/api/src/main/java/io/opencensus/trace/Span.java index 428f0201..c609c13f 100644 --- a/api/src/main/java/io/opencensus/trace/Span.java +++ b/api/src/main/java/io/opencensus/trace/Span.java @@ -1,9 +1,12 @@ /* - * Copyright 2016, Google Inc. + * Copyright 2016-17, 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. diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java index 259a5f29..6567b649 100644 --- a/api/src/main/java/io/opencensus/trace/SpanBuilder.java +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/SpanContext.java b/api/src/main/java/io/opencensus/trace/SpanContext.java index 56a046f1..5e88b9fd 100644 --- a/api/src/main/java/io/opencensus/trace/SpanContext.java +++ b/api/src/main/java/io/opencensus/trace/SpanContext.java @@ -1,9 +1,12 @@ /* - * Copyright 2016, Google Inc. + * Copyright 2016-17, 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. diff --git a/api/src/main/java/io/opencensus/trace/SpanId.java b/api/src/main/java/io/opencensus/trace/SpanId.java index 8128c9d7..446a228e 100644 --- a/api/src/main/java/io/opencensus/trace/SpanId.java +++ b/api/src/main/java/io/opencensus/trace/SpanId.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/Status.java b/api/src/main/java/io/opencensus/trace/Status.java index fab8a833..f34ab693 100644 --- a/api/src/main/java/io/opencensus/trace/Status.java +++ b/api/src/main/java/io/opencensus/trace/Status.java @@ -1,9 +1,12 @@ /* - * Copyright 2016, Google Inc. + * Copyright 2016-17, 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. diff --git a/api/src/main/java/io/opencensus/trace/TraceComponent.java b/api/src/main/java/io/opencensus/trace/TraceComponent.java index 033de24d..4472ba26 100644 --- a/api/src/main/java/io/opencensus/trace/TraceComponent.java +++ b/api/src/main/java/io/opencensus/trace/TraceComponent.java @@ -1,9 +1,12 @@ /* - * Copyright 2016, Google Inc. + * Copyright 2016-17, 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. diff --git a/api/src/main/java/io/opencensus/trace/TraceId.java b/api/src/main/java/io/opencensus/trace/TraceId.java index 191f593f..6badf6e5 100644 --- a/api/src/main/java/io/opencensus/trace/TraceId.java +++ b/api/src/main/java/io/opencensus/trace/TraceId.java @@ -1,9 +1,12 @@ /* - * Copyright 2016, Google Inc. + * Copyright 2016-17, 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. diff --git a/api/src/main/java/io/opencensus/trace/TraceOptions.java b/api/src/main/java/io/opencensus/trace/TraceOptions.java index d41737fa..8241d4f9 100644 --- a/api/src/main/java/io/opencensus/trace/TraceOptions.java +++ b/api/src/main/java/io/opencensus/trace/TraceOptions.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/Tracer.java b/api/src/main/java/io/opencensus/trace/Tracer.java index a76719f7..24853fbc 100644 --- a/api/src/main/java/io/opencensus/trace/Tracer.java +++ b/api/src/main/java/io/opencensus/trace/Tracer.java @@ -1,9 +1,12 @@ /* - * Copyright 2016, Google Inc. + * Copyright 2016-17, 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. diff --git a/api/src/main/java/io/opencensus/trace/Tracing.java b/api/src/main/java/io/opencensus/trace/Tracing.java index 2f6c891e..f370e014 100644 --- a/api/src/main/java/io/opencensus/trace/Tracing.java +++ b/api/src/main/java/io/opencensus/trace/Tracing.java @@ -1,9 +1,12 @@ /* - * Copyright 2016, Google Inc. + * Copyright 2016-17, 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. diff --git a/api/src/main/java/io/opencensus/trace/config/TraceConfig.java b/api/src/main/java/io/opencensus/trace/config/TraceConfig.java index 01cb6d04..bebf4a7f 100644 --- a/api/src/main/java/io/opencensus/trace/config/TraceConfig.java +++ b/api/src/main/java/io/opencensus/trace/config/TraceConfig.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/config/TraceParams.java b/api/src/main/java/io/opencensus/trace/config/TraceParams.java index 73192348..234cc74d 100644 --- a/api/src/main/java/io/opencensus/trace/config/TraceParams.java +++ b/api/src/main/java/io/opencensus/trace/config/TraceParams.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java index be5cad47..abf5c531 100644 --- a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java +++ b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java b/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java index e87036c4..bee65027 100644 --- a/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java index 316cc36b..32b9a80d 100644 --- a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/export/SpanData.java b/api/src/main/java/io/opencensus/trace/export/SpanData.java index bd4daa86..ab88b532 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanData.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanData.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/export/SpanExporter.java b/api/src/main/java/io/opencensus/trace/export/SpanExporter.java index 44b95488..e872904f 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanExporter.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanExporter.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java b/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java index ab3ad5f2..47090036 100644 --- a/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java +++ b/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java b/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java index 382333e3..e8abda76 100644 --- a/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java +++ b/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java b/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java index b8a2c750..7951e733 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java +++ b/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java b/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java index f40a9475..a9221cbf 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java +++ b/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java index f76c498f..855e9fba 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java +++ b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/samplers/Samplers.java b/api/src/main/java/io/opencensus/trace/samplers/Samplers.java index f5ff4531..3d33a7f1 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/Samplers.java +++ b/api/src/main/java/io/opencensus/trace/samplers/Samplers.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java b/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java index b18f663f..cf0d2a65 100644 --- a/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java +++ b/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/common/DurationTest.java b/api/src/test/java/io/opencensus/common/DurationTest.java index e0dd7a99..ada60aaf 100644 --- a/api/src/test/java/io/opencensus/common/DurationTest.java +++ b/api/src/test/java/io/opencensus/common/DurationTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/common/FunctionsTest.java b/api/src/test/java/io/opencensus/common/FunctionsTest.java index 6479ad86..e4d37569 100644 --- a/api/src/test/java/io/opencensus/common/FunctionsTest.java +++ b/api/src/test/java/io/opencensus/common/FunctionsTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/common/TimestampTest.java b/api/src/test/java/io/opencensus/common/TimestampTest.java index 6936247e..68492cb2 100644 --- a/api/src/test/java/io/opencensus/common/TimestampTest.java +++ b/api/src/test/java/io/opencensus/common/TimestampTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/internal/ProviderTest.java b/api/src/test/java/io/opencensus/internal/ProviderTest.java index ed6e8a02..1f4c33fa 100644 --- a/api/src/test/java/io/opencensus/internal/ProviderTest.java +++ b/api/src/test/java/io/opencensus/internal/ProviderTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2016, Google Inc. + * Copyright 2016-17, 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. diff --git a/api/src/test/java/io/opencensus/internal/StringUtilTest.java b/api/src/test/java/io/opencensus/internal/StringUtilTest.java index 14144391..790ce5f7 100644 --- a/api/src/test/java/io/opencensus/internal/StringUtilTest.java +++ b/api/src/test/java/io/opencensus/internal/StringUtilTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2016, Google Inc. + * Copyright 2016-17, 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. diff --git a/api/src/test/java/io/opencensus/trace/AnnotationTest.java b/api/src/test/java/io/opencensus/trace/AnnotationTest.java index fbfe5fd3..0db5d93c 100644 --- a/api/src/test/java/io/opencensus/trace/AnnotationTest.java +++ b/api/src/test/java/io/opencensus/trace/AnnotationTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/trace/AttributeValueTest.java b/api/src/test/java/io/opencensus/trace/AttributeValueTest.java index e078c4ef..01226d1b 100644 --- a/api/src/test/java/io/opencensus/trace/AttributeValueTest.java +++ b/api/src/test/java/io/opencensus/trace/AttributeValueTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/trace/BlankSpanTest.java b/api/src/test/java/io/opencensus/trace/BlankSpanTest.java index ad1eea8b..8f7993ef 100644 --- a/api/src/test/java/io/opencensus/trace/BlankSpanTest.java +++ b/api/src/test/java/io/opencensus/trace/BlankSpanTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java b/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java index 9b8f6328..afc7db63 100644 --- a/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java +++ b/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java b/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java index d531fba5..ac5956d9 100644 --- a/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java +++ b/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/trace/LinkTest.java b/api/src/test/java/io/opencensus/trace/LinkTest.java index d0d7a147..5c1ebf5d 100644 --- a/api/src/test/java/io/opencensus/trace/LinkTest.java +++ b/api/src/test/java/io/opencensus/trace/LinkTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/trace/NetworkEventTest.java b/api/src/test/java/io/opencensus/trace/NetworkEventTest.java index 946e8ce1..82162caf 100644 --- a/api/src/test/java/io/opencensus/trace/NetworkEventTest.java +++ b/api/src/test/java/io/opencensus/trace/NetworkEventTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java b/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java index 72999115..a8c18819 100644 --- a/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java +++ b/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/trace/SpanContextTest.java b/api/src/test/java/io/opencensus/trace/SpanContextTest.java index c0eb5d40..c211d513 100644 --- a/api/src/test/java/io/opencensus/trace/SpanContextTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanContextTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/trace/SpanIdTest.java b/api/src/test/java/io/opencensus/trace/SpanIdTest.java index a35fddce..36226da5 100644 --- a/api/src/test/java/io/opencensus/trace/SpanIdTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanIdTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/trace/SpanTest.java b/api/src/test/java/io/opencensus/trace/SpanTest.java index c8f7cb50..1a25d6b7 100644 --- a/api/src/test/java/io/opencensus/trace/SpanTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/trace/StatusTest.java b/api/src/test/java/io/opencensus/trace/StatusTest.java index c66a3428..108db2d2 100644 --- a/api/src/test/java/io/opencensus/trace/StatusTest.java +++ b/api/src/test/java/io/opencensus/trace/StatusTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/trace/TraceComponentTest.java b/api/src/test/java/io/opencensus/trace/TraceComponentTest.java index 238a8420..a086efe3 100644 --- a/api/src/test/java/io/opencensus/trace/TraceComponentTest.java +++ b/api/src/test/java/io/opencensus/trace/TraceComponentTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/trace/TraceIdTest.java b/api/src/test/java/io/opencensus/trace/TraceIdTest.java index cd1b7c24..8c1a1004 100644 --- a/api/src/test/java/io/opencensus/trace/TraceIdTest.java +++ b/api/src/test/java/io/opencensus/trace/TraceIdTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2016, Google Inc. + * Copyright 2016-17, 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. diff --git a/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java b/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java index fb240646..7d0019b0 100644 --- a/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java +++ b/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/trace/TracerTest.java b/api/src/test/java/io/opencensus/trace/TracerTest.java index 04816cc2..7c65742e 100644 --- a/api/src/test/java/io/opencensus/trace/TracerTest.java +++ b/api/src/test/java/io/opencensus/trace/TracerTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/trace/TracingTest.java b/api/src/test/java/io/opencensus/trace/TracingTest.java index 10891f2f..a4245e6f 100644 --- a/api/src/test/java/io/opencensus/trace/TracingTest.java +++ b/api/src/test/java/io/opencensus/trace/TracingTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2016, Google Inc. + * Copyright 2016-17, 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. diff --git a/api/src/test/java/io/opencensus/trace/config/TraceConfigTest.java b/api/src/test/java/io/opencensus/trace/config/TraceConfigTest.java index cbb6092c..ee80cab4 100644 --- a/api/src/test/java/io/opencensus/trace/config/TraceConfigTest.java +++ b/api/src/test/java/io/opencensus/trace/config/TraceConfigTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java b/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java index 165f0211..7ede0a29 100644 --- a/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java +++ b/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java b/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java index 82a29b95..01c1a086 100644 --- a/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java +++ b/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java index 21fc7945..cb962121 100644 --- a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java +++ b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/trace/propagation/BinaryFormatTest.java b/api/src/test/java/io/opencensus/trace/propagation/BinaryFormatTest.java index b5994ba0..4cb11938 100644 --- a/api/src/test/java/io/opencensus/trace/propagation/BinaryFormatTest.java +++ b/api/src/test/java/io/opencensus/trace/propagation/BinaryFormatTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. 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 24baee69..62f04d98 100644 --- a/api/src/test/java/io/opencensus/trace/propagation/PropagationComponentTest.java +++ b/api/src/test/java/io/opencensus/trace/propagation/PropagationComponentTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. diff --git a/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java b/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java index 8b9d782a..a9e79cc6 100644 --- a/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java +++ b/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java @@ -1,9 +1,12 @@ /* - * Copyright 2017, Google Inc. + * 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. -- cgit v1.2.3 From 3e0ddbb7d87639a496e686e7aa4156c939047532 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Wed, 23 Aug 2017 09:53:55 -0700 Subject: Add uncompressed and compressed message sizes and deprecate the old message size. (#528) * Add uncompressed and compressed message sizes and deprecate the old message size. * Fix review comments. --- .../java/io/opencensus/trace/NetworkEvent.java | 52 ++++++++++++++++++---- .../java/io/opencensus/trace/NetworkEventTest.java | 38 +++++++++++++--- 2 files changed, 76 insertions(+), 14 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/NetworkEvent.java b/api/src/main/java/io/opencensus/trace/NetworkEvent.java index c933d62b..08b7dc66 100644 --- a/api/src/main/java/io/opencensus/trace/NetworkEvent.java +++ b/api/src/main/java/io/opencensus/trace/NetworkEvent.java @@ -53,8 +53,8 @@ public abstract class NetworkEvent { .setMessageId(messageId) // We need to set a value for the message size because the autovalue requires all // primitives to be initialized. - // TODO(bdrutu): Consider to change the API to require message size. - .setMessageSize(0); + .setUncompressedMessageSize(0) + .setCompressedMessageSize(0); } /** @@ -77,16 +77,32 @@ public abstract class NetworkEvent { /** * Returns the message id argument that serves to uniquely identify each network message. * - * @return The message id of the {@code NetworkEvent}. + * @return the message id of the {@code NetworkEvent}. */ public abstract long getMessageId(); /** - * Returns The message size in bytes of the {@code NetworkEvent}. + * Returns the uncompressed size in bytes of the {@code NetworkEvent}. * - * @return The message size in bytes of the {@code NetworkEvent}. + * @return the uncompressed size in bytes of the {@code NetworkEvent}. */ - public abstract long getMessageSize(); + public abstract long getUncompressedMessageSize(); + + /** + * Returns the compressed size in bytes of the {@code NetworkEvent}. + * + * @return the compressed size in bytes of the {@code NetworkEvent}. + */ + public abstract long getCompressedMessageSize(); + + /** + * @deprecated Use {@link #getUncompressedMessageSize}. + * @return the uncompressed size in bytes of the {@code NetworkEvent}. + */ + @Deprecated + public long getMessageSize() { + return getUncompressedMessageSize(); + } /** Builder class for {@link NetworkEvent}. */ @AutoValue.Builder @@ -106,12 +122,30 @@ public abstract class NetworkEvent { public abstract Builder setKernelTimestamp(@Nullable Timestamp kernelTimestamp); /** - * Sets the message size. + * @deprecated Use {@link #setUncompressedMessageSize}. + * @param messageSize represents the uncompressed size in bytes of this message. + * @return this. + */ + @Deprecated + public Builder setMessageSize(long messageSize) { + return setUncompressedMessageSize(messageSize); + } + + /** + * Sets the uncompressed message size. + * + * @param uncompressedMessageSize represents the uncompressed size in bytes of this message. + * @return this. + */ + public abstract Builder setUncompressedMessageSize(long uncompressedMessageSize); + + /** + * Sets the compressed message size. * - * @param messageSize represents the size in bytes of this network message. + * @param compressedMessageSize represents the compressed size in bytes of this message. * @return this. */ - public abstract Builder setMessageSize(long messageSize); + public abstract Builder setCompressedMessageSize(long compressedMessageSize); /** * Builds and returns a {@code NetworkEvent} with the desired values. diff --git a/api/src/test/java/io/opencensus/trace/NetworkEventTest.java b/api/src/test/java/io/opencensus/trace/NetworkEventTest.java index 82162caf..8c132377 100644 --- a/api/src/test/java/io/opencensus/trace/NetworkEventTest.java +++ b/api/src/test/java/io/opencensus/trace/NetworkEventTest.java @@ -37,7 +37,7 @@ public class NetworkEventTest { assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); assertThat(networkEvent.getMessageId()).isEqualTo(1L); assertThat(networkEvent.getKernelTimestamp()).isNull(); - assertThat(networkEvent.getMessageSize()).isEqualTo(0L); + assertThat(networkEvent.getUncompressedMessageSize()).isEqualTo(0L); } @Test @@ -49,7 +49,18 @@ public class NetworkEventTest { assertThat(networkEvent.getKernelTimestamp()).isEqualTo(Timestamp.fromMillis(123456L)); assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); assertThat(networkEvent.getMessageId()).isEqualTo(1L); - assertThat(networkEvent.getMessageSize()).isEqualTo(0L); + assertThat(networkEvent.getUncompressedMessageSize()).isEqualTo(0L); + } + + @Test + public void buildNetworkEvent_WithUncompressedMessageSize() { + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).setUncompressedMessageSize(123L).build(); + assertThat(networkEvent.getKernelTimestamp()).isNull(); + assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); + assertThat(networkEvent.getMessageId()).isEqualTo(1L); + assertThat(networkEvent.getUncompressedMessageSize()).isEqualTo(123L); + assertThat(networkEvent.getMessageSize()).isEqualTo(123L); } @Test @@ -60,6 +71,17 @@ public class NetworkEventTest { assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); assertThat(networkEvent.getMessageId()).isEqualTo(1L); assertThat(networkEvent.getMessageSize()).isEqualTo(123L); + assertThat(networkEvent.getUncompressedMessageSize()).isEqualTo(123L); + } + + @Test + public void buildNetworkEvent_WithCompressedMessageSize() { + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).setCompressedMessageSize(123L).build(); + assertThat(networkEvent.getKernelTimestamp()).isNull(); + assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.SENT); + assertThat(networkEvent.getMessageId()).isEqualTo(1L); + assertThat(networkEvent.getCompressedMessageSize()).isEqualTo(123L); } @Test @@ -67,12 +89,16 @@ public class NetworkEventTest { NetworkEvent networkEvent = NetworkEvent.builder(NetworkEvent.Type.RECV, 1L) .setKernelTimestamp(Timestamp.fromMillis(123456L)) - .setMessageSize(123L) + .setUncompressedMessageSize(123L) + .setCompressedMessageSize(63L) .build(); assertThat(networkEvent.getKernelTimestamp()).isEqualTo(Timestamp.fromMillis(123456L)); assertThat(networkEvent.getType()).isEqualTo(NetworkEvent.Type.RECV); assertThat(networkEvent.getMessageId()).isEqualTo(1L); + assertThat(networkEvent.getUncompressedMessageSize()).isEqualTo(123L); + // Test that getMessageSize returns same as getUncompressedMessageSize(); assertThat(networkEvent.getMessageSize()).isEqualTo(123L); + assertThat(networkEvent.getCompressedMessageSize()).isEqualTo(63L); } @Test @@ -80,11 +106,13 @@ public class NetworkEventTest { NetworkEvent networkEvent = NetworkEvent.builder(NetworkEvent.Type.SENT, 1L) .setKernelTimestamp(Timestamp.fromMillis(123456L)) - .setMessageSize(123L) + .setUncompressedMessageSize(123L) + .setCompressedMessageSize(63L) .build(); assertThat(networkEvent.toString()).contains(Timestamp.fromMillis(123456L).toString()); assertThat(networkEvent.toString()).contains("type=SENT"); assertThat(networkEvent.toString()).contains("messageId=1"); - assertThat(networkEvent.toString()).contains("messageSize=123"); + assertThat(networkEvent.toString()).contains("compressedMessageSize=63"); + assertThat(networkEvent.toString()).contains("uncompressedMessageSize=123"); } } -- cgit v1.2.3 From 1fb102567c48b02ece1f8a7d8ba50cacab1f46d1 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Tue, 29 Aug 2017 22:33:13 -0700 Subject: Add new api that is easier to use for user to add only one Attribute. (#571) * Add new api that is easier to use for user to add only one Attribute. * Rename addAttribute[s] to putAttribute[s] and deprecate the old API. * Update tests to use putAttributes. --- .../main/java/io/opencensus/trace/BlankSpan.java | 5 ++++ api/src/main/java/io/opencensus/trace/Span.java | 32 ++++++++++++++++++++-- .../java/io/opencensus/trace/BlankSpanTest.java | 2 ++ .../test/java/io/opencensus/trace/SpanTest.java | 12 ++++++++ 4 files changed, 49 insertions(+), 2 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/BlankSpan.java b/api/src/main/java/io/opencensus/trace/BlankSpan.java index 05087983..b7cfb08f 100644 --- a/api/src/main/java/io/opencensus/trace/BlankSpan.java +++ b/api/src/main/java/io/opencensus/trace/BlankSpan.java @@ -34,8 +34,13 @@ public final class BlankSpan extends Span { super(SpanContext.INVALID, null); } + /** No-op implementation of the {@link Span#putAttribute(String, AttributeValue)} method. */ + @Override + public void putAttribute(String key, AttributeValue value) {} + /** No-op implementation of the {@link Span#addAttributes(Map)} method. */ @Override + @SuppressWarnings("deprecation") public void addAttributes(Map attributes) {} /** No-op implementation of the {@link Span#addAnnotation(String, Map)} method. */ diff --git a/api/src/main/java/io/opencensus/trace/Span.java b/api/src/main/java/io/opencensus/trace/Span.java index c609c13f..20a859e1 100644 --- a/api/src/main/java/io/opencensus/trace/Span.java +++ b/api/src/main/java/io/opencensus/trace/Span.java @@ -77,10 +77,38 @@ public abstract class Span { } /** - * Adds a set of attributes to the {@code Span}. + * Sets an attribute to the {@code Span}. If the {@code Span} previously contained a mapping + * for the key, the old value is replaced by the specified value. * + * @param key the key for this attribute. + * @param value the value for this attribute. + */ + public void putAttribute(String key, AttributeValue value) { + // Not final because for performance reasons we want to override this in the implementation. + // Also a default implementation is needed to not break the compatibility (users may extend this + // for testing). + addAttributes(Collections.singletonMap(key, value)); + } + + /** + * Sets a set of attributes to the {@code Span}. The effect of this call is equivalent to that of + * calling {@link #putAttribute(String, AttributeValue)} once for each element in the specified + * map. + * + * @param attributes the attributes that will be added and associated with the {@code Span}. + */ + public void putAttributes(Map attributes) { + // Not final because we want to start overriding this method from the beginning, this will + // allow us to remove the addAttributes faster. + addAttributes(attributes); + } + + + /** + * @deprecated Use {@link #putAttributes(Map)} * @param attributes the attributes that will be added and associated with the {@code Span}. */ + @Deprecated public abstract void addAttributes(Map attributes); /** @@ -97,7 +125,7 @@ public abstract class Span { * * @param description the description of the annotation time event. * @param attributes the attributes that will be added; these are associated with this annotation, - * not the {@code Span} as for {@link #addAttributes}. + * not the {@code Span} as for {@link #addAttributes(Map)}. */ public abstract void addAnnotation(String description, Map attributes); diff --git a/api/src/test/java/io/opencensus/trace/BlankSpanTest.java b/api/src/test/java/io/opencensus/trace/BlankSpanTest.java index 8f7993ef..4e8342e2 100644 --- a/api/src/test/java/io/opencensus/trace/BlankSpanTest.java +++ b/api/src/test/java/io/opencensus/trace/BlankSpanTest.java @@ -44,6 +44,8 @@ public class BlankSpanTest { multipleAttributes.put("MyBooleanAttributeKey", AttributeValue.booleanAttributeValue(true)); multipleAttributes.put("MyLongAttributeKey", AttributeValue.longAttributeValue(123)); // Tests only that all the methods are not crashing/throwing errors. + BlankSpan.INSTANCE.putAttribute( + "MyStringAttributeKey2", AttributeValue.stringAttributeValue("MyStringAttributeValue2")); BlankSpan.INSTANCE.addAttributes(attributes); BlankSpan.INSTANCE.addAttributes(multipleAttributes); BlankSpan.INSTANCE.addAnnotation("MyAnnotation"); diff --git a/api/src/test/java/io/opencensus/trace/SpanTest.java b/api/src/test/java/io/opencensus/trace/SpanTest.java index 1a25d6b7..5d36bb14 100644 --- a/api/src/test/java/io/opencensus/trace/SpanTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanTest.java @@ -17,9 +17,11 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.eq; import static org.mockito.Matchers.same; import static org.mockito.Mockito.verify; +import java.util.Collections; import java.util.EnumSet; import java.util.Map; import java.util.Random; @@ -81,6 +83,16 @@ public class SpanTest { assertThat(span.getOptions()).isEqualTo(spanOptions); } + @Test + public void addAttributeCallsAddAttributesByDefault() { + Span span = Mockito.spy(new NoopSpan(spanContext, spanOptions)); + span.putAttribute("MyKey", AttributeValue.booleanAttributeValue(true)); + span.end(); + verify(span) + .addAttributes( + eq(Collections.singletonMap("MyKey", AttributeValue.booleanAttributeValue(true)))); + } + @Test public void endCallsEndWithDefaultOptions() { Span span = Mockito.spy(new NoopSpan(spanContext, spanOptions)); -- cgit v1.2.3 From 8b19f6e3a6cf88ee2661df86e2415cea8fee0609 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Mon, 4 Sep 2017 14:52:57 -0700 Subject: Add IntervalBucket and tests. (#537) --- api/src/main/java/io/opencensus/common/Duration.java | 1 + 1 file changed, 1 insertion(+) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Duration.java b/api/src/main/java/io/opencensus/common/Duration.java index e355d7ed..b69416e8 100644 --- a/api/src/main/java/io/opencensus/common/Duration.java +++ b/api/src/main/java/io/opencensus/common/Duration.java @@ -31,6 +31,7 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue +// TODO(songya): implements Comparable public abstract class Duration { private static final Duration ZERO = create(0, 0); -- cgit v1.2.3 From 36a87b81fee117cdc1fe028eb12094da94277580 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Tue, 5 Sep 2017 16:11:21 -0700 Subject: Implement Duration.compareTo() (#582) * Update Duration.compareTo() * Add check for negative duration for interval --- .../main/java/io/opencensus/common/Duration.java | 21 +++++++++++++++++++-- .../main/java/io/opencensus/common/TimeUtil.java | 2 +- .../main/java/io/opencensus/common/Timestamp.java | 9 +++------ .../java/io/opencensus/common/DurationTest.java | 15 +++++++++++++++ 4 files changed, 38 insertions(+), 9 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Duration.java b/api/src/main/java/io/opencensus/common/Duration.java index b69416e8..77ba3db7 100644 --- a/api/src/main/java/io/opencensus/common/Duration.java +++ b/api/src/main/java/io/opencensus/common/Duration.java @@ -22,6 +22,7 @@ import static io.opencensus.common.TimeUtil.MILLIS_PER_SECOND; import static io.opencensus.common.TimeUtil.NANOS_PER_MILLI; import com.google.auto.value.AutoValue; +import com.google.common.primitives.Longs; import javax.annotation.concurrent.Immutable; /** @@ -31,8 +32,7 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue -// TODO(songya): implements Comparable -public abstract class Duration { +public abstract class Duration implements Comparable { private static final Duration ZERO = create(0, 0); /** @@ -88,5 +88,22 @@ public abstract class Duration { */ public abstract int getNanos(); + /** + * Compares this {@code Duration} to the specified {@code Duration}. + * + * @param otherDuration the other {@code Duration} to compare to, not {@code null}. + * @return the comparator value: zero if equal, negative if this duration is smaller + * than otherDuration, positive if larger. + * @throws NullPointerException if otherDuration is {@code null}. + */ + @Override + public int compareTo(Duration otherDuration) { + int cmp = Longs.compare(getSeconds(), otherDuration.getSeconds()); + if (cmp != 0) { + return cmp; + } + return Longs.compare(getNanos(), otherDuration.getNanos()); + } + Duration() {} } diff --git a/api/src/main/java/io/opencensus/common/TimeUtil.java b/api/src/main/java/io/opencensus/common/TimeUtil.java index be6b2627..ab64c5df 100644 --- a/api/src/main/java/io/opencensus/common/TimeUtil.java +++ b/api/src/main/java/io/opencensus/common/TimeUtil.java @@ -16,7 +16,7 @@ package io.opencensus.common; -/** Created by bdrutu on 6/14/17. */ +/** Util class for {@link Timestamp} and {@link Duration}. */ final class TimeUtil { static final long MAX_SECONDS = 315576000000L; static final int MAX_NANOS = 999999999; diff --git a/api/src/main/java/io/opencensus/common/Timestamp.java b/api/src/main/java/io/opencensus/common/Timestamp.java index e15ae349..3edf412a 100644 --- a/api/src/main/java/io/opencensus/common/Timestamp.java +++ b/api/src/main/java/io/opencensus/common/Timestamp.java @@ -24,6 +24,7 @@ import static io.opencensus.common.TimeUtil.NANOS_PER_SECOND; import com.google.auto.value.AutoValue; import com.google.common.math.LongMath; +import com.google.common.primitives.Longs; import java.math.RoundingMode; import javax.annotation.concurrent.Immutable; @@ -143,15 +144,11 @@ public abstract class Timestamp implements Comparable { */ @Override public int compareTo(Timestamp otherTimestamp) { - int cmp = compareLong(getSeconds(), otherTimestamp.getSeconds()); + int cmp = Longs.compare(getSeconds(), otherTimestamp.getSeconds()); if (cmp != 0) { return cmp; } - return compareLong(getNanos(), otherTimestamp.getNanos()); - } - - private static int compareLong(long x, long y) { - return (x < y) ? -1 : ((x == y) ? 0 : 1); + return Longs.compare(getNanos(), otherTimestamp.getNanos()); } // Returns a Timestamp with the specified duration added. diff --git a/api/src/test/java/io/opencensus/common/DurationTest.java b/api/src/test/java/io/opencensus/common/DurationTest.java index ada60aaf..1aad997b 100644 --- a/api/src/test/java/io/opencensus/common/DurationTest.java +++ b/api/src/test/java/io/opencensus/common/DurationTest.java @@ -62,6 +62,21 @@ public class DurationTest { assertThat(Duration.fromMillis(-3456)).isEqualTo(Duration.create(-3, -456000000)); } + @Test + public void duration_CompareLength() { + assertThat(Duration.create(0, 0).compareTo(Duration.create(0, 0))).isEqualTo(0); + assertThat(Duration.create(24, 42).compareTo(Duration.create(24, 42))).isEqualTo(0); + assertThat(Duration.create(-24, -42).compareTo(Duration.create(-24, -42))).isEqualTo(0); + assertThat(Duration.create(25, 42).compareTo(Duration.create(24, 42))).isEqualTo(1); + assertThat(Duration.create(24, 45).compareTo(Duration.create(24, 42))).isEqualTo(1); + assertThat(Duration.create(24, 42).compareTo(Duration.create(25, 42))).isEqualTo(-1); + assertThat(Duration.create(24, 42).compareTo(Duration.create(24, 45))).isEqualTo(-1); + assertThat(Duration.create(-24, -45).compareTo(Duration.create(-24, -42))).isEqualTo(-1); + assertThat(Duration.create(-24, -42).compareTo(Duration.create(-25, -42))).isEqualTo(1); + assertThat(Duration.create(24, 42).compareTo(Duration.create(-24, -42))).isEqualTo(1); + + } + @Test public void testDurationEqual() { // Positive tests. -- cgit v1.2.3 From 365c32f2bb4e270d43e19d3494126b20374628c8 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Thu, 7 Sep 2017 17:03:50 -0700 Subject: Add a simple traceconfigz page. (#590) * Add a simple traceconfigz page. * Apply google formatter. * Fix warning VA_FORMAT_STRING_USES_NEWLINE. * Add getDescription and polish the HTML. * Update based on comments. --- api/src/main/java/io/opencensus/trace/Sampler.java | 12 +++++++++++- .../io/opencensus/trace/samplers/AlwaysSampleSampler.java | 5 +++++ .../io/opencensus/trace/samplers/NeverSampleSampler.java | 5 +++++ .../io/opencensus/trace/samplers/ProbabilitySampler.java | 5 +++++ 4 files changed, 26 insertions(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/Sampler.java b/api/src/main/java/io/opencensus/trace/Sampler.java index f56a0deb..429ffe92 100644 --- a/api/src/main/java/io/opencensus/trace/Sampler.java +++ b/api/src/main/java/io/opencensus/trace/Sampler.java @@ -30,7 +30,7 @@ public abstract class Sampler { * is a root span. * @param traceId the {@link TraceId} for the new {@code Span}. This will be identical to that in * the parentContext, unless this is a root span. - * @param spanId the span ID for the new {@code Span}. + * @param spanId the {@link SpanId} for the new {@code Span}. * @param name the name of the new {@code Span}. * @param parentLinks the parentLinks associated with the new {@code Span}. * @return {@code true} if the {@code Span} is sampled. @@ -42,4 +42,14 @@ public abstract class Sampler { SpanId spanId, String name, List parentLinks); + + /** + * Returns the description of this {@code Sampler}. This may be displayed on debug pages or in + * the logs. + * + *

Example: "ProbabilitySampler{0.000100}" + * + * @return the description of this {@code Sampler}. + */ + public abstract String getDescription(); } diff --git a/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java b/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java index 7951e733..7b61e235 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java +++ b/api/src/main/java/io/opencensus/trace/samplers/AlwaysSampleSampler.java @@ -43,6 +43,11 @@ final class AlwaysSampleSampler extends Sampler { return true; } + @Override + public String getDescription() { + return toString(); + } + @Override public String toString() { return "AlwaysSampleSampler"; diff --git a/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java b/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java index a9221cbf..c6de645a 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java +++ b/api/src/main/java/io/opencensus/trace/samplers/NeverSampleSampler.java @@ -43,6 +43,11 @@ final class NeverSampleSampler extends Sampler { return false; } + @Override + public String getDescription() { + return toString(); + } + @Override public String toString() { return "NeverSampleSampler"; diff --git a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java index 855e9fba..251454ab 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java +++ b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java @@ -92,4 +92,9 @@ abstract class ProbabilitySampler extends Sampler { // code is executed in-line for every Span creation). return Math.abs(traceId.getLowerLong()) < getIdUpperBound(); } + + @Override + public final String getDescription() { + return String.format("ProbabilitySampler{%.6f}", getProbability()); + } } -- cgit v1.2.3 From 9209e54ed9035716cd3095cb2903b253a1f19962 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Mon, 11 Sep 2017 19:15:15 -0700 Subject: Fix NarrowingCompoundAssignment error that shows only in errorprone > 2.0.20 (#617) --- api/src/main/java/io/opencensus/common/Timestamp.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Timestamp.java b/api/src/main/java/io/opencensus/common/Timestamp.java index 3edf412a..0fa7c800 100644 --- a/api/src/main/java/io/opencensus/common/Timestamp.java +++ b/api/src/main/java/io/opencensus/common/Timestamp.java @@ -126,10 +126,10 @@ public abstract class Timestamp implements Comparable { int durationNanos = getNanos() - timestamp.getNanos(); if (durationSeconds < 0 && durationNanos > 0) { durationSeconds += 1; - durationNanos -= NANOS_PER_SECOND; + durationNanos = (int) (durationNanos - NANOS_PER_SECOND); } else if (durationSeconds > 0 && durationNanos < 0) { durationSeconds -= 1; - durationNanos += NANOS_PER_SECOND; + durationNanos = (int) (durationNanos + NANOS_PER_SECOND); } return Duration.create(durationSeconds, durationNanos); } -- cgit v1.2.3 From 150cc0515e259b3886b241fab91b91c7d143b0a1 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Wed, 13 Sep 2017 16:45:53 -0700 Subject: Add a method to list all registered span names. (#623) * Add a method to list all registered span names. * Change the name to getRegisteredSpanNamesForCollection --- .../main/java/io/opencensus/trace/export/SampledSpanStore.java | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java index 32b9a80d..0d1c110c 100644 --- a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java @@ -27,6 +27,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; @@ -102,6 +103,14 @@ public abstract class SampledSpanStore { */ public abstract void unregisterSpanNamesForCollection(Collection spanNames); + /** + * Returns the set of unique span names registered to the library. For this set of span names the + * library will collect latency based sampled spans and error based sampled spans. + * + * @return the set of unique span names registered to the library. + */ + public abstract Set getRegisteredSpanNamesForCollection(); + /** The summary of all available data. */ @AutoValue @Immutable -- cgit v1.2.3 From 7782a953a5c6ea4ecfe127ae7bff053f6c2c22d5 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Sat, 16 Sep 2017 08:20:38 -0700 Subject: Implement deprecated method addAttributes in the Span and remove it from anywhere else. (#633) * Implement deprecated method addAttributes in the Span and remove it from anywhere else. * Fix tests and add warning to override putAttributes. --- api/src/main/java/io/opencensus/trace/BlankSpan.java | 5 ++--- api/src/main/java/io/opencensus/trace/Span.java | 8 +++++--- api/src/test/java/io/opencensus/trace/SpanTest.java | 6 +++--- 3 files changed, 10 insertions(+), 9 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/BlankSpan.java b/api/src/main/java/io/opencensus/trace/BlankSpan.java index b7cfb08f..fcb3e546 100644 --- a/api/src/main/java/io/opencensus/trace/BlankSpan.java +++ b/api/src/main/java/io/opencensus/trace/BlankSpan.java @@ -38,10 +38,9 @@ public final class BlankSpan extends Span { @Override public void putAttribute(String key, AttributeValue value) {} - /** No-op implementation of the {@link Span#addAttributes(Map)} method. */ + /** No-op implementation of the {@link Span#putAttributes(Map)} method. */ @Override - @SuppressWarnings("deprecation") - public void addAttributes(Map attributes) {} + public void putAttributes(Map attributes) {} /** No-op implementation of the {@link Span#addAnnotation(String, Map)} method. */ @Override diff --git a/api/src/main/java/io/opencensus/trace/Span.java b/api/src/main/java/io/opencensus/trace/Span.java index 20a859e1..b58a1fde 100644 --- a/api/src/main/java/io/opencensus/trace/Span.java +++ b/api/src/main/java/io/opencensus/trace/Span.java @@ -87,7 +87,7 @@ public abstract class Span { // Not final because for performance reasons we want to override this in the implementation. // Also a default implementation is needed to not break the compatibility (users may extend this // for testing). - addAttributes(Collections.singletonMap(key, value)); + putAttributes(Collections.singletonMap(key, value)); } /** @@ -99,7 +99,7 @@ public abstract class Span { */ public void putAttributes(Map attributes) { // Not final because we want to start overriding this method from the beginning, this will - // allow us to remove the addAttributes faster. + // allow us to remove the addAttributes faster. All implementations MUST override this method. addAttributes(attributes); } @@ -109,7 +109,9 @@ public abstract class Span { * @param attributes the attributes that will be added and associated with the {@code Span}. */ @Deprecated - public abstract void addAttributes(Map attributes); + public void addAttributes(Map attributes) { + putAttributes(attributes); + } /** * Adds an annotation to the {@code Span}. diff --git a/api/src/test/java/io/opencensus/trace/SpanTest.java b/api/src/test/java/io/opencensus/trace/SpanTest.java index 5d36bb14..60c58b6a 100644 --- a/api/src/test/java/io/opencensus/trace/SpanTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanTest.java @@ -84,12 +84,12 @@ public class SpanTest { } @Test - public void addAttributeCallsAddAttributesByDefault() { + public void putAttributeCallsAddAttributesByDefault() { Span span = Mockito.spy(new NoopSpan(spanContext, spanOptions)); span.putAttribute("MyKey", AttributeValue.booleanAttributeValue(true)); span.end(); verify(span) - .addAttributes( + .putAttributes( eq(Collections.singletonMap("MyKey", AttributeValue.booleanAttributeValue(true)))); } @@ -107,7 +107,7 @@ public class SpanTest { } @Override - public void addAttributes(Map attributes) {} + public void putAttributes(Map attributes) {} @Override public void addAnnotation(String description, Map attributes) {} -- cgit v1.2.3 From 53cb6c8bec4540c66c4cbd22535797a76fef921a Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Mon, 18 Sep 2017 11:33:49 -0700 Subject: Add a new SpanContextParseException and use it in BinaryFormat. (#642) * Add a new SpanContextParseException and use it in BinaryFormat * Fix review comments. --- .../opencensus/trace/propagation/BinaryFormat.java | 57 ++++++++++++++++++---- .../propagation/SpanContextParseException.java | 41 ++++++++++++++++ .../trace/propagation/BinaryFormatTest.java | 23 ++++++++- .../propagation/SpanContextParseExceptionTest.java | 42 ++++++++++++++++ 4 files changed, 151 insertions(+), 12 deletions(-) create mode 100644 api/src/main/java/io/opencensus/trace/propagation/SpanContextParseException.java create mode 100644 api/src/test/java/io/opencensus/trace/propagation/SpanContextParseExceptionTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java b/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java index 47090036..f9c59142 100644 --- a/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java +++ b/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java @@ -32,7 +32,7 @@ import java.text.ParseException; * Tracing.getPropagationComponent().getBinaryFormat(); * void onSendRequest() { * try (Scope ss = tracer.spanBuilder("Sent.MyRequest").startScopedSpan()) { - * byte[] binaryValue = binaryFormat.toBinaryValue(tracer.getCurrentContext().context()); + * byte[] binaryValue = binaryFormat.toByteArray(tracer.getCurrentContext().context()); * // Send the request including the binaryValue and wait for the response. * } * } @@ -49,9 +49,9 @@ import java.text.ParseException; * SpanContext spanContext = SpanContext.INVALID; * try { * if (binaryValue != null) { - * spanContext = binaryFormat.fromBinaryValue(binaryValue); + * spanContext = binaryFormat.fromByteArray(binaryValue); * } - * } catch (ParseException e) { + * } catch (SpanContextParseException e) { * // Maybe log the exception. * } * try (Scope ss = @@ -65,23 +65,60 @@ public abstract class BinaryFormat { static final NoopBinaryFormat NOOP_BINARY_FORMAT = new NoopBinaryFormat(); /** - * Serializes a {@link SpanContext} using the binary format. - * + * @deprecated use {@link #toByteArray(SpanContext)}. * @param spanContext the {@code SpanContext} to serialize. * @return the serialized binary value. * @throws NullPointerException if the {@code spanContext} is {@code null}. */ - public abstract byte[] toBinaryValue(SpanContext spanContext); + @Deprecated + public byte[] toBinaryValue(SpanContext spanContext) { + return toByteArray(spanContext); + } /** - * Parses the {@link SpanContext} from the binary format. + * Serializes a {@link SpanContext} into a byte array using the binary format. * + * @param spanContext the {@code SpanContext} to serialize. + * @return the serialized binary value. + * @throws NullPointerException if the {@code spanContext} is {@code null}. + */ + public byte[] toByteArray(SpanContext spanContext) { + // Implementation must override this method. + return toBinaryValue(spanContext); + } + + /** + * @deprecated use {@link #fromByteArray(byte[])}. * @param bytes a binary encoded buffer from which the {@code SpanContext} will be parsed. * @return the parsed {@code SpanContext}. * @throws NullPointerException if the {@code input} is {@code null}. * @throws ParseException if the version is not supported or the input is invalid */ - public abstract SpanContext fromBinaryValue(byte[] bytes) throws ParseException; + @Deprecated + public SpanContext fromBinaryValue(byte[] bytes) throws ParseException { + try { + return fromByteArray(bytes); + } catch (SpanContextParseException e) { + throw new ParseException(e.toString(), 0); + } + } + + /** + * Parses the {@link SpanContext} from a byte array using the binary format. + * + * @param bytes a binary encoded buffer from which the {@code SpanContext} will be parsed. + * @return the parsed {@code SpanContext}. + * @throws NullPointerException if the {@code input} is {@code null}. + * @throws SpanContextParseException if the version is not supported or the input is invalid + */ + public SpanContext fromByteArray(byte[] bytes) throws SpanContextParseException { + // Implementation must override this method. + try { + return fromBinaryValue(bytes); + } catch (ParseException e) { + throw new SpanContextParseException("Error while parsing.", e); + } + } /** * Returns the no-op implementation of the {@code BinaryFormat}. @@ -94,13 +131,13 @@ public abstract class BinaryFormat { private static final class NoopBinaryFormat extends BinaryFormat { @Override - public byte[] toBinaryValue(SpanContext spanContext) { + public byte[] toByteArray(SpanContext spanContext) { checkNotNull(spanContext, "spanContext"); return new byte[0]; } @Override - public SpanContext fromBinaryValue(byte[] bytes) throws ParseException { + public SpanContext fromByteArray(byte[] bytes) { checkNotNull(bytes, "bytes"); return SpanContext.INVALID; } diff --git a/api/src/main/java/io/opencensus/trace/propagation/SpanContextParseException.java b/api/src/main/java/io/opencensus/trace/propagation/SpanContextParseException.java new file mode 100644 index 00000000..fa7f2d4e --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/propagation/SpanContextParseException.java @@ -0,0 +1,41 @@ +/* + * 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; + +/** Exception thrown when a {@link io.opencensus.trace.SpanContext} cannot be parsed. */ +public final class SpanContextParseException extends Exception { + private static final long serialVersionUID = 0L; + + /** + * Constructs a new {@code SpanContextParseException} with the given message. + * + * @param message a message describing the parse error. + */ + public SpanContextParseException(String message) { + super(message); + } + + /** + * Constructs a new {@code SpanContextParseException} with the given message and cause. + * + * @param message a message describing the parse error. + * @param cause the cause of the parse error. + */ + public SpanContextParseException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/api/src/test/java/io/opencensus/trace/propagation/BinaryFormatTest.java b/api/src/test/java/io/opencensus/trace/propagation/BinaryFormatTest.java index 4cb11938..64544ffe 100644 --- a/api/src/test/java/io/opencensus/trace/propagation/BinaryFormatTest.java +++ b/api/src/test/java/io/opencensus/trace/propagation/BinaryFormatTest.java @@ -27,8 +27,7 @@ import org.junit.runners.JUnit4; /** Unit tests for {@link BinaryFormat}. */ @RunWith(JUnit4.class) public class BinaryFormatTest { - private static final BinaryFormat binaryFormat = - BinaryFormat.getNoopBinaryFormat(); + private static final BinaryFormat binaryFormat = BinaryFormat.getNoopBinaryFormat(); @Test(expected = NullPointerException.class) public void toBinaryValue_NullSpanContext() { @@ -40,6 +39,16 @@ public class BinaryFormatTest { assertThat(binaryFormat.toBinaryValue(SpanContext.INVALID)).isEqualTo(new byte[0]); } + @Test(expected = NullPointerException.class) + public void toByteArray_NullSpanContext() { + binaryFormat.toByteArray(null); + } + + @Test + public void toByteArray_NotNullSpanContext() { + assertThat(binaryFormat.toByteArray(SpanContext.INVALID)).isEqualTo(new byte[0]); + } + @Test(expected = NullPointerException.class) public void fromBinaryValue_NullInput() throws ParseException { binaryFormat.fromBinaryValue(null); @@ -49,4 +58,14 @@ public class BinaryFormatTest { public void fromBinaryValue_NotNullInput() throws ParseException { assertThat(binaryFormat.fromBinaryValue(new byte[0])).isEqualTo(SpanContext.INVALID); } + + @Test(expected = NullPointerException.class) + public void fromByteArray_NullInput() throws SpanContextParseException { + binaryFormat.fromByteArray(null); + } + + @Test + public void fromByteArray_NotNullInput() throws SpanContextParseException { + assertThat(binaryFormat.fromByteArray(new byte[0])).isEqualTo(SpanContext.INVALID); + } } diff --git a/api/src/test/java/io/opencensus/trace/propagation/SpanContextParseExceptionTest.java b/api/src/test/java/io/opencensus/trace/propagation/SpanContextParseExceptionTest.java new file mode 100644 index 00000000..92efb35d --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/propagation/SpanContextParseExceptionTest.java @@ -0,0 +1,42 @@ +/* + * 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 java.io.IOException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link SpanContextParseException}. */ +@RunWith(JUnit4.class) +public class SpanContextParseExceptionTest { + + @Test + public void createWithMessage() { + assertThat(new SpanContextParseException("my message").getMessage()).isEqualTo("my message"); + } + + @Test + public void createWithMessageAndCause() { + IOException cause = new IOException(); + SpanContextParseException parseException = new SpanContextParseException("my message", cause); + assertThat(parseException.getMessage()).isEqualTo("my message"); + assertThat(parseException.getCause()).isEqualTo(cause); + } +} -- cgit v1.2.3 From 586e0e2ed0896f8aacb1251d3026ddf4f9f711ac Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Mon, 18 Sep 2017 15:03:25 -0700 Subject: Move current TagContext logic from the API to the implementation (closes #632). This commit makes all methods in Tagger and TagContextBuilder abstract. It also changes the no-op Tagger and TagContextBuilder so that they do not access the current context. This change gives the implementation more flexibility to control when it accesses the current context. For example, it could avoid setting the current context when tagging is not enabled. It also simplifies the code by not splitting the current context logic between the API and implementation classes. --- .../java/io/opencensus/internal/NoopScope.java | 37 ++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 api/src/main/java/io/opencensus/internal/NoopScope.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/NoopScope.java b/api/src/main/java/io/opencensus/internal/NoopScope.java new file mode 100644 index 00000000..a3521939 --- /dev/null +++ b/api/src/main/java/io/opencensus/internal/NoopScope.java @@ -0,0 +1,37 @@ +/* + * 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.internal; + +import io.opencensus.common.Scope; + +public final class NoopScope implements Scope { + private static final Scope INSTANCE = new NoopScope(); + + private NoopScope() {} + + /** + * Returns a {@code NoopScope}. + * + * @return a {@code NoopScope}. + */ + public static Scope getInstance() { + return INSTANCE; + } + + @Override + public void close() {} +} -- cgit v1.2.3 From cb041e8408f67fa0e91a09ffe22e1297fcea8258 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Wed, 20 Sep 2017 11:21:58 -0700 Subject: Add Javadoc to NoopScope. --- api/src/main/java/io/opencensus/internal/NoopScope.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/NoopScope.java b/api/src/main/java/io/opencensus/internal/NoopScope.java index a3521939..d65d2d80 100644 --- a/api/src/main/java/io/opencensus/internal/NoopScope.java +++ b/api/src/main/java/io/opencensus/internal/NoopScope.java @@ -18,6 +18,9 @@ package io.opencensus.internal; import io.opencensus.common.Scope; +/** + * A {@link Scope} that does nothing when it is closed. + */ public final class NoopScope implements Scope { private static final Scope INSTANCE = new NoopScope(); -- cgit v1.2.3 From 672ab4eaaec365bafd5d9bd25895e0bd3ad9fda4 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Wed, 20 Sep 2017 12:57:10 -0700 Subject: Clarify NoopScope Javadoc. --- api/src/main/java/io/opencensus/internal/NoopScope.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/NoopScope.java b/api/src/main/java/io/opencensus/internal/NoopScope.java index d65d2d80..1edac98e 100644 --- a/api/src/main/java/io/opencensus/internal/NoopScope.java +++ b/api/src/main/java/io/opencensus/internal/NoopScope.java @@ -19,7 +19,7 @@ package io.opencensus.internal; import io.opencensus.common.Scope; /** - * A {@link Scope} that does nothing when it is closed. + * A {@link Scope} that does nothing when it is created or closed. */ public final class NoopScope implements Scope { private static final Scope INSTANCE = new NoopScope(); -- cgit v1.2.3 From 83fed9c3af641b227496ce96f9cc0b51b316df82 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Thu, 21 Sep 2017 19:39:25 -0700 Subject: Change when we check the sampler. (#657) * Change when we check the sampler. * Fix comments. * Deprecate setIsSampled without an argument. --- .../java/io/opencensus/trace/TraceOptions.java | 20 ++++++-- .../trace/samplers/ProbabilitySampler.java | 4 -- .../java/io/opencensus/trace/SpanContextTest.java | 15 ++++-- .../test/java/io/opencensus/trace/SpanTest.java | 2 +- .../java/io/opencensus/trace/TraceOptionsTest.java | 14 ++++-- .../io/opencensus/trace/samplers/SamplersTest.java | 53 ++++++++-------------- 6 files changed, 55 insertions(+), 53 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/TraceOptions.java b/api/src/main/java/io/opencensus/trace/TraceOptions.java index 8241d4f9..35181e28 100644 --- a/api/src/main/java/io/opencensus/trace/TraceOptions.java +++ b/api/src/main/java/io/opencensus/trace/TraceOptions.java @@ -182,12 +182,26 @@ public final class TraceOptions { } /** - * Marks this trace as sampled. - * + * @deprecated Use {@code Builder.setIsSampled(true)}. * @return this. */ + @Deprecated public Builder setIsSampled() { - options |= IS_SAMPLED; + return setIsSampled(true); + } + + /** + * Sets the sampling bit in the options. + * + * @param isSampled the sampling bit. + * @return this. + */ + public Builder setIsSampled(boolean isSampled) { + if (isSampled) { + options = (byte) (options | IS_SAMPLED); + } else { + options = (byte) (options & ~IS_SAMPLED);; + } return this; } diff --git a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java index 251454ab..ea02a80d 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java +++ b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java @@ -79,10 +79,6 @@ abstract class ProbabilitySampler extends Sampler { SpanId spanId, String name, @Nullable List parentLinks) { - // Always enable sampling if parent was sampled. - if (parentContext != null && parentContext.getTraceOptions().isSampled()) { - return true; - } // Always sample if we are within probability range. This is true even for child spans (that // may have had a different sampling decision made) to allow for different sampling policies, // and dynamic increases to sampling probabilities for debugging purposes. diff --git a/api/src/test/java/io/opencensus/trace/SpanContextTest.java b/api/src/test/java/io/opencensus/trace/SpanContextTest.java index c211d513..f5a9954f 100644 --- a/api/src/test/java/io/opencensus/trace/SpanContextTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanContextTest.java @@ -41,7 +41,7 @@ public class SpanContextTest { SpanContext.create( TraceId.fromBytes(secondTraceIdBytes), SpanId.fromBytes(secondSpanIdBytes), - TraceOptions.builder().setIsSampled().build()); + TraceOptions.builder().setIsSampled(true).build()); @Test public void invalidSpanContext() { @@ -82,7 +82,8 @@ public class SpanContextTest { @Test public void getTraceOptions() { assertThat(first.getTraceOptions()).isEqualTo(TraceOptions.DEFAULT); - assertThat(second.getTraceOptions()).isEqualTo(TraceOptions.builder().setIsSampled().build()); + assertThat(second.getTraceOptions()) + .isEqualTo(TraceOptions.builder().setIsSampled(true).build()); } @Test @@ -93,13 +94,17 @@ public class SpanContextTest { SpanContext.create( TraceId.fromBytes(firstTraceIdBytes), SpanId.fromBytes(firstSpanIdBytes), - TraceOptions.DEFAULT)); + TraceOptions.DEFAULT), + SpanContext.create( + TraceId.fromBytes(firstTraceIdBytes), + SpanId.fromBytes(firstSpanIdBytes), + TraceOptions.builder().setIsSampled(false).build())); tester.addEqualityGroup( second, SpanContext.create( TraceId.fromBytes(secondTraceIdBytes), SpanId.fromBytes(secondSpanIdBytes), - TraceOptions.builder().setIsSampled().build())); + TraceOptions.builder().setIsSampled(true).build())); tester.testEquals(); } @@ -111,6 +116,6 @@ public class SpanContextTest { assertThat(second.toString()).contains(TraceId.fromBytes(secondTraceIdBytes).toString()); assertThat(second.toString()).contains(SpanId.fromBytes(secondSpanIdBytes).toString()); assertThat(second.toString()) - .contains(TraceOptions.builder().setIsSampled().build().toString()); + .contains(TraceOptions.builder().setIsSampled(true).build().toString()); } } diff --git a/api/src/test/java/io/opencensus/trace/SpanTest.java b/api/src/test/java/io/opencensus/trace/SpanTest.java index 60c58b6a..1e05e60f 100644 --- a/api/src/test/java/io/opencensus/trace/SpanTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanTest.java @@ -46,7 +46,7 @@ public class SpanTest { SpanContext.create( TraceId.generateRandomId(random), SpanId.generateRandomId(random), - TraceOptions.builder().setIsSampled().build()); + TraceOptions.builder().setIsSampled(true).build()); notSampledSpanContext = SpanContext.create( TraceId.generateRandomId(random), diff --git a/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java b/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java index 7d0019b0..a892384b 100644 --- a/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java +++ b/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java @@ -33,7 +33,10 @@ public class TraceOptionsTest { @Test public void getOptions() { assertThat(TraceOptions.DEFAULT.getOptions()).isEqualTo(0); - assertThat(TraceOptions.builder().setIsSampled().build().getOptions()).isEqualTo(1); + assertThat(TraceOptions.builder().setIsSampled(false).build().getOptions()).isEqualTo(0); + assertThat(TraceOptions.builder().setIsSampled(true).build().getOptions()).isEqualTo(1); + assertThat(TraceOptions.builder().setIsSampled(true).setIsSampled(false).build().getOptions()) + .isEqualTo(0); assertThat(TraceOptions.fromBytes(firstBytes).getOptions()).isEqualTo(-1); assertThat(TraceOptions.fromBytes(secondBytes).getOptions()).isEqualTo(1); assertThat(TraceOptions.fromBytes(thirdBytes).getOptions()).isEqualTo(6); @@ -42,7 +45,7 @@ public class TraceOptionsTest { @Test public void isSampled() { assertThat(TraceOptions.DEFAULT.isSampled()).isFalse(); - assertThat(TraceOptions.builder().setIsSampled().build().isSampled()).isTrue(); + assertThat(TraceOptions.builder().setIsSampled(true).build().isSampled()).isTrue(); } @Test @@ -56,7 +59,7 @@ public class TraceOptionsTest { public void builder_FromOptions() { assertThat( TraceOptions.builder(TraceOptions.fromBytes(thirdBytes)) - .setIsSampled() + .setIsSampled(true) .build() .getOptions()) .isEqualTo(6 | 1); @@ -67,7 +70,7 @@ public class TraceOptionsTest { EqualsTester tester = new EqualsTester(); tester.addEqualityGroup(TraceOptions.DEFAULT); tester.addEqualityGroup( - TraceOptions.fromBytes(secondBytes), TraceOptions.builder().setIsSampled().build()); + TraceOptions.fromBytes(secondBytes), TraceOptions.builder().setIsSampled(true).build()); tester.addEqualityGroup(TraceOptions.fromBytes(firstBytes)); tester.testEquals(); } @@ -75,6 +78,7 @@ public class TraceOptionsTest { @Test public void traceOptions_ToString() { assertThat(TraceOptions.DEFAULT.toString()).contains("sampled=false"); - assertThat(TraceOptions.builder().setIsSampled().build().toString()).contains("sampled=true"); + assertThat(TraceOptions.builder().setIsSampled(true).build().toString()) + .contains("sampled=true"); } } diff --git a/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java b/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java index a9e79cc6..0999e8f8 100644 --- a/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java +++ b/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java @@ -33,12 +33,14 @@ import org.junit.runners.JUnit4; /** Unit tests for {@link Samplers}. */ @RunWith(JUnit4.class) public class SamplersTest { + private static final String SPAN_NAME = "MySpanName"; + private static final int NUM_SAMPLE_TRIES = 1000; private final Random random = new Random(1234); private final TraceId traceId = TraceId.generateRandomId(random); private final SpanId parentSpanId = SpanId.generateRandomId(random); private final SpanId spanId = SpanId.generateRandomId(random); private final SpanContext sampledSpanContext = - SpanContext.create(traceId, parentSpanId, TraceOptions.builder().setIsSampled().build()); + SpanContext.create(traceId, parentSpanId, TraceOptions.builder().setIsSampled(true).build()); private final SpanContext notSampledSpanContext = SpanContext.create(traceId, parentSpanId, TraceOptions.DEFAULT); @@ -114,59 +116,40 @@ public class SamplersTest { Samplers.probabilitySampler(-0.00001); } - private final void probabilitySampler_AlwaysReturnTrueForSampled(Sampler sampler) { - final int numSamples = 100; // Number of traces for which to generate sampling decisions. - for (int i = 0; i < numSamples; i++) { - assertThat( - sampler.shouldSample( - sampledSpanContext, - false, - TraceId.generateRandomId(random), - spanId, - "bar", - Collections.emptyList())) - .isTrue(); - } - } - - private final void probabilitySampler_SamplesWithProbabilityForUnsampled( - Sampler sampler, double probability) { - final int numSamples = 1000; // Number of traces for which to generate sampling decisions. + // Applies the given sampler to NUM_SAMPLE_TRIES random traceId/spanId pairs. + private static void assertSamplerSamplesWithProbability( + Sampler sampler, SpanContext parent, double probability) { + Random random = new Random(1234); int count = 0; // Count of spans with sampling enabled - for (int i = 0; i < numSamples; i++) { + for (int i = 0; i < NUM_SAMPLE_TRIES; i++) { if (sampler.shouldSample( - notSampledSpanContext, + parent, false, TraceId.generateRandomId(random), - spanId, - "bar", + SpanId.generateRandomId(random), + SPAN_NAME, Collections.emptyList())) { count++; } } - double proportionSampled = (double) count / numSamples; + double proportionSampled = (double) count / NUM_SAMPLE_TRIES; // Allow for a large amount of slop (+/- 10%) in number of sampled traces, to avoid flakiness. assertThat(proportionSampled < probability + 0.1 && proportionSampled > probability - 0.1) .isTrue(); } @Test - public void probabilitySamper_SamplesWithProbability() { + public void probabilitySampler_differentProbabilities() { final Sampler neverSample = Samplers.probabilitySampler(0.0); - probabilitySampler_AlwaysReturnTrueForSampled(neverSample); - probabilitySampler_SamplesWithProbabilityForUnsampled(neverSample, 0.0); + assertSamplerSamplesWithProbability(neverSample, sampledSpanContext, 0.0); final Sampler alwaysSample = Samplers.probabilitySampler(1.0); - probabilitySampler_AlwaysReturnTrueForSampled(alwaysSample); - probabilitySampler_SamplesWithProbabilityForUnsampled(alwaysSample, 1.0); + assertSamplerSamplesWithProbability(alwaysSample, sampledSpanContext, 1.0); final Sampler fiftyPercentSample = Samplers.probabilitySampler(0.5); - probabilitySampler_AlwaysReturnTrueForSampled(fiftyPercentSample); - probabilitySampler_SamplesWithProbabilityForUnsampled(fiftyPercentSample, 0.5); + assertSamplerSamplesWithProbability(fiftyPercentSample, sampledSpanContext, 0.5); final Sampler twentyPercentSample = Samplers.probabilitySampler(0.2); - probabilitySampler_AlwaysReturnTrueForSampled(twentyPercentSample); - probabilitySampler_SamplesWithProbabilityForUnsampled(twentyPercentSample, 0.2); + assertSamplerSamplesWithProbability(twentyPercentSample, sampledSpanContext, 0.2); final Sampler twoThirdsSample = Samplers.probabilitySampler(2.0 / 3.0); - probabilitySampler_AlwaysReturnTrueForSampled(twoThirdsSample); - probabilitySampler_SamplesWithProbabilityForUnsampled(twoThirdsSample, 2.0 / 3.0); + assertSamplerSamplesWithProbability(twoThirdsSample, sampledSpanContext, 2.0 / 3.0); } @Test -- cgit v1.2.3 From 23d498078cf3acd028f5917822be8560cc13df28 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Fri, 22 Sep 2017 14:08:46 -0700 Subject: Fix probability sampler and sampling. (#661) * Fix probability sampler and sampling. * Add more tests and fix comments. --- .../trace/samplers/ProbabilitySampler.java | 12 +- .../test/java/io/opencensus/trace/NoopSpan.java | 52 ++++++++ .../test/java/io/opencensus/trace/SpanTest.java | 26 ---- .../io/opencensus/trace/samplers/SamplersTest.java | 138 +++++++++++++++++++-- 4 files changed, 193 insertions(+), 35 deletions(-) create mode 100644 api/src/test/java/io/opencensus/trace/NoopSpan.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java index ea02a80d..d6247344 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java +++ b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java @@ -56,7 +56,7 @@ abstract class ProbabilitySampler extends Sampler { static ProbabilitySampler create(double probability) { checkArgument( probability >= 0.0 && probability <= 1.0, "probability must be in range [0.0, 1.0]"); - long idUpperBound = 0; + long idUpperBound; // Special case the limits, to avoid any possible issues with lack of precision across // double/long boundaries. For probability == 0.0, we use Long.MIN_VALUE as this guarantees // that we will never sample a trace, even in the case where the id == Long.MIN_VALUE, since @@ -79,6 +79,16 @@ abstract class ProbabilitySampler extends Sampler { SpanId spanId, String name, @Nullable List parentLinks) { + // If the parent is sampled keep the sampling decision. + if (parentContext != null && parentContext.getTraceOptions().isSampled()) { + return true; + } + // If any parent link is sampled keep the sampling decision. + for (Span parentLink : parentLinks) { + if (parentLink.getContext().getTraceOptions().isSampled()) { + return true; + } + } // Always sample if we are within probability range. This is true even for child spans (that // may have had a different sampling decision made) to allow for different sampling policies, // and dynamic increases to sampling probabilities for debugging purposes. diff --git a/api/src/test/java/io/opencensus/trace/NoopSpan.java b/api/src/test/java/io/opencensus/trace/NoopSpan.java new file mode 100644 index 00000000..0217529d --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/NoopSpan.java @@ -0,0 +1,52 @@ +/* + * 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; + +import java.util.EnumSet; +import java.util.Map; +import javax.annotation.Nullable; + +/** + * Class to be used in tests where an implementation for the Span is needed. + * + *

Not final to allow Mockito to "spy" this class. + */ +public class NoopSpan extends Span { + + /** Creates a new {@code NoopSpan}. */ + public NoopSpan(SpanContext context, @Nullable EnumSet options) { + super(context, options); + } + + @Override + public void putAttributes(Map attributes) {} + + @Override + public void addAnnotation(String description, Map attributes) {} + + @Override + public void addAnnotation(Annotation annotation) {} + + @Override + public void addNetworkEvent(NetworkEvent networkEvent) {} + + @Override + public void addLink(Link link) {} + + @Override + public void end(EndSpanOptions options) {} +} diff --git a/api/src/test/java/io/opencensus/trace/SpanTest.java b/api/src/test/java/io/opencensus/trace/SpanTest.java index 1e05e60f..327b9abe 100644 --- a/api/src/test/java/io/opencensus/trace/SpanTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanTest.java @@ -23,7 +23,6 @@ import static org.mockito.Mockito.verify; import java.util.Collections; import java.util.EnumSet; -import java.util.Map; import java.util.Random; import org.junit.Before; import org.junit.Test; @@ -99,29 +98,4 @@ public class SpanTest { span.end(); verify(span).end(same(EndSpanOptions.DEFAULT)); } - - // No-op implementation of the Span for testing only. - private static class NoopSpan extends Span { - private NoopSpan(SpanContext context, EnumSet options) { - super(context, options); - } - - @Override - public void putAttributes(Map attributes) {} - - @Override - public void addAnnotation(String description, Map attributes) {} - - @Override - public void addAnnotation(Annotation annotation) {} - - @Override - public void addNetworkEvent(NetworkEvent networkEvent) {} - - @Override - public void addLink(Link link) {} - - @Override - public void end(EndSpanOptions options) {} - } } diff --git a/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java b/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java index 0999e8f8..6cb41975 100644 --- a/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java +++ b/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java @@ -18,13 +18,17 @@ package io.opencensus.trace.samplers; import static com.google.common.truth.Truth.assertThat; +import io.opencensus.trace.NoopSpan; import io.opencensus.trace.Sampler; import io.opencensus.trace.Span; import io.opencensus.trace.SpanContext; import io.opencensus.trace.SpanId; import io.opencensus.trace.TraceId; import io.opencensus.trace.TraceOptions; +import java.util.Arrays; import java.util.Collections; +import java.util.EnumSet; +import java.util.List; import java.util.Random; import org.junit.Test; import org.junit.runner.RunWith; @@ -43,6 +47,8 @@ public class SamplersTest { SpanContext.create(traceId, parentSpanId, TraceOptions.builder().setIsSampled(true).build()); private final SpanContext notSampledSpanContext = SpanContext.create(traceId, parentSpanId, TraceOptions.DEFAULT); + private final Span sampledSpan = + new NoopSpan(sampledSpanContext, EnumSet.of(Span.Options.RECORD_EVENTS)); @Test public void alwaysSampleSampler_AlwaysReturnTrue() { @@ -118,7 +124,7 @@ public class SamplersTest { // Applies the given sampler to NUM_SAMPLE_TRIES random traceId/spanId pairs. private static void assertSamplerSamplesWithProbability( - Sampler sampler, SpanContext parent, double probability) { + Sampler sampler, SpanContext parent, List parentLinks, double probability) { Random random = new Random(1234); int count = 0; // Count of spans with sampling enabled for (int i = 0; i < NUM_SAMPLE_TRIES; i++) { @@ -128,7 +134,7 @@ public class SamplersTest { TraceId.generateRandomId(random), SpanId.generateRandomId(random), SPAN_NAME, - Collections.emptyList())) { + parentLinks)) { count++; } } @@ -139,17 +145,133 @@ public class SamplersTest { } @Test - public void probabilitySampler_differentProbabilities() { + public void probabilitySampler_DifferentProbabilities_NotSampledParent() { final Sampler neverSample = Samplers.probabilitySampler(0.0); - assertSamplerSamplesWithProbability(neverSample, sampledSpanContext, 0.0); + assertSamplerSamplesWithProbability( + neverSample, notSampledSpanContext, Collections.emptyList(), 0.0); final Sampler alwaysSample = Samplers.probabilitySampler(1.0); - assertSamplerSamplesWithProbability(alwaysSample, sampledSpanContext, 1.0); + assertSamplerSamplesWithProbability( + alwaysSample, notSampledSpanContext, Collections.emptyList(), 1.0); final Sampler fiftyPercentSample = Samplers.probabilitySampler(0.5); - assertSamplerSamplesWithProbability(fiftyPercentSample, sampledSpanContext, 0.5); + assertSamplerSamplesWithProbability( + fiftyPercentSample, notSampledSpanContext, Collections.emptyList(), 0.5); final Sampler twentyPercentSample = Samplers.probabilitySampler(0.2); - assertSamplerSamplesWithProbability(twentyPercentSample, sampledSpanContext, 0.2); + assertSamplerSamplesWithProbability( + twentyPercentSample, notSampledSpanContext, Collections.emptyList(), 0.2); final Sampler twoThirdsSample = Samplers.probabilitySampler(2.0 / 3.0); - assertSamplerSamplesWithProbability(twoThirdsSample, sampledSpanContext, 2.0 / 3.0); + assertSamplerSamplesWithProbability( + twoThirdsSample, notSampledSpanContext, Collections.emptyList(), 2.0 / 3.0); + } + + @Test + public void probabilitySampler_DifferentProbabilities_SampledParent() { + final Sampler neverSample = Samplers.probabilitySampler(0.0); + assertSamplerSamplesWithProbability( + neverSample, sampledSpanContext, Collections.emptyList(), 1.0); + final Sampler alwaysSample = Samplers.probabilitySampler(1.0); + assertSamplerSamplesWithProbability( + alwaysSample, sampledSpanContext, Collections.emptyList(), 1.0); + final Sampler fiftyPercentSample = Samplers.probabilitySampler(0.5); + assertSamplerSamplesWithProbability( + fiftyPercentSample, sampledSpanContext, Collections.emptyList(), 1.0); + final Sampler twentyPercentSample = Samplers.probabilitySampler(0.2); + assertSamplerSamplesWithProbability( + twentyPercentSample, sampledSpanContext, Collections.emptyList(), 1.0); + final Sampler twoThirdsSample = Samplers.probabilitySampler(2.0 / 3.0); + assertSamplerSamplesWithProbability( + twoThirdsSample, sampledSpanContext, Collections.emptyList(), 1.0); + } + + @Test + public void probabilitySampler_DifferentProbabilities_SampledParentLink() { + final Sampler neverSample = Samplers.probabilitySampler(0.0); + assertSamplerSamplesWithProbability( + neverSample, notSampledSpanContext, Arrays.asList(sampledSpan), 1.0); + final Sampler alwaysSample = Samplers.probabilitySampler(1.0); + assertSamplerSamplesWithProbability( + alwaysSample, notSampledSpanContext, Arrays.asList(sampledSpan), 1.0); + final Sampler fiftyPercentSample = Samplers.probabilitySampler(0.5); + assertSamplerSamplesWithProbability( + fiftyPercentSample, notSampledSpanContext, Arrays.asList(sampledSpan), 1.0); + final Sampler twentyPercentSample = Samplers.probabilitySampler(0.2); + assertSamplerSamplesWithProbability( + twentyPercentSample, notSampledSpanContext, Arrays.asList(sampledSpan), 1.0); + final Sampler twoThirdsSample = Samplers.probabilitySampler(2.0 / 3.0); + assertSamplerSamplesWithProbability( + twoThirdsSample, notSampledSpanContext, Arrays.asList(sampledSpan), 1.0); + } + + @Test + public void probabilitySampler_SampleBasedOnTraceId() { + final Sampler defaultProbability = Samplers.probabilitySampler(0.0001); + // This traceId will not be sampled by the ProbabilitySampler because the first 8 bytes as long + // is not less than probability * Long.MAX_VALUE; + TraceId notSampledtraceId = + TraceId.fromBytes( + new byte[] { + (byte) 0x8F, + (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }); + assertThat( + defaultProbability.shouldSample( + null, + false, + notSampledtraceId, + SpanId.generateRandomId(random), + SPAN_NAME, + Collections.emptyList())) + .isFalse(); + // This traceId will be sampled by the ProbabilitySampler because the first 8 bytes as long + // is less than probability * Long.MAX_VALUE; + TraceId sampledtraceId = + TraceId.fromBytes( + new byte[] { + (byte) 0x00, + (byte) 0x00, + (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }); + assertThat( + defaultProbability.shouldSample( + null, + false, + sampledtraceId, + SpanId.generateRandomId(random), + SPAN_NAME, + Collections.emptyList())) + .isTrue(); + } + + @Test + public void probabilitySampler_getDescription() { + assertThat((Samplers.probabilitySampler(0.5)).getDescription()) + .isEqualTo("ProbabilitySampler{0.500000}"); } @Test -- cgit v1.2.3 From 802d0cde2a8a087490bb41cc618130453fcfa536 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Wed, 27 Sep 2017 16:52:42 -0700 Subject: Clean up io.opencensus.internal.StringUtil. We don't need StringUtil.sanitize, since we no longer sanitize tags. Additionally, we don't need to throw an AssertionError from the constructor to discourage instantiation of the class, because the class is now in the internal package. --- .../java/io/opencensus/internal/StringUtil.java | 32 +--------------------- .../io/opencensus/internal/StringUtilTest.java | 23 ++++------------ 2 files changed, 6 insertions(+), 49 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/StringUtil.java b/api/src/main/java/io/opencensus/internal/StringUtil.java index 6f9ff807..70f5299e 100644 --- a/api/src/main/java/io/opencensus/internal/StringUtil.java +++ b/api/src/main/java/io/opencensus/internal/StringUtil.java @@ -19,33 +19,6 @@ package io.opencensus.internal; /** Internal utility methods for working with tag keys, tag values, and metric names. */ public final class StringUtil { - public static final int MAX_LENGTH = 255; - public static final char UNPRINTABLE_CHAR_SUBSTITUTE = '_'; - - /** - * Transforms the given {@code String} into a valid tag key, tag value, or metric name. This - * method replaces non-printable characters with underscores and truncates to {@link - * StringUtil#MAX_LENGTH}. - * - * @param str the {@code String} to be sanitized. - * @return the {@code String} with all non-printable characters replaced by underscores, truncated - * to {@code MAX_LENGTH}. - */ - public static String sanitize(String str) { - if (str.length() > MAX_LENGTH) { - str = str.substring(0, MAX_LENGTH); - } - if (isPrintableString(str)) { - return str; - } - StringBuilder builder = new StringBuilder(str.length()); - for (int i = 0; i < str.length(); i++) { - char ch = str.charAt(i); - builder.append(isPrintableChar(ch) ? ch : UNPRINTABLE_CHAR_SUBSTITUTE); - } - return builder.toString(); - } - /** * Determines whether the {@code String} contains only printable characters. * @@ -65,8 +38,5 @@ public final class StringUtil { return ch >= ' ' && ch <= '~'; } - // Visible for testing - StringUtil() { - throw new AssertionError(); - } + private StringUtil() {} } diff --git a/api/src/test/java/io/opencensus/internal/StringUtilTest.java b/api/src/test/java/io/opencensus/internal/StringUtilTest.java index 790ce5f7..b5c74be0 100644 --- a/api/src/test/java/io/opencensus/internal/StringUtilTest.java +++ b/api/src/test/java/io/opencensus/internal/StringUtilTest.java @@ -16,9 +16,9 @@ package io.opencensus.internal; -import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; -import java.util.Arrays; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -26,23 +26,10 @@ import org.junit.runners.JUnit4; /** Tests for {@link StringUtil}. */ @RunWith(JUnit4.class) public final class StringUtilTest { - @Test - public void testMaxLength() { - char[] string = new char[StringUtil.MAX_LENGTH]; - char[] truncString = new char[StringUtil.MAX_LENGTH + 10]; - Arrays.fill(string, 'v'); - Arrays.fill(truncString, 'v'); - assertThat(StringUtil.sanitize(new String(truncString))).isEqualTo(new String(string)); - } @Test - public void testBadChar() { - String string = "\2ab\3cd"; - assertThat(StringUtil.sanitize(string)).isEqualTo("_ab_cd"); - } - - @Test(expected = AssertionError.class) - public void testConstructor() { - new StringUtil(); + public void isPrintableString() { + assertTrue(StringUtil.isPrintableString("abcd")); + assertFalse(StringUtil.isPrintableString("\2ab\3cd")); } } -- cgit v1.2.3 From dbff329210261a13e5a8c5ab525114cfdbfd8448 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Wed, 18 Oct 2017 11:48:22 -0700 Subject: Add an option in EndSpanOptions to register the span name for sampled store. (#703) * Add an option in SpanBuilder to register the span name for sampled store. * Change to LocalSpanStore name the SpanBuilder. * Move the option to EndSpanOptions. * Fix comments. --- .../java/io/opencensus/common/ExperimentalApi.java | 52 ++++++++++++++++++++++ .../java/io/opencensus/trace/EndSpanOptions.java | 37 ++++++++++++++- .../io/opencensus/trace/EndSpanOptionsTest.java | 8 ++++ 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 api/src/main/java/io/opencensus/common/ExperimentalApi.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/ExperimentalApi.java b/api/src/main/java/io/opencensus/common/ExperimentalApi.java new file mode 100644 index 00000000..266da4e9 --- /dev/null +++ b/api/src/main/java/io/opencensus/common/ExperimentalApi.java @@ -0,0 +1,52 @@ +/* + * 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.common; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Indicates a public API that can change at any time, and has no guarantee of API stability and + * backward-compatibility. + * + *

Usage guidelines: + *

    + *
  1. This annotation is used only on public API. Internal interfaces should not use it.
  2. + *
  3. After OpenCensus has gained API stability, this annotation can only be added to new API. + * Adding it to an existing API is considered API-breaking.
  4. + *
  5. Removing this annotation from an API gives it stable status.
  6. + *
+ */ +@Internal +@Retention(RetentionPolicy.SOURCE) +@Target({ + ElementType.ANNOTATION_TYPE, + ElementType.CONSTRUCTOR, + ElementType.FIELD, + ElementType.METHOD, + ElementType.PACKAGE, + ElementType.TYPE}) +@Documented +public @interface ExperimentalApi { + /** + * Context information such as links to discussion thread, tracking issue etc. + */ + String value() default ""; +} \ No newline at end of file diff --git a/api/src/main/java/io/opencensus/trace/EndSpanOptions.java b/api/src/main/java/io/opencensus/trace/EndSpanOptions.java index 8711517b..4323ffa8 100644 --- a/api/src/main/java/io/opencensus/trace/EndSpanOptions.java +++ b/api/src/main/java/io/opencensus/trace/EndSpanOptions.java @@ -19,6 +19,8 @@ package io.opencensus.trace; import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import java.util.Collection; import javax.annotation.concurrent.Immutable; /** @@ -37,9 +39,25 @@ public abstract class EndSpanOptions { * @return a new {@code Builder} with default options. */ public static Builder builder() { - return new AutoValue_EndSpanOptions.Builder().setStatus(Status.OK); + return new AutoValue_EndSpanOptions.Builder() + .setStatus(Status.OK) + .setSampleToLocalSpanStore(false); } + /** + * If {@code true} this is equivalent with calling the {@link + * io.opencensus.trace.export.SampledSpanStore#registerSpanNamesForCollection(Collection)} in + * advance for this span name. + * + *

It is strongly recommended to use the {@link + * io.opencensus.trace.export.SampledSpanStore#registerSpanNamesForCollection(Collection)} API + * instead. + * + * @return this. + */ + @ExperimentalApi + public abstract boolean getSampleToLocalSpanStore(); + /** * Returns the status. * @@ -60,6 +78,23 @@ public abstract class EndSpanOptions { */ public abstract Builder setStatus(Status status); + /** + * If set to {@code true} this is equivalent with calling the {@link + * io.opencensus.trace.export.SampledSpanStore#registerSpanNamesForCollection(Collection)} in + * advance for the given span name. + * + *

WARNING: setting this option to a randomly generated span name can OOM your process + * because the library will save samples for each name. + * + *

It is strongly recommended to use the {@link + * io.opencensus.trace.export.SampledSpanStore#registerSpanNamesForCollection(Collection)} API + * instead. + * + * @return this. + */ + @ExperimentalApi + public abstract Builder setSampleToLocalSpanStore(boolean sampleToLocalSpanStore); + abstract EndSpanOptions autoBuild(); // not public /** diff --git a/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java b/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java index ac5956d9..cae21064 100644 --- a/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java +++ b/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java @@ -34,6 +34,7 @@ public class EndSpanOptionsTest { @Test public void endSpanOptions_DefaultOptions() { assertThat(EndSpanOptions.DEFAULT.getStatus()).isEqualTo(Status.OK); + assertThat(EndSpanOptions.DEFAULT.getSampleToLocalSpanStore()).isFalse(); } @Test @@ -46,6 +47,13 @@ public class EndSpanOptionsTest { .isEqualTo(Status.CANCELLED.withDescription("ThisIsAnError")); } + @Test + public void setSampleToLocalSpanStore() { + EndSpanOptions endSpanOptions = + EndSpanOptions.builder().setSampleToLocalSpanStore(true).build(); + assertThat(endSpanOptions.getSampleToLocalSpanStore()).isTrue(); + } + @Test public void endSpanOptions_EqualsAndHashCode() { EqualsTester tester = new EqualsTester(); -- cgit v1.2.3 From bd96a9c62b8a2f2a4cf43792ed827262688c0358 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Mon, 23 Oct 2017 12:35:01 -0700 Subject: Record the agent label for stackdriver trace exporter. (#717) --- .../common/OpenCensusLibraryInformation.java | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java new file mode 100644 index 00000000..e2548651 --- /dev/null +++ b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java @@ -0,0 +1,29 @@ +/* + * Copyright 2016-17, 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.common; + +/** + * Class holder for all common constants (such as the version) for the OpenCensus Java library. + */ +@ExperimentalApi +public final class OpenCensusLibraryInformation { + + /** + * The current version of the OpenCensus Java library. + */ + public static final String VERSION = "0.8.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION +} -- cgit v1.2.3 From 92e363fb2daa1a8aee308d3bd5fc20c9e83eeab2 Mon Sep 17 00:00:00 2001 From: sebright Date: Mon, 23 Oct 2017 17:13:14 -0700 Subject: Move stats and tags packages to opencensus-api to prepare for release. (#723) --- .../main/java/io/opencensus/stats/Aggregation.java | 179 ++++++++++++ .../java/io/opencensus/stats/AggregationData.java | 312 +++++++++++++++++++++ .../java/io/opencensus/stats/BucketBoundaries.java | 58 ++++ api/src/main/java/io/opencensus/stats/Measure.java | 150 ++++++++++ .../main/java/io/opencensus/stats/MeasureMap.java | 128 +++++++++ .../main/java/io/opencensus/stats/Measurement.java | 99 +++++++ .../main/java/io/opencensus/stats/NoopStats.java | 151 ++++++++++ api/src/main/java/io/opencensus/stats/Stats.java | 95 +++++++ .../io/opencensus/stats/StatsCollectionState.java | 36 +++ .../java/io/opencensus/stats/StatsComponent.java | 50 ++++ .../java/io/opencensus/stats/StatsRecorder.java | 42 +++ api/src/main/java/io/opencensus/stats/View.java | 229 +++++++++++++++ .../main/java/io/opencensus/stats/ViewData.java | 182 ++++++++++++ .../main/java/io/opencensus/stats/ViewManager.java | 34 +++ .../java/io/opencensus/tags/InternalUtils.java | 31 ++ api/src/main/java/io/opencensus/tags/NoopTags.java | 232 +++++++++++++++ api/src/main/java/io/opencensus/tags/Tag.java | 208 ++++++++++++++ .../main/java/io/opencensus/tags/TagContext.java | 99 +++++++ .../java/io/opencensus/tags/TagContextBuilder.java | 83 ++++++ api/src/main/java/io/opencensus/tags/TagKey.java | 244 ++++++++++++++++ api/src/main/java/io/opencensus/tags/TagValue.java | 182 ++++++++++++ api/src/main/java/io/opencensus/tags/Tagger.java | 78 ++++++ .../main/java/io/opencensus/tags/TaggingState.java | 40 +++ api/src/main/java/io/opencensus/tags/Tags.java | 104 +++++++ .../java/io/opencensus/tags/TagsComponent.java | 52 ++++ .../main/java/io/opencensus/tags/package-info.java | 33 +++ .../propagation/TagContextBinarySerializer.java | 51 ++++ .../tags/propagation/TagContextParseException.java | 43 +++ .../tags/propagation/TagPropagationComponent.java | 31 ++ .../io/opencensus/tags/unsafe/ContextUtils.java | 52 ++++ .../io/opencensus/stats/AggregationDataTest.java | 168 +++++++++++ .../java/io/opencensus/stats/AggregationTest.java | 119 ++++++++ .../io/opencensus/stats/BucketBoundariesTest.java | 90 ++++++ .../java/io/opencensus/stats/MeasureMapTest.java | 132 +++++++++ .../test/java/io/opencensus/stats/MeasureTest.java | 155 ++++++++++ .../java/io/opencensus/stats/NoopStatsTest.java | 118 ++++++++ .../io/opencensus/stats/NoopViewManagerTest.java | 134 +++++++++ .../io/opencensus/stats/StatsRecorderTest.java | 81 ++++++ .../test/java/io/opencensus/stats/StatsTest.java | 82 ++++++ .../java/io/opencensus/stats/ViewDataTest.java | 221 +++++++++++++++ .../test/java/io/opencensus/stats/ViewTest.java | 162 +++++++++++ .../java/io/opencensus/tags/InternalUtilsTest.java | 49 ++++ .../test/java/io/opencensus/tags/NoopTagsTest.java | 192 +++++++++++++ .../java/io/opencensus/tags/TagContextTest.java | 106 +++++++ .../test/java/io/opencensus/tags/TagKeyTest.java | 156 +++++++++++ api/src/test/java/io/opencensus/tags/TagTest.java | 158 +++++++++++ .../test/java/io/opencensus/tags/TagValueTest.java | 154 ++++++++++ api/src/test/java/io/opencensus/tags/TagsTest.java | 85 ++++++ .../propagation/TagContextParseExceptionTest.java | 42 +++ .../opencensus/tags/unsafe/ContextUtilsTest.java | 62 ++++ 50 files changed, 5774 insertions(+) create mode 100644 api/src/main/java/io/opencensus/stats/Aggregation.java create mode 100644 api/src/main/java/io/opencensus/stats/AggregationData.java create mode 100644 api/src/main/java/io/opencensus/stats/BucketBoundaries.java create mode 100644 api/src/main/java/io/opencensus/stats/Measure.java create mode 100644 api/src/main/java/io/opencensus/stats/MeasureMap.java create mode 100644 api/src/main/java/io/opencensus/stats/Measurement.java create mode 100644 api/src/main/java/io/opencensus/stats/NoopStats.java create mode 100644 api/src/main/java/io/opencensus/stats/Stats.java create mode 100644 api/src/main/java/io/opencensus/stats/StatsCollectionState.java create mode 100644 api/src/main/java/io/opencensus/stats/StatsComponent.java create mode 100644 api/src/main/java/io/opencensus/stats/StatsRecorder.java create mode 100644 api/src/main/java/io/opencensus/stats/View.java create mode 100644 api/src/main/java/io/opencensus/stats/ViewData.java create mode 100644 api/src/main/java/io/opencensus/stats/ViewManager.java create mode 100644 api/src/main/java/io/opencensus/tags/InternalUtils.java create mode 100644 api/src/main/java/io/opencensus/tags/NoopTags.java create mode 100644 api/src/main/java/io/opencensus/tags/Tag.java create mode 100644 api/src/main/java/io/opencensus/tags/TagContext.java create mode 100644 api/src/main/java/io/opencensus/tags/TagContextBuilder.java create mode 100644 api/src/main/java/io/opencensus/tags/TagKey.java create mode 100644 api/src/main/java/io/opencensus/tags/TagValue.java create mode 100644 api/src/main/java/io/opencensus/tags/Tagger.java create mode 100644 api/src/main/java/io/opencensus/tags/TaggingState.java create mode 100644 api/src/main/java/io/opencensus/tags/Tags.java create mode 100644 api/src/main/java/io/opencensus/tags/TagsComponent.java create mode 100644 api/src/main/java/io/opencensus/tags/package-info.java create mode 100644 api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java create mode 100644 api/src/main/java/io/opencensus/tags/propagation/TagContextParseException.java create mode 100644 api/src/main/java/io/opencensus/tags/propagation/TagPropagationComponent.java create mode 100644 api/src/main/java/io/opencensus/tags/unsafe/ContextUtils.java create mode 100644 api/src/test/java/io/opencensus/stats/AggregationDataTest.java create mode 100644 api/src/test/java/io/opencensus/stats/AggregationTest.java create mode 100644 api/src/test/java/io/opencensus/stats/BucketBoundariesTest.java create mode 100644 api/src/test/java/io/opencensus/stats/MeasureMapTest.java create mode 100644 api/src/test/java/io/opencensus/stats/MeasureTest.java create mode 100644 api/src/test/java/io/opencensus/stats/NoopStatsTest.java create mode 100644 api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java create mode 100644 api/src/test/java/io/opencensus/stats/StatsRecorderTest.java create mode 100644 api/src/test/java/io/opencensus/stats/StatsTest.java create mode 100644 api/src/test/java/io/opencensus/stats/ViewDataTest.java create mode 100644 api/src/test/java/io/opencensus/stats/ViewTest.java create mode 100644 api/src/test/java/io/opencensus/tags/InternalUtilsTest.java create mode 100644 api/src/test/java/io/opencensus/tags/NoopTagsTest.java create mode 100644 api/src/test/java/io/opencensus/tags/TagContextTest.java create mode 100644 api/src/test/java/io/opencensus/tags/TagKeyTest.java create mode 100644 api/src/test/java/io/opencensus/tags/TagTest.java create mode 100644 api/src/test/java/io/opencensus/tags/TagValueTest.java create mode 100644 api/src/test/java/io/opencensus/tags/TagsTest.java create mode 100644 api/src/test/java/io/opencensus/tags/propagation/TagContextParseExceptionTest.java create mode 100644 api/src/test/java/io/opencensus/tags/unsafe/ContextUtilsTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/Aggregation.java b/api/src/main/java/io/opencensus/stats/Aggregation.java new file mode 100644 index 00000000..f12517c8 --- /dev/null +++ b/api/src/main/java/io/opencensus/stats/Aggregation.java @@ -0,0 +1,179 @@ +/* + * 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.stats; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.Function; +import javax.annotation.concurrent.Immutable; + +/** + * {@link Aggregation} is the process of combining a certain set of {@code MeasureValue}s + * for a given {@code Measure} into an {@link AggregationData}. + * + *

{@link Aggregation} currently supports 4 types of basic aggregation: + *

    + *
  • Sum + *
  • Count + *
  • Mean + *
  • Distribution + *
+ * + *

When creating a {@link View}, one {@link Aggregation} needs to be specified as how to + * aggregate {@code MeasureValue}s. + */ +@Immutable +public abstract class Aggregation { + + private Aggregation() { + } + + /** + * Applies the given match function to the underlying data type. + */ + public abstract T match( + Function p0, + Function p1, + Function p2, + Function p3, + Function defaultFunction); + + /** Calculate sum on aggregated {@code MeasureValue}s. */ + @Immutable + @AutoValue + public abstract static class Sum extends Aggregation { + + Sum() { + } + + private static final Sum INSTANCE = new AutoValue_Aggregation_Sum(); + + /** + * Construct a {@code Sum}. + * + * @return a new {@code Sum}. + */ + public static Sum create() { + return INSTANCE; + } + + @Override + public final T match( + Function p0, + Function p1, + Function p2, + Function p3, + Function defaultFunction) { + return p0.apply(this); + } + } + + /** Calculate count on aggregated {@code MeasureValue}s. */ + @Immutable + @AutoValue + public abstract static class Count extends Aggregation { + + Count() { + } + + private static final Count INSTANCE = new AutoValue_Aggregation_Count(); + + /** + * Construct a {@code Count}. + * + * @return a new {@code Count}. + */ + public static Count create() { + return INSTANCE; + } + + @Override + public final T match( + Function p0, + Function p1, + Function p2, + Function p3, + Function defaultFunction) { + return p1.apply(this); + } + } + + /** Calculate mean on aggregated {@code MeasureValue}s. */ + @Immutable + @AutoValue + public abstract static class Mean extends Aggregation { + + Mean() { + } + + private static final Mean INSTANCE = new AutoValue_Aggregation_Mean(); + + /** + * Construct a {@code Mean}. + * + * @return a new {@code Mean}. + */ + public static Mean create() { + return INSTANCE; + } + + @Override + public final T match( + Function p0, + Function p1, + Function p2, + Function p3, + Function defaultFunction) { + return p2.apply(this); + } + } + + /** + * Calculate distribution stats on aggregated {@code MeasureValue}s. Distribution includes + * mean, count, histogram, min, max and sum of squared deviations. + */ + @Immutable + @AutoValue + public abstract static class Distribution extends Aggregation { + + Distribution() { + } + + /** + * Construct a {@code Distribution}. + * + * @return a new {@code Distribution}. + */ + public static Distribution create(BucketBoundaries bucketBoundaries) { + checkNotNull(bucketBoundaries, "bucketBoundaries should not be null."); + return new AutoValue_Aggregation_Distribution(bucketBoundaries); + } + + public abstract BucketBoundaries getBucketBoundaries(); + + @Override + public final T match( + Function p0, + Function p1, + Function p2, + Function p3, + Function defaultFunction) { + return p3.apply(this); + } + } +} diff --git a/api/src/main/java/io/opencensus/stats/AggregationData.java b/api/src/main/java/io/opencensus/stats/AggregationData.java new file mode 100644 index 00000000..fdf09592 --- /dev/null +++ b/api/src/main/java/io/opencensus/stats/AggregationData.java @@ -0,0 +1,312 @@ +/* + * 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.stats; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.Function; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.annotation.concurrent.Immutable; + +/** + * {@link AggregationData} is the result of applying a given {@link Aggregation} to a set of + * {@code MeasureValue}s. + * + *

{@link AggregationData} currently supports 5 types of basic aggregation values: + *

    + *
  • SumDataDouble + *
  • SumDataLong + *
  • CountData + *
  • MeanData + *
  • DistributionData + *
+ * + *

{@link ViewData} will contain one {@link AggregationData}, corresponding to its + * {@link Aggregation} definition in {@link View}. + */ +@Immutable +public abstract class AggregationData { + + private AggregationData() { + } + + /** + * Applies the given match function to the underlying data type. + */ + public abstract T match( + Function p0, + Function p1, + Function p2, + Function p3, + Function p4, + Function defaultFunction); + + /** The sum value of aggregated {@code MeasureValueDouble}s. */ + @Immutable + @AutoValue + public abstract static class SumDataDouble extends AggregationData { + + SumDataDouble() { + } + + /** + * Creates a {@code SumDataDouble}. + * + * @param sum the aggregated sum. + * @return a {@code SumDataDouble}. + */ + public static SumDataDouble create(double sum) { + return new AutoValue_AggregationData_SumDataDouble(sum); + } + + /** + * Returns the aggregated sum. + * + * @return the aggregated sum. + */ + public abstract double getSum(); + + @Override + public final T match( + Function p0, + Function p1, + Function p2, + Function p3, + Function p4, + Function defaultFunction) { + return p0.apply(this); + } + } + + /** The sum value of aggregated {@code MeasureValueLong}s. */ + @Immutable + @AutoValue + public abstract static class SumDataLong extends AggregationData { + + SumDataLong() { + } + + /** + * Creates a {@code SumDataLong}. + * + * @param sum the aggregated sum. + * @return a {@code SumDataLong}. + */ + public static SumDataLong create(long sum) { + return new AutoValue_AggregationData_SumDataLong(sum); + } + + /** + * Returns the aggregated sum. + * + * @return the aggregated sum. + */ + public abstract long getSum(); + + @Override + public final T match( + Function p0, + Function p1, + Function p2, + Function p3, + Function p4, + Function defaultFunction) { + return p1.apply(this); + } + } + + /** The count value of aggregated {@code MeasureValue}s. */ + @Immutable + @AutoValue + public abstract static class CountData extends AggregationData { + + CountData() { + } + + /** + * Creates a {@code CountData}. + * + * @param count the aggregated count. + * @return a {@code CountData}. + */ + public static CountData create(long count) { + return new AutoValue_AggregationData_CountData(count); + } + + /** + * Returns the aggregated count. + * + * @return the aggregated count. + */ + public abstract long getCount(); + + @Override + public final T match( + Function p0, + Function p1, + Function p2, + Function p3, + Function p4, + Function defaultFunction) { + return p2.apply(this); + } + } + + /** The mean value of aggregated {@code MeasureValue}s. */ + @Immutable + @AutoValue + public abstract static class MeanData extends AggregationData { + + MeanData() { + } + + /** + * Creates a {@code MeanData}. + * + * @param mean the aggregated mean. + * @param count the aggregated count. + * @return a {@code MeanData}. + */ + public static MeanData create(double mean, long count) { + return new AutoValue_AggregationData_MeanData(mean, count); + } + + /** + * Returns the aggregated mean. + * + * @return the aggregated mean. + */ + public abstract double getMean(); + + /** + * Returns the aggregated count. + * + * @return the aggregated count. + */ + public abstract long getCount(); + + @Override + public final T match( + Function p0, + Function p1, + Function p2, + Function p3, + Function p4, + Function defaultFunction) { + return p3.apply(this); + } + } + + /** + * The distribution stats of aggregated {@code MeasureValue}s. Distribution stats include mean, + * count, histogram, min, max and sum of squared deviations. + */ + @Immutable + @AutoValue + public abstract static class DistributionData extends AggregationData { + + DistributionData() { + } + + /** + * Creates a {@code DistributionData}. + * + * @param mean mean value. + * @param count count value. + * @param min min value. + * @param max max value. + * @param sumOfSquaredDeviations sum of squared deviations. + * @param bucketCounts histogram bucket counts. + * @return a {@code DistributionData}. + */ + public static DistributionData create( + double mean, long count, double min, double max, double sumOfSquaredDeviations, + long[] bucketCounts) { + if (min != Double.POSITIVE_INFINITY || max != Double.NEGATIVE_INFINITY) { + checkArgument(min <= max, "max should be greater or equal to min."); + } + + checkNotNull(bucketCounts, "bucket counts should not be null."); + List boxedBucketCounts = new ArrayList(); + for (long bucketCount : bucketCounts) { + boxedBucketCounts.add(bucketCount); + } + + return new AutoValue_AggregationData_DistributionData( + mean, count, min, max, sumOfSquaredDeviations, + Collections.unmodifiableList(boxedBucketCounts)); + } + + /** + * Returns the aggregated mean. + * + * @return the aggregated mean. + */ + public abstract double getMean(); + + /** + * Returns the aggregated count. + * + * @return the aggregated count. + */ + public abstract long getCount(); + + /** + * Returns the minimum of the population values. + * + * @return the minimum of the population values. + */ + public abstract double getMin(); + + /** + * Returns the maximum of the population values. + * + * @return the maximum of the population values. + */ + public abstract double getMax(); + + /** + * Returns the aggregated sum of squared deviations. + * + * @return the aggregated sum of squared deviations. + */ + public abstract double getSumOfSquaredDeviations(); + + /** + * Returns the aggregated bucket counts. The returned list is immutable, trying to update it + * will throw an {@code UnsupportedOperationException}. + * + * @return the aggregated bucket counts. + */ + public abstract List getBucketCounts(); + + @Override + public final T match( + Function p0, + Function p1, + Function p2, + Function p3, + Function p4, + Function defaultFunction) { + return p4.apply(this); + } + } +} diff --git a/api/src/main/java/io/opencensus/stats/BucketBoundaries.java b/api/src/main/java/io/opencensus/stats/BucketBoundaries.java new file mode 100644 index 00000000..b9a808f4 --- /dev/null +++ b/api/src/main/java/io/opencensus/stats/BucketBoundaries.java @@ -0,0 +1,58 @@ +/* + * 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.stats; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.annotation.concurrent.Immutable; + +/** The bucket boundaries for a histogram. */ +@Immutable +@AutoValue +public abstract class BucketBoundaries { + + /** + * @param bucketBoundaries the boundaries for the buckets in the underlying histogram. + * @return a new {@code BucketBoundaries} with the specified boundaries. + * @throws NullPointerException if {@code bucketBoundaries} is null. + * @throws IllegalArgumentException if {@code bucketBoundaries} is not sorted. + */ + public static final BucketBoundaries create(List bucketBoundaries) { + checkNotNull(bucketBoundaries, "bucketBoundaries list should not be null."); + List bucketBoundariesCopy = new ArrayList(bucketBoundaries); // Deep copy. + // Check if sorted. + if (bucketBoundariesCopy.size() > 1) { + double lower = bucketBoundariesCopy.get(0); + for (int i = 1; i < bucketBoundariesCopy.size(); i++) { + double next = bucketBoundariesCopy.get(i); + checkArgument(lower < next, "Bucket boundaries not sorted."); + lower = next; + } + } + return new AutoValue_BucketBoundaries(Collections.unmodifiableList(bucketBoundariesCopy)); + } + + /** + * @return a list of histogram bucket boundaries. + */ + public abstract List getBoundaries(); +} diff --git a/api/src/main/java/io/opencensus/stats/Measure.java b/api/src/main/java/io/opencensus/stats/Measure.java new file mode 100644 index 00000000..e7a0ec96 --- /dev/null +++ b/api/src/main/java/io/opencensus/stats/Measure.java @@ -0,0 +1,150 @@ +/* + * 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.stats; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.auto.value.AutoValue; +import com.google.common.annotations.VisibleForTesting; +import io.opencensus.common.Function; +import io.opencensus.internal.StringUtil; +import javax.annotation.concurrent.Immutable; + +/** The definition of the {@link Measurement} that is taken by OpenCensus library. */ +@Immutable +public abstract class Measure { + + @VisibleForTesting static final int NAME_MAX_LENGTH = 256; + + /** + * Applies the given match function to the underlying data type. + */ + public abstract T match( + Function p0, + Function p1, + Function defaultFunction); + + /** + * Name of measure, as a {@code String}. Should be a ASCII string with a length no greater than + * 256 characters. + * + *

Suggested format for name: {@code /}. + */ + public abstract String getName(); + + /** + * Detailed description of the measure, used in documentation. + */ + public abstract String getDescription(); + + /** + * The units in which {@link Measure} values are measured. + * + *

The suggested grammar for a unit is as follows: + * Expression = Component { "." Component } { "/" Component } ; + * Component = [ PREFIX ] UNIT [ Annotation ] | Annotation | "1" ; + * Annotation = "{" NAME "}" ; + * For example, string “MBy{transmitted}/ms” stands for megabytes per milliseconds, and the + * annotation transmitted inside {} is just a comment of the unit. + */ + // TODO(songya): determine whether we want to check the grammar on string unit. + public abstract String getUnit(); + + // Prevents this class from being subclassed anywhere else. + private Measure() { + } + + /** {@link Measure} with {@code Double} typed values. */ + @Immutable + @AutoValue + public abstract static class MeasureDouble extends Measure { + + MeasureDouble() { + } + + /** + * Constructs a new {@link MeasureDouble}. + * + * @param name name of {@code Measure}. Suggested format: {@code /}. + * @param description description of {@code Measure}. + * @param unit unit of {@code Measure}. + * @return a {@code MeasureDouble}. + */ + public static MeasureDouble create(String name, String description, String unit) { + checkArgument(StringUtil.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, + "Name should be a ASCII string with a length no greater than 256 characters."); + return new AutoValue_Measure_MeasureDouble(name, description, unit); + } + + @Override + public T match( + Function p0, + Function p1, + Function defaultFunction) { + return p0.apply(this); + } + + @Override + public abstract String getName(); + + @Override + public abstract String getDescription(); + + @Override + public abstract String getUnit(); + } + + /** {@link Measure} with {@code Long} typed values. */ + @Immutable + @AutoValue + public abstract static class MeasureLong extends Measure { + + MeasureLong() { + } + + /** + * Constructs a new {@link MeasureLong}. + * + * @param name name of {@code Measure}. Suggested format: {@code /}. + * @param description description of {@code Measure}. + * @param unit unit of {@code Measure}. + * @return a {@code MeasureLong}. + */ + public static MeasureLong create(String name, String description, String unit) { + checkArgument(StringUtil.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, + "Name should be a ASCII string with a length no greater than 256 characters."); + return new AutoValue_Measure_MeasureLong(name, description, unit); + } + + @Override + public T match( + Function p0, + Function p1, + Function defaultFunction) { + return p1.apply(this); + } + + @Override + public abstract String getName(); + + @Override + public abstract String getDescription(); + + @Override + public abstract String getUnit(); + } +} diff --git a/api/src/main/java/io/opencensus/stats/MeasureMap.java b/api/src/main/java/io/opencensus/stats/MeasureMap.java new file mode 100644 index 00000000..0cc972f0 --- /dev/null +++ b/api/src/main/java/io/opencensus/stats/MeasureMap.java @@ -0,0 +1,128 @@ +/* + * Copyright 2016-17, 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.stats; + +import io.opencensus.stats.Measure.MeasureDouble; +import io.opencensus.stats.Measure.MeasureLong; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * A map from {@link Measure}'s to measured values. + */ +public final class MeasureMap { + + /** + * Returns a {@link Builder} for the {@link MeasureMap} class. + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Returns an {@link Iterator} over the measure/value mappings in this {@link MeasureMap}. + * The {@code Iterator} does not support {@link Iterator#remove()}. + */ + public Iterator iterator() { + return new MeasureMapIterator(); + } + + private final ArrayList measurements; + + private MeasureMap(ArrayList measurements) { + this.measurements = measurements; + } + + /** + * Builder for the {@link MeasureMap} class. + */ + public static class Builder { + /** + * Associates the {@link MeasureDouble} with the given value. Subsequent updates to the + * same {@link MeasureDouble} will overwrite the previous value. + * + * @param measure the {@link MeasureDouble} + * @param value the value to be associated with {@code measure} + * @return this + */ + public Builder put(MeasureDouble measure, double value) { + measurements.add(Measurement.MeasurementDouble.create(measure, value)); + return this; + } + + /** + * Associates the {@link MeasureLong} with the given value. Subsequent updates to the + * same {@link MeasureLong} will overwrite the previous value. + * + * @param measure the {@link MeasureLong} + * @param value the value to be associated with {@code measure} + * @return this + */ + public Builder put(MeasureLong measure, long value) { + measurements.add(Measurement.MeasurementLong.create(measure, value)); + return this; + } + + /** + * Constructs a {@link MeasureMap} from the current measurements. + */ + public MeasureMap build() { + // Note: this makes adding measurements quadratic but is fastest for the sizes of + // MeasureMaps that we should see. We may want to go to a strategy of sort/eliminate + // for larger MeasureMaps. + for (int i = measurements.size() - 1; i >= 0; i--) { + for (int j = i - 1; j >= 0; j--) { + if (measurements.get(i).getMeasure() == measurements.get(j).getMeasure()) { + measurements.remove(j); + j--; + } + } + } + return new MeasureMap(measurements); + } + + private final ArrayList measurements = new ArrayList(); + + private Builder() { + } + } + + // Provides an unmodifiable Iterator over this instance's measurements. + private final class MeasureMapIterator implements Iterator { + @Override + public boolean hasNext() { + return position < length; + } + + @Override + public Measurement next() { + if (position >= measurements.size()) { + throw new NoSuchElementException(); + } + return measurements.get(position++); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + private final int length = measurements.size(); + private int position = 0; + } +} diff --git a/api/src/main/java/io/opencensus/stats/Measurement.java b/api/src/main/java/io/opencensus/stats/Measurement.java new file mode 100644 index 00000000..10fc5888 --- /dev/null +++ b/api/src/main/java/io/opencensus/stats/Measurement.java @@ -0,0 +1,99 @@ +/* + * Copyright 2016-17, 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.stats; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.Function; +import io.opencensus.stats.Measure.MeasureDouble; +import io.opencensus.stats.Measure.MeasureLong; +import javax.annotation.concurrent.Immutable; + +/** Immutable representation of a Measurement. */ +@Immutable +public abstract class Measurement { + + /** + * Applies the given match function to the underlying data type. + */ + public abstract T match( + Function p0, + Function p1, + Function defaultFunction); + + /** + * Extracts the measured {@link Measure}. + */ + public abstract Measure getMeasure(); + + // Prevents this class from being subclassed anywhere else. + private Measurement() { + } + + /** {@code Double} typed {@link Measurement}. */ + @Immutable + @AutoValue + public abstract static class MeasurementDouble extends Measurement { + MeasurementDouble() {} + + /** + * Constructs a new {@link MeasurementDouble}. + */ + public static MeasurementDouble create(MeasureDouble measure, double value) { + return new AutoValue_Measurement_MeasurementDouble(measure, value); + } + + @Override + public abstract MeasureDouble getMeasure(); + + public abstract double getValue(); + + @Override + public T match( + Function p0, + Function p1, + Function defaultFunction) { + return p0.apply(this); + } + } + + /** {@code Long} typed {@link Measurement}. */ + @Immutable + @AutoValue + public abstract static class MeasurementLong extends Measurement { + MeasurementLong() {} + + /** + * Constructs a new {@link MeasurementLong}. + */ + public static MeasurementLong create(MeasureLong measure, long value) { + return new AutoValue_Measurement_MeasurementLong(measure, value); + } + + @Override + public abstract MeasureLong getMeasure(); + + public abstract long getValue(); + + @Override + public T match( + Function p0, + Function p1, + Function defaultFunction) { + return p1.apply(this); + } + } +} diff --git a/api/src/main/java/io/opencensus/stats/NoopStats.java b/api/src/main/java/io/opencensus/stats/NoopStats.java new file mode 100644 index 00000000..79ddb359 --- /dev/null +++ b/api/src/main/java/io/opencensus/stats/NoopStats.java @@ -0,0 +1,151 @@ +/* + * 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.stats; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Maps; +import io.opencensus.common.Functions; +import io.opencensus.common.Timestamp; +import io.opencensus.stats.ViewData.AggregationWindowData; +import io.opencensus.stats.ViewData.AggregationWindowData.CumulativeData; +import io.opencensus.stats.ViewData.AggregationWindowData.IntervalData; +import io.opencensus.tags.TagContext; +import io.opencensus.tags.TagValue; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import javax.annotation.concurrent.GuardedBy; +import javax.annotation.concurrent.Immutable; +import javax.annotation.concurrent.ThreadSafe; + +/** No-op implementations of stats classes. */ +final class NoopStats { + + private NoopStats() {} + + /** + * Returns a {@code StatsComponent} that has a no-op implementation for {@link StatsRecorder}. + * + * @return a {@code StatsComponent} that has a no-op implementation for {@code StatsRecorder}. + */ + static StatsComponent newNoopStatsComponent() { + return new NoopStatsComponent(); + } + + /** + * Returns a {@code StatsRecorder} that does not record any data. + * + * @return a {@code StatsRecorder} that does not record any data. + */ + static StatsRecorder getNoopStatsRecorder() { + return NoopStatsRecorder.INSTANCE; + } + + /** + * Returns a {@code ViewManager} that maintains a map of views, but always returns empty {@link + * ViewData}s. + * + * @return a {@code ViewManager} that maintains a map of views, but always returns empty {@code + * ViewData}s. + */ + static ViewManager newNoopViewManager() { + return new NoopViewManager(); + } + + @ThreadSafe + private static final class NoopStatsComponent extends StatsComponent { + private final ViewManager viewManager = newNoopViewManager(); + + @Override + public ViewManager getViewManager() { + return viewManager; + } + + @Override + public StatsRecorder getStatsRecorder() { + return getNoopStatsRecorder(); + } + + @Override + public StatsCollectionState getState() { + return StatsCollectionState.DISABLED; + } + + @Override + public void setState(StatsCollectionState state) { + Preconditions.checkNotNull(state, "state"); + } + } + + @Immutable + private static final class NoopStatsRecorder extends StatsRecorder { + static final StatsRecorder INSTANCE = new NoopStatsRecorder(); + + @Override + public void record(TagContext tags, MeasureMap measureValues) { + checkNotNull(tags, "tags"); + checkNotNull(measureValues, "measureValues"); + } + } + + @ThreadSafe + private static final class NoopViewManager extends ViewManager { + private static final Timestamp ZERO_TIMESTAMP = Timestamp.create(0, 0); + + @GuardedBy("views") + private final Map views = Maps.newHashMap(); + + @Override + public void registerView(View newView) { + checkNotNull(newView, "newView"); + synchronized (views) { + View existing = views.get(newView.getName()); + checkArgument( + existing == null || newView.equals(existing), + "A different view with the same name already exists."); + if (existing == null) { + views.put(newView.getName(), newView); + } + } + } + + @Override + public ViewData getView(View.Name name) { + checkNotNull(name, "name"); + synchronized (views) { + View view = views.get(name); + if (view == null) { + throw new IllegalArgumentException("View is not registered."); + } else { + return ViewData.create( + view, + Collections., AggregationData>emptyMap(), + view.getWindow() + .match( + Functions.returnConstant( + CumulativeData.create(ZERO_TIMESTAMP, ZERO_TIMESTAMP)), + Functions.returnConstant( + IntervalData.create(ZERO_TIMESTAMP)), + Functions.throwAssertionError())); + } + } + } + } +} diff --git a/api/src/main/java/io/opencensus/stats/Stats.java b/api/src/main/java/io/opencensus/stats/Stats.java new file mode 100644 index 00000000..016455e9 --- /dev/null +++ b/api/src/main/java/io/opencensus/stats/Stats.java @@ -0,0 +1,95 @@ +/* + * Copyright 2016-17, 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.stats; + +import com.google.common.annotations.VisibleForTesting; +import io.opencensus.internal.Provider; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** Class for accessing the default {@link StatsComponent}. */ +public final class Stats { + private static final Logger logger = Logger.getLogger(Stats.class.getName()); + + private static final StatsComponent statsComponent = + loadStatsComponent(StatsComponent.class.getClassLoader()); + + /** Returns the default {@link StatsRecorder}. */ + public static StatsRecorder getStatsRecorder() { + return statsComponent.getStatsRecorder(); + } + + /** Returns the default {@link ViewManager}. */ + public static ViewManager getViewManager() { + return statsComponent.getViewManager(); + } + + /** + * Returns the current {@code StatsCollectionState}. + * + *

When no implementation is available, {@code getState} always returns {@link + * StatsCollectionState#DISABLED}. + * + * @return the current {@code StatsCollectionState}. + */ + public static StatsCollectionState getState() { + return statsComponent.getState(); + } + + /** + * Sets the current {@code StatsCollectionState}. + * + *

When no implementation is available, {@code setState} has no effect. + * + * @param state the new {@code StatsCollectionState}. + */ + public static void setState(StatsCollectionState state) { + statsComponent.setState(state); + } + + // Any provider that may be used for StatsComponent can be added here. + @VisibleForTesting + static StatsComponent loadStatsComponent(ClassLoader classLoader) { + try { + // Call Class.forName with literal string name of the class to help shading tools. + return Provider.createInstance( + Class.forName("io.opencensus.impl.stats.StatsComponentImpl", true, classLoader), + StatsComponent.class); + } catch (ClassNotFoundException e) { + logger.log( + Level.FINE, + "Couldn't load full implementation for StatsComponent, now trying to load lite " + + "implementation.", + e); + } + try { + // Call Class.forName with literal string name of the class to help shading tools. + return Provider.createInstance( + Class.forName("io.opencensus.impllite.stats.StatsComponentImplLite", true, classLoader), + StatsComponent.class); + } catch (ClassNotFoundException e) { + logger.log( + Level.FINE, + "Couldn't load lite implementation for StatsComponent, now using " + + "default implementation for StatsComponent.", + e); + } + return NoopStats.newNoopStatsComponent(); + } + + private Stats() {} +} diff --git a/api/src/main/java/io/opencensus/stats/StatsCollectionState.java b/api/src/main/java/io/opencensus/stats/StatsCollectionState.java new file mode 100644 index 00000000..7e5641b1 --- /dev/null +++ b/api/src/main/java/io/opencensus/stats/StatsCollectionState.java @@ -0,0 +1,36 @@ +/* + * 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.stats; + +/** State of the {@link StatsComponent}. */ +public enum StatsCollectionState { + + /** + * State that fully enables stats collection. + * + *

The {@link StatsComponent} collects stats for registered views. + */ + ENABLED, + + /** + * State that disables stats collection. + * + *

The {@link StatsComponent} does not need to collect stats for registered views and may + * return empty {@link ViewData}s from {@link ViewManager#getView(View.Name)}. + */ + DISABLED +} diff --git a/api/src/main/java/io/opencensus/stats/StatsComponent.java b/api/src/main/java/io/opencensus/stats/StatsComponent.java new file mode 100644 index 00000000..69fbcb5c --- /dev/null +++ b/api/src/main/java/io/opencensus/stats/StatsComponent.java @@ -0,0 +1,50 @@ +/* + * 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.stats; + +/** + * Class that holds the implementations for {@link ViewManager} and {@link StatsRecorder}. + * + *

All objects returned by methods on {@code StatsComponent} are cacheable. + */ +public abstract class StatsComponent { + + /** Returns the default {@link ViewManager}. */ + public abstract ViewManager getViewManager(); + + /** Returns the default {@link StatsRecorder}. */ + public abstract StatsRecorder getStatsRecorder(); + + /** + * Returns the current {@code StatsCollectionState}. + * + *

When no implementation is available, {@code getState} always returns {@link + * StatsCollectionState#DISABLED}. + * + * @return the current {@code StatsCollectionState}. + */ + public abstract StatsCollectionState getState(); + + /** + * Sets the current {@code StatsCollectionState}. + * + *

When no implementation is available, {@code setState} has no effect. + * + * @param state the new {@code StatsCollectionState}. + */ + public abstract void setState(StatsCollectionState state); +} diff --git a/api/src/main/java/io/opencensus/stats/StatsRecorder.java b/api/src/main/java/io/opencensus/stats/StatsRecorder.java new file mode 100644 index 00000000..cab21c29 --- /dev/null +++ b/api/src/main/java/io/opencensus/stats/StatsRecorder.java @@ -0,0 +1,42 @@ +/* + * 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.stats; + +import io.opencensus.tags.TagContext; +import io.opencensus.tags.unsafe.ContextUtils; + +/** Provides methods to record stats against tags. */ +public abstract class StatsRecorder { + + /** + * Records a set of measurements with the tags in the current context. + * + * @param measureValues the measurements to record. + */ + public final void record(MeasureMap measureValues) { + // Use the context key directly, to avoid depending on the tags implementation. + record(ContextUtils.TAG_CONTEXT_KEY.get(), measureValues); + } + + /** + * Records a set of measurements with a set of tags. + * + * @param tags the tags associated with the measurements. + * @param measureValues the measurements to record. + */ + public abstract void record(TagContext tags, MeasureMap measureValues); +} diff --git a/api/src/main/java/io/opencensus/stats/View.java b/api/src/main/java/io/opencensus/stats/View.java new file mode 100644 index 00000000..31b06461 --- /dev/null +++ b/api/src/main/java/io/opencensus/stats/View.java @@ -0,0 +1,229 @@ +/* + * Copyright 2016-17, 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.stats; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.auto.value.AutoValue; +import com.google.common.annotations.VisibleForTesting; +import io.opencensus.common.Duration; +import io.opencensus.common.Function; +import io.opencensus.internal.StringUtil; +import io.opencensus.tags.TagKey; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import javax.annotation.concurrent.Immutable; + +/** + * A View specifies an aggregation and a set of tag keys. The aggregation will be broken + * down by the unique set of matching tag values for each measure. + */ +@Immutable +@AutoValue +public abstract class View { + + @VisibleForTesting static final int NAME_MAX_LENGTH = 256; + + View() { + } + + /** + * Name of view. Must be unique. + */ + public abstract Name getName(); + + /** + * More detailed description, for documentation purposes. + */ + public abstract String getDescription(); + + /** + * Measure type of this view. + */ + public abstract Measure getMeasure(); + + /** + * The {@link Aggregation} associated with this {@link View}. + */ + public abstract Aggregation getAggregation(); + + /** + * Columns (a.k.a Tag Keys) to match with the associated {@link Measure}. + * + *

{@link Measure} will be recorded in a "greedy" way. That is, every view aggregates every + * measure. This is similar to doing a GROUPBY on view’s columns. Columns must be unique. + */ + public abstract List getColumns(); + + /** + * Returns the time {@link AggregationWindow} for this {@code View}. + * + * @return the time {@link AggregationWindow}. + */ + public abstract AggregationWindow getWindow(); + + /** + * Constructs a new {@link View}. + * + * @param name the {@link Name} of view. Must be unique. + * @param description the description of view. + * @param measure the {@link Measure} to be aggregated by this view. + * @param aggregation the basic {@link Aggregation} that this view will support. + * @param columns the {@link TagKey}s that this view will aggregate on. Columns should not contain + * duplicates. + * @param window the {@link AggregationWindow} of view. + * @return a new {@link View}. + */ + public static View create( + Name name, + String description, + Measure measure, + Aggregation aggregation, + List columns, + AggregationWindow window) { + checkArgument(new HashSet(columns).size() == columns.size(), + "Columns have duplicate."); + + return new AutoValue_View( + name, + description, + measure, + aggregation, + Collections.unmodifiableList(new ArrayList(columns)), + window); + } + + /** + * The name of a {@code View}. + */ + // This type should be used as the key when associating data with Views. + @Immutable + @AutoValue + public abstract static class Name { + + Name() {} + + /** + * Returns the name as a {@code String}. + * + * @return the name as a {@code String}. + */ + public abstract String asString(); + + /** + * Creates a {@code View.Name} from a {@code String}. Should be a ASCII string with a length + * no greater than 256 characters. + * + *

Suggested format for name: {@code /}. + * + * @param name the name {@code String}. + * @return a {@code View.Name} with the given name {@code String}. + */ + public static Name create(String name) { + checkArgument(StringUtil.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, + "Name should be a ASCII string with a length no greater than 256 characters."); + return new AutoValue_View_Name(name); + } + } + + /** The time window for a {@code View}. */ + @Immutable + public abstract static class AggregationWindow { + + private AggregationWindow() {} + + /** + * Applies the given match function to the underlying data type. + */ + public abstract T match( + Function p0, + Function p1, + Function defaultFunction); + + /** Cumulative (infinite interval) time {@code AggregationWindow}. */ + @Immutable + @AutoValue + public abstract static class Cumulative extends AggregationWindow { + + private static final Cumulative CUMULATIVE = + new AutoValue_View_AggregationWindow_Cumulative(); + + Cumulative() {} + + /** + * Constructs a cumulative {@code AggregationWindow} that does not have an explicit {@code + * Duration}. Instead, cumulative {@code AggregationWindow} always has an interval of infinite + * {@code Duration}. + * + * @return a cumulative {@code AggregationWindow}. + */ + public static Cumulative create() { + return CUMULATIVE; + } + + @Override + public final T match( + Function p0, + Function p1, + Function defaultFunction) { + return p0.apply(this); + } + } + + /** Interval (finite interval) time {@code AggregationWindow.} */ + @Immutable + @AutoValue + public abstract static class Interval extends AggregationWindow { + + private static final Duration ZERO = Duration.create(0, 0); + + Interval() {} + + /** + * Returns the {@code Duration} associated with this {@code Interval}. + * + * @return a {@code Duration}. + */ + public abstract Duration getDuration(); + + + /** + * Constructs an interval {@code AggregationWindow} that has a finite explicit {@code + * Duration}. + * + *

The {@code Duration} should be able to round to milliseconds. Currently interval window + * cannot have smaller {@code Duration} such as microseconds or nanoseconds. + * + * @return an interval {@code AggregationWindow}. + */ + public static Interval create(Duration duration) { + checkArgument(duration.compareTo(ZERO) > 0, "Duration must be positive"); + return new AutoValue_View_AggregationWindow_Interval(duration); + } + + @Override + public final T match( + Function p0, + Function p1, + Function defaultFunction) { + return p1.apply(this); + } + } + } +} diff --git a/api/src/main/java/io/opencensus/stats/ViewData.java b/api/src/main/java/io/opencensus/stats/ViewData.java new file mode 100644 index 00000000..e4872091 --- /dev/null +++ b/api/src/main/java/io/opencensus/stats/ViewData.java @@ -0,0 +1,182 @@ +/* + * Copyright 2016-17, 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.stats; + +import com.google.auto.value.AutoValue; +import com.google.common.collect.Maps; +import io.opencensus.common.Function; +import io.opencensus.common.Functions; +import io.opencensus.common.Timestamp; +import io.opencensus.tags.TagValue; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import javax.annotation.concurrent.Immutable; + +/** The aggregated data for a particular {@link View}. */ +@Immutable +@AutoValue +public abstract class ViewData { + + // Prevents this class from being subclassed anywhere else. + ViewData() {} + + /** The {@link View} associated with this {@link ViewData}. */ + public abstract View getView(); + + /** + * The {@link AggregationData} grouped by combination of tag values, associated with this + * {@link ViewData}. + */ + public abstract Map, AggregationData> getAggregationMap(); + + /** + * Returns the {@link AggregationWindowData} associated with this {@link ViewData}. + * + * @return the {@code AggregationWindowData}. + */ + public abstract AggregationWindowData getWindowData(); + + /** Constructs a new {@link ViewData}. */ + public static ViewData create( + View view, + Map, ? extends AggregationData> map, + final AggregationWindowData windowData) { + view.getWindow() + .match( + new Function() { + @Override + public Void apply(View.AggregationWindow.Cumulative arg) { + if (!(windowData instanceof AggregationWindowData.CumulativeData)) { + throw new IllegalArgumentException( + "AggregationWindow and AggregationWindowData types mismatch. " + + "AggregationWindow: " + + arg + + " AggregationWindowData: " + + windowData); + } + return null; + } + }, + new Function() { + @Override + public Void apply(View.AggregationWindow.Interval arg) { + if (!(windowData instanceof AggregationWindowData.IntervalData)) { + throw new IllegalArgumentException( + "AggregationWindow and AggregationWindowData types mismatch. " + + "AggregationWindow: " + + arg + + " AggregationWindowData: " + + windowData); + } + return null; + } + }, + Functions.throwIllegalArgumentException()); + + Map, AggregationData> deepCopy = Maps.newHashMap(); + for (Entry, ? extends AggregationData> entry : map + .entrySet()) { + deepCopy.put( + Collections.unmodifiableList(new ArrayList(entry.getKey())), + entry.getValue()); + } + + return new AutoValue_ViewData(view, Collections.unmodifiableMap(deepCopy), windowData); + } + + /** The {@code AggregationWindowData} for a {@link ViewData}. */ + @Immutable + public abstract static class AggregationWindowData { + + private AggregationWindowData() {} + + /** Applies the given match function to the underlying data type. */ + public abstract T match( + Function p0, + Function p1, + Function defaultFunction); + + /** Cumulative {@code AggregationWindowData.} */ + @Immutable + @AutoValue + public abstract static class CumulativeData extends AggregationWindowData { + + CumulativeData() {} + + /** + * Returns the start {@code Timestamp} for a {@link CumulativeData}. + * + * @return the start {@code Timestamp}. + */ + public abstract Timestamp getStart(); + + /** + * Returns the end {@code Timestamp} for a {@link CumulativeData}. + * + * @return the end {@code Timestamp}. + */ + public abstract Timestamp getEnd(); + + @Override + public final T match( + Function p0, + Function p1, + Function defaultFunction) { + return p0.apply(this); + } + + /** Constructs a new {@link CumulativeData}. */ + public static CumulativeData create(Timestamp start, Timestamp end) { + if (start.compareTo(end) > 0) { + throw new IllegalArgumentException("Start time is later than end time."); + } + return new AutoValue_ViewData_AggregationWindowData_CumulativeData(start, end); + } + } + + /** Interval {@code AggregationWindowData.} */ + @Immutable + @AutoValue + public abstract static class IntervalData extends AggregationWindowData { + + IntervalData() {} + + /** + * Returns the end {@code Timestamp} for an {@link IntervalData}. + * + * @return the end {@code Timestamp}. + */ + public abstract Timestamp getEnd(); + + @Override + public final T match( + Function p0, + Function p1, + Function defaultFunction) { + return p1.apply(this); + } + + /** Constructs a new {@link IntervalData}. */ + public static IntervalData create(Timestamp end) { + return new AutoValue_ViewData_AggregationWindowData_IntervalData(end); + } + } + } +} diff --git a/api/src/main/java/io/opencensus/stats/ViewManager.java b/api/src/main/java/io/opencensus/stats/ViewManager.java new file mode 100644 index 00000000..16bf749e --- /dev/null +++ b/api/src/main/java/io/opencensus/stats/ViewManager.java @@ -0,0 +1,34 @@ +/* + * Copyright 2016-17, 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.stats; + +/** + * Provides facilities to register {@link View}s for collecting stats and retrieving + * stats data as a {@link ViewData}. + */ +public abstract class ViewManager { + /** + * Pull model for stats. Registers a {@link View} that will collect data to be accessed + * via {@link #getView(View.Name)}. + */ + public abstract void registerView(View view); + + /** + * Returns the current stats data, {@link ViewData}, associated with the given view name. + */ + public abstract ViewData getView(View.Name view); +} diff --git a/api/src/main/java/io/opencensus/tags/InternalUtils.java b/api/src/main/java/io/opencensus/tags/InternalUtils.java new file mode 100644 index 00000000..c55ca7d4 --- /dev/null +++ b/api/src/main/java/io/opencensus/tags/InternalUtils.java @@ -0,0 +1,31 @@ +/* + * 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.tags; + +import java.util.Iterator; + +/** + * Internal tagging utilities. + */ +@io.opencensus.common.Internal +public final class InternalUtils { + private InternalUtils() {} + + public static Iterator getTags(TagContext tags) { + return tags.getIterator(); + } +} diff --git a/api/src/main/java/io/opencensus/tags/NoopTags.java b/api/src/main/java/io/opencensus/tags/NoopTags.java new file mode 100644 index 00000000..2267edb0 --- /dev/null +++ b/api/src/main/java/io/opencensus/tags/NoopTags.java @@ -0,0 +1,232 @@ +/* + * 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.tags; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.Preconditions; +import io.opencensus.common.Scope; +import io.opencensus.internal.NoopScope; +import io.opencensus.tags.TagKey.TagKeyBoolean; +import io.opencensus.tags.TagKey.TagKeyLong; +import io.opencensus.tags.TagKey.TagKeyString; +import io.opencensus.tags.TagValue.TagValueBoolean; +import io.opencensus.tags.TagValue.TagValueLong; +import io.opencensus.tags.TagValue.TagValueString; +import io.opencensus.tags.propagation.TagContextBinarySerializer; +import io.opencensus.tags.propagation.TagPropagationComponent; +import java.util.Collections; +import java.util.Iterator; +import javax.annotation.concurrent.Immutable; + +/** No-op implementations of tagging classes. */ +final class NoopTags { + + private NoopTags() {} + + /** + * Returns a {@code TagsComponent} that has a no-op implementation for {@link Tagger}. + * + * @return a {@code TagsComponent} that has a no-op implementation for {@code Tagger}. + */ + static TagsComponent getNoopTagsComponent() { + return NoopTagsComponent.INSTANCE; + } + + /** + * Returns a {@code Tagger} that only produces {@link TagContext}s with no tags. + * + * @return a {@code Tagger} that only produces {@code TagContext}s with no tags. + */ + static Tagger getNoopTagger() { + return NoopTagger.INSTANCE; + } + + /** + * Returns a {@code TagContextBuilder} that ignores all calls to {@link TagContextBuilder#put}. + * + * @return a {@code TagContextBuilder} that ignores all calls to {@link TagContextBuilder#put}. + */ + static TagContextBuilder getNoopTagContextBuilder() { + return NoopTagContextBuilder.INSTANCE; + } + + /** + * Returns a {@code TagContext} that does not contain any tags. + * + * @return a {@code TagContext} that does not contain any tags. + */ + static TagContext getNoopTagContext() { + return NoopTagContext.INSTANCE; + } + + /** Returns a {@code TagPropagationComponent} that contains no-op serializers. */ + static TagPropagationComponent getNoopTagPropagationComponent() { + return NoopTagPropagationComponent.INSTANCE; + } + + /** + * Returns a {@code TagContextBinarySerializer} that serializes all {@code TagContext}s to zero + * bytes and deserializes all inputs to empty {@code TagContext}s. + */ + static TagContextBinarySerializer getNoopTagContextBinarySerializer() { + return NoopTagContextBinarySerializer.INSTANCE; + } + + @Immutable + private static final class NoopTagsComponent extends TagsComponent { + static final TagsComponent INSTANCE = new NoopTagsComponent(); + + @Override + public Tagger getTagger() { + return getNoopTagger(); + } + + @Override + public TagPropagationComponent getTagPropagationComponent() { + return getNoopTagPropagationComponent(); + } + + @Override + public TaggingState getState() { + return TaggingState.DISABLED; + } + + @Override + public void setState(TaggingState state) { + Preconditions.checkNotNull(state, "state"); + } + } + + @Immutable + private static final class NoopTagger extends Tagger { + static final Tagger INSTANCE = new NoopTagger(); + + @Override + public TagContext empty() { + return getNoopTagContext(); + } + + @Override + public TagContext getCurrentTagContext() { + return getNoopTagContext(); + } + + @Override + public TagContextBuilder emptyBuilder() { + return getNoopTagContextBuilder(); + } + + @Override + public TagContextBuilder toBuilder(TagContext tags) { + checkNotNull(tags, "tags"); + return getNoopTagContextBuilder(); + } + + @Override + public TagContextBuilder currentBuilder() { + return getNoopTagContextBuilder(); + } + + @Override + public Scope withTagContext(TagContext tags) { + checkNotNull(tags, "tags"); + return NoopScope.getInstance(); + } + } + + @Immutable + private static final class NoopTagContextBuilder extends TagContextBuilder { + static final TagContextBuilder INSTANCE = new NoopTagContextBuilder(); + + @Override + public TagContextBuilder put(TagKeyString key, TagValueString value) { + checkNotNull(key, "key"); + checkNotNull(value, "value"); + return this; + } + + @Override + public TagContextBuilder put(TagKeyLong key, TagValueLong value) { + checkNotNull(key, "key"); + checkNotNull(value, "value"); + return this; + } + + @Override + public TagContextBuilder put(TagKeyBoolean key, TagValueBoolean value) { + checkNotNull(key, "key"); + checkNotNull(value, "value"); + return this; + } + + @Override + public TagContextBuilder remove(TagKey key) { + checkNotNull(key, "key"); + return this; + } + + @Override + public TagContext build() { + return getNoopTagContext(); + } + + @Override + public Scope buildScoped() { + return NoopScope.getInstance(); + } + } + + @Immutable + private static final class NoopTagContext extends TagContext { + static final TagContext INSTANCE = new NoopTagContext(); + + // TODO(sebright): Is there any way to let the user know that their tags were ignored? + @Override + protected Iterator getIterator() { + return Collections.emptySet().iterator(); + } + } + + @Immutable + private static final class NoopTagPropagationComponent extends TagPropagationComponent { + static final TagPropagationComponent INSTANCE = new NoopTagPropagationComponent(); + + @Override + public TagContextBinarySerializer getBinarySerializer() { + return getNoopTagContextBinarySerializer(); + } + } + + @Immutable + private static final class NoopTagContextBinarySerializer extends TagContextBinarySerializer { + static final TagContextBinarySerializer INSTANCE = new NoopTagContextBinarySerializer(); + static final byte[] EMPTY_BYTE_ARRAY = {}; + + @Override + public byte[] toByteArray(TagContext tags) { + checkNotNull(tags, "tags"); + return EMPTY_BYTE_ARRAY; + } + + @Override + public TagContext fromByteArray(byte[] bytes) { + checkNotNull(bytes, "bytes"); + return getNoopTagContext(); + } + } +} diff --git a/api/src/main/java/io/opencensus/tags/Tag.java b/api/src/main/java/io/opencensus/tags/Tag.java new file mode 100644 index 00000000..a53cd838 --- /dev/null +++ b/api/src/main/java/io/opencensus/tags/Tag.java @@ -0,0 +1,208 @@ +/* + * 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.tags; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.Function; +import io.opencensus.tags.TagKey.TagKeyBoolean; +import io.opencensus.tags.TagKey.TagKeyLong; +import io.opencensus.tags.TagKey.TagKeyString; +import io.opencensus.tags.TagValue.TagValueBoolean; +import io.opencensus.tags.TagValue.TagValueLong; +import io.opencensus.tags.TagValue.TagValueString; +import javax.annotation.concurrent.Immutable; + +/** {@link TagKey} paired with a value. */ +@Immutable +public abstract class Tag { + + /** + * Returns the tag's key. + * + * @return the tag's key. + */ + public abstract TagKey getKey(); + + /** + * Returns the associated tag value. + * + * @return the associated tag value. + */ + public abstract TagValue getValue(); + + Tag() {} + + /** + * Applies a function to the tag's key and value. The function that is called depends on the type + * of the tag. This is similar to the visitor pattern. {@code match} also takes a function to + * handle the default case, for backwards compatibility when tag types are added. For example, + * this code serializes a {@code Tag} and tries to handle new tag types by calling {@code + * toString()}. + * + *

{@code
+   * byte[] serializedValue =
+   *     tag.match(
+   *         stringTag -> serializeString(stringTag.getValue().asString()),
+   *         longTag -> serializeLong(longTag.getValue()),
+   *         booleanTag -> serializeBoolean(booleanTag.getValue()),
+   *         unknownTag -> serializeString(unknownTag.toString()));
+   * }
+ * + *

Without lambdas: + * + *


+   *   byte[] serializedValue =
+   *       tag.match(
+   *           new Function<TagString, String>() {
+   *            {@literal @}Override
+   *             public String apply(TagString stringTag) {
+   *               return serializeString(stringTag.getValue().asString());
+   *             }
+   *           },
+   *           new Function<TagLong, String>() {
+   *            {@literal @}Override
+   *             public String apply(TagLong longTag) {
+   *               serializeLong(longTag.getValue());
+   *             }
+   *           },
+   *           new Function<TagBoolean, String>() {
+   *            {@literal @}Override
+   *             public String apply(TagBoolean booleanTag) {
+   *               serializeBoolean(booleanTag.getValue());
+   *             }
+   *           },
+   *           new Function<Tag, String>() {
+   *            {@literal @}Override
+   *             public String apply(TagBoolean unknownTag) {
+   *               serializeString(unknownTag.toString());
+   *             }
+   *           });
+   * 
+ * + * @param stringFunction the function to call when the tag has a {@code String} value. + * @param longFunction the function to call when the tag has a {@code long} value. + * @param booleanFunction the function to call when the tag has a {@code boolean} value. + * @param defaultFunction the function to call when the tag has a value other than {@code String}, + * {@code long}, or {@code boolean}. + * @param The result type of the function. + * @return The result of calling the function that matches the tag's type. + */ + public abstract T match( + Function stringFunction, + Function longFunction, + Function booleanFunction, + Function defaultFunction); + + /** A tag with a {@code String} key and value. */ + @Immutable + @AutoValue + public abstract static class TagString extends Tag { + TagString() {} + + /** + * Creates a {@code TagString} from the given {@code String} key and value. + * + * @param key the tag key. + * @param value the tag value. + * @return a {@code TagString} with the given key and value. + */ + public static TagString create(TagKeyString key, TagValueString value) { + return new AutoValue_Tag_TagString(key, value); + } + + @Override + public abstract TagKeyString getKey(); + + @Override + public abstract TagValueString getValue(); + + @Override + public final T match( + Function stringFunction, + Function longFunction, + Function booleanFunction, + Function defaultFunction) { + return stringFunction.apply(this); + } + } + + /** A tag with a {@code long} key and value. */ + @Immutable + @AutoValue + public abstract static class TagLong extends Tag { + TagLong() {} + + /** + * Creates a {@code TagLong} from the given {@code long} key and value. + * + * @param key the tag key. + * @param value the tag value. + * @return a {@code TagLong} with the given key and value. + */ + public static TagLong create(TagKeyLong key, TagValueLong value) { + return new AutoValue_Tag_TagLong(key, value); + } + + @Override + public abstract TagKeyLong getKey(); + + @Override + public abstract TagValueLong getValue(); + + @Override + public final T match( + Function stringFunction, + Function longFunction, + Function booleanFunction, + Function defaultFunction) { + return longFunction.apply(this); + } + } + + /** A tag with a {@code boolean} key and value. */ + @Immutable + @AutoValue + public abstract static class TagBoolean extends Tag { + TagBoolean() {} + + /** + * Creates a {@code TagBoolean} from the given {@code boolean} key and value. + * + * @param key the tag key. + * @param value the tag value. + * @return a {@code TagBoolean} with the given key and value. + */ + public static TagBoolean create(TagKeyBoolean key, TagValueBoolean value) { + return new AutoValue_Tag_TagBoolean(key, value); + } + + @Override + public abstract TagKeyBoolean getKey(); + + @Override + public abstract TagValueBoolean getValue(); + + @Override + public final T match( + Function stringFunction, + Function longFunction, + Function booleanFunction, + Function defaultFunction) { + return booleanFunction.apply(this); + } + } +} diff --git a/api/src/main/java/io/opencensus/tags/TagContext.java b/api/src/main/java/io/opencensus/tags/TagContext.java new file mode 100644 index 00000000..be8f0dc1 --- /dev/null +++ b/api/src/main/java/io/opencensus/tags/TagContext.java @@ -0,0 +1,99 @@ +/* + * 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.tags; + +import com.google.common.collect.HashMultiset; +import com.google.common.collect.ImmutableMultiset; +import com.google.common.collect.Lists; +import com.google.common.collect.Multiset; +import io.opencensus.tags.TagValue.TagValueString; +import java.util.Iterator; +import javax.annotation.concurrent.Immutable; + +/** + * A map from keys to values that can be used to label anything that is associated with a specific + * operation. + * + *

For example, {@code TagContext}s can be used to label stats, log messages, or debugging + * information. + * + *

Keys have type {@link TagKey}. Values have type {@link TagValueString}, though the library + * will support more types in the future, including {@code long} and {@code boolean}. + */ +@Immutable +public abstract class TagContext { + + /** + * Returns an iterator over the tags in this {@code TagContext}. + * + * @return an iterator over the tags in this {@code TagContext}. + */ + // This method is protected to prevent client code from accessing the tags of any TagContext. We + // don't currently support efficient access to tags. However, every TagContext subclass needs to + // provide access to its tags to the stats and tagging implementations by implementing this + // method. If we decide to support access to tags in the future, we can add a public iterator() + // method and implement it for all subclasses by calling getIterator(). + // + // The stats and tagging implementations can access any TagContext's tags through + // io.opencensus.tags.InternalUtils.getTags, which calls this method. + protected abstract Iterator getIterator(); + + @Override + public String toString() { + return "TagContext"; + } + + /** + * Returns true iff the other object is an instance of {@code TagContext} and contains the same + * key-value pairs. Implementations are free to override this method to provide better + * performance. + */ + @Override + public boolean equals(Object other) { + if (!(other instanceof TagContext)) { + return false; + } + TagContext otherTags = (TagContext) other; + Iterator iter1 = getIterator(); + Iterator iter2 = otherTags.getIterator(); + Multiset tags1 = + iter1 == null + ? ImmutableMultiset.of() + : HashMultiset.create(Lists.newArrayList(iter1)); + Multiset tags2 = + iter2 == null + ? ImmutableMultiset.of() + : HashMultiset.create(Lists.newArrayList(iter2)); + return tags1.equals(tags2); + } + + @Override + public final int hashCode() { + int hashCode = 0; + Iterator i = getIterator(); + if (i == null) { + return hashCode; + } + while (i.hasNext()) { + Tag tag = i.next(); + if (tag != null) { + hashCode += tag.hashCode(); + } + } + return hashCode; + } +} diff --git a/api/src/main/java/io/opencensus/tags/TagContextBuilder.java b/api/src/main/java/io/opencensus/tags/TagContextBuilder.java new file mode 100644 index 00000000..bbd6da7c --- /dev/null +++ b/api/src/main/java/io/opencensus/tags/TagContextBuilder.java @@ -0,0 +1,83 @@ +/* + * 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.tags; + +import io.opencensus.common.Scope; +import io.opencensus.tags.TagKey.TagKeyBoolean; +import io.opencensus.tags.TagKey.TagKeyLong; +import io.opencensus.tags.TagKey.TagKeyString; +import io.opencensus.tags.TagValue.TagValueBoolean; +import io.opencensus.tags.TagValue.TagValueLong; +import io.opencensus.tags.TagValue.TagValueString; + +/** Builder for the {@link TagContext} class. */ +// TODO(sebright): Decide what to do when 'put' is called with a key that has the same name as an +// existing key, but a different type. We currently keep both keys. +public abstract class TagContextBuilder { + + /** + * Adds the key/value pair regardless of whether the key is present. + * + * @param key the {@code TagKey} which will be set. + * @param value the value to set for the given key. + * @return this + */ + public abstract TagContextBuilder put(TagKeyString key, TagValueString value); + + /** + * Adds the key/value pair regardless of whether the key is present. + * + * @param key the {@code TagKey} which will be set. + * @param value the value to set for the given key. + * @return this + */ + public abstract TagContextBuilder put(TagKeyLong key, TagValueLong value); + + /** + * Adds the key/value pair regardless of whether the key is present. + * + * @param key the {@code TagKey} which will be set. + * @param value the value to set for the given key. + * @return this + */ + public abstract TagContextBuilder put(TagKeyBoolean key, TagValueBoolean value); + + /** + * Removes the key if it exists. + * + * @param key the {@code TagKey} which will be removed. + * @return this + */ + public abstract TagContextBuilder remove(TagKey key); + + /** + * Creates a {@code TagContext} from this builder. + * + * @return a {@code TagContext} with the same tags as this builder. + */ + public abstract TagContext build(); + + /** + * Enters the scope of code where the {@link TagContext} created from this builder is in the + * current context and returns an object that represents that scope. The scope is exited when the + * returned object is closed. + * + * @return an object that defines a scope where the {@code TagContext} created from this builder + * is set to the current context. + */ + public abstract Scope buildScoped(); +} diff --git a/api/src/main/java/io/opencensus/tags/TagKey.java b/api/src/main/java/io/opencensus/tags/TagKey.java new file mode 100644 index 00000000..943f12d7 --- /dev/null +++ b/api/src/main/java/io/opencensus/tags/TagKey.java @@ -0,0 +1,244 @@ +/* + * 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.tags; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.Function; +import io.opencensus.internal.StringUtil; +import io.opencensus.tags.TagValue.TagValueString; +import javax.annotation.concurrent.Immutable; + +/** + * A key to a value stored in a {@link TagContext}. + * + *

There is one {@code TagKey} subclass corresponding to each tag value type, so that each key + * can only be paired with a single type of value. For example, {@link TagKeyString} can only be + * used to set {@link TagValueString} values in a {@code TagContext}. + * + *

Each {@code TagKey} has a {@code String} name. Names have a maximum length of {@link + * #MAX_LENGTH} and contain only printable ASCII characters. + * + *

{@code TagKey}s are designed to be used as constants. Declaring each key as a constant ensures + * that the keys have consistent value types and prevents key names from being validated multiple + * times. + */ +@Immutable +public abstract class TagKey { + /** The maximum length for a tag key name. The value is {@value #MAX_LENGTH}. */ + public static final int MAX_LENGTH = 255; + + TagKey() {} + + public abstract String getName(); + + /** + * Applies a function to the {@code TagKey} subclass. The function that is called depends on the + * type of the tag key. This is similar to the visitor pattern. {@code match} also takes a + * function to handle the default case, for backwards compatibility when tag types are added. For + * example, this code creates a {@code Tag} from a {@code TagKey}. It handles new tag types by + * logging an error and returning a {@code TagKeyString}. + * + *

{@code
+   * Tag tag =
+   *     tagKey.match(
+   *         stringKey -> TagString.create(stringKey, TagValueString.create("string value")),
+   *         longKey -> TagLong.create(longKey, 100L),
+   *         booleanKey -> TagBoolean.create(booleanKey, true),
+   *         unknownKey -> {
+   *           logger.log(Level.WARNING, "Unknown tag key type: " + unknownKey.toString());
+   *           return TagString.create(
+   *               TagKeyString.create(unknownKey.getName()),
+   *               TagValueString.create("string value"));
+   *         });
+   * }
+ * + *

Without lambdas: + * + *


+   *   Tag tag =
+   *       tagKey.match(
+   *           new Function<TagKeyString, Tag>() {
+   *            {@literal @}Override
+   *             public Tag apply(TagKeyString stringKey) {
+   *               return TagString.create(stringKey, TagValueString.create("string value"));
+   *             }
+   *           },
+   *           new Function<TagKeyLong, Tag>() {
+   *            {@literal @}Override
+   *             public Tag apply(TagKeyLong longKey) {
+   *               return TagLong.create(longKey, 100L);
+   *             }
+   *           },
+   *           new Function<TagKeyBoolean, Tag>() {
+   *            {@literal @}Override
+   *             public Tag apply(TagKeyBoolean booleanKey) {
+   *               return TagBoolean.create(booleanKey, true);
+   *             }
+   *           },
+   *           new Function<TagKey, Tag>() {
+   *            {@literal @}Override
+   *             public Tag apply(TagKey unknownKey) {
+   *               logger.log(Level.WARNING, "Unknown tag key type: " + unknownKey.toString());
+   *               return TagString.create(
+   *                   TagKeyString.create(unknownKey.getName()),
+   *                   TagValueString.create("string value"));
+   *             }
+   *           });
+   * 
+ * + * @param stringFunction the function to call when the {@code TagKey} is a {@code TagKeyString}. + * @param longFunction the function to call when the {@code TagKey} is a {@code TagKeyLong}. + * @param booleanFunction the function to call when the {@code TagKey} is a {@code TagKeyBoolean}. + * @param defaultFunction the function to call when the tag key has a type other than {@code + * String}, {@code long}, or {@code boolean}. + * @param The result type of the function. + * @return The result of calling the function that matches the tag key's type. + */ + // TODO(sebright): Should we make this public in the first release? + public abstract T match( + Function stringFunction, + Function longFunction, + Function booleanFunction, + Function defaultFunction); + + /** + * Determines whether the given {@code String} is a valid tag key. + * + * @param name the tag key name to be validated. + * @return whether the name is valid. + */ + private static boolean isValid(String name) { + return name.length() <= MAX_LENGTH && StringUtil.isPrintableString(name); + } + + /** A {@code TagKey} for values of type {@code String}. */ + @Immutable + @AutoValue + public abstract static class TagKeyString extends TagKey { + + /** + * Constructs a {@code TagKeyString} with the given name. + * + *

The name must meet the following requirements: + * + *

    + *
  1. It cannot be longer than {@link #MAX_LENGTH}. + *
  2. It can only contain printable ASCII characters. + *
+ * + * @param name the name of the key. + * @return a {@code TagKeyString} with the given name. + * @throws IllegalArgumentException if the name is not valid. + */ + public static TagKeyString create(String name) { + // TODO(sebright): Should we disallow an empty name? + checkArgument(isValid(name)); + return new AutoValue_TagKey_TagKeyString(name); + } + + @Override + public final T match( + Function stringFunction, + Function longFunction, + Function booleanFunction, + Function defaultFunction) { + return stringFunction.apply(this); + } + } + + /** + * A {@code TagKey} for values of type {@code long}. + * + *

Note that {@link TagKeyLong} isn't supported by the implementation yet, so the factory + * method isn't exposed. + */ + @Immutable + @AutoValue + public abstract static class TagKeyLong extends TagKey { + + /** + * Constructs a {@code TagKeyLong} with the given name. + * + *

The name must meet the following requirements: + * + *

    + *
  1. It cannot be longer than {@link #MAX_LENGTH}. + *
  2. It can only contain printable ASCII characters. + *
+ * + * @param name the name of the key. + * @return a {@code TagKeyLong} with the given name. + * @throws IllegalArgumentException if the name is not valid. + */ + // TODO(sebright): Make this public once we support types other than String. + static TagKeyLong create(String name) { + checkArgument(isValid(name)); + return new AutoValue_TagKey_TagKeyLong(name); + } + + @Override + public final T match( + Function stringFunction, + Function longFunction, + Function booleanFunction, + Function defaultFunction) { + return longFunction.apply(this); + } + } + + /** + * A {@code TagKey} for values of type {@code boolean}. + * + *

Note that {@link TagKeyBoolean} isn't supported by the implementation yet, so the factory + * method isn't exposed. + */ + @Immutable + @AutoValue + public abstract static class TagKeyBoolean extends TagKey { + + /** + * Constructs a {@code TagKeyBoolean} with the given name. + * + *

The name must meet the following requirements: + * + *

    + *
  1. It cannot be longer than {@link #MAX_LENGTH}. + *
  2. It can only contain printable ASCII characters. + *
+ * + * @param name the name of the key. + * @return a {@code TagKeyBoolean} with the given name. + * @throws IllegalArgumentException if the name is not valid. + */ + // TODO(sebright): Make this public once we support types other than String. + static TagKeyBoolean create(String name) { + checkArgument(isValid(name)); + return new AutoValue_TagKey_TagKeyBoolean(name); + } + + @Override + public final T match( + Function stringFunction, + Function longFunction, + Function booleanFunction, + Function defaultFunction) { + return booleanFunction.apply(this); + } + } +} diff --git a/api/src/main/java/io/opencensus/tags/TagValue.java b/api/src/main/java/io/opencensus/tags/TagValue.java new file mode 100644 index 00000000..7da713c5 --- /dev/null +++ b/api/src/main/java/io/opencensus/tags/TagValue.java @@ -0,0 +1,182 @@ +/* + * 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.tags; + +import com.google.auto.value.AutoValue; +import com.google.common.base.Preconditions; +import io.opencensus.common.Function; +import io.opencensus.internal.StringUtil; +import io.opencensus.tags.TagKey.TagKeyBoolean; +import io.opencensus.tags.TagKey.TagKeyLong; +import io.opencensus.tags.TagKey.TagKeyString; +import javax.annotation.concurrent.Immutable; + +/** A validated tag value. */ +@Immutable +public abstract class TagValue { + + TagValue() {} + + /** + * Applies a function to a tag value. The function that is called depends on the type of the + * value. This is similar to the visitor pattern. {@code match} also takes a function to handle + * the default case, for backwards compatibility when tag types are added. + * + * @param stringFunction the function to call when the tag value has type {@code String}. + * @param longFunction the function to call when the tag value has type {@code long}. + * @param booleanFunction the function to call when the tag value has type {@code boolean}. + * @param defaultFunction the function to call when the tag value has a type other than {@code + * String}, {@code long}, or {@code boolean}. + * @param The result type of the function. + * @return The result of calling the function that matches the tag value's type. + */ + public abstract T match( + Function stringFunction, + Function longFunction, + Function booleanFunction, + Function defaultFunction); + + /** + * A validated tag value associated with a {@link TagKeyString}. + * + *

Validation ensures that the {@code String} has a maximum length of {@link #MAX_LENGTH} and + * contains only printable ASCII characters. + */ + @Immutable + @AutoValue + public abstract static class TagValueString extends TagValue { + /** The maximum length for a {@code String} tag value. The value is {@value #MAX_LENGTH}. */ + public static final int MAX_LENGTH = 256; + + TagValueString() {} + + /** + * Constructs a {@code TagValueString} from the given string. The string must meet the following + * requirements: + * + *

    + *
  1. It cannot be longer than {@link #MAX_LENGTH}. + *
  2. It can only contain printable ASCII characters. + *
+ * + * @param value the tag value. + * @throws IllegalArgumentException if the {@code String} is not valid. + */ + public static TagValueString create(String value) { + Preconditions.checkArgument(isValid(value)); + return new AutoValue_TagValue_TagValueString(value); + } + + @Override + public final T match( + Function stringFunction, + Function longFunction, + Function booleanFunction, + Function defaultFunction) { + return stringFunction.apply(this); + } + + /** + * Returns the tag value as a {@code String}. + * + * @return the tag value as a {@code String}. + */ + public abstract String asString(); + + /** + * Determines whether the given {@code String} is a valid tag value. + * + * @param value the tag value to be validated. + * @return whether the value is valid. + */ + private static boolean isValid(String value) { + return value.length() <= MAX_LENGTH && StringUtil.isPrintableString(value); + } + } + + /** A tag value associated with a {@link TagKeyLong}. */ + @Immutable + @AutoValue + public abstract static class TagValueLong extends TagValue { + + TagValueLong() {} + + /** + * Constructs a {@code TagValueLong} from the given {@code long}. + * + * @param value the tag value. + */ + public static TagValueLong create(long value) { + return new AutoValue_TagValue_TagValueLong(value); + } + + @Override + public final T match( + Function stringFunction, + Function longFunction, + Function booleanFunction, + Function defaultFunction) { + return longFunction.apply(this); + } + + /** + * Returns the tag value as a {@code long}. + * + * @return the tag value as a {@code long}. + */ + public abstract long asLong(); + } + + /** A tag value associated with a {@link TagKeyBoolean}. */ + @Immutable + @AutoValue + public abstract static class TagValueBoolean extends TagValue { + private static final TagValueBoolean TRUE_VALUE = createInternal(true); + private static final TagValueBoolean FALSE_VALUE = createInternal(false); + + TagValueBoolean() {} + + /** + * Constructs a {@code TagValueBoolean} from the given {@code boolean}. + * + * @param value the tag value. + */ + public static TagValueBoolean create(boolean value) { + return value ? TRUE_VALUE : FALSE_VALUE; + } + + private static TagValueBoolean createInternal(boolean value) { + return new AutoValue_TagValue_TagValueBoolean(value); + } + + @Override + public final T match( + Function stringFunction, + Function longFunction, + Function booleanFunction, + Function defaultFunction) { + return booleanFunction.apply(this); + } + + /** + * Returns the tag value as a {@code boolean}. + * + * @return the tag value as a {@code boolean}. + */ + public abstract boolean asBoolean(); + } +} diff --git a/api/src/main/java/io/opencensus/tags/Tagger.java b/api/src/main/java/io/opencensus/tags/Tagger.java new file mode 100644 index 00000000..1d786f71 --- /dev/null +++ b/api/src/main/java/io/opencensus/tags/Tagger.java @@ -0,0 +1,78 @@ +/* + * 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.tags; + +import io.opencensus.common.Scope; + +/** + * Object for creating new {@link TagContext}s and {@code TagContext}s based on the current context. + * + *

This class returns {@link TagContextBuilder builders} that can be used to create the + * implementation-dependent {@link TagContext}s. + * + *

Implementations may have different constraints and are free to convert tag contexts to their + * own subtypes. This means callers cannot assume the {@link #getCurrentTagContext() current + * context} is the same instance as the one {@link #withTagContext(TagContext) placed into scope}. + */ +public abstract class Tagger { + + /** + * Returns an empty {@code TagContext}. + * + * @return an empty {@code TagContext}. + */ + public abstract TagContext empty(); + + /** + * Returns the current {@code TagContext}. + * + * @return the current {@code TagContext}. + */ + public abstract TagContext getCurrentTagContext(); + + /** + * Returns a new empty {@code Builder}. + * + * @return a new empty {@code Builder}. + */ + public abstract TagContextBuilder emptyBuilder(); + + /** + * Returns a builder based on this {@code TagContext}. + * + * @return a builder based on this {@code TagContext}. + */ + public abstract TagContextBuilder toBuilder(TagContext tags); + + /** + * Returns a new builder created from the current {@code TagContext}. + * + * @return a new builder created from the current {@code TagContext}. + */ + public abstract TagContextBuilder currentBuilder(); + + /** + * Enters the scope of code where the given {@code TagContext} is in the current context and + * returns an object that represents that scope. The scope is exited when the returned object is + * closed. + * + * @param tags the {@code TagContext} to be set to the current context. + * @return an object that defines a scope where the given {@code TagContext} is set to the current + * context. + */ + public abstract Scope withTagContext(TagContext tags); +} diff --git a/api/src/main/java/io/opencensus/tags/TaggingState.java b/api/src/main/java/io/opencensus/tags/TaggingState.java new file mode 100644 index 00000000..861aca74 --- /dev/null +++ b/api/src/main/java/io/opencensus/tags/TaggingState.java @@ -0,0 +1,40 @@ +/* + * 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.tags; + +/** State of the {@link TagsComponent}. */ +public enum TaggingState { + // TODO(sebright): Should we add a state that propagates the tags, but doesn't allow + // modifications? + + /** + * State that fully enables tagging. + * + *

The {@link TagsComponent} can add tags to {@link TagContext}s, propagate {@code TagContext}s + * in the current context, and serialize {@code TagContext}s. + */ + ENABLED, + + /** + * State that disables tagging. + * + *

The {@link TagsComponent} may not add tags to {@link TagContext}s, propagate {@code + * TagContext}s in the current context, or serialize {@code TagContext}s. + */ + // TODO(sebright): Document how this interacts with stats collection. + DISABLED +} diff --git a/api/src/main/java/io/opencensus/tags/Tags.java b/api/src/main/java/io/opencensus/tags/Tags.java new file mode 100644 index 00000000..5378fa5a --- /dev/null +++ b/api/src/main/java/io/opencensus/tags/Tags.java @@ -0,0 +1,104 @@ +/* + * 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.tags; + +import com.google.common.annotations.VisibleForTesting; +import io.opencensus.internal.Provider; +import io.opencensus.tags.propagation.TagPropagationComponent; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** Class for accessing the default {@link TagsComponent}. */ +public final class Tags { + private static final Logger logger = Logger.getLogger(Tags.class.getName()); + + private static final TagsComponent tagsComponent = + loadTagsComponent(TagsComponent.class.getClassLoader()); + + private Tags() {} + + /** + * Returns the default {@code Tagger}. + * + * @return the default {@code Tagger}. + */ + public static Tagger getTagger() { + return tagsComponent.getTagger(); + } + + /** + * Returns the default {@code TagPropagationComponent}. + * + * @return the default {@code TagPropagationComponent}. + */ + public static TagPropagationComponent getTagPropagationComponent() { + return tagsComponent.getTagPropagationComponent(); + } + + /** + * Returns the current {@code TaggingState}. + * + *

When no implementation is available, {@code getState} always returns {@link + * TaggingState#DISABLED}. + * + * @return the current {@code TaggingState}. + */ + public static TaggingState getState() { + return tagsComponent.getState(); + } + + /** + * Sets the current {@code TaggingState}. + * + *

When no implementation is available, {@code setState} has no effect. + * + * @param state the new {@code TaggingState}. + */ + public static void setState(TaggingState state) { + tagsComponent.setState(state); + } + + // Any provider that may be used for TagsComponent can be added here. + @VisibleForTesting + static TagsComponent loadTagsComponent(ClassLoader classLoader) { + try { + // Call Class.forName with literal string name of the class to help shading tools. + return Provider.createInstance( + Class.forName("io.opencensus.impl.tags.TagsComponentImpl", true, classLoader), + TagsComponent.class); + } catch (ClassNotFoundException e) { + logger.log( + Level.FINE, + "Couldn't load full implementation for TagsComponent, now trying to load lite " + + "implementation.", + e); + } + try { + // Call Class.forName with literal string name of the class to help shading tools. + return Provider.createInstance( + Class.forName("io.opencensus.impllite.tags.TagsComponentImplLite", true, classLoader), + TagsComponent.class); + } catch (ClassNotFoundException e) { + logger.log( + Level.FINE, + "Couldn't load lite implementation for TagsComponent, now using " + + "default implementation for TagsComponent.", + e); + } + return NoopTags.getNoopTagsComponent(); + } +} diff --git a/api/src/main/java/io/opencensus/tags/TagsComponent.java b/api/src/main/java/io/opencensus/tags/TagsComponent.java new file mode 100644 index 00000000..755173d8 --- /dev/null +++ b/api/src/main/java/io/opencensus/tags/TagsComponent.java @@ -0,0 +1,52 @@ +/* + * 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.tags; + +import io.opencensus.tags.propagation.TagPropagationComponent; + +/** + * Class that holds the implementation for {@link Tagger} and {@link TagPropagationComponent}. + * + *

All objects returned by methods on {@code TagsComponent} are cacheable. + */ +public abstract class TagsComponent { + + /** Returns the {@link Tagger} for this implementation. */ + public abstract Tagger getTagger(); + + /** Returns the {@link TagPropagationComponent} for this implementation. */ + public abstract TagPropagationComponent getTagPropagationComponent(); + + /** + * Returns the current {@code TaggingState}. + * + *

When no implementation is available, {@code getState} always returns {@link + * TaggingState#DISABLED}. + * + * @return the current {@code TaggingState}. + */ + public abstract TaggingState getState(); + + /** + * Sets the current {@code TaggingState}. + * + *

When no implementation is available, {@code setState} has no effect. + * + * @param state the new {@code TaggingState}. + */ + public abstract void setState(TaggingState state); +} diff --git a/api/src/main/java/io/opencensus/tags/package-info.java b/api/src/main/java/io/opencensus/tags/package-info.java new file mode 100644 index 00000000..2a332f6d --- /dev/null +++ b/api/src/main/java/io/opencensus/tags/package-info.java @@ -0,0 +1,33 @@ +/* + * 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. + */ + +/** + * API for associating tags with scoped operations. + * + *

This package manages a set of tags in the {@code io.grpc.Context}. The tags can be used to + * label anything that is associated with a specific operation. For example, the {@code + * io.opencensus.stats} package labels all stats with the current tags. + * + *

{@link io.opencensus.tags.Tag Tags} are key-value pairs. The {@link io.opencensus.tags.TagKey + * keys} are wrapped {@code String}s, but the values can have multiple types, such as {@code + * String}, {@code long}, and {@code boolean}. They are stored as a map in a {@link + * io.opencensus.tags.TagContext}. + * + *

Note that tags are independent of the tracing data that is propagated in the {@code + * io.grpc.Context}, such as trace ID. + */ +// TODO(sebright): Add code examples after the API is updated to use a TagContext factory. +package io.opencensus.tags; diff --git a/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java b/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java new file mode 100644 index 00000000..e54e5d3d --- /dev/null +++ b/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java @@ -0,0 +1,51 @@ +/* + * 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.tags.propagation; + +import io.opencensus.tags.TagContext; + +/** + * Object for serializing and deserializing {@link TagContext}s with the binary format. + * + *

See opencensus-specs + * for the specification of the cross-language binary serialization format. + */ +public abstract class TagContextBinarySerializer { + + /** + * Serializes the {@code TagContext} into the on-the-wire representation. + * + *

This method should be the inverse of {@link #fromByteArray}. + * + * @param tags the {@code TagContext} to serialize. + * @return the on-the-wire representation of a {@code TagContext}. + */ + public abstract byte[] toByteArray(TagContext tags); + + /** + * Creates a {@code TagContext} from the given on-the-wire encoded representation. + * + *

This method should be the inverse of {@link #toByteArray}. + * + * @param bytes on-the-wire representation of a {@code TagContext}. + * @return a {@code TagContext} deserialized from {@code bytes}. + * @throws TagContextParseException if there is a parse error or the serialized {@code TagContext} + * contains invalid tags. + */ + public abstract TagContext fromByteArray(byte[] bytes) throws TagContextParseException; +} diff --git a/api/src/main/java/io/opencensus/tags/propagation/TagContextParseException.java b/api/src/main/java/io/opencensus/tags/propagation/TagContextParseException.java new file mode 100644 index 00000000..0174c416 --- /dev/null +++ b/api/src/main/java/io/opencensus/tags/propagation/TagContextParseException.java @@ -0,0 +1,43 @@ +/* + * 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.tags.propagation; + +import io.opencensus.tags.TagContext; + +/** Exception thrown when a {@link TagContext} cannot be parsed. */ +public final class TagContextParseException extends Exception { + private static final long serialVersionUID = 0L; + + /** + * Constructs a new {@code TagContextParseException} with the given message. + * + * @param message a message describing the parse error. + */ + public TagContextParseException(String message) { + super(message); + } + + /** + * Constructs a new {@code TagContextParseException} with the given message and cause. + * + * @param message a message describing the parse error. + * @param cause the cause of the parse error. + */ + public TagContextParseException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/api/src/main/java/io/opencensus/tags/propagation/TagPropagationComponent.java b/api/src/main/java/io/opencensus/tags/propagation/TagPropagationComponent.java new file mode 100644 index 00000000..c51a845c --- /dev/null +++ b/api/src/main/java/io/opencensus/tags/propagation/TagPropagationComponent.java @@ -0,0 +1,31 @@ +/* + * 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.tags.propagation; + +import io.opencensus.tags.TagContext; + +/** Object containing all supported {@link TagContext} propagation formats. */ +// TODO(sebright): Add an HTTP serializer. +public abstract class TagPropagationComponent { + + /** + * Returns the {@link TagContextBinarySerializer} for this implementation. + * + * @return the {@code TagContextBinarySerializer} for this implementation. + */ + public abstract TagContextBinarySerializer getBinarySerializer(); +} diff --git a/api/src/main/java/io/opencensus/tags/unsafe/ContextUtils.java b/api/src/main/java/io/opencensus/tags/unsafe/ContextUtils.java new file mode 100644 index 00000000..2baf1a2a --- /dev/null +++ b/api/src/main/java/io/opencensus/tags/unsafe/ContextUtils.java @@ -0,0 +1,52 @@ +/* + * 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.tags.unsafe; + +import io.grpc.Context; +import io.opencensus.tags.Tag; +import io.opencensus.tags.TagContext; +import java.util.Collections; +import java.util.Iterator; +import javax.annotation.concurrent.Immutable; + +/** + * Utility methods for accessing the {@link TagContext} contained in the {@link io.grpc.Context}. + * + *

Most code should interact with the current context via the public APIs in {@link + * io.opencensus.tags.TagContext} and avoid accessing {@link #TAG_CONTEXT_KEY} directly. + */ +public final class ContextUtils { + private static final TagContext EMPTY_TAG_CONTEXT = new EmptyTagContext(); + + private ContextUtils() {} + + /** + * The {@link io.grpc.Context.Key} used to interact with the {@code TagContext} contained in the + * {@link io.grpc.Context}. + */ + public static final Context.Key TAG_CONTEXT_KEY = + Context.keyWithDefault("opencensus-tag-context-key", EMPTY_TAG_CONTEXT); + + @Immutable + private static final class EmptyTagContext extends TagContext { + + @Override + protected Iterator getIterator() { + return Collections.emptySet().iterator(); + } + } +} diff --git a/api/src/test/java/io/opencensus/stats/AggregationDataTest.java b/api/src/test/java/io/opencensus/stats/AggregationDataTest.java new file mode 100644 index 00000000..3eafd18e --- /dev/null +++ b/api/src/test/java/io/opencensus/stats/AggregationDataTest.java @@ -0,0 +1,168 @@ +/* + * 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.stats; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Function; +import io.opencensus.common.Functions; +import io.opencensus.stats.AggregationData.CountData; +import io.opencensus.stats.AggregationData.DistributionData; +import io.opencensus.stats.AggregationData.MeanData; +import io.opencensus.stats.AggregationData.SumDataDouble; +import io.opencensus.stats.AggregationData.SumDataLong; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link io.opencensus.stats.AggregationData}. */ +@RunWith(JUnit4.class) +public class AggregationDataTest { + + private static final double TOLERANCE = 1e-6; + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void testCreateDistributionData() { + DistributionData distributionData = DistributionData.create( + 7.7, 10, 1.1, 9.9, 32.2, new long[]{4, 1, 5}); + assertThat(distributionData.getMean()).isWithin(TOLERANCE).of(7.7); + assertThat(distributionData.getCount()).isEqualTo(10); + assertThat(distributionData.getMin()).isWithin(TOLERANCE).of(1.1); + assertThat(distributionData.getMax()).isWithin(TOLERANCE).of(9.9); + assertThat(distributionData.getSumOfSquaredDeviations()).isWithin(TOLERANCE).of(32.2); + assertThat(distributionData.getBucketCounts()).containsExactly(4L, 1L, 5L).inOrder(); + } + + @Test + public void preventNullBucketCountData() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("bucket counts should not be null."); + DistributionData.create(1, 1, 1, 1, 0, null); + } + + @Test + public void preventMinIsGreaterThanMax() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("max should be greater or equal to min."); + DistributionData.create(1, 1, 10, 1, 0, new long[]{0, 1, 0}); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + SumDataDouble.create(10.0), + SumDataDouble.create(10.0)) + .addEqualityGroup( + SumDataDouble.create(20.0), + SumDataDouble.create(20.0)) + .addEqualityGroup( + SumDataLong.create(20), + SumDataLong.create(20)) + .addEqualityGroup( + CountData.create(40), + CountData.create(40)) + .addEqualityGroup( + CountData.create(80), + CountData.create(80)) + .addEqualityGroup( + DistributionData.create(10, 10, 1, 1, 0, new long[]{0, 10, 0}), + DistributionData.create(10, 10, 1, 1, 0, new long[]{0, 10, 0})) + .addEqualityGroup( + DistributionData.create(10, 10, 1, 1, 0, new long[]{0, 10, 100})) + .addEqualityGroup( + DistributionData.create(110, 10, 1, 1, 0, new long[]{0, 10, 0})) + .addEqualityGroup( + DistributionData.create(10, 110, 1, 1, 0, new long[]{0, 10, 0})) + .addEqualityGroup( + DistributionData.create(10, 10, -1, 1, 0, new long[]{0, 10, 0})) + .addEqualityGroup( + DistributionData.create(10, 10, 1, 5, 0, new long[]{0, 10, 0})) + .addEqualityGroup( + DistributionData.create(10, 10, 1, 1, 55.5, new long[]{0, 10, 0})) + .addEqualityGroup( + MeanData.create(5.0, 1), + MeanData.create(5.0, 1)) + .addEqualityGroup( + MeanData.create(-5.0, 1), + MeanData.create(-5.0, 1)) + .testEquals(); + } + + @Test + public void testMatchAndGet() { + List aggregations = Arrays.asList( + SumDataDouble.create(10.0), + SumDataLong.create(100000000), + CountData.create(40), + MeanData.create(5.0, 1), + DistributionData.create(1, 1, 1, 1, 0, new long[]{0, 10, 0})); + + final List actual = new ArrayList(); + for (AggregationData aggregation : aggregations) { + aggregation.match( + new Function() { + @Override + public Void apply(SumDataDouble arg) { + actual.add(arg.getSum()); + return null; + } + }, + new Function() { + @Override + public Void apply(SumDataLong arg) { + actual.add(arg.getSum()); + return null; + } + }, + new Function() { + @Override + public Void apply(CountData arg) { + actual.add(arg.getCount()); + return null; + } + }, + new Function() { + @Override + public Void apply(MeanData arg) { + actual.add(arg.getMean()); + return null; + } + }, + new Function() { + @Override + public Void apply(DistributionData arg) { + actual.add(arg.getBucketCounts()); + return null; + } + }, + Functions.throwIllegalArgumentException()); + } + + assertThat(actual).isEqualTo( + Arrays.asList(10.0, 100000000L, 40L, 5.0, Arrays.asList(0L, 10L, 0L))); + } +} diff --git a/api/src/test/java/io/opencensus/stats/AggregationTest.java b/api/src/test/java/io/opencensus/stats/AggregationTest.java new file mode 100644 index 00000000..66376cbb --- /dev/null +++ b/api/src/test/java/io/opencensus/stats/AggregationTest.java @@ -0,0 +1,119 @@ +/* + * 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.stats; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Function; +import io.opencensus.common.Functions; +import io.opencensus.stats.Aggregation.Count; +import io.opencensus.stats.Aggregation.Distribution; +import io.opencensus.stats.Aggregation.Mean; +import io.opencensus.stats.Aggregation.Sum; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link io.opencensus.stats.Aggregation}. */ +@RunWith(JUnit4.class) +public class AggregationTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void testCreateDistribution() { + BucketBoundaries bucketBoundaries = BucketBoundaries.create(Arrays.asList(0.1, 2.2, 33.3)); + Distribution distribution = Distribution.create(bucketBoundaries); + assertThat(distribution.getBucketBoundaries()).isEqualTo(bucketBoundaries); + } + + @Test + public void testNullBucketBoundaries() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("bucketBoundaries should not be null."); + Distribution.create(null); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + Sum.create(), + Sum.create()) + .addEqualityGroup( + Count.create(), + Count.create()) + .addEqualityGroup( + Distribution.create(BucketBoundaries.create(Arrays.asList(-10.0, 1.0, 5.0))), + Distribution.create(BucketBoundaries.create(Arrays.asList(-10.0, 1.0, 5.0)))) + .addEqualityGroup( + Distribution.create(BucketBoundaries.create(Arrays.asList(0.0, 1.0, 5.0))), + Distribution.create(BucketBoundaries.create(Arrays.asList(0.0, 1.0, 5.0)))) + .addEqualityGroup( + Mean.create(), + Mean.create()) + .testEquals(); + } + + @Test + public void testMatch() { + List aggregations = Arrays.asList( + Sum.create(), + Count.create(), + Mean.create(), + Distribution.create(BucketBoundaries.create(Arrays.asList(-10.0, 1.0, 5.0)))); + + List actual = new ArrayList(); + for (Aggregation aggregation : aggregations) { + actual.add(aggregation.match( + new Function() { + @Override + public String apply(Sum arg) { + return "SUM"; + } + }, + new Function() { + @Override + public String apply(Count arg) { + return "COUNT"; + } + }, + new Function() { + @Override + public String apply(Mean arg) { + return "MEAN"; + } + }, + new Function() { + @Override + public String apply(Distribution arg) { + return "DISTRIBUTION"; + } + }, + Functions.throwIllegalArgumentException())); + } + + assertThat(actual).isEqualTo(Arrays.asList("SUM", "COUNT", "MEAN", "DISTRIBUTION")); + } +} diff --git a/api/src/test/java/io/opencensus/stats/BucketBoundariesTest.java b/api/src/test/java/io/opencensus/stats/BucketBoundariesTest.java new file mode 100644 index 00000000..e3fd3222 --- /dev/null +++ b/api/src/test/java/io/opencensus/stats/BucketBoundariesTest.java @@ -0,0 +1,90 @@ +/* + * 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.stats; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Unit tests for {@link io.opencensus.stats.BucketBoundaries}. + */ +@RunWith(JUnit4.class) +public class BucketBoundariesTest { + + @Rule + public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void testConstructBoundaries() { + List buckets = Arrays.asList(0.0, 1.0, 2.0); + BucketBoundaries bucketBoundaries = BucketBoundaries.create(buckets); + assertThat(bucketBoundaries.getBoundaries()).isEqualTo(buckets); + } + + @Test + public void testBoundariesDoesNotChangeWithOriginalList() { + List original = new ArrayList(); + original.add(0.0); + original.add(1.0); + original.add(2.0); + BucketBoundaries bucketBoundaries = BucketBoundaries.create(original); + original.set(2, 3.0); + original.add(4.0); + List expected = Arrays.asList(0.0, 1.0, 2.0); + assertThat(bucketBoundaries.getBoundaries()).isNotEqualTo(original); + assertThat(bucketBoundaries.getBoundaries()).isEqualTo(expected); + } + + @Test + public void testNullBoundaries() throws Exception { + thrown.expect(NullPointerException.class); + BucketBoundaries.create(null); + } + + @Test + public void testUnsortedBoundaries() throws Exception { + List buckets = Arrays.asList(0.0, 1.0, 1.0); + thrown.expect(IllegalArgumentException.class); + BucketBoundaries.create(buckets); + } + + @Test + public void testNoBoundaries() { + List buckets = Arrays.asList(); + BucketBoundaries bucketBoundaries = BucketBoundaries.create(buckets); + assertThat(bucketBoundaries.getBoundaries()).isEqualTo(buckets); + } + + @Test + public void testBucketBoundariesEquals() { + new EqualsTester() + .addEqualityGroup( + BucketBoundaries.create(Arrays.asList(-1.0, 2.0)), + BucketBoundaries.create(Arrays.asList(-1.0, 2.0))) + .addEqualityGroup(BucketBoundaries.create(Arrays.asList(-1.0))) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/stats/MeasureMapTest.java b/api/src/test/java/io/opencensus/stats/MeasureMapTest.java new file mode 100644 index 00000000..1a408e85 --- /dev/null +++ b/api/src/test/java/io/opencensus/stats/MeasureMapTest.java @@ -0,0 +1,132 @@ +/* + * Copyright 2016-17, 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.stats; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.collect.Lists; +import io.opencensus.stats.Measure.MeasureDouble; +import io.opencensus.stats.Measure.MeasureLong; +import io.opencensus.stats.Measurement.MeasurementDouble; +import io.opencensus.stats.Measurement.MeasurementLong; +import java.util.ArrayList; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link MeasureMap}. */ +@RunWith(JUnit4.class) +public class MeasureMapTest { + + @Test + public void testPutDouble() { + MeasureMap metrics = MeasureMap.builder().put(M1, 44.4).build(); + assertContains(metrics, MeasurementDouble.create(M1, 44.4)); + } + + @Test + public void testPutLong() { + MeasureMap metrics = MeasureMap.builder().put(M3, 9999L).put(M4, 8888L).build(); + assertContains(metrics, + MeasurementLong.create(M3, 9999L), + MeasurementLong.create(M4, 8888L)); + } + + @Test + public void testCombination() { + MeasureMap metrics = + MeasureMap.builder().put(M1, 44.4).put(M2, 66.6).put(M3, 9999L).put(M4, 8888L).build(); + assertContains(metrics, + MeasurementDouble.create(M1, 44.4), + MeasurementDouble.create(M2, 66.6), + MeasurementLong.create(M3, 9999L), + MeasurementLong.create(M4, 8888L)); + } + + @Test + public void testBuilderEmpty() { + MeasureMap metrics = MeasureMap.builder().build(); + assertContains(metrics); + } + + @Test + public void testBuilder() { + ArrayList expected = new ArrayList(10); + MeasureMap.Builder builder = MeasureMap.builder(); + for (int i = 1; i <= 10; i++) { + expected + .add(MeasurementDouble.create(makeSimpleMeasureDouble("m" + i), i * 11.1)); + builder.put(makeSimpleMeasureDouble("m" + i), i * 11.1); + assertContains(builder.build(), expected.toArray(new Measurement[i])); + } + } + + @Test + public void testDuplicateMeasureDoubles() { + assertContains(MeasureMap.builder().put(M1, 1.0).put(M1, 2.0).build(), + MeasurementDouble.create(M1, 2.0)); + assertContains(MeasureMap.builder().put(M1, 1.0).put(M1, 2.0).put(M1, 3.0).build(), + MeasurementDouble.create(M1, 3.0)); + assertContains(MeasureMap.builder().put(M1, 1.0).put(M2, 2.0).put(M1, 3.0).build(), + MeasurementDouble.create(M1, 3.0), + MeasurementDouble.create(M2, 2.0)); + assertContains(MeasureMap.builder().put(M1, 1.0).put(M1, 2.0).put(M2, 2.0).build(), + MeasurementDouble.create(M1, 2.0), + MeasurementDouble.create(M2, 2.0)); + } + + @Test + public void testDuplicateMeasureLongs() { + assertContains(MeasureMap.builder().put(M3, 100L).put(M3, 100L).build(), + MeasurementLong.create(M3, 100L)); + assertContains(MeasureMap.builder().put(M3, 100L).put(M3, 200L).put(M3, 300L).build(), + MeasurementLong.create(M3, 300L)); + assertContains(MeasureMap.builder().put(M3, 100L).put(M4, 200L).put(M3, 300L).build(), + MeasurementLong.create(M3, 300L), + MeasurementLong.create(M4, 200L)); + assertContains(MeasureMap.builder().put(M3, 100L).put(M3, 200L).put(M4, 200L).build(), + MeasurementLong.create(M3, 200L), + MeasurementLong.create(M4, 200L)); + } + + @Test + public void testDuplicateMeasures() { + assertContains(MeasureMap.builder().put(M3, 100L).put(M1, 1.0).put(M3, 300L).build(), + MeasurementLong.create(M3, 300L), + MeasurementDouble.create(M1, 1.0)); + assertContains(MeasureMap.builder().put(M2, 2.0).put(M3, 100L).put(M2, 3.0).build(), + MeasurementDouble.create(M2, 3.0), + MeasurementLong.create(M3, 100L)); + } + + private static final MeasureDouble M1 = makeSimpleMeasureDouble("m1"); + private static final MeasureDouble M2 = makeSimpleMeasureDouble("m2"); + private static final MeasureLong M3 = makeSimpleMeasureLong("m3"); + private static final MeasureLong M4 = makeSimpleMeasureLong("m4"); + + private static MeasureDouble makeSimpleMeasureDouble(String measure) { + return Measure.MeasureDouble.create(measure, measure + " description", "1"); + } + + private static MeasureLong makeSimpleMeasureLong(String measure) { + return Measure.MeasureLong.create(measure, measure + " description", "1"); + } + + private static void assertContains(MeasureMap metrics, Measurement... measurements) { + assertThat(Lists.newArrayList(metrics.iterator())).containsExactly((Object[]) measurements); + } +} diff --git a/api/src/test/java/io/opencensus/stats/MeasureTest.java b/api/src/test/java/io/opencensus/stats/MeasureTest.java new file mode 100644 index 00000000..d243637a --- /dev/null +++ b/api/src/test/java/io/opencensus/stats/MeasureTest.java @@ -0,0 +1,155 @@ +/* + * Copyright 2016-17, 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.stats; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.collect.Lists; +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Function; +import io.opencensus.common.Functions; +import io.opencensus.stats.Measure.MeasureDouble; +import io.opencensus.stats.Measure.MeasureLong; +import java.util.Arrays; +import java.util.List; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link Measure}. */ +@RunWith(JUnit4.class) +public final class MeasureTest { + + @Rule + public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void testConstants() { + assertThat(Measure.NAME_MAX_LENGTH).isEqualTo(256); + } + + @Test + public void preventTooLongMeasureName() { + char[] chars = new char[Measure.NAME_MAX_LENGTH + 1]; + Arrays.fill(chars, 'a'); + String longName = String.valueOf(chars); + thrown.expect(IllegalArgumentException.class); + Measure.MeasureDouble.create(longName, "description", "1"); + } + + @Test + public void preventNonPrintableMeasureName() { + thrown.expect(IllegalArgumentException.class); + Measure.MeasureDouble.create("\2", "description", "1"); + } + + @Test + public void testMeasureDoubleComponents() { + Measure measurement = Measure.MeasureDouble.create( + "Foo", + "The description of Foo", + "Mbit/s"); + assertThat(measurement.getName()).isEqualTo("Foo"); + assertThat(measurement.getDescription()).isEqualTo("The description of Foo"); + assertThat(measurement.getUnit()).isEqualTo("Mbit/s"); + } + + @Test + public void testMeasureLongComponents() { + Measure measurement = Measure.MeasureLong.create( + "Bar", + "The description of Bar", + "1"); + assertThat(measurement.getName()).isEqualTo("Bar"); + assertThat(measurement.getDescription()).isEqualTo("The description of Bar"); + assertThat(measurement.getUnit()).isEqualTo("1"); + } + + @Test + public void testMeasureDoubleEquals() { + new EqualsTester() + .addEqualityGroup( + Measure.MeasureDouble.create( + "name", + "description", + "bit/s"), + Measure.MeasureDouble.create( + "name", + "description", + "bit/s")) + .addEqualityGroup( + Measure.MeasureDouble.create( + "name", + "description 2", + "bit/s")) + .testEquals(); + } + + @Test + public void testMeasureLongEquals() { + new EqualsTester() + .addEqualityGroup( + Measure.MeasureLong.create( + "name", + "description", + "bit/s"), + Measure.MeasureLong.create( + "name", + "description", + "bit/s")) + .addEqualityGroup( + Measure.MeasureLong.create( + "name", + "description 2", + "bit/s")) + .testEquals(); + } + + @Test + public void testMatch() { + List measures = Arrays.asList( + MeasureDouble.create("measure1", "description", "1"), + MeasureLong.create("measure2", "description", "1")); + List outputs = Lists.newArrayList(); + for (Measure measure : measures) { + outputs.add( + measure.match( + new Function() { + @Override + public String apply(MeasureDouble arg) { + return "double"; + } + }, + new Function() { + @Override + public String apply(MeasureLong arg) { + return "long"; + } + }, + Functions.throwAssertionError())); + } + assertThat(outputs).containsExactly("double", "long").inOrder(); + } + + @Test + public void testMeasureDoubleIsNotEqualToMeasureLong() { + assertThat(Measure.MeasureDouble.create("name", "description", "bit/s")) + .isNotEqualTo(Measure.MeasureLong.create("name", "description", "bit/s")); + } +} diff --git a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java new file mode 100644 index 00000000..8348adc4 --- /dev/null +++ b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java @@ -0,0 +1,118 @@ +/* + * 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.stats; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.stats.Measure.MeasureDouble; +import io.opencensus.tags.Tag; +import io.opencensus.tags.Tag.TagString; +import io.opencensus.tags.TagContext; +import io.opencensus.tags.TagKey.TagKeyString; +import io.opencensus.tags.TagValue.TagValueString; +import java.util.Collections; +import java.util.Iterator; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Unit tests for {@link NoopStats}. Tests for {@link NoopStats#newNoopViewManager} are in {@link + * NoopViewManagerTest} + */ +@RunWith(JUnit4.class) +public final class NoopStatsTest { + private static final TagString TAG = + TagString.create(TagKeyString.create("key"), TagValueString.create("value")); + private static final MeasureDouble MEASURE = + Measure.MeasureDouble.create("my measure", "description", "s"); + + private final TagContext tagContext = + new TagContext() { + + @Override + protected Iterator getIterator() { + return Collections.singleton(TAG).iterator(); + } + }; + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void noopStatsComponent() { + assertThat(NoopStats.newNoopStatsComponent().getStatsRecorder()) + .isSameAs(NoopStats.getNoopStatsRecorder()); + assertThat(NoopStats.newNoopStatsComponent().getViewManager()) + .isInstanceOf(NoopStats.newNoopViewManager().getClass()); + } + + @Test + public void noopStatsComponent_GetState() { + assertThat(NoopStats.newNoopStatsComponent().getState()) + .isEqualTo(StatsCollectionState.DISABLED); + } + + @Test + public void noopStatsComponent_SetState_IgnoresInput() { + StatsComponent noopStatsComponent = NoopStats.newNoopStatsComponent(); + noopStatsComponent.setState(StatsCollectionState.ENABLED); + assertThat(noopStatsComponent.getState()).isEqualTo(StatsCollectionState.DISABLED); + } + + @Test + public void noopStatsComponent_SetState_DisallowsNull() { + StatsComponent noopStatsComponent = NoopStats.newNoopStatsComponent(); + thrown.expect(NullPointerException.class); + noopStatsComponent.setState(null); + } + + // The NoopStatsRecorder should do nothing, so this test just checks that record doesn't throw an + // exception. + @Test + public void noopStatsRecorder_Record() { + NoopStats.getNoopStatsRecorder() + .record(tagContext, MeasureMap.builder().put(MEASURE, 5).build()); + } + + // The NoopStatsRecorder should do nothing, so this test just checks that record doesn't throw an + // exception. + @Test + public void noopStatsRecorder_RecordWithCurrentContext() { + NoopStats.getNoopStatsRecorder().record(MeasureMap.builder().put(MEASURE, 6).build()); + } + + @Test + public void noopStatsRecorder_Record_DisallowNullTagContext() { + MeasureMap measures = MeasureMap.builder().put(MEASURE, 7).build(); + thrown.expect(NullPointerException.class); + NoopStats.getNoopStatsRecorder().record(null, measures); + } + + @Test + public void noopStatsRecorder_Record_DisallowNullMeasureMap() { + thrown.expect(NullPointerException.class); + NoopStats.getNoopStatsRecorder().record(tagContext, null); + } + + @Test + public void noopStatsRecorder_RecordWithCurrentContext_DisallowNullMeasureMap() { + thrown.expect(NullPointerException.class); + NoopStats.getNoopStatsRecorder().record(null); + } +} diff --git a/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java b/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java new file mode 100644 index 00000000..01196e1d --- /dev/null +++ b/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java @@ -0,0 +1,134 @@ +/* + * 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.stats; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.common.Duration; +import io.opencensus.common.Timestamp; +import io.opencensus.stats.Aggregation.Sum; +import io.opencensus.stats.Measure.MeasureDouble; +import io.opencensus.stats.View.AggregationWindow.Cumulative; +import io.opencensus.stats.View.AggregationWindow.Interval; +import io.opencensus.stats.View.Name; +import io.opencensus.stats.ViewData.AggregationWindowData.CumulativeData; +import io.opencensus.stats.ViewData.AggregationWindowData.IntervalData; +import io.opencensus.tags.TagKey.TagKeyString; +import java.util.Arrays; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link NoopStats#newNoopViewManager}. */ +@RunWith(JUnit4.class) +public final class NoopViewManagerTest { + private static final MeasureDouble MEASURE = + Measure.MeasureDouble.create("my measure", "description", "s"); + private static final TagKeyString KEY = TagKeyString.create("KEY"); + private static final Name VIEW_NAME = Name.create("my view"); + private static final String VIEW_DESCRIPTION = "view description"; + private static final Sum AGGREGATION = Sum.create(); + private static final Cumulative CUMULATIVE = Cumulative.create(); + private static final Duration TEN_SECONDS = Duration.create(10, 0); + private static final Interval INTERVAL = Interval.create(TEN_SECONDS); + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void noopViewManager_RegisterView_DisallowRegisteringDifferentViewWithSameName() { + final View view1 = + View.create( + VIEW_NAME, "description 1", MEASURE, AGGREGATION, Arrays.asList(KEY), CUMULATIVE); + final View view2 = + View.create( + VIEW_NAME, "description 2", MEASURE, AGGREGATION, Arrays.asList(KEY), CUMULATIVE); + ViewManager viewManager = NoopStats.newNoopViewManager(); + viewManager.registerView(view1); + + try { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("A different view with the same name already exists."); + viewManager.registerView(view2); + } finally { + assertThat(viewManager.getView(VIEW_NAME).getView()).isEqualTo(view1); + } + } + + @Test + public void noopViewManager_RegisterView_AllowRegisteringSameViewTwice() { + View view = + View.create( + VIEW_NAME, VIEW_DESCRIPTION, MEASURE, AGGREGATION, Arrays.asList(KEY), CUMULATIVE); + ViewManager viewManager = NoopStats.newNoopViewManager(); + viewManager.registerView(view); + viewManager.registerView(view); + } + + @Test + public void noopViewManager_RegisterView_DisallowNull() { + ViewManager viewManager = NoopStats.newNoopViewManager(); + thrown.expect(NullPointerException.class); + viewManager.registerView(null); + } + + @Test + public void noopViewManager_GetView_DisallowGettingNonExistentView() { + ViewManager viewManager = NoopStats.newNoopViewManager(); + + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("View is not registered."); + viewManager.getView(VIEW_NAME); + } + + @Test + public void noopViewManager_GetView_Cumulative() { + View view = + View.create( + VIEW_NAME, VIEW_DESCRIPTION, MEASURE, AGGREGATION, Arrays.asList(KEY), CUMULATIVE); + ViewManager viewManager = NoopStats.newNoopViewManager(); + viewManager.registerView(view); + + ViewData viewData = viewManager.getView(VIEW_NAME); + assertThat(viewData.getView()).isEqualTo(view); + assertThat(viewData.getAggregationMap()).isEmpty(); + assertThat(viewData.getWindowData()) + .isEqualTo(CumulativeData.create(Timestamp.create(0, 0), Timestamp.create(0, 0))); + } + + @Test + public void noopViewManager_GetView_Interval() { + View view = + View.create( + VIEW_NAME, VIEW_DESCRIPTION, MEASURE, AGGREGATION, Arrays.asList(KEY), INTERVAL); + ViewManager viewManager = NoopStats.newNoopViewManager(); + viewManager.registerView(view); + + ViewData viewData = viewManager.getView(VIEW_NAME); + assertThat(viewData.getView()).isEqualTo(view); + assertThat(viewData.getAggregationMap()).isEmpty(); + assertThat(viewData.getWindowData()).isEqualTo(IntervalData.create(Timestamp.create(0, 0))); + } + + @Test + public void noopViewManager_GetView_DisallowNull() { + ViewManager viewManager = NoopStats.newNoopViewManager(); + thrown.expect(NullPointerException.class); + viewManager.getView(null); + } +} diff --git a/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java b/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java new file mode 100644 index 00000000..793da8a0 --- /dev/null +++ b/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java @@ -0,0 +1,81 @@ +/* + * 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.stats; + +import static org.mockito.Matchers.same; +import static org.mockito.Mockito.verify; + +import io.grpc.Context; +import io.opencensus.stats.Measure.MeasureDouble; +import io.opencensus.tags.Tag; +import io.opencensus.tags.Tag.TagString; +import io.opencensus.tags.TagContext; +import io.opencensus.tags.TagKey.TagKeyString; +import io.opencensus.tags.TagValue.TagValueString; +import io.opencensus.tags.unsafe.ContextUtils; +import java.util.Collections; +import java.util.Iterator; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** Tests for {@link StatsRecorder}. */ +@RunWith(JUnit4.class) +public final class StatsRecorderTest { + private static final TagString TAG = + TagString.create(TagKeyString.create("key"), TagValueString.create("value")); + private static final MeasureDouble MEASURE = + Measure.MeasureDouble.create("my measure", "description", "bit/s"); + + private final TagContext tagContext = + new TagContext() { + + @Override + protected Iterator getIterator() { + return Collections.singleton(TAG).iterator(); + } + }; + + @Mock private StatsRecorder statsRecorder; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void record_CurrentContextNotSet() { + MeasureMap measures = MeasureMap.builder().put(MEASURE, 1.0).build(); + statsRecorder.record(measures); + verify(statsRecorder).record(same(ContextUtils.TAG_CONTEXT_KEY.get()), same(measures)); + } + + @Test + public void record_CurrentContextSet() { + Context orig = Context.current().withValue(ContextUtils.TAG_CONTEXT_KEY, tagContext).attach(); + try { + MeasureMap measures = MeasureMap.builder().put(MEASURE, 2.0).build(); + statsRecorder.record(measures); + verify(statsRecorder).record(same(tagContext), same(measures)); + } finally { + Context.current().detach(orig); + } + } +} diff --git a/api/src/test/java/io/opencensus/stats/StatsTest.java b/api/src/test/java/io/opencensus/stats/StatsTest.java new file mode 100644 index 00000000..cb2f3a23 --- /dev/null +++ b/api/src/test/java/io/opencensus/stats/StatsTest.java @@ -0,0 +1,82 @@ +/* + * Copyright 2016-17, 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.stats; + +import static com.google.common.truth.Truth.assertThat; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link Stats}. */ +@RunWith(JUnit4.class) +public final class StatsTest { + @Rule public ExpectedException thrown = ExpectedException.none(); + + @Test + public void loadStatsManager_UsesProvidedClassLoader() { + final RuntimeException toThrow = new RuntimeException("UseClassLoader"); + thrown.expect(RuntimeException.class); + thrown.expectMessage("UseClassLoader"); + Stats.loadStatsComponent( + new ClassLoader() { + @Override + public Class loadClass(String name) { + throw toThrow; + } + }); + } + + @Test + public void loadStatsManager_IgnoresMissingClasses() { + assertThat( + Stats.loadStatsComponent( + new ClassLoader() { + @Override + public Class loadClass(String name) throws ClassNotFoundException { + throw new ClassNotFoundException(); + } + }) + .getClass() + .getName()) + .isEqualTo("io.opencensus.stats.NoopStats$NoopStatsComponent"); + } + + @Test + public void defaultValues() { + assertThat(Stats.getStatsRecorder()).isEqualTo(NoopStats.getNoopStatsRecorder()); + assertThat(Stats.getViewManager()).isInstanceOf(NoopStats.newNoopViewManager().getClass()); + } + + @Test + public void getState() { + assertThat(Stats.getState()).isEqualTo(StatsCollectionState.DISABLED); + } + + @Test + public void setState_IgnoresInput() { + Stats.setState(StatsCollectionState.ENABLED); + assertThat(Stats.getState()).isEqualTo(StatsCollectionState.DISABLED); + } + + @Test(expected = NullPointerException.class) + public void setState_DisallowsNull() { + Stats.setState(null); + } +} diff --git a/api/src/test/java/io/opencensus/stats/ViewDataTest.java b/api/src/test/java/io/opencensus/stats/ViewDataTest.java new file mode 100644 index 00000000..43cc956a --- /dev/null +++ b/api/src/test/java/io/opencensus/stats/ViewDataTest.java @@ -0,0 +1,221 @@ +/* + * Copyright 2016-17, 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.stats; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.fail; + +import com.google.common.collect.ImmutableMap; +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Duration; +import io.opencensus.common.Function; +import io.opencensus.common.Functions; +import io.opencensus.common.Timestamp; +import io.opencensus.stats.Aggregation.Distribution; +import io.opencensus.stats.AggregationData.DistributionData; +import io.opencensus.stats.View.AggregationWindow; +import io.opencensus.stats.View.AggregationWindow.Cumulative; +import io.opencensus.stats.View.AggregationWindow.Interval; +import io.opencensus.stats.ViewData.AggregationWindowData; +import io.opencensus.stats.ViewData.AggregationWindowData.CumulativeData; +import io.opencensus.stats.ViewData.AggregationWindowData.IntervalData; +import io.opencensus.tags.TagKey.TagKeyString; +import io.opencensus.tags.TagValue; +import io.opencensus.tags.TagValue.TagValueString; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for class {@link ViewData}. */ +@RunWith(JUnit4.class) +public final class ViewDataTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void testCumulativeViewData() { + View view = View.create(NAME, DESCRIPTION, MEASURE, DISTRIBUTION, tagKeys, CUMULATIVE); + Timestamp start = Timestamp.fromMillis(1000); + Timestamp end = Timestamp.fromMillis(2000); + AggregationWindowData windowData = CumulativeData.create(start, end); + ViewData viewData = ViewData.create(view, ENTRIES, windowData); + assertThat(viewData.getView()).isEqualTo(view); + assertThat(viewData.getAggregationMap()).isEqualTo(ENTRIES); + assertThat(viewData.getWindowData()).isEqualTo(windowData); + } + + @Test + public void testIntervalViewData() { + View view = View.create(NAME, DESCRIPTION, MEASURE, DISTRIBUTION, tagKeys, INTERVAL_HOUR); + Timestamp end = Timestamp.fromMillis(2000); + AggregationWindowData windowData = IntervalData.create(end); + ViewData viewData = ViewData.create(view, ENTRIES, windowData); + assertThat(viewData.getView()).isEqualTo(view); + assertThat(viewData.getAggregationMap()).isEqualTo(ENTRIES); + assertThat(viewData.getWindowData()).isEqualTo(windowData); + } + + @Test + public void testViewDataEquals() { + View cumulativeView = + View.create(NAME, DESCRIPTION, MEASURE, DISTRIBUTION, tagKeys, CUMULATIVE); + View intervalView = + View.create(NAME, DESCRIPTION, MEASURE, DISTRIBUTION, tagKeys, INTERVAL_HOUR); + + new EqualsTester() + .addEqualityGroup( + ViewData.create( + cumulativeView, + ENTRIES, + CumulativeData.create( + Timestamp.fromMillis(1000), Timestamp.fromMillis(2000))), + ViewData.create( + cumulativeView, + ENTRIES, + CumulativeData.create( + Timestamp.fromMillis(1000), Timestamp.fromMillis(2000)))) + .addEqualityGroup( + ViewData.create( + cumulativeView, + ENTRIES, + CumulativeData.create( + Timestamp.fromMillis(1000), Timestamp.fromMillis(3000)))) + .addEqualityGroup( + ViewData.create( + intervalView, + ENTRIES, + IntervalData.create(Timestamp.fromMillis(2000))), + ViewData.create( + intervalView, + ENTRIES, + IntervalData.create(Timestamp.fromMillis(2000)))) + .addEqualityGroup( + ViewData.create( + intervalView, + Collections., AggregationData>emptyMap(), + IntervalData.create(Timestamp.fromMillis(2000)))) + .testEquals(); + } + + @Test + public void testAggregationWindowDataMatch() { + final Timestamp start = Timestamp.fromMillis(1000); + final Timestamp end = Timestamp.fromMillis(2000); + final AggregationWindowData windowData1 = CumulativeData.create(start, end); + final AggregationWindowData windowData2 = IntervalData.create(end); + windowData1.match( + new Function() { + @Override + public Void apply(CumulativeData windowData) { + assertThat(windowData.getStart()).isEqualTo(start); + assertThat(windowData.getEnd()).isEqualTo(end); + return null; + } + }, + new Function() { + @Override + public Void apply(IntervalData windowData) { + fail("CumulativeData expected."); + return null; + } + }, + Functions.throwIllegalArgumentException()); + windowData2.match( + new Function() { + @Override + public Void apply(CumulativeData windowData) { + fail("IntervalData expected."); + return null; + } + }, + new Function() { + @Override + public Void apply(IntervalData windowData) { + assertThat(windowData.getEnd()).isEqualTo(end); + return null; + } + }, + Functions.throwIllegalArgumentException()); + } + + @Test + public void preventWindowAndAggregationWindowDataMismatch() { + thrown.expect(IllegalArgumentException.class); + ViewData.create( + View.create(NAME, DESCRIPTION, MEASURE, DISTRIBUTION, tagKeys, INTERVAL_HOUR), + ENTRIES, + CumulativeData.create( + Timestamp.fromMillis(1000), Timestamp.fromMillis(2000))); + } + + @Test + public void preventWindowAndAggregationWindowDataMismatch2() { + thrown.expect(IllegalArgumentException.class); + ViewData.create( + View.create(NAME, DESCRIPTION, MEASURE, DISTRIBUTION, tagKeys, CUMULATIVE), + ENTRIES, + IntervalData.create(Timestamp.fromMillis(1000))); + } + + @Test + public void preventStartTimeLaterThanEndTime() { + thrown.expect(IllegalArgumentException.class); + CumulativeData.create(Timestamp.fromMillis(3000), Timestamp.fromMillis(2000)); + } + + // tag keys + private static final TagKeyString K1 = TagKeyString.create("k1"); + private static final TagKeyString K2 = TagKeyString.create("k2"); + private final List tagKeys = Arrays.asList(K1, K2); + + // tag values + private static final TagValueString V1 = TagValueString.create("v1"); + private static final TagValueString V2 = TagValueString.create("v2"); + private static final TagValueString V10 = TagValueString.create("v10"); + private static final TagValueString V20 = TagValueString.create("v20"); + + private static final AggregationWindow CUMULATIVE = Cumulative.create(); + private static final AggregationWindow INTERVAL_HOUR = Interval.create(Duration.create(3600, 0)); + + private static final BucketBoundaries BUCKET_BOUNDARIES = BucketBoundaries.create( + Arrays.asList(10.0, 20.0, 30.0, 40.0)); + + private static final Aggregation DISTRIBUTION = Distribution.create(BUCKET_BOUNDARIES); + + private static final ImmutableMap, DistributionData> ENTRIES = + ImmutableMap.of( + Arrays.asList(V1, V2), + DistributionData.create(1, 1, 1, 1, 0, new long[]{0, 1, 0}), + Arrays.asList(V10, V20), + DistributionData.create(-5, 6, -20, 5, 100.1, new long[]{5, 0, 1})); + + // name + private static final View.Name NAME = View.Name.create("test-view"); + // description + private static final String DESCRIPTION = "test-view-descriptor description"; + // measure + private static final Measure MEASURE = Measure.MeasureDouble.create( + "measure", + "measure description", + "1"); +} diff --git a/api/src/test/java/io/opencensus/stats/ViewTest.java b/api/src/test/java/io/opencensus/stats/ViewTest.java new file mode 100644 index 00000000..99215352 --- /dev/null +++ b/api/src/test/java/io/opencensus/stats/ViewTest.java @@ -0,0 +1,162 @@ +/* + * Copyright 2016-17, 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.stats; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.collect.ImmutableList; +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Duration; +import io.opencensus.stats.Aggregation.Mean; +import io.opencensus.stats.View.AggregationWindow.Cumulative; +import io.opencensus.stats.View.AggregationWindow.Interval; +import io.opencensus.tags.TagKey.TagKeyString; +import java.util.Arrays; +import java.util.List; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link View}. */ +@RunWith(JUnit4.class) +public final class ViewTest { + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void testConstants() { + assertThat(View.NAME_MAX_LENGTH).isEqualTo(256); + } + + @Test + public void testDistributionView() { + final View view = View.create( + NAME, DESCRIPTION, MEASURE, MEAN, keys, Cumulative.create()); + assertThat(view.getName()).isEqualTo(NAME); + assertThat(view.getDescription()).isEqualTo(DESCRIPTION); + assertThat(view.getMeasure().getName()).isEqualTo(MEASURE.getName()); + assertThat(view.getAggregation()).isEqualTo(MEAN); + assertThat(view.getColumns()).hasSize(2); + assertThat(view.getColumns()).containsExactly(FOO, BAR).inOrder(); + assertThat(view.getWindow()).isEqualTo(Cumulative.create()); + } + + @Test + public void testIntervalView() { + final View view = View.create( + NAME, DESCRIPTION, MEASURE, MEAN, keys, Interval.create(MINUTE)); + assertThat(view.getName()).isEqualTo(NAME); + assertThat(view.getDescription()).isEqualTo(DESCRIPTION); + assertThat(view.getMeasure().getName()) + .isEqualTo(MEASURE.getName()); + assertThat(view.getAggregation()).isEqualTo(MEAN); + assertThat(view.getColumns()).hasSize(2); + assertThat(view.getColumns()).containsExactly(FOO, BAR).inOrder(); + assertThat(view.getWindow()).isEqualTo(Interval.create(MINUTE)); + } + + @Test + public void testViewEquals() { + new EqualsTester() + .addEqualityGroup( + View.create( + NAME, DESCRIPTION, MEASURE, MEAN, keys, Cumulative.create()), + View.create( + NAME, DESCRIPTION, MEASURE, MEAN, keys, Cumulative.create())) + .addEqualityGroup( + View.create( + NAME, DESCRIPTION + 2, MEASURE, MEAN, keys, Cumulative.create())) + .addEqualityGroup( + View.create( + NAME, DESCRIPTION, MEASURE, MEAN, keys, Interval.create(MINUTE)), + View.create( + NAME, DESCRIPTION, MEASURE, MEAN, keys, Interval.create(MINUTE))) + .addEqualityGroup( + View.create( + NAME, DESCRIPTION, MEASURE, MEAN, keys, Interval.create(TWO_MINUTES))) + .testEquals(); + } + + @Test(expected = IllegalArgumentException.class) + public void preventDuplicateColumns() { + View.create( + NAME, + DESCRIPTION, + MEASURE, + MEAN, + Arrays.asList(TagKeyString.create("duplicate"), TagKeyString.create("duplicate")), + Cumulative.create()); + } + + @Test(expected = NullPointerException.class) + public void preventNullViewName() { + View.create(null, DESCRIPTION, MEASURE, MEAN, keys, Interval.create(MINUTE)); + } + + @Test + public void preventTooLongViewName() { + char[] chars = new char[View.NAME_MAX_LENGTH + 1]; + Arrays.fill(chars, 'a'); + String longName = String.valueOf(chars); + thrown.expect(IllegalArgumentException.class); + View.Name.create(longName); + } + + @Test + public void preventNonPrintableViewName() { + thrown.expect(IllegalArgumentException.class); + View.Name.create("\2"); + } + + @Test + public void testViewName() { + assertThat(View.Name.create("my name").asString()).isEqualTo("my name"); + } + + @Test(expected = NullPointerException.class) + public void preventNullNameString() { + View.Name.create(null); + } + + @Test(expected = IllegalArgumentException.class) + public void preventNegativeIntervalDuration() { + Interval.create(NEG_TEN_SECONDS); + } + + @Test + public void testViewNameEquals() { + new EqualsTester() + .addEqualityGroup( + View.Name.create("view-1"), View.Name.create("view-1")) + .addEqualityGroup(View.Name.create("view-2")) + .testEquals(); + } + + private static final View.Name NAME = View.Name.create("test-view-name"); + private static final String DESCRIPTION = "test-view-name description"; + private static final Measure MEASURE = Measure.MeasureDouble.create( + "measure", "measure description", "1"); + private static final TagKeyString FOO = TagKeyString.create("foo"); + private static final TagKeyString BAR = TagKeyString.create("bar"); + private static final List keys = ImmutableList.of(FOO, BAR); + private static final Mean MEAN = Mean.create(); + private static final Duration MINUTE = Duration.create(60, 0); + private static final Duration TWO_MINUTES = Duration.create(120, 0); + private static final Duration NEG_TEN_SECONDS = Duration.create(-10, 0); +} diff --git a/api/src/test/java/io/opencensus/tags/InternalUtilsTest.java b/api/src/test/java/io/opencensus/tags/InternalUtilsTest.java new file mode 100644 index 00000000..ba69ef88 --- /dev/null +++ b/api/src/test/java/io/opencensus/tags/InternalUtilsTest.java @@ -0,0 +1,49 @@ +/* + * 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.tags; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.collect.Lists; +import io.opencensus.tags.Tag.TagString; +import io.opencensus.tags.TagKey.TagKeyString; +import io.opencensus.tags.TagValue.TagValueString; +import java.util.Iterator; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link InternalUtils}. */ +@RunWith(JUnit4.class) +public final class InternalUtilsTest { + + @Test + public void getTags() { + final Iterator iterator = + Lists.newArrayList( + TagString.create(TagKeyString.create("k"), TagValueString.create("v"))) + .iterator(); + TagContext ctx = + new TagContext() { + @Override + protected Iterator getIterator() { + return iterator; + } + }; + assertThat(InternalUtils.getTags(ctx)).isSameAs(iterator); + } +} diff --git a/api/src/test/java/io/opencensus/tags/NoopTagsTest.java b/api/src/test/java/io/opencensus/tags/NoopTagsTest.java new file mode 100644 index 00000000..2ee1c8cc --- /dev/null +++ b/api/src/test/java/io/opencensus/tags/NoopTagsTest.java @@ -0,0 +1,192 @@ +/* + * 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.tags; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.collect.Lists; +import io.opencensus.internal.NoopScope; +import io.opencensus.tags.Tag.TagString; +import io.opencensus.tags.TagKey.TagKeyBoolean; +import io.opencensus.tags.TagKey.TagKeyLong; +import io.opencensus.tags.TagKey.TagKeyString; +import io.opencensus.tags.TagValue.TagValueBoolean; +import io.opencensus.tags.TagValue.TagValueLong; +import io.opencensus.tags.TagValue.TagValueString; +import io.opencensus.tags.propagation.TagContextBinarySerializer; +import io.opencensus.tags.propagation.TagContextParseException; +import java.util.Arrays; +import java.util.Iterator; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link NoopTags}. */ +@RunWith(JUnit4.class) +public final class NoopTagsTest { + private static final TagKeyString KEY_STRING = TagKeyString.create("key"); + private static final TagValueString VALUE_STRING = TagValueString.create("value"); + private static final TagKeyLong KEY_LONG = TagKeyLong.create("key"); + private static final TagValueLong VALUE_LONG = TagValueLong.create(1L); + private static final TagKeyBoolean KEY_BOOLEAN = TagKeyBoolean.create("key"); + private static final TagValueBoolean VALUE_BOOLEAN = TagValueBoolean.create(true); + + private static final TagContext TAG_CONTEXT = + new TagContext() { + + @Override + protected Iterator getIterator() { + return Arrays.asList(TagString.create(KEY_STRING, VALUE_STRING)).iterator(); + } + }; + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void noopTagsComponent() { + assertThat(NoopTags.getNoopTagsComponent().getTagger()).isSameAs(NoopTags.getNoopTagger()); + assertThat(NoopTags.getNoopTagsComponent().getTagPropagationComponent()) + .isSameAs(NoopTags.getNoopTagPropagationComponent()); + } + + @Test + public void noopTagsComponent_SetState_DisallowsNull() { + TagsComponent noopTagsComponent = NoopTags.getNoopTagsComponent(); + thrown.expect(NullPointerException.class); + noopTagsComponent.setState(null); + } + + @Test + public void noopTagger() { + Tagger noopTagger = NoopTags.getNoopTagger(); + assertThat(noopTagger.empty()).isSameAs(NoopTags.getNoopTagContext()); + assertThat(noopTagger.getCurrentTagContext()).isSameAs(NoopTags.getNoopTagContext()); + assertThat(noopTagger.emptyBuilder()).isSameAs(NoopTags.getNoopTagContextBuilder()); + assertThat(noopTagger.toBuilder(TAG_CONTEXT)).isSameAs(NoopTags.getNoopTagContextBuilder()); + assertThat(noopTagger.currentBuilder()).isSameAs(NoopTags.getNoopTagContextBuilder()); + assertThat(noopTagger.withTagContext(TAG_CONTEXT)).isSameAs(NoopScope.getInstance()); + } + + @Test + public void noopTagger_ToBuilder_DisallowsNull() { + Tagger noopTagger = NoopTags.getNoopTagger(); + thrown.expect(NullPointerException.class); + noopTagger.toBuilder(null); + } + + @Test + public void noopTagger_WithTagContext_DisallowsNull() { + Tagger noopTagger = NoopTags.getNoopTagger(); + thrown.expect(NullPointerException.class); + noopTagger.withTagContext(null); + } + + @Test + public void noopTagContextBuilder() { + assertThat(NoopTags.getNoopTagContextBuilder().build()).isSameAs(NoopTags.getNoopTagContext()); + assertThat(NoopTags.getNoopTagContextBuilder().put(KEY_STRING, VALUE_STRING).build()) + .isSameAs(NoopTags.getNoopTagContext()); + assertThat(NoopTags.getNoopTagContextBuilder().buildScoped()).isSameAs(NoopScope.getInstance()); + assertThat(NoopTags.getNoopTagContextBuilder().put(KEY_STRING, VALUE_STRING).buildScoped()) + .isSameAs(NoopScope.getInstance()); + } + + @Test + public void noopTagContextBuilder_PutString_DisallowsNullKey() { + TagContextBuilder noopBuilder = NoopTags.getNoopTagContextBuilder(); + thrown.expect(NullPointerException.class); + noopBuilder.put(null, VALUE_STRING); + } + + @Test + public void noopTagContextBuilder_PutString_DisallowsNullValue() { + TagContextBuilder noopBuilder = NoopTags.getNoopTagContextBuilder(); + thrown.expect(NullPointerException.class); + noopBuilder.put(KEY_STRING, null); + } + + @Test + public void noopTagContextBuilder_PutLong_DisallowsNullKey() { + TagContextBuilder noopBuilder = NoopTags.getNoopTagContextBuilder(); + thrown.expect(NullPointerException.class); + noopBuilder.put(null, VALUE_LONG); + } + + @Test + public void noopTagContextBuilder_PutLong_DisallowsNullValue() { + TagContextBuilder noopBuilder = NoopTags.getNoopTagContextBuilder(); + thrown.expect(NullPointerException.class); + noopBuilder.put(KEY_LONG, null); + } + + @Test + public void noopTagContextBuilder_PutBoolean_DisallowsNullKey() { + TagContextBuilder noopBuilder = NoopTags.getNoopTagContextBuilder(); + thrown.expect(NullPointerException.class); + noopBuilder.put(null, VALUE_BOOLEAN); + } + + @Test + public void noopTagContextBuilder_PutBoolean_DisallowsNullValue() { + TagContextBuilder noopBuilder = NoopTags.getNoopTagContextBuilder(); + thrown.expect(NullPointerException.class); + noopBuilder.put(KEY_BOOLEAN, null); + } + + @Test + public void noopTagContextBuilder_Remove_DisallowsNullKey() { + TagContextBuilder noopBuilder = NoopTags.getNoopTagContextBuilder(); + thrown.expect(NullPointerException.class); + noopBuilder.remove(null); + } + + @Test + public void noopTagContext() { + assertThat(Lists.newArrayList(NoopTags.getNoopTagContext().getIterator())).isEmpty(); + } + + @Test + public void noopTagPropagationComponent() { + assertThat(NoopTags.getNoopTagPropagationComponent().getBinarySerializer()) + .isSameAs(NoopTags.getNoopTagContextBinarySerializer()); + } + + @Test + public void noopTagContextBinarySerializer() throws TagContextParseException { + assertThat(NoopTags.getNoopTagContextBinarySerializer().toByteArray(TAG_CONTEXT)) + .isEqualTo(new byte[0]); + assertThat(NoopTags.getNoopTagContextBinarySerializer().fromByteArray(new byte[5])) + .isEqualTo(NoopTags.getNoopTagContext()); + } + + @Test + public void noopTagContextBinarySerializer_ToByteArray_DisallowsNull() { + TagContextBinarySerializer noopSerializer = NoopTags.getNoopTagContextBinarySerializer(); + thrown.expect(NullPointerException.class); + noopSerializer.toByteArray(null); + } + + @Test + public void noopTagContextBinarySerializer_FromByteArray_DisallowsNull() + throws TagContextParseException { + TagContextBinarySerializer noopSerializer = NoopTags.getNoopTagContextBinarySerializer(); + thrown.expect(NullPointerException.class); + noopSerializer.fromByteArray(null); + } +} diff --git a/api/src/test/java/io/opencensus/tags/TagContextTest.java b/api/src/test/java/io/opencensus/tags/TagContextTest.java new file mode 100644 index 00000000..d6adfe12 --- /dev/null +++ b/api/src/test/java/io/opencensus/tags/TagContextTest.java @@ -0,0 +1,106 @@ +/* + * 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.tags; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.collect.Lists; +import com.google.common.testing.EqualsTester; +import io.opencensus.tags.Tag.TagString; +import io.opencensus.tags.TagKey.TagKeyString; +import io.opencensus.tags.TagValue.TagValueString; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link TagContext}. */ +@RunWith(JUnit4.class) +public final class TagContextTest { + private static final Tag TAG1 = + TagString.create(TagKeyString.create("key"), TagValueString.create("val")); + private static final Tag TAG2 = + TagString.create(TagKeyString.create("key2"), TagValueString.create("val")); + + @Test + public void equals_IgnoresTagOrderAndTagContextClass() { + new EqualsTester() + .addEqualityGroup( + new SimpleTagContext(TAG1, TAG2), + new SimpleTagContext(TAG1, TAG2), + new SimpleTagContext(TAG2, TAG1), + new TagContext() { + @Override + protected Iterator getIterator() { + return Lists.newArrayList(TAG1, TAG2).iterator(); + } + }) + .testEquals(); + } + + @Test + public void equals_HandlesNullIterator() { + new EqualsTester() + .addEqualityGroup( + new SimpleTagContext((List) null), + new SimpleTagContext((List) null), + new SimpleTagContext()) + .testEquals(); + } + + @Test + public void equals_DoesNotIgnoreNullTags() { + new EqualsTester() + .addEqualityGroup(new SimpleTagContext(TAG1)) + .addEqualityGroup(new SimpleTagContext(TAG1, null), new SimpleTagContext(null, TAG1)) + .addEqualityGroup(new SimpleTagContext(TAG1, null, null)) + .testEquals(); + } + + @Test + public void equals_DoesNotIgnoreDuplicateTags() { + new EqualsTester() + .addEqualityGroup(new SimpleTagContext(TAG1)) + .addEqualityGroup(new SimpleTagContext(TAG1, TAG1)) + .testEquals(); + } + + @Test + public void testToString() { + assertThat(new SimpleTagContext().toString()).isEqualTo("TagContext"); + assertThat(new SimpleTagContext(TAG1, TAG2).toString()).isEqualTo("TagContext"); + } + + private static final class SimpleTagContext extends TagContext { + private final List tags; + + SimpleTagContext(Tag... tags) { + this(Lists.newArrayList(tags)); + } + + SimpleTagContext(List tags) { + this.tags = tags == null ? null : Collections.unmodifiableList(Lists.newArrayList(tags)); + } + + @Override + protected Iterator getIterator() { + return tags == null ? null : tags.iterator(); + } + } +} diff --git a/api/src/test/java/io/opencensus/tags/TagKeyTest.java b/api/src/test/java/io/opencensus/tags/TagKeyTest.java new file mode 100644 index 00000000..5b70ba7a --- /dev/null +++ b/api/src/test/java/io/opencensus/tags/TagKeyTest.java @@ -0,0 +1,156 @@ +/* + * 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.tags; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Function; +import io.opencensus.common.Functions; +import io.opencensus.tags.TagKey.TagKeyBoolean; +import io.opencensus.tags.TagKey.TagKeyLong; +import io.opencensus.tags.TagKey.TagKeyString; +import java.util.Arrays; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link TagKey}. */ +@RunWith(JUnit4.class) +public final class TagKeyTest { + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void testGetName() { + assertThat(TagKeyString.create("foo").getName()).isEqualTo("foo"); + } + + @Test + public void createString_AllowTagKeyNameWithMaxLength() { + char[] key = new char[TagKey.MAX_LENGTH]; + Arrays.fill(key, 'k'); + TagKeyString.create(new String(key)); + } + + @Test + public void createString_DisallowTagKeyNameOverMaxLength() { + char[] key = new char[TagKey.MAX_LENGTH + 1]; + Arrays.fill(key, 'k'); + thrown.expect(IllegalArgumentException.class); + TagKeyString.create(new String(key)); + } + + @Test + public void createString_DisallowUnprintableChars() { + thrown.expect(IllegalArgumentException.class); + TagKeyString.create("\2ab\3cd"); + } + + @Test + public void testMatchStringKey() { + assertThat( + TagKeyString.create("key") + .match( + new Function() { + @Override + public String apply(TagKeyString tag) { + return tag.getName(); + } + }, + new Function() { + @Override + public String apply(TagKeyLong tag) { + throw new AssertionError(); + } + }, + new Function() { + @Override + public String apply(TagKeyBoolean tag) { + throw new AssertionError(); + } + }, + Functions.throwIllegalArgumentException())) + .isEqualTo("key"); + } + + @Test + public void testMatchLongKey() { + assertThat( + TagKeyLong.create("key") + .match( + new Function() { + @Override + public String apply(TagKeyString tag) { + throw new AssertionError(); + } + }, + new Function() { + @Override + public String apply(TagKeyLong tag) { + return tag.getName(); + } + }, + new Function() { + @Override + public String apply(TagKeyBoolean tag) { + throw new AssertionError(); + } + }, + Functions.throwIllegalArgumentException())) + .isEqualTo("key"); + } + + @Test + public void testMatchBooleanKey() { + assertThat( + TagKeyBoolean.create("key") + .match( + new Function() { + @Override + public String apply(TagKeyString tag) { + throw new AssertionError(); + } + }, + new Function() { + @Override + public String apply(TagKeyLong tag) { + throw new AssertionError(); + } + }, + new Function() { + @Override + public String apply(TagKeyBoolean tag) { + return tag.getName(); + } + }, + Functions.throwIllegalArgumentException())) + .isEqualTo("key"); + } + + @Test + public void testTagKeyEquals() { + new EqualsTester() + .addEqualityGroup(TagKeyString.create("foo"), TagKeyString.create("foo")) + .addEqualityGroup(TagKeyLong.create("foo")) + .addEqualityGroup(TagKeyBoolean.create("foo")) + .addEqualityGroup(TagKeyString.create("bar")) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/tags/TagTest.java b/api/src/test/java/io/opencensus/tags/TagTest.java new file mode 100644 index 00000000..79b2eb4d --- /dev/null +++ b/api/src/test/java/io/opencensus/tags/TagTest.java @@ -0,0 +1,158 @@ +/* + * 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.tags; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Function; +import io.opencensus.common.Functions; +import io.opencensus.tags.Tag.TagBoolean; +import io.opencensus.tags.Tag.TagLong; +import io.opencensus.tags.Tag.TagString; +import io.opencensus.tags.TagKey.TagKeyBoolean; +import io.opencensus.tags.TagKey.TagKeyLong; +import io.opencensus.tags.TagKey.TagKeyString; +import io.opencensus.tags.TagValue.TagValueBoolean; +import io.opencensus.tags.TagValue.TagValueLong; +import io.opencensus.tags.TagValue.TagValueString; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link Tag}. */ +@RunWith(JUnit4.class) +public final class TagTest { + + @Test + public void testGetStringKey() { + assertThat(TagString.create(TagKeyString.create("k"), TagValueString.create("v")).getKey()) + .isEqualTo(TagKeyString.create("k")); + } + + @Test + public void testGetLongKey() { + assertThat(TagLong.create(TagKeyLong.create("k"), TagValueLong.create(2L)).getKey()) + .isEqualTo(TagKeyLong.create("k")); + } + + @Test + public void testGetBooleanKey() { + assertThat(TagBoolean.create(TagKeyBoolean.create("k"), TagValueBoolean.create(false)).getKey()) + .isEqualTo(TagKeyBoolean.create("k")); + } + + @Test + public void testMatchStringTag() { + assertThat( + TagString.create(TagKeyString.create("k1"), TagValueString.create("value")) + .match( + new Function() { + @Override + public String apply(TagString tag) { + return tag.getValue().asString(); + } + }, + new Function() { + @Override + public String apply(TagLong tag) { + throw new AssertionError(); + } + }, + new Function() { + @Override + public String apply(TagBoolean tag) { + throw new AssertionError(); + } + }, + Functions.throwIllegalArgumentException())) + .isEqualTo("value"); + } + + @Test + public void testMatchLong() { + assertThat( + TagLong.create(TagKeyLong.create("k2"), TagValueLong.create(3L)) + .match( + new Function() { + @Override + public Long apply(TagString tag) { + throw new AssertionError(); + } + }, + new Function() { + @Override + public Long apply(TagLong tag) { + return tag.getValue().asLong(); + } + }, + new Function() { + @Override + public Long apply(TagBoolean tag) { + throw new AssertionError(); + } + }, + Functions.throwIllegalArgumentException())) + .isEqualTo(3L); + } + + @Test + public void testMatchBoolean() { + assertThat( + TagBoolean.create(TagKeyBoolean.create("k3"), TagValueBoolean.create(false)) + .match( + new Function() { + @Override + public Boolean apply(TagString tag) { + throw new AssertionError(); + } + }, + new Function() { + @Override + public Boolean apply(TagLong tag) { + throw new AssertionError(); + } + }, + new Function() { + @Override + public Boolean apply(TagBoolean tag) { + return tag.getValue().asBoolean(); + } + }, + Functions.throwIllegalArgumentException())) + .isEqualTo(false); + } + + @Test + public void testTagEquals() { + new EqualsTester() + .addEqualityGroup( + TagString.create(TagKeyString.create("Key1"), TagValueString.create("foo")), + TagString.create(TagKeyString.create("Key1"), TagValueString.create("foo"))) + .addEqualityGroup( + TagLong.create(TagKeyLong.create("Key1"), TagValueLong.create(100L)), + TagLong.create(TagKeyLong.create("Key1"), TagValueLong.create(100L))) + .addEqualityGroup( + TagBoolean.create(TagKeyBoolean.create("Key1"), TagValueBoolean.create(true)), + TagBoolean.create(TagKeyBoolean.create("Key1"), TagValueBoolean.create(true))) + .addEqualityGroup( + TagBoolean.create(TagKeyBoolean.create("Key2"), TagValueBoolean.create(true))) + .addEqualityGroup( + TagBoolean.create(TagKeyBoolean.create("Key1"), TagValueBoolean.create(false))) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/tags/TagValueTest.java b/api/src/test/java/io/opencensus/tags/TagValueTest.java new file mode 100644 index 00000000..b1382312 --- /dev/null +++ b/api/src/test/java/io/opencensus/tags/TagValueTest.java @@ -0,0 +1,154 @@ +/* + * 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.tags; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Function; +import io.opencensus.common.Functions; +import io.opencensus.tags.TagValue.TagValueBoolean; +import io.opencensus.tags.TagValue.TagValueLong; +import io.opencensus.tags.TagValue.TagValueString; +import java.util.Arrays; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link TagValue}. */ +@RunWith(JUnit4.class) +public final class TagValueTest { + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void testMatchStringValue() { + assertThat( + TagValueString.create("value") + .match( + new Function() { + @Override + public String apply(TagValueString tag) { + return tag.asString(); + } + }, + new Function() { + @Override + public String apply(TagValueLong tag) { + throw new AssertionError(); + } + }, + new Function() { + @Override + public String apply(TagValueBoolean tag) { + throw new AssertionError(); + } + }, + Functions.throwIllegalArgumentException())) + .isEqualTo("value"); + } + + @Test + public void testMatchLongValue() { + assertThat( + TagValueLong.create(1234) + .match( + new Function() { + @Override + public Long apply(TagValueString tag) { + throw new AssertionError(); + } + }, + new Function() { + @Override + public Long apply(TagValueLong tag) { + return tag.asLong(); + } + }, + new Function() { + @Override + public Long apply(TagValueBoolean tag) { + throw new AssertionError(); + } + }, + Functions.throwIllegalArgumentException())) + .isEqualTo(1234); + } + + @Test + public void testMatchBooleanValue() { + assertThat( + TagValueBoolean.create(false) + .match( + new Function() { + @Override + public Boolean apply(TagValueString tag) { + throw new AssertionError(); + } + }, + new Function() { + @Override + public Boolean apply(TagValueLong tag) { + throw new AssertionError(); + } + }, + new Function() { + @Override + public Boolean apply(TagValueBoolean tag) { + return tag.asBoolean(); + } + }, + Functions.throwIllegalArgumentException())) + .isEqualTo(false); + } + + @Test + public void allowStringTagValueWithMaxLength() { + char[] chars = new char[TagValueString.MAX_LENGTH]; + Arrays.fill(chars, 'v'); + String value = new String(chars); + assertThat(TagValueString.create(value).asString()).isEqualTo(value); + } + + @Test + public void disallowStringTagValueOverMaxLength() { + char[] chars = new char[TagValueString.MAX_LENGTH + 1]; + Arrays.fill(chars, 'v'); + String value = new String(chars); + thrown.expect(IllegalArgumentException.class); + TagValueString.create(value); + } + + @Test + public void disallowStringTagValueWithUnprintableChars() { + String value = "\2ab\3cd"; + thrown.expect(IllegalArgumentException.class); + TagValueString.create(value); + } + + @Test + public void testTagValueEquals() { + new EqualsTester() + .addEqualityGroup(TagValueString.create("foo"), TagValueString.create("foo")) + .addEqualityGroup(TagValueLong.create(2)) + .addEqualityGroup(TagValueBoolean.create(true)) + .addEqualityGroup(TagValueString.create("bar")) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/tags/TagsTest.java b/api/src/test/java/io/opencensus/tags/TagsTest.java new file mode 100644 index 00000000..e87407db --- /dev/null +++ b/api/src/test/java/io/opencensus/tags/TagsTest.java @@ -0,0 +1,85 @@ +/* + * 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.tags; + +import static com.google.common.truth.Truth.assertThat; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Tags}. */ +@RunWith(JUnit4.class) +public class TagsTest { + @Rule public ExpectedException thrown = ExpectedException.none(); + + @Test + public void loadTagsComponent_UsesProvidedClassLoader() { + final RuntimeException toThrow = new RuntimeException("UseClassLoader"); + thrown.expect(RuntimeException.class); + thrown.expectMessage("UseClassLoader"); + Tags.loadTagsComponent( + new ClassLoader() { + @Override + public Class loadClass(String name) { + throw toThrow; + } + }); + } + + @Test + public void loadTagsComponent_IgnoresMissingClasses() { + ClassLoader classLoader = + new ClassLoader() { + @Override + public Class loadClass(String name) throws ClassNotFoundException { + throw new ClassNotFoundException(); + } + }; + assertThat(Tags.loadTagsComponent(classLoader).getClass().getName()) + .isEqualTo("io.opencensus.tags.NoopTags$NoopTagsComponent"); + } + + @Test + public void getState() { + assertThat(Tags.getState()).isEqualTo(TaggingState.DISABLED); + } + + @Test + public void setState_IgnoresInput() { + Tags.setState(TaggingState.ENABLED); + assertThat(Tags.getState()).isEqualTo(TaggingState.DISABLED); + } + + @Test(expected = NullPointerException.class) + public void setState_DisallowsNull() { + Tags.setState(null); + } + + @Test + public void defaultTagger() { + assertThat(Tags.getTagger()).isEqualTo(NoopTags.getNoopTagger()); + } + + @Test + public void defaultTagContextSerializer() { + assertThat(Tags.getTagPropagationComponent()) + .isEqualTo(NoopTags.getNoopTagPropagationComponent()); + } +} diff --git a/api/src/test/java/io/opencensus/tags/propagation/TagContextParseExceptionTest.java b/api/src/test/java/io/opencensus/tags/propagation/TagContextParseExceptionTest.java new file mode 100644 index 00000000..0c2afadc --- /dev/null +++ b/api/src/test/java/io/opencensus/tags/propagation/TagContextParseExceptionTest.java @@ -0,0 +1,42 @@ +/* + * 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.tags.propagation; + +import static com.google.common.truth.Truth.assertThat; + +import java.io.IOException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TagContextParseException}. */ +@RunWith(JUnit4.class) +public final class TagContextParseExceptionTest { + + @Test + public void createWithMessage() { + assertThat(new TagContextParseException("my message").getMessage()).isEqualTo("my message"); + } + + @Test + public void createWithMessageAndCause() { + IOException cause = new IOException(); + TagContextParseException parseException = new TagContextParseException("my message", cause); + assertThat(parseException.getMessage()).isEqualTo("my message"); + assertThat(parseException.getCause()).isEqualTo(cause); + } +} diff --git a/api/src/test/java/io/opencensus/tags/unsafe/ContextUtilsTest.java b/api/src/test/java/io/opencensus/tags/unsafe/ContextUtilsTest.java new file mode 100644 index 00000000..c35c5dc4 --- /dev/null +++ b/api/src/test/java/io/opencensus/tags/unsafe/ContextUtilsTest.java @@ -0,0 +1,62 @@ +/* + * 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.tags.unsafe; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.collect.Lists; +import io.grpc.Context; +import io.opencensus.tags.InternalUtils; +import io.opencensus.tags.Tag; +import io.opencensus.tags.TagContext; +import java.util.List; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link ContextUtils}. */ +@RunWith(JUnit4.class) +public final class ContextUtilsTest { + @Test + public void testContextKeyName() { + // Context.Key.toString() returns the name. + assertThat(ContextUtils.TAG_CONTEXT_KEY.toString()).isEqualTo("opencensus-tag-context-key"); + } + + @Test + public void testGetCurrentTagContext_DefaultContext() { + TagContext tags = ContextUtils.TAG_CONTEXT_KEY.get(); + assertThat(tags).isNotNull(); + assertThat(asList(tags)).isEmpty(); + } + + @Test + public void testGetCurrentTagContext_ContextSetToNull() { + Context orig = Context.current().withValue(ContextUtils.TAG_CONTEXT_KEY, null).attach(); + try { + TagContext tags = ContextUtils.TAG_CONTEXT_KEY.get(); + assertThat(tags).isNotNull(); + assertThat(asList(tags)).isEmpty(); + } finally { + Context.current().detach(orig); + } + } + + private static List asList(TagContext tags) { + return Lists.newArrayList(InternalUtils.getTags(tags)); + } +} -- cgit v1.2.3 From 0a53489afb6c83d7d676c5bc80a16baf8b03dc9b Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 26 Sep 2017 15:26:55 -0700 Subject: Move MeasureMap from the API to the implementation. --- .../main/java/io/opencensus/stats/MeasureMap.java | 128 -------------------- .../main/java/io/opencensus/stats/NoopStats.java | 33 +++++- .../java/io/opencensus/stats/StatsBuilder.java | 47 ++++++++ .../java/io/opencensus/stats/StatsRecorder.java | 15 +-- .../java/io/opencensus/stats/MeasureMapTest.java | 132 --------------------- .../java/io/opencensus/stats/NoopStatsTest.java | 21 +--- .../io/opencensus/stats/StatsRecorderTest.java | 13 +- 7 files changed, 94 insertions(+), 295 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/stats/MeasureMap.java create mode 100644 api/src/main/java/io/opencensus/stats/StatsBuilder.java delete mode 100644 api/src/test/java/io/opencensus/stats/MeasureMapTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/MeasureMap.java b/api/src/main/java/io/opencensus/stats/MeasureMap.java deleted file mode 100644 index 0cc972f0..00000000 --- a/api/src/main/java/io/opencensus/stats/MeasureMap.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2016-17, 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.stats; - -import io.opencensus.stats.Measure.MeasureDouble; -import io.opencensus.stats.Measure.MeasureLong; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * A map from {@link Measure}'s to measured values. - */ -public final class MeasureMap { - - /** - * Returns a {@link Builder} for the {@link MeasureMap} class. - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Returns an {@link Iterator} over the measure/value mappings in this {@link MeasureMap}. - * The {@code Iterator} does not support {@link Iterator#remove()}. - */ - public Iterator iterator() { - return new MeasureMapIterator(); - } - - private final ArrayList measurements; - - private MeasureMap(ArrayList measurements) { - this.measurements = measurements; - } - - /** - * Builder for the {@link MeasureMap} class. - */ - public static class Builder { - /** - * Associates the {@link MeasureDouble} with the given value. Subsequent updates to the - * same {@link MeasureDouble} will overwrite the previous value. - * - * @param measure the {@link MeasureDouble} - * @param value the value to be associated with {@code measure} - * @return this - */ - public Builder put(MeasureDouble measure, double value) { - measurements.add(Measurement.MeasurementDouble.create(measure, value)); - return this; - } - - /** - * Associates the {@link MeasureLong} with the given value. Subsequent updates to the - * same {@link MeasureLong} will overwrite the previous value. - * - * @param measure the {@link MeasureLong} - * @param value the value to be associated with {@code measure} - * @return this - */ - public Builder put(MeasureLong measure, long value) { - measurements.add(Measurement.MeasurementLong.create(measure, value)); - return this; - } - - /** - * Constructs a {@link MeasureMap} from the current measurements. - */ - public MeasureMap build() { - // Note: this makes adding measurements quadratic but is fastest for the sizes of - // MeasureMaps that we should see. We may want to go to a strategy of sort/eliminate - // for larger MeasureMaps. - for (int i = measurements.size() - 1; i >= 0; i--) { - for (int j = i - 1; j >= 0; j--) { - if (measurements.get(i).getMeasure() == measurements.get(j).getMeasure()) { - measurements.remove(j); - j--; - } - } - } - return new MeasureMap(measurements); - } - - private final ArrayList measurements = new ArrayList(); - - private Builder() { - } - } - - // Provides an unmodifiable Iterator over this instance's measurements. - private final class MeasureMapIterator implements Iterator { - @Override - public boolean hasNext() { - return position < length; - } - - @Override - public Measurement next() { - if (position >= measurements.size()) { - throw new NoSuchElementException(); - } - return measurements.get(position++); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - private final int length = measurements.size(); - private int position = 0; - } -} diff --git a/api/src/main/java/io/opencensus/stats/NoopStats.java b/api/src/main/java/io/opencensus/stats/NoopStats.java index 79ddb359..9ffb2a2a 100644 --- a/api/src/main/java/io/opencensus/stats/NoopStats.java +++ b/api/src/main/java/io/opencensus/stats/NoopStats.java @@ -23,6 +23,8 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Maps; import io.opencensus.common.Functions; import io.opencensus.common.Timestamp; +import io.opencensus.stats.Measure.MeasureDouble; +import io.opencensus.stats.Measure.MeasureLong; import io.opencensus.stats.ViewData.AggregationWindowData; import io.opencensus.stats.ViewData.AggregationWindowData.CumulativeData; import io.opencensus.stats.ViewData.AggregationWindowData.IntervalData; @@ -58,6 +60,15 @@ final class NoopStats { return NoopStatsRecorder.INSTANCE; } + /** + * Returns a {@code StatsBuilder} that ignores all calls to {@link StatsBuilder#put}. + * + * @return a {@code StatsBuilder} that ignores all calls to {@code StatsBuilder#put}. + */ + static StatsBuilder getNoopStatsBuilder() { + return NoopStatsBuilder.INSTANCE; + } + /** * Returns a {@code ViewManager} that maintains a map of views, but always returns empty {@link * ViewData}s. @@ -99,10 +110,28 @@ final class NoopStats { static final StatsRecorder INSTANCE = new NoopStatsRecorder(); @Override - public void record(TagContext tags, MeasureMap measureValues) { + public StatsBuilder builder(TagContext tags) { checkNotNull(tags, "tags"); - checkNotNull(measureValues, "measureValues"); + return getNoopStatsBuilder(); + } + } + + @Immutable + private static final class NoopStatsBuilder extends StatsBuilder { + static final StatsBuilder INSTANCE = new NoopStatsBuilder(); + + @Override + public StatsBuilder put(MeasureDouble measure, double value) { + return this; + } + + @Override + public StatsBuilder put(MeasureLong measure, long value) { + return this; } + + @Override + public void record() {} } @ThreadSafe diff --git a/api/src/main/java/io/opencensus/stats/StatsBuilder.java b/api/src/main/java/io/opencensus/stats/StatsBuilder.java new file mode 100644 index 00000000..514e62a1 --- /dev/null +++ b/api/src/main/java/io/opencensus/stats/StatsBuilder.java @@ -0,0 +1,47 @@ +/* + * 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.stats; + +import io.opencensus.stats.Measure.MeasureDouble; +import io.opencensus.stats.Measure.MeasureLong; + +/** A builder for a map from {@link Measure}s to measured values. */ +public abstract class StatsBuilder { + + /** + * Associates the {@link MeasureDouble} with the given value. Subsequent updates to the same + * {@link MeasureDouble} will overwrite the previous value. + * + * @param measure the {@link MeasureDouble} + * @param value the value to be associated with {@code measure} + * @return this + */ + public abstract StatsBuilder put(MeasureDouble measure, double value); + + /** + * Associates the {@link MeasureLong} with the given value. Subsequent updates to the same {@link + * MeasureLong} will overwrite the previous value. + * + * @param measure the {@link MeasureLong} + * @param value the value to be associated with {@code measure} + * @return this + */ + public abstract StatsBuilder put(MeasureLong measure, long value); + + /** Records all of the measures, using the same timestamp. */ + public abstract void record(); +} diff --git a/api/src/main/java/io/opencensus/stats/StatsRecorder.java b/api/src/main/java/io/opencensus/stats/StatsRecorder.java index cab21c29..eb0ea842 100644 --- a/api/src/main/java/io/opencensus/stats/StatsRecorder.java +++ b/api/src/main/java/io/opencensus/stats/StatsRecorder.java @@ -21,22 +21,23 @@ import io.opencensus.tags.unsafe.ContextUtils; /** Provides methods to record stats against tags. */ public abstract class StatsRecorder { + // TODO(sebright): Should we provide convenience methods for only recording one measure? /** - * Records a set of measurements with the tags in the current context. + * Returns an object for recording multiple measures with the tags in the current context. * - * @param measureValues the measurements to record. + * @return an object for recording multiple measures with the tags in the current context. */ - public final void record(MeasureMap measureValues) { + public final StatsBuilder builder() { // Use the context key directly, to avoid depending on the tags implementation. - record(ContextUtils.TAG_CONTEXT_KEY.get(), measureValues); + return builder(ContextUtils.TAG_CONTEXT_KEY.get()); } /** - * Records a set of measurements with a set of tags. + * Returns an object for recording multiple measures with a set of tags. * * @param tags the tags associated with the measurements. - * @param measureValues the measurements to record. + * @return an object for recording multiple measures with a set of tags. */ - public abstract void record(TagContext tags, MeasureMap measureValues); + public abstract StatsBuilder builder(TagContext tags); } diff --git a/api/src/test/java/io/opencensus/stats/MeasureMapTest.java b/api/src/test/java/io/opencensus/stats/MeasureMapTest.java deleted file mode 100644 index 1a408e85..00000000 --- a/api/src/test/java/io/opencensus/stats/MeasureMapTest.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2016-17, 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.stats; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.collect.Lists; -import io.opencensus.stats.Measure.MeasureDouble; -import io.opencensus.stats.Measure.MeasureLong; -import io.opencensus.stats.Measurement.MeasurementDouble; -import io.opencensus.stats.Measurement.MeasurementLong; -import java.util.ArrayList; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Tests for {@link MeasureMap}. */ -@RunWith(JUnit4.class) -public class MeasureMapTest { - - @Test - public void testPutDouble() { - MeasureMap metrics = MeasureMap.builder().put(M1, 44.4).build(); - assertContains(metrics, MeasurementDouble.create(M1, 44.4)); - } - - @Test - public void testPutLong() { - MeasureMap metrics = MeasureMap.builder().put(M3, 9999L).put(M4, 8888L).build(); - assertContains(metrics, - MeasurementLong.create(M3, 9999L), - MeasurementLong.create(M4, 8888L)); - } - - @Test - public void testCombination() { - MeasureMap metrics = - MeasureMap.builder().put(M1, 44.4).put(M2, 66.6).put(M3, 9999L).put(M4, 8888L).build(); - assertContains(metrics, - MeasurementDouble.create(M1, 44.4), - MeasurementDouble.create(M2, 66.6), - MeasurementLong.create(M3, 9999L), - MeasurementLong.create(M4, 8888L)); - } - - @Test - public void testBuilderEmpty() { - MeasureMap metrics = MeasureMap.builder().build(); - assertContains(metrics); - } - - @Test - public void testBuilder() { - ArrayList expected = new ArrayList(10); - MeasureMap.Builder builder = MeasureMap.builder(); - for (int i = 1; i <= 10; i++) { - expected - .add(MeasurementDouble.create(makeSimpleMeasureDouble("m" + i), i * 11.1)); - builder.put(makeSimpleMeasureDouble("m" + i), i * 11.1); - assertContains(builder.build(), expected.toArray(new Measurement[i])); - } - } - - @Test - public void testDuplicateMeasureDoubles() { - assertContains(MeasureMap.builder().put(M1, 1.0).put(M1, 2.0).build(), - MeasurementDouble.create(M1, 2.0)); - assertContains(MeasureMap.builder().put(M1, 1.0).put(M1, 2.0).put(M1, 3.0).build(), - MeasurementDouble.create(M1, 3.0)); - assertContains(MeasureMap.builder().put(M1, 1.0).put(M2, 2.0).put(M1, 3.0).build(), - MeasurementDouble.create(M1, 3.0), - MeasurementDouble.create(M2, 2.0)); - assertContains(MeasureMap.builder().put(M1, 1.0).put(M1, 2.0).put(M2, 2.0).build(), - MeasurementDouble.create(M1, 2.0), - MeasurementDouble.create(M2, 2.0)); - } - - @Test - public void testDuplicateMeasureLongs() { - assertContains(MeasureMap.builder().put(M3, 100L).put(M3, 100L).build(), - MeasurementLong.create(M3, 100L)); - assertContains(MeasureMap.builder().put(M3, 100L).put(M3, 200L).put(M3, 300L).build(), - MeasurementLong.create(M3, 300L)); - assertContains(MeasureMap.builder().put(M3, 100L).put(M4, 200L).put(M3, 300L).build(), - MeasurementLong.create(M3, 300L), - MeasurementLong.create(M4, 200L)); - assertContains(MeasureMap.builder().put(M3, 100L).put(M3, 200L).put(M4, 200L).build(), - MeasurementLong.create(M3, 200L), - MeasurementLong.create(M4, 200L)); - } - - @Test - public void testDuplicateMeasures() { - assertContains(MeasureMap.builder().put(M3, 100L).put(M1, 1.0).put(M3, 300L).build(), - MeasurementLong.create(M3, 300L), - MeasurementDouble.create(M1, 1.0)); - assertContains(MeasureMap.builder().put(M2, 2.0).put(M3, 100L).put(M2, 3.0).build(), - MeasurementDouble.create(M2, 3.0), - MeasurementLong.create(M3, 100L)); - } - - private static final MeasureDouble M1 = makeSimpleMeasureDouble("m1"); - private static final MeasureDouble M2 = makeSimpleMeasureDouble("m2"); - private static final MeasureLong M3 = makeSimpleMeasureLong("m3"); - private static final MeasureLong M4 = makeSimpleMeasureLong("m4"); - - private static MeasureDouble makeSimpleMeasureDouble(String measure) { - return Measure.MeasureDouble.create(measure, measure + " description", "1"); - } - - private static MeasureLong makeSimpleMeasureLong(String measure) { - return Measure.MeasureLong.create(measure, measure + " description", "1"); - } - - private static void assertContains(MeasureMap metrics, Measurement... measurements) { - assertThat(Lists.newArrayList(metrics.iterator())).containsExactly((Object[]) measurements); - } -} diff --git a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java index 8348adc4..d40ba006 100644 --- a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java +++ b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java @@ -86,33 +86,20 @@ public final class NoopStatsTest { // exception. @Test public void noopStatsRecorder_Record() { - NoopStats.getNoopStatsRecorder() - .record(tagContext, MeasureMap.builder().put(MEASURE, 5).build()); + NoopStats.getNoopStatsRecorder().builder(tagContext).put(MEASURE, 5).record(); } // The NoopStatsRecorder should do nothing, so this test just checks that record doesn't throw an // exception. @Test public void noopStatsRecorder_RecordWithCurrentContext() { - NoopStats.getNoopStatsRecorder().record(MeasureMap.builder().put(MEASURE, 6).build()); + NoopStats.getNoopStatsRecorder().builder().put(MEASURE, 6).record(); } @Test public void noopStatsRecorder_Record_DisallowNullTagContext() { - MeasureMap measures = MeasureMap.builder().put(MEASURE, 7).build(); + StatsRecorder noopStatsRecorder = NoopStats.getNoopStatsRecorder(); thrown.expect(NullPointerException.class); - NoopStats.getNoopStatsRecorder().record(null, measures); - } - - @Test - public void noopStatsRecorder_Record_DisallowNullMeasureMap() { - thrown.expect(NullPointerException.class); - NoopStats.getNoopStatsRecorder().record(tagContext, null); - } - - @Test - public void noopStatsRecorder_RecordWithCurrentContext_DisallowNullMeasureMap() { - thrown.expect(NullPointerException.class); - NoopStats.getNoopStatsRecorder().record(null); + noopStatsRecorder.builder(null); } } diff --git a/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java b/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java index 793da8a0..e1a10729 100644 --- a/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java +++ b/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java @@ -20,7 +20,6 @@ import static org.mockito.Matchers.same; import static org.mockito.Mockito.verify; import io.grpc.Context; -import io.opencensus.stats.Measure.MeasureDouble; import io.opencensus.tags.Tag; import io.opencensus.tags.Tag.TagString; import io.opencensus.tags.TagContext; @@ -41,8 +40,6 @@ import org.mockito.MockitoAnnotations; public final class StatsRecorderTest { private static final TagString TAG = TagString.create(TagKeyString.create("key"), TagValueString.create("value")); - private static final MeasureDouble MEASURE = - Measure.MeasureDouble.create("my measure", "description", "bit/s"); private final TagContext tagContext = new TagContext() { @@ -62,18 +59,16 @@ public final class StatsRecorderTest { @Test public void record_CurrentContextNotSet() { - MeasureMap measures = MeasureMap.builder().put(MEASURE, 1.0).build(); - statsRecorder.record(measures); - verify(statsRecorder).record(same(ContextUtils.TAG_CONTEXT_KEY.get()), same(measures)); + statsRecorder.builder(); + verify(statsRecorder).builder(same(ContextUtils.TAG_CONTEXT_KEY.get())); } @Test public void record_CurrentContextSet() { Context orig = Context.current().withValue(ContextUtils.TAG_CONTEXT_KEY, tagContext).attach(); try { - MeasureMap measures = MeasureMap.builder().put(MEASURE, 2.0).build(); - statsRecorder.record(measures); - verify(statsRecorder).record(same(tagContext), same(measures)); + statsRecorder.builder(); + verify(statsRecorder).builder(same(tagContext)); } finally { Context.current().detach(orig); } -- cgit v1.2.3 From 44b7acb1f269dc146ac27456baadb6dcda27cf62 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Wed, 27 Sep 2017 14:27:48 -0700 Subject: Rename StatsRecorder.builder to newStatsBuilder. --- api/src/main/java/io/opencensus/stats/NoopStats.java | 2 +- api/src/main/java/io/opencensus/stats/StatsRecorder.java | 6 +++--- api/src/test/java/io/opencensus/stats/NoopStatsTest.java | 6 +++--- api/src/test/java/io/opencensus/stats/StatsRecorderTest.java | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/NoopStats.java b/api/src/main/java/io/opencensus/stats/NoopStats.java index 9ffb2a2a..1dee64a9 100644 --- a/api/src/main/java/io/opencensus/stats/NoopStats.java +++ b/api/src/main/java/io/opencensus/stats/NoopStats.java @@ -110,7 +110,7 @@ final class NoopStats { static final StatsRecorder INSTANCE = new NoopStatsRecorder(); @Override - public StatsBuilder builder(TagContext tags) { + public StatsBuilder newStatsBuilder(TagContext tags) { checkNotNull(tags, "tags"); return getNoopStatsBuilder(); } diff --git a/api/src/main/java/io/opencensus/stats/StatsRecorder.java b/api/src/main/java/io/opencensus/stats/StatsRecorder.java index eb0ea842..a5f3f0db 100644 --- a/api/src/main/java/io/opencensus/stats/StatsRecorder.java +++ b/api/src/main/java/io/opencensus/stats/StatsRecorder.java @@ -28,9 +28,9 @@ public abstract class StatsRecorder { * * @return an object for recording multiple measures with the tags in the current context. */ - public final StatsBuilder builder() { + public final StatsBuilder newStatsBuilder() { // Use the context key directly, to avoid depending on the tags implementation. - return builder(ContextUtils.TAG_CONTEXT_KEY.get()); + return newStatsBuilder(ContextUtils.TAG_CONTEXT_KEY.get()); } /** @@ -39,5 +39,5 @@ public abstract class StatsRecorder { * @param tags the tags associated with the measurements. * @return an object for recording multiple measures with a set of tags. */ - public abstract StatsBuilder builder(TagContext tags); + public abstract StatsBuilder newStatsBuilder(TagContext tags); } diff --git a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java index d40ba006..e05fba30 100644 --- a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java +++ b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java @@ -86,20 +86,20 @@ public final class NoopStatsTest { // exception. @Test public void noopStatsRecorder_Record() { - NoopStats.getNoopStatsRecorder().builder(tagContext).put(MEASURE, 5).record(); + NoopStats.getNoopStatsRecorder().newStatsBuilder(tagContext).put(MEASURE, 5).record(); } // The NoopStatsRecorder should do nothing, so this test just checks that record doesn't throw an // exception. @Test public void noopStatsRecorder_RecordWithCurrentContext() { - NoopStats.getNoopStatsRecorder().builder().put(MEASURE, 6).record(); + NoopStats.getNoopStatsRecorder().newStatsBuilder().put(MEASURE, 6).record(); } @Test public void noopStatsRecorder_Record_DisallowNullTagContext() { StatsRecorder noopStatsRecorder = NoopStats.getNoopStatsRecorder(); thrown.expect(NullPointerException.class); - noopStatsRecorder.builder(null); + noopStatsRecorder.newStatsBuilder(null); } } diff --git a/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java b/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java index e1a10729..77752431 100644 --- a/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java +++ b/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java @@ -59,16 +59,16 @@ public final class StatsRecorderTest { @Test public void record_CurrentContextNotSet() { - statsRecorder.builder(); - verify(statsRecorder).builder(same(ContextUtils.TAG_CONTEXT_KEY.get())); + statsRecorder.newStatsBuilder(); + verify(statsRecorder).newStatsBuilder(same(ContextUtils.TAG_CONTEXT_KEY.get())); } @Test public void record_CurrentContextSet() { Context orig = Context.current().withValue(ContextUtils.TAG_CONTEXT_KEY, tagContext).attach(); try { - statsRecorder.builder(); - verify(statsRecorder).builder(same(tagContext)); + statsRecorder.newStatsBuilder(); + verify(statsRecorder).newStatsBuilder(same(tagContext)); } finally { Context.current().detach(orig); } -- cgit v1.2.3 From 6ab924006556c1a4928d67aa8cf7f55c12533434 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Thu, 5 Oct 2017 16:06:16 -0700 Subject: Rename newStatsBuilder(TagContext) to newStatsBuilderWithExplicitTagContext. --- api/src/main/java/io/opencensus/stats/NoopStats.java | 2 +- api/src/main/java/io/opencensus/stats/StatsRecorder.java | 4 ++-- api/src/test/java/io/opencensus/stats/NoopStatsTest.java | 7 +++++-- api/src/test/java/io/opencensus/stats/StatsRecorderTest.java | 5 +++-- 4 files changed, 11 insertions(+), 7 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/NoopStats.java b/api/src/main/java/io/opencensus/stats/NoopStats.java index 1dee64a9..c6be7a47 100644 --- a/api/src/main/java/io/opencensus/stats/NoopStats.java +++ b/api/src/main/java/io/opencensus/stats/NoopStats.java @@ -110,7 +110,7 @@ final class NoopStats { static final StatsRecorder INSTANCE = new NoopStatsRecorder(); @Override - public StatsBuilder newStatsBuilder(TagContext tags) { + public StatsBuilder newStatsBuilderWithExplicitTagContext(TagContext tags) { checkNotNull(tags, "tags"); return getNoopStatsBuilder(); } diff --git a/api/src/main/java/io/opencensus/stats/StatsRecorder.java b/api/src/main/java/io/opencensus/stats/StatsRecorder.java index a5f3f0db..98b3ad4e 100644 --- a/api/src/main/java/io/opencensus/stats/StatsRecorder.java +++ b/api/src/main/java/io/opencensus/stats/StatsRecorder.java @@ -30,7 +30,7 @@ public abstract class StatsRecorder { */ public final StatsBuilder newStatsBuilder() { // Use the context key directly, to avoid depending on the tags implementation. - return newStatsBuilder(ContextUtils.TAG_CONTEXT_KEY.get()); + return newStatsBuilderWithExplicitTagContext(ContextUtils.TAG_CONTEXT_KEY.get()); } /** @@ -39,5 +39,5 @@ public abstract class StatsRecorder { * @param tags the tags associated with the measurements. * @return an object for recording multiple measures with a set of tags. */ - public abstract StatsBuilder newStatsBuilder(TagContext tags); + public abstract StatsBuilder newStatsBuilderWithExplicitTagContext(TagContext tags); } diff --git a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java index e05fba30..fa12bce6 100644 --- a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java +++ b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java @@ -86,7 +86,10 @@ public final class NoopStatsTest { // exception. @Test public void noopStatsRecorder_Record() { - NoopStats.getNoopStatsRecorder().newStatsBuilder(tagContext).put(MEASURE, 5).record(); + NoopStats.getNoopStatsRecorder() + .newStatsBuilderWithExplicitTagContext(tagContext) + .put(MEASURE, 5) + .record(); } // The NoopStatsRecorder should do nothing, so this test just checks that record doesn't throw an @@ -100,6 +103,6 @@ public final class NoopStatsTest { public void noopStatsRecorder_Record_DisallowNullTagContext() { StatsRecorder noopStatsRecorder = NoopStats.getNoopStatsRecorder(); thrown.expect(NullPointerException.class); - noopStatsRecorder.newStatsBuilder(null); + noopStatsRecorder.newStatsBuilderWithExplicitTagContext(null); } } diff --git a/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java b/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java index 77752431..a9edbda1 100644 --- a/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java +++ b/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java @@ -60,7 +60,8 @@ public final class StatsRecorderTest { @Test public void record_CurrentContextNotSet() { statsRecorder.newStatsBuilder(); - verify(statsRecorder).newStatsBuilder(same(ContextUtils.TAG_CONTEXT_KEY.get())); + verify(statsRecorder) + .newStatsBuilderWithExplicitTagContext(same(ContextUtils.TAG_CONTEXT_KEY.get())); } @Test @@ -68,7 +69,7 @@ public final class StatsRecorderTest { Context orig = Context.current().withValue(ContextUtils.TAG_CONTEXT_KEY, tagContext).attach(); try { statsRecorder.newStatsBuilder(); - verify(statsRecorder).newStatsBuilder(same(tagContext)); + verify(statsRecorder).newStatsBuilderWithExplicitTagContext(same(tagContext)); } finally { Context.current().detach(orig); } -- cgit v1.2.3 From fc86613fd3527481de9884f6e20a968efc641627 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Thu, 19 Oct 2017 10:53:51 -0700 Subject: Rename StatsBuilder to StatsRecord. This commit also renames StatsRecorder.newStatsBuilder to newRecord and StatsRecorder.newStatsBuilderWithExplicitTagContext to newRecordWithExplicitTagContext. --- .../main/java/io/opencensus/stats/NoopStats.java | 20 ++++----- .../java/io/opencensus/stats/StatsBuilder.java | 47 ---------------------- .../main/java/io/opencensus/stats/StatsRecord.java | 47 ++++++++++++++++++++++ .../java/io/opencensus/stats/StatsRecorder.java | 14 +++---- .../java/io/opencensus/stats/NoopStatsTest.java | 6 +-- .../io/opencensus/stats/StatsRecorderTest.java | 8 ++-- 6 files changed, 71 insertions(+), 71 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/stats/StatsBuilder.java create mode 100644 api/src/main/java/io/opencensus/stats/StatsRecord.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/NoopStats.java b/api/src/main/java/io/opencensus/stats/NoopStats.java index c6be7a47..bf875de7 100644 --- a/api/src/main/java/io/opencensus/stats/NoopStats.java +++ b/api/src/main/java/io/opencensus/stats/NoopStats.java @@ -61,12 +61,12 @@ final class NoopStats { } /** - * Returns a {@code StatsBuilder} that ignores all calls to {@link StatsBuilder#put}. + * Returns a {@code StatsRecord} that ignores all calls to {@link StatsRecord#put}. * - * @return a {@code StatsBuilder} that ignores all calls to {@code StatsBuilder#put}. + * @return a {@code StatsRecord} that ignores all calls to {@code StatsRecord#put}. */ - static StatsBuilder getNoopStatsBuilder() { - return NoopStatsBuilder.INSTANCE; + static StatsRecord getNoopStatsRecord() { + return NoopStatsRecord.INSTANCE; } /** @@ -110,23 +110,23 @@ final class NoopStats { static final StatsRecorder INSTANCE = new NoopStatsRecorder(); @Override - public StatsBuilder newStatsBuilderWithExplicitTagContext(TagContext tags) { + public StatsRecord newRecordWithExplicitTagContext(TagContext tags) { checkNotNull(tags, "tags"); - return getNoopStatsBuilder(); + return getNoopStatsRecord(); } } @Immutable - private static final class NoopStatsBuilder extends StatsBuilder { - static final StatsBuilder INSTANCE = new NoopStatsBuilder(); + private static final class NoopStatsRecord extends StatsRecord { + static final StatsRecord INSTANCE = new NoopStatsRecord(); @Override - public StatsBuilder put(MeasureDouble measure, double value) { + public StatsRecord put(MeasureDouble measure, double value) { return this; } @Override - public StatsBuilder put(MeasureLong measure, long value) { + public StatsRecord put(MeasureLong measure, long value) { return this; } diff --git a/api/src/main/java/io/opencensus/stats/StatsBuilder.java b/api/src/main/java/io/opencensus/stats/StatsBuilder.java deleted file mode 100644 index 514e62a1..00000000 --- a/api/src/main/java/io/opencensus/stats/StatsBuilder.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.stats; - -import io.opencensus.stats.Measure.MeasureDouble; -import io.opencensus.stats.Measure.MeasureLong; - -/** A builder for a map from {@link Measure}s to measured values. */ -public abstract class StatsBuilder { - - /** - * Associates the {@link MeasureDouble} with the given value. Subsequent updates to the same - * {@link MeasureDouble} will overwrite the previous value. - * - * @param measure the {@link MeasureDouble} - * @param value the value to be associated with {@code measure} - * @return this - */ - public abstract StatsBuilder put(MeasureDouble measure, double value); - - /** - * Associates the {@link MeasureLong} with the given value. Subsequent updates to the same {@link - * MeasureLong} will overwrite the previous value. - * - * @param measure the {@link MeasureLong} - * @param value the value to be associated with {@code measure} - * @return this - */ - public abstract StatsBuilder put(MeasureLong measure, long value); - - /** Records all of the measures, using the same timestamp. */ - public abstract void record(); -} diff --git a/api/src/main/java/io/opencensus/stats/StatsRecord.java b/api/src/main/java/io/opencensus/stats/StatsRecord.java new file mode 100644 index 00000000..42159e61 --- /dev/null +++ b/api/src/main/java/io/opencensus/stats/StatsRecord.java @@ -0,0 +1,47 @@ +/* + * 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.stats; + +import io.opencensus.stats.Measure.MeasureDouble; +import io.opencensus.stats.Measure.MeasureLong; + +/** A map from {@link Measure}s to measured values to be recorded at the same time. */ +public abstract class StatsRecord { + + /** + * Associates the {@link MeasureDouble} with the given value. Subsequent updates to the same + * {@link MeasureDouble} will overwrite the previous value. + * + * @param measure the {@link MeasureDouble} + * @param value the value to be associated with {@code measure} + * @return this + */ + public abstract StatsRecord put(MeasureDouble measure, double value); + + /** + * Associates the {@link MeasureLong} with the given value. Subsequent updates to the same {@link + * MeasureLong} will overwrite the previous value. + * + * @param measure the {@link MeasureLong} + * @param value the value to be associated with {@code measure} + * @return this + */ + public abstract StatsRecord put(MeasureLong measure, long value); + + /** Records all of the measures at the same time. */ + public abstract void record(); +} diff --git a/api/src/main/java/io/opencensus/stats/StatsRecorder.java b/api/src/main/java/io/opencensus/stats/StatsRecorder.java index 98b3ad4e..5ad20b6f 100644 --- a/api/src/main/java/io/opencensus/stats/StatsRecorder.java +++ b/api/src/main/java/io/opencensus/stats/StatsRecorder.java @@ -24,20 +24,20 @@ public abstract class StatsRecorder { // TODO(sebright): Should we provide convenience methods for only recording one measure? /** - * Returns an object for recording multiple measures with the tags in the current context. + * Returns an object for recording multiple measurements with the tags in the current context. * - * @return an object for recording multiple measures with the tags in the current context. + * @return an object for recording multiple measurements with the tags in the current context. */ - public final StatsBuilder newStatsBuilder() { + public final StatsRecord newRecord() { // Use the context key directly, to avoid depending on the tags implementation. - return newStatsBuilderWithExplicitTagContext(ContextUtils.TAG_CONTEXT_KEY.get()); + return newRecordWithExplicitTagContext(ContextUtils.TAG_CONTEXT_KEY.get()); } /** - * Returns an object for recording multiple measures with a set of tags. + * Returns an object for recording multiple measurements with a set of tags. * * @param tags the tags associated with the measurements. - * @return an object for recording multiple measures with a set of tags. + * @return an object for recording multiple measurements with a set of tags. */ - public abstract StatsBuilder newStatsBuilderWithExplicitTagContext(TagContext tags); + public abstract StatsRecord newRecordWithExplicitTagContext(TagContext tags); } diff --git a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java index fa12bce6..aa7a562b 100644 --- a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java +++ b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java @@ -87,7 +87,7 @@ public final class NoopStatsTest { @Test public void noopStatsRecorder_Record() { NoopStats.getNoopStatsRecorder() - .newStatsBuilderWithExplicitTagContext(tagContext) + .newRecordWithExplicitTagContext(tagContext) .put(MEASURE, 5) .record(); } @@ -96,13 +96,13 @@ public final class NoopStatsTest { // exception. @Test public void noopStatsRecorder_RecordWithCurrentContext() { - NoopStats.getNoopStatsRecorder().newStatsBuilder().put(MEASURE, 6).record(); + NoopStats.getNoopStatsRecorder().newRecord().put(MEASURE, 6).record(); } @Test public void noopStatsRecorder_Record_DisallowNullTagContext() { StatsRecorder noopStatsRecorder = NoopStats.getNoopStatsRecorder(); thrown.expect(NullPointerException.class); - noopStatsRecorder.newStatsBuilderWithExplicitTagContext(null); + noopStatsRecorder.newRecordWithExplicitTagContext(null); } } diff --git a/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java b/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java index a9edbda1..6129d0f4 100644 --- a/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java +++ b/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java @@ -59,17 +59,17 @@ public final class StatsRecorderTest { @Test public void record_CurrentContextNotSet() { - statsRecorder.newStatsBuilder(); + statsRecorder.newRecord(); verify(statsRecorder) - .newStatsBuilderWithExplicitTagContext(same(ContextUtils.TAG_CONTEXT_KEY.get())); + .newRecordWithExplicitTagContext(same(ContextUtils.TAG_CONTEXT_KEY.get())); } @Test public void record_CurrentContextSet() { Context orig = Context.current().withValue(ContextUtils.TAG_CONTEXT_KEY, tagContext).attach(); try { - statsRecorder.newStatsBuilder(); - verify(statsRecorder).newStatsBuilderWithExplicitTagContext(same(tagContext)); + statsRecorder.newRecord(); + verify(statsRecorder).newRecordWithExplicitTagContext(same(tagContext)); } finally { Context.current().detach(orig); } -- cgit v1.2.3 From 6f94a23dbef32f87522ce373cf0f05537aa9155a Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Mon, 23 Oct 2017 13:39:26 -0700 Subject: Make StatsRecord.record take the TagContext, not StatsRecorder.newRecord. StatsRecorder now has one method, newRecord(). StatsRecord has record() and recordWithExplicitTagContext(TagContext tags). This is slightly more flexible, because it allows a StatsRecord to be reused to record the same stats with different TagContexts, at least at the API level. --- api/src/main/java/io/opencensus/stats/NoopStats.java | 7 ++++--- api/src/main/java/io/opencensus/stats/StatsRecord.java | 14 +++++++++++++- api/src/main/java/io/opencensus/stats/StatsRecorder.java | 16 +--------------- api/src/test/java/io/opencensus/stats/NoopStatsTest.java | 8 ++++---- .../test/java/io/opencensus/stats/StatsRecorderTest.java | 14 +++++++++----- 5 files changed, 31 insertions(+), 28 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/NoopStats.java b/api/src/main/java/io/opencensus/stats/NoopStats.java index bf875de7..e97f3cc8 100644 --- a/api/src/main/java/io/opencensus/stats/NoopStats.java +++ b/api/src/main/java/io/opencensus/stats/NoopStats.java @@ -110,8 +110,7 @@ final class NoopStats { static final StatsRecorder INSTANCE = new NoopStatsRecorder(); @Override - public StatsRecord newRecordWithExplicitTagContext(TagContext tags) { - checkNotNull(tags, "tags"); + public StatsRecord newRecord() { return getNoopStatsRecord(); } } @@ -131,7 +130,9 @@ final class NoopStats { } @Override - public void record() {} + public void recordWithExplicitTagContext(TagContext tags) { + checkNotNull(tags, "tags"); + } } @ThreadSafe diff --git a/api/src/main/java/io/opencensus/stats/StatsRecord.java b/api/src/main/java/io/opencensus/stats/StatsRecord.java index 42159e61..1d865c21 100644 --- a/api/src/main/java/io/opencensus/stats/StatsRecord.java +++ b/api/src/main/java/io/opencensus/stats/StatsRecord.java @@ -18,6 +18,8 @@ package io.opencensus.stats; import io.opencensus.stats.Measure.MeasureDouble; import io.opencensus.stats.Measure.MeasureLong; +import io.opencensus.tags.TagContext; +import io.opencensus.tags.unsafe.ContextUtils; /** A map from {@link Measure}s to measured values to be recorded at the same time. */ public abstract class StatsRecord { @@ -43,5 +45,15 @@ public abstract class StatsRecord { public abstract StatsRecord put(MeasureLong measure, long value); /** Records all of the measures at the same time. */ - public abstract void record(); + public final void record() { + // Use the context key directly, to avoid depending on the tags implementation. + recordWithExplicitTagContext(ContextUtils.TAG_CONTEXT_KEY.get()); + } + + /** + * Records all of the measures at the same time, with an explicit {@link TagContext}. + * + * @param tags the tags associated with the measurements. + */ + public abstract void recordWithExplicitTagContext(TagContext tags); } diff --git a/api/src/main/java/io/opencensus/stats/StatsRecorder.java b/api/src/main/java/io/opencensus/stats/StatsRecorder.java index 5ad20b6f..190c1561 100644 --- a/api/src/main/java/io/opencensus/stats/StatsRecorder.java +++ b/api/src/main/java/io/opencensus/stats/StatsRecorder.java @@ -16,9 +16,6 @@ package io.opencensus.stats; -import io.opencensus.tags.TagContext; -import io.opencensus.tags.unsafe.ContextUtils; - /** Provides methods to record stats against tags. */ public abstract class StatsRecorder { // TODO(sebright): Should we provide convenience methods for only recording one measure? @@ -28,16 +25,5 @@ public abstract class StatsRecorder { * * @return an object for recording multiple measurements with the tags in the current context. */ - public final StatsRecord newRecord() { - // Use the context key directly, to avoid depending on the tags implementation. - return newRecordWithExplicitTagContext(ContextUtils.TAG_CONTEXT_KEY.get()); - } - - /** - * Returns an object for recording multiple measurements with a set of tags. - * - * @param tags the tags associated with the measurements. - * @return an object for recording multiple measurements with a set of tags. - */ - public abstract StatsRecord newRecordWithExplicitTagContext(TagContext tags); + public abstract StatsRecord newRecord(); } diff --git a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java index aa7a562b..fe3e8108 100644 --- a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java +++ b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java @@ -87,9 +87,9 @@ public final class NoopStatsTest { @Test public void noopStatsRecorder_Record() { NoopStats.getNoopStatsRecorder() - .newRecordWithExplicitTagContext(tagContext) + .newRecord() .put(MEASURE, 5) - .record(); + .recordWithExplicitTagContext(tagContext); } // The NoopStatsRecorder should do nothing, so this test just checks that record doesn't throw an @@ -101,8 +101,8 @@ public final class NoopStatsTest { @Test public void noopStatsRecorder_Record_DisallowNullTagContext() { - StatsRecorder noopStatsRecorder = NoopStats.getNoopStatsRecorder(); + StatsRecord record = NoopStats.getNoopStatsRecorder().newRecord(); thrown.expect(NullPointerException.class); - noopStatsRecorder.newRecordWithExplicitTagContext(null); + record.recordWithExplicitTagContext(null); } } diff --git a/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java b/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java index 6129d0f4..0f94cb33 100644 --- a/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java +++ b/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java @@ -18,6 +18,7 @@ package io.opencensus.stats; import static org.mockito.Matchers.same; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import io.grpc.Context; import io.opencensus.tags.Tag; @@ -51,25 +52,28 @@ public final class StatsRecorderTest { }; @Mock private StatsRecorder statsRecorder; + @Mock private StatsRecord statsRecord; @Before public void setUp() { MockitoAnnotations.initMocks(this); + when(statsRecorder.newRecord()).thenReturn(statsRecord); } @Test public void record_CurrentContextNotSet() { - statsRecorder.newRecord(); - verify(statsRecorder) - .newRecordWithExplicitTagContext(same(ContextUtils.TAG_CONTEXT_KEY.get())); + StatsRecord record = statsRecorder.newRecord(); + record.record(); + verify(record).recordWithExplicitTagContext(same(ContextUtils.TAG_CONTEXT_KEY.get())); } @Test public void record_CurrentContextSet() { Context orig = Context.current().withValue(ContextUtils.TAG_CONTEXT_KEY, tagContext).attach(); try { - statsRecorder.newRecord(); - verify(statsRecorder).newRecordWithExplicitTagContext(same(tagContext)); + StatsRecord record = statsRecorder.newRecord(); + record.record(); + verify(record).recordWithExplicitTagContext(same(tagContext)); } finally { Context.current().detach(orig); } -- cgit v1.2.3 From a84a39ee58668a4c443c2a69425abf38afe0c49e Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Mon, 23 Oct 2017 17:45:24 -0700 Subject: Improve documentation of stats recording methods. --- api/src/main/java/io/opencensus/stats/StatsRecord.java | 10 +++++++++- api/src/main/java/io/opencensus/stats/StatsRecorder.java | 4 ++-- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/StatsRecord.java b/api/src/main/java/io/opencensus/stats/StatsRecord.java index 1d865c21..babf28f6 100644 --- a/api/src/main/java/io/opencensus/stats/StatsRecord.java +++ b/api/src/main/java/io/opencensus/stats/StatsRecord.java @@ -20,8 +20,10 @@ import io.opencensus.stats.Measure.MeasureDouble; import io.opencensus.stats.Measure.MeasureLong; import io.opencensus.tags.TagContext; import io.opencensus.tags.unsafe.ContextUtils; +import javax.annotation.concurrent.NotThreadSafe; /** A map from {@link Measure}s to measured values to be recorded at the same time. */ +@NotThreadSafe public abstract class StatsRecord { /** @@ -44,7 +46,11 @@ public abstract class StatsRecord { */ public abstract StatsRecord put(MeasureLong measure, long value); - /** Records all of the measures at the same time. */ + /** + * Records all of the measures at the same time, with the current {@link TagContext}. + * + *

This method records all of the stats in the {@code StatsRecord} every time it is called. + */ public final void record() { // Use the context key directly, to avoid depending on the tags implementation. recordWithExplicitTagContext(ContextUtils.TAG_CONTEXT_KEY.get()); @@ -53,6 +59,8 @@ public abstract class StatsRecord { /** * Records all of the measures at the same time, with an explicit {@link TagContext}. * + *

This method records all of the stats in the {@code StatsRecord} every time it is called. + * * @param tags the tags associated with the measurements. */ public abstract void recordWithExplicitTagContext(TagContext tags); diff --git a/api/src/main/java/io/opencensus/stats/StatsRecorder.java b/api/src/main/java/io/opencensus/stats/StatsRecorder.java index 190c1561..fcf2cb96 100644 --- a/api/src/main/java/io/opencensus/stats/StatsRecorder.java +++ b/api/src/main/java/io/opencensus/stats/StatsRecorder.java @@ -21,9 +21,9 @@ public abstract class StatsRecorder { // TODO(sebright): Should we provide convenience methods for only recording one measure? /** - * Returns an object for recording multiple measurements with the tags in the current context. + * Returns an object for recording multiple measurements. * - * @return an object for recording multiple measurements with the tags in the current context. + * @return an object for recording multiple measurements. */ public abstract StatsRecord newRecord(); } -- cgit v1.2.3 From 21d0ac659fb31b958faccfabc5d0d5062edfea9e Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Mon, 23 Oct 2017 18:31:31 -0700 Subject: Make StatsRecord.record abstract. --- .../main/java/io/opencensus/stats/NoopStats.java | 3 + .../main/java/io/opencensus/stats/StatsRecord.java | 6 +- .../io/opencensus/stats/StatsRecorderTest.java | 81 ---------------------- 3 files changed, 4 insertions(+), 86 deletions(-) delete mode 100644 api/src/test/java/io/opencensus/stats/StatsRecorderTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/NoopStats.java b/api/src/main/java/io/opencensus/stats/NoopStats.java index e97f3cc8..969a9272 100644 --- a/api/src/main/java/io/opencensus/stats/NoopStats.java +++ b/api/src/main/java/io/opencensus/stats/NoopStats.java @@ -129,6 +129,9 @@ final class NoopStats { return this; } + @Override + public void record() {} + @Override public void recordWithExplicitTagContext(TagContext tags) { checkNotNull(tags, "tags"); diff --git a/api/src/main/java/io/opencensus/stats/StatsRecord.java b/api/src/main/java/io/opencensus/stats/StatsRecord.java index babf28f6..3f4cbdfd 100644 --- a/api/src/main/java/io/opencensus/stats/StatsRecord.java +++ b/api/src/main/java/io/opencensus/stats/StatsRecord.java @@ -19,7 +19,6 @@ package io.opencensus.stats; import io.opencensus.stats.Measure.MeasureDouble; import io.opencensus.stats.Measure.MeasureLong; import io.opencensus.tags.TagContext; -import io.opencensus.tags.unsafe.ContextUtils; import javax.annotation.concurrent.NotThreadSafe; /** A map from {@link Measure}s to measured values to be recorded at the same time. */ @@ -51,10 +50,7 @@ public abstract class StatsRecord { * *

This method records all of the stats in the {@code StatsRecord} every time it is called. */ - public final void record() { - // Use the context key directly, to avoid depending on the tags implementation. - recordWithExplicitTagContext(ContextUtils.TAG_CONTEXT_KEY.get()); - } + public abstract void record(); /** * Records all of the measures at the same time, with an explicit {@link TagContext}. diff --git a/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java b/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java deleted file mode 100644 index 0f94cb33..00000000 --- a/api/src/test/java/io/opencensus/stats/StatsRecorderTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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.stats; - -import static org.mockito.Matchers.same; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import io.grpc.Context; -import io.opencensus.tags.Tag; -import io.opencensus.tags.Tag.TagString; -import io.opencensus.tags.TagContext; -import io.opencensus.tags.TagKey.TagKeyString; -import io.opencensus.tags.TagValue.TagValueString; -import io.opencensus.tags.unsafe.ContextUtils; -import java.util.Collections; -import java.util.Iterator; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** Tests for {@link StatsRecorder}. */ -@RunWith(JUnit4.class) -public final class StatsRecorderTest { - private static final TagString TAG = - TagString.create(TagKeyString.create("key"), TagValueString.create("value")); - - private final TagContext tagContext = - new TagContext() { - - @Override - protected Iterator getIterator() { - return Collections.singleton(TAG).iterator(); - } - }; - - @Mock private StatsRecorder statsRecorder; - @Mock private StatsRecord statsRecord; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - when(statsRecorder.newRecord()).thenReturn(statsRecord); - } - - @Test - public void record_CurrentContextNotSet() { - StatsRecord record = statsRecorder.newRecord(); - record.record(); - verify(record).recordWithExplicitTagContext(same(ContextUtils.TAG_CONTEXT_KEY.get())); - } - - @Test - public void record_CurrentContextSet() { - Context orig = Context.current().withValue(ContextUtils.TAG_CONTEXT_KEY, tagContext).attach(); - try { - StatsRecord record = statsRecorder.newRecord(); - record.record(); - verify(record).recordWithExplicitTagContext(same(tagContext)); - } finally { - Context.current().detach(orig); - } - } -} -- cgit v1.2.3 From 60cefdd2301263f16766298f7a3048ba7e9a5853 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Mon, 23 Oct 2017 14:19:17 -0700 Subject: Make DistributionData.create take a List instead of a long[] for bucket counts. List is consistent with the return type of DistributionData.getBucketCounts(). --- .../java/io/opencensus/stats/AggregationData.java | 13 +++++---- .../io/opencensus/stats/AggregationDataTest.java | 31 +++++++++++++--------- .../java/io/opencensus/stats/ViewDataTest.java | 4 +-- 3 files changed, 27 insertions(+), 21 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/AggregationData.java b/api/src/main/java/io/opencensus/stats/AggregationData.java index fdf09592..b91d0d19 100644 --- a/api/src/main/java/io/opencensus/stats/AggregationData.java +++ b/api/src/main/java/io/opencensus/stats/AggregationData.java @@ -20,8 +20,8 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; +import com.google.common.collect.Lists; import io.opencensus.common.Function; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.annotation.concurrent.Immutable; @@ -239,20 +239,19 @@ public abstract class AggregationData { */ public static DistributionData create( double mean, long count, double min, double max, double sumOfSquaredDeviations, - long[] bucketCounts) { + List bucketCounts) { if (min != Double.POSITIVE_INFINITY || max != Double.NEGATIVE_INFINITY) { checkArgument(min <= max, "max should be greater or equal to min."); } checkNotNull(bucketCounts, "bucket counts should not be null."); - List boxedBucketCounts = new ArrayList(); - for (long bucketCount : bucketCounts) { - boxedBucketCounts.add(bucketCount); + List bucketCountsCopy = Collections.unmodifiableList(Lists.newArrayList(bucketCounts)); + for (Long bucket : bucketCountsCopy) { + checkNotNull(bucket, "bucket should not be null."); } return new AutoValue_AggregationData_DistributionData( - mean, count, min, max, sumOfSquaredDeviations, - Collections.unmodifiableList(boxedBucketCounts)); + mean, count, min, max, sumOfSquaredDeviations, bucketCountsCopy); } /** diff --git a/api/src/test/java/io/opencensus/stats/AggregationDataTest.java b/api/src/test/java/io/opencensus/stats/AggregationDataTest.java index 3eafd18e..d4403c93 100644 --- a/api/src/test/java/io/opencensus/stats/AggregationDataTest.java +++ b/api/src/test/java/io/opencensus/stats/AggregationDataTest.java @@ -47,7 +47,7 @@ public class AggregationDataTest { @Test public void testCreateDistributionData() { DistributionData distributionData = DistributionData.create( - 7.7, 10, 1.1, 9.9, 32.2, new long[]{4, 1, 5}); + 7.7, 10, 1.1, 9.9, 32.2, Arrays.asList(4L, 1L, 5L)); assertThat(distributionData.getMean()).isWithin(TOLERANCE).of(7.7); assertThat(distributionData.getCount()).isEqualTo(10); assertThat(distributionData.getMin()).isWithin(TOLERANCE).of(1.1); @@ -57,17 +57,24 @@ public class AggregationDataTest { } @Test - public void preventNullBucketCountData() { + public void preventNullBucketCountList() { thrown.expect(NullPointerException.class); thrown.expectMessage("bucket counts should not be null."); DistributionData.create(1, 1, 1, 1, 0, null); } + @Test + public void preventNullBucket() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("bucket should not be null."); + DistributionData.create(1, 1, 1, 1, 0, Arrays.asList(0L, 1L, null)); + } + @Test public void preventMinIsGreaterThanMax() { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("max should be greater or equal to min."); - DistributionData.create(1, 1, 10, 1, 0, new long[]{0, 1, 0}); + DistributionData.create(1, 1, 10, 1, 0, Arrays.asList(0L, 1L, 0L)); } @Test @@ -89,20 +96,20 @@ public class AggregationDataTest { CountData.create(80), CountData.create(80)) .addEqualityGroup( - DistributionData.create(10, 10, 1, 1, 0, new long[]{0, 10, 0}), - DistributionData.create(10, 10, 1, 1, 0, new long[]{0, 10, 0})) + DistributionData.create(10, 10, 1, 1, 0, Arrays.asList(0L, 10L, 0L)), + DistributionData.create(10, 10, 1, 1, 0, Arrays.asList(0L, 10L, 0L))) .addEqualityGroup( - DistributionData.create(10, 10, 1, 1, 0, new long[]{0, 10, 100})) + DistributionData.create(10, 10, 1, 1, 0, Arrays.asList(0L, 10L, 100L))) .addEqualityGroup( - DistributionData.create(110, 10, 1, 1, 0, new long[]{0, 10, 0})) + DistributionData.create(110, 10, 1, 1, 0, Arrays.asList(0L, 10L, 0L))) .addEqualityGroup( - DistributionData.create(10, 110, 1, 1, 0, new long[]{0, 10, 0})) + DistributionData.create(10, 110, 1, 1, 0, Arrays.asList(0L, 10L, 0L))) .addEqualityGroup( - DistributionData.create(10, 10, -1, 1, 0, new long[]{0, 10, 0})) + DistributionData.create(10, 10, -1, 1, 0, Arrays.asList(0L, 10L, 0L))) .addEqualityGroup( - DistributionData.create(10, 10, 1, 5, 0, new long[]{0, 10, 0})) + DistributionData.create(10, 10, 1, 5, 0, Arrays.asList(0L, 10L, 0L))) .addEqualityGroup( - DistributionData.create(10, 10, 1, 1, 55.5, new long[]{0, 10, 0})) + DistributionData.create(10, 10, 1, 1, 55.5, Arrays.asList(0L, 10L, 0L))) .addEqualityGroup( MeanData.create(5.0, 1), MeanData.create(5.0, 1)) @@ -119,7 +126,7 @@ public class AggregationDataTest { SumDataLong.create(100000000), CountData.create(40), MeanData.create(5.0, 1), - DistributionData.create(1, 1, 1, 1, 0, new long[]{0, 10, 0})); + DistributionData.create(1, 1, 1, 1, 0, Arrays.asList(0L, 10L, 0L))); final List actual = new ArrayList(); for (AggregationData aggregation : aggregations) { diff --git a/api/src/test/java/io/opencensus/stats/ViewDataTest.java b/api/src/test/java/io/opencensus/stats/ViewDataTest.java index 43cc956a..cd364385 100644 --- a/api/src/test/java/io/opencensus/stats/ViewDataTest.java +++ b/api/src/test/java/io/opencensus/stats/ViewDataTest.java @@ -205,9 +205,9 @@ public final class ViewDataTest { private static final ImmutableMap, DistributionData> ENTRIES = ImmutableMap.of( Arrays.asList(V1, V2), - DistributionData.create(1, 1, 1, 1, 0, new long[]{0, 1, 0}), + DistributionData.create(1, 1, 1, 1, 0, Arrays.asList(0L, 1L, 0L)), Arrays.asList(V10, V20), - DistributionData.create(-5, 6, -20, 5, 100.1, new long[]{5, 0, 1})); + DistributionData.create(-5, 6, -20, 5, 100.1, Arrays.asList(5L, 0L, 1L))); // name private static final View.Name NAME = View.Name.create("test-view"); -- cgit v1.2.3 From 534a586dc1aba439da0271129c57a91219c4de2d Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Wed, 25 Oct 2017 12:40:55 -0700 Subject: Rename 'StatsRecord.recordWithExplicitTagContext' to 'record'. --- api/src/main/java/io/opencensus/stats/NoopStats.java | 2 +- api/src/main/java/io/opencensus/stats/StatsRecord.java | 2 +- api/src/test/java/io/opencensus/stats/NoopStatsTest.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/NoopStats.java b/api/src/main/java/io/opencensus/stats/NoopStats.java index 969a9272..8a792c07 100644 --- a/api/src/main/java/io/opencensus/stats/NoopStats.java +++ b/api/src/main/java/io/opencensus/stats/NoopStats.java @@ -133,7 +133,7 @@ final class NoopStats { public void record() {} @Override - public void recordWithExplicitTagContext(TagContext tags) { + public void record(TagContext tags) { checkNotNull(tags, "tags"); } } diff --git a/api/src/main/java/io/opencensus/stats/StatsRecord.java b/api/src/main/java/io/opencensus/stats/StatsRecord.java index 3f4cbdfd..3f7658e1 100644 --- a/api/src/main/java/io/opencensus/stats/StatsRecord.java +++ b/api/src/main/java/io/opencensus/stats/StatsRecord.java @@ -59,5 +59,5 @@ public abstract class StatsRecord { * * @param tags the tags associated with the measurements. */ - public abstract void recordWithExplicitTagContext(TagContext tags); + public abstract void record(TagContext tags); } diff --git a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java index fe3e8108..9639ab94 100644 --- a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java +++ b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java @@ -89,7 +89,7 @@ public final class NoopStatsTest { NoopStats.getNoopStatsRecorder() .newRecord() .put(MEASURE, 5) - .recordWithExplicitTagContext(tagContext); + .record(tagContext); } // The NoopStatsRecorder should do nothing, so this test just checks that record doesn't throw an @@ -103,6 +103,6 @@ public final class NoopStatsTest { public void noopStatsRecorder_Record_DisallowNullTagContext() { StatsRecord record = NoopStats.getNoopStatsRecorder().newRecord(); thrown.expect(NullPointerException.class); - record.recordWithExplicitTagContext(null); + record.record(null); } } -- cgit v1.2.3 From 89f06e756efed61b9307f51af760d6a4b291572a Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Wed, 25 Oct 2017 15:25:33 -0700 Subject: Remove contention between threads and worker thread when register span names. (#729) * Remove contention between threads and worker thread when register span names. * Mark getRegisteredSpanNamesForCollection as test only. --- api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java index 0d1c110c..b19ad3a1 100644 --- a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; +import com.google.common.annotations.VisibleForTesting; import io.opencensus.trace.Span; import io.opencensus.trace.Status; import io.opencensus.trace.Status.CanonicalCode; @@ -109,6 +110,7 @@ public abstract class SampledSpanStore { * * @return the set of unique span names registered to the library. */ + @VisibleForTesting public abstract Set getRegisteredSpanNamesForCollection(); /** The summary of all available data. */ -- cgit v1.2.3 From 2536bd35d6b24fab12695ee973b8a1fbba949b3a Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 17 Oct 2017 13:23:24 -0700 Subject: Remove support for multiple tag types. This commit removes the class hierarchies for TagKey, TagValue, and Tag. The three classes are now concrete AutoValue classes that use Strings for keys and values. The serialization format isn't affected, because it already only supported string tags. --- api/src/main/java/io/opencensus/stats/View.java | 2 +- .../main/java/io/opencensus/stats/ViewData.java | 4 +- api/src/main/java/io/opencensus/tags/NoopTags.java | 22 +-- api/src/main/java/io/opencensus/tags/Tag.java | 189 ++---------------- .../main/java/io/opencensus/tags/TagContext.java | 8 +- .../java/io/opencensus/tags/TagContextBuilder.java | 26 +-- api/src/main/java/io/opencensus/tags/TagKey.java | 212 +++------------------ api/src/main/java/io/opencensus/tags/TagValue.java | 177 ++++------------- .../main/java/io/opencensus/tags/package-info.java | 7 +- .../java/io/opencensus/stats/NoopStatsTest.java | 8 +- .../io/opencensus/stats/NoopViewManagerTest.java | 4 +- .../java/io/opencensus/stats/ViewDataTest.java | 19 +- .../test/java/io/opencensus/stats/ViewTest.java | 10 +- .../java/io/opencensus/tags/InternalUtilsTest.java | 5 +- .../test/java/io/opencensus/tags/NoopTagsTest.java | 57 +----- .../java/io/opencensus/tags/TagContextTest.java | 7 +- .../test/java/io/opencensus/tags/TagKeyTest.java | 106 +---------- api/src/test/java/io/opencensus/tags/TagTest.java | 124 +----------- .../test/java/io/opencensus/tags/TagValueTest.java | 109 +---------- 19 files changed, 140 insertions(+), 956 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/View.java b/api/src/main/java/io/opencensus/stats/View.java index 31b06461..26b1177f 100644 --- a/api/src/main/java/io/opencensus/stats/View.java +++ b/api/src/main/java/io/opencensus/stats/View.java @@ -95,7 +95,7 @@ public abstract class View { String description, Measure measure, Aggregation aggregation, - List columns, + List columns, AggregationWindow window) { checkArgument(new HashSet(columns).size() == columns.size(), "Columns have duplicate."); diff --git a/api/src/main/java/io/opencensus/stats/ViewData.java b/api/src/main/java/io/opencensus/stats/ViewData.java index e4872091..007022e7 100644 --- a/api/src/main/java/io/opencensus/stats/ViewData.java +++ b/api/src/main/java/io/opencensus/stats/ViewData.java @@ -56,7 +56,7 @@ public abstract class ViewData { /** Constructs a new {@link ViewData}. */ public static ViewData create( View view, - Map, ? extends AggregationData> map, + Map, ? extends AggregationData> map, final AggregationWindowData windowData) { view.getWindow() .match( @@ -91,7 +91,7 @@ public abstract class ViewData { Functions.throwIllegalArgumentException()); Map, AggregationData> deepCopy = Maps.newHashMap(); - for (Entry, ? extends AggregationData> entry : map + for (Entry, ? extends AggregationData> entry : map .entrySet()) { deepCopy.put( Collections.unmodifiableList(new ArrayList(entry.getKey())), diff --git a/api/src/main/java/io/opencensus/tags/NoopTags.java b/api/src/main/java/io/opencensus/tags/NoopTags.java index 2267edb0..b7c86a2d 100644 --- a/api/src/main/java/io/opencensus/tags/NoopTags.java +++ b/api/src/main/java/io/opencensus/tags/NoopTags.java @@ -21,12 +21,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.base.Preconditions; import io.opencensus.common.Scope; import io.opencensus.internal.NoopScope; -import io.opencensus.tags.TagKey.TagKeyBoolean; -import io.opencensus.tags.TagKey.TagKeyLong; -import io.opencensus.tags.TagKey.TagKeyString; -import io.opencensus.tags.TagValue.TagValueBoolean; -import io.opencensus.tags.TagValue.TagValueLong; -import io.opencensus.tags.TagValue.TagValueString; import io.opencensus.tags.propagation.TagContextBinarySerializer; import io.opencensus.tags.propagation.TagPropagationComponent; import java.util.Collections; @@ -154,21 +148,7 @@ final class NoopTags { static final TagContextBuilder INSTANCE = new NoopTagContextBuilder(); @Override - public TagContextBuilder put(TagKeyString key, TagValueString value) { - checkNotNull(key, "key"); - checkNotNull(value, "value"); - return this; - } - - @Override - public TagContextBuilder put(TagKeyLong key, TagValueLong value) { - checkNotNull(key, "key"); - checkNotNull(value, "value"); - return this; - } - - @Override - public TagContextBuilder put(TagKeyBoolean key, TagValueBoolean value) { + public TagContextBuilder put(TagKey key, TagValue value) { checkNotNull(key, "key"); checkNotNull(value, "value"); return this; diff --git a/api/src/main/java/io/opencensus/tags/Tag.java b/api/src/main/java/io/opencensus/tags/Tag.java index a53cd838..18a56547 100644 --- a/api/src/main/java/io/opencensus/tags/Tag.java +++ b/api/src/main/java/io/opencensus/tags/Tag.java @@ -17,192 +17,37 @@ package io.opencensus.tags; import com.google.auto.value.AutoValue; -import io.opencensus.common.Function; -import io.opencensus.tags.TagKey.TagKeyBoolean; -import io.opencensus.tags.TagKey.TagKeyLong; -import io.opencensus.tags.TagKey.TagKeyString; -import io.opencensus.tags.TagValue.TagValueBoolean; -import io.opencensus.tags.TagValue.TagValueLong; -import io.opencensus.tags.TagValue.TagValueString; import javax.annotation.concurrent.Immutable; -/** {@link TagKey} paired with a value. */ +/** {@link TagKey} paired with a {@link TagValue}. */ @Immutable +@AutoValue public abstract class Tag { + Tag() {} + /** - * Returns the tag's key. + * Creates a {@code Tag} from the given key and value. * - * @return the tag's key. + * @param key the tag key. + * @param value the tag value. + * @return a {@code Tag} with the given key and value. */ - public abstract TagKey getKey(); + public static Tag create(TagKey key, TagValue value) { + return new AutoValue_Tag(key, value); + } /** - * Returns the associated tag value. + * Returns the tag's key. * - * @return the associated tag value. + * @return the tag's key. */ - public abstract TagValue getValue(); - - Tag() {} + public abstract TagKey getKey(); /** - * Applies a function to the tag's key and value. The function that is called depends on the type - * of the tag. This is similar to the visitor pattern. {@code match} also takes a function to - * handle the default case, for backwards compatibility when tag types are added. For example, - * this code serializes a {@code Tag} and tries to handle new tag types by calling {@code - * toString()}. - * - *
{@code
-   * byte[] serializedValue =
-   *     tag.match(
-   *         stringTag -> serializeString(stringTag.getValue().asString()),
-   *         longTag -> serializeLong(longTag.getValue()),
-   *         booleanTag -> serializeBoolean(booleanTag.getValue()),
-   *         unknownTag -> serializeString(unknownTag.toString()));
-   * }
+ * Returns the tag's value. * - *

Without lambdas: - * - *


-   *   byte[] serializedValue =
-   *       tag.match(
-   *           new Function<TagString, String>() {
-   *            {@literal @}Override
-   *             public String apply(TagString stringTag) {
-   *               return serializeString(stringTag.getValue().asString());
-   *             }
-   *           },
-   *           new Function<TagLong, String>() {
-   *            {@literal @}Override
-   *             public String apply(TagLong longTag) {
-   *               serializeLong(longTag.getValue());
-   *             }
-   *           },
-   *           new Function<TagBoolean, String>() {
-   *            {@literal @}Override
-   *             public String apply(TagBoolean booleanTag) {
-   *               serializeBoolean(booleanTag.getValue());
-   *             }
-   *           },
-   *           new Function<Tag, String>() {
-   *            {@literal @}Override
-   *             public String apply(TagBoolean unknownTag) {
-   *               serializeString(unknownTag.toString());
-   *             }
-   *           });
-   * 
- * - * @param stringFunction the function to call when the tag has a {@code String} value. - * @param longFunction the function to call when the tag has a {@code long} value. - * @param booleanFunction the function to call when the tag has a {@code boolean} value. - * @param defaultFunction the function to call when the tag has a value other than {@code String}, - * {@code long}, or {@code boolean}. - * @param The result type of the function. - * @return The result of calling the function that matches the tag's type. + * @return the tag's value. */ - public abstract T match( - Function stringFunction, - Function longFunction, - Function booleanFunction, - Function defaultFunction); - - /** A tag with a {@code String} key and value. */ - @Immutable - @AutoValue - public abstract static class TagString extends Tag { - TagString() {} - - /** - * Creates a {@code TagString} from the given {@code String} key and value. - * - * @param key the tag key. - * @param value the tag value. - * @return a {@code TagString} with the given key and value. - */ - public static TagString create(TagKeyString key, TagValueString value) { - return new AutoValue_Tag_TagString(key, value); - } - - @Override - public abstract TagKeyString getKey(); - - @Override - public abstract TagValueString getValue(); - - @Override - public final T match( - Function stringFunction, - Function longFunction, - Function booleanFunction, - Function defaultFunction) { - return stringFunction.apply(this); - } - } - - /** A tag with a {@code long} key and value. */ - @Immutable - @AutoValue - public abstract static class TagLong extends Tag { - TagLong() {} - - /** - * Creates a {@code TagLong} from the given {@code long} key and value. - * - * @param key the tag key. - * @param value the tag value. - * @return a {@code TagLong} with the given key and value. - */ - public static TagLong create(TagKeyLong key, TagValueLong value) { - return new AutoValue_Tag_TagLong(key, value); - } - - @Override - public abstract TagKeyLong getKey(); - - @Override - public abstract TagValueLong getValue(); - - @Override - public final T match( - Function stringFunction, - Function longFunction, - Function booleanFunction, - Function defaultFunction) { - return longFunction.apply(this); - } - } - - /** A tag with a {@code boolean} key and value. */ - @Immutable - @AutoValue - public abstract static class TagBoolean extends Tag { - TagBoolean() {} - - /** - * Creates a {@code TagBoolean} from the given {@code boolean} key and value. - * - * @param key the tag key. - * @param value the tag value. - * @return a {@code TagBoolean} with the given key and value. - */ - public static TagBoolean create(TagKeyBoolean key, TagValueBoolean value) { - return new AutoValue_Tag_TagBoolean(key, value); - } - - @Override - public abstract TagKeyBoolean getKey(); - - @Override - public abstract TagValueBoolean getValue(); - - @Override - public final T match( - Function stringFunction, - Function longFunction, - Function booleanFunction, - Function defaultFunction) { - return booleanFunction.apply(this); - } - } + public abstract TagValue getValue(); } diff --git a/api/src/main/java/io/opencensus/tags/TagContext.java b/api/src/main/java/io/opencensus/tags/TagContext.java index be8f0dc1..8147906b 100644 --- a/api/src/main/java/io/opencensus/tags/TagContext.java +++ b/api/src/main/java/io/opencensus/tags/TagContext.java @@ -20,19 +20,15 @@ import com.google.common.collect.HashMultiset; import com.google.common.collect.ImmutableMultiset; import com.google.common.collect.Lists; import com.google.common.collect.Multiset; -import io.opencensus.tags.TagValue.TagValueString; import java.util.Iterator; import javax.annotation.concurrent.Immutable; /** - * A map from keys to values that can be used to label anything that is associated with a specific - * operation. + * A map from {@link TagKey} to {@link TagValue} that can be used to label anything that is + * associated with a specific operation. * *

For example, {@code TagContext}s can be used to label stats, log messages, or debugging * information. - * - *

Keys have type {@link TagKey}. Values have type {@link TagValueString}, though the library - * will support more types in the future, including {@code long} and {@code boolean}. */ @Immutable public abstract class TagContext { diff --git a/api/src/main/java/io/opencensus/tags/TagContextBuilder.java b/api/src/main/java/io/opencensus/tags/TagContextBuilder.java index bbd6da7c..2ac36455 100644 --- a/api/src/main/java/io/opencensus/tags/TagContextBuilder.java +++ b/api/src/main/java/io/opencensus/tags/TagContextBuilder.java @@ -17,12 +17,6 @@ package io.opencensus.tags; import io.opencensus.common.Scope; -import io.opencensus.tags.TagKey.TagKeyBoolean; -import io.opencensus.tags.TagKey.TagKeyLong; -import io.opencensus.tags.TagKey.TagKeyString; -import io.opencensus.tags.TagValue.TagValueBoolean; -import io.opencensus.tags.TagValue.TagValueLong; -import io.opencensus.tags.TagValue.TagValueString; /** Builder for the {@link TagContext} class. */ // TODO(sebright): Decide what to do when 'put' is called with a key that has the same name as an @@ -36,25 +30,7 @@ public abstract class TagContextBuilder { * @param value the value to set for the given key. * @return this */ - public abstract TagContextBuilder put(TagKeyString key, TagValueString value); - - /** - * Adds the key/value pair regardless of whether the key is present. - * - * @param key the {@code TagKey} which will be set. - * @param value the value to set for the given key. - * @return this - */ - public abstract TagContextBuilder put(TagKeyLong key, TagValueLong value); - - /** - * Adds the key/value pair regardless of whether the key is present. - * - * @param key the {@code TagKey} which will be set. - * @param value the value to set for the given key. - * @return this - */ - public abstract TagContextBuilder put(TagKeyBoolean key, TagValueBoolean value); + public abstract TagContextBuilder put(TagKey key, TagValue value); /** * Removes the key if it exists. diff --git a/api/src/main/java/io/opencensus/tags/TagKey.java b/api/src/main/java/io/opencensus/tags/TagKey.java index 943f12d7..7e532849 100644 --- a/api/src/main/java/io/opencensus/tags/TagKey.java +++ b/api/src/main/java/io/opencensus/tags/TagKey.java @@ -19,103 +19,52 @@ package io.opencensus.tags; import static com.google.common.base.Preconditions.checkArgument; import com.google.auto.value.AutoValue; -import io.opencensus.common.Function; import io.opencensus.internal.StringUtil; -import io.opencensus.tags.TagValue.TagValueString; import javax.annotation.concurrent.Immutable; /** * A key to a value stored in a {@link TagContext}. * - *

There is one {@code TagKey} subclass corresponding to each tag value type, so that each key - * can only be paired with a single type of value. For example, {@link TagKeyString} can only be - * used to set {@link TagValueString} values in a {@code TagContext}. - * *

Each {@code TagKey} has a {@code String} name. Names have a maximum length of {@link * #MAX_LENGTH} and contain only printable ASCII characters. * - *

{@code TagKey}s are designed to be used as constants. Declaring each key as a constant ensures - * that the keys have consistent value types and prevents key names from being validated multiple - * times. + *

{@code TagKey}s are designed to be used as constants. Declaring each key as a constant + * prevents key names from being validated multiple times. */ @Immutable +@AutoValue public abstract class TagKey { /** The maximum length for a tag key name. The value is {@value #MAX_LENGTH}. */ public static final int MAX_LENGTH = 255; TagKey() {} - public abstract String getName(); - /** - * Applies a function to the {@code TagKey} subclass. The function that is called depends on the - * type of the tag key. This is similar to the visitor pattern. {@code match} also takes a - * function to handle the default case, for backwards compatibility when tag types are added. For - * example, this code creates a {@code Tag} from a {@code TagKey}. It handles new tag types by - * logging an error and returning a {@code TagKeyString}. + * Constructs a {@code TagKey} with the given name. * - *

{@code
-   * Tag tag =
-   *     tagKey.match(
-   *         stringKey -> TagString.create(stringKey, TagValueString.create("string value")),
-   *         longKey -> TagLong.create(longKey, 100L),
-   *         booleanKey -> TagBoolean.create(booleanKey, true),
-   *         unknownKey -> {
-   *           logger.log(Level.WARNING, "Unknown tag key type: " + unknownKey.toString());
-   *           return TagString.create(
-   *               TagKeyString.create(unknownKey.getName()),
-   *               TagValueString.create("string value"));
-   *         });
-   * }
+ *

The name must meet the following requirements: * - *

Without lambdas: + *

    + *
  1. It cannot be longer than {@link #MAX_LENGTH}. + *
  2. It can only contain printable ASCII characters. + *
* - *

-   *   Tag tag =
-   *       tagKey.match(
-   *           new Function<TagKeyString, Tag>() {
-   *            {@literal @}Override
-   *             public Tag apply(TagKeyString stringKey) {
-   *               return TagString.create(stringKey, TagValueString.create("string value"));
-   *             }
-   *           },
-   *           new Function<TagKeyLong, Tag>() {
-   *            {@literal @}Override
-   *             public Tag apply(TagKeyLong longKey) {
-   *               return TagLong.create(longKey, 100L);
-   *             }
-   *           },
-   *           new Function<TagKeyBoolean, Tag>() {
-   *            {@literal @}Override
-   *             public Tag apply(TagKeyBoolean booleanKey) {
-   *               return TagBoolean.create(booleanKey, true);
-   *             }
-   *           },
-   *           new Function<TagKey, Tag>() {
-   *            {@literal @}Override
-   *             public Tag apply(TagKey unknownKey) {
-   *               logger.log(Level.WARNING, "Unknown tag key type: " + unknownKey.toString());
-   *               return TagString.create(
-   *                   TagKeyString.create(unknownKey.getName()),
-   *                   TagValueString.create("string value"));
-   *             }
-   *           });
-   * 
+ * @param name the name of the key. + * @return a {@code TagKey} with the given name. + * @throws IllegalArgumentException if the name is not valid. + */ + public static TagKey create(String name) { + // TODO(sebright): Should we disallow an empty name? + checkArgument(isValid(name)); + return new AutoValue_TagKey(name); + } + + /** + * Returns the name of the key. * - * @param stringFunction the function to call when the {@code TagKey} is a {@code TagKeyString}. - * @param longFunction the function to call when the {@code TagKey} is a {@code TagKeyLong}. - * @param booleanFunction the function to call when the {@code TagKey} is a {@code TagKeyBoolean}. - * @param defaultFunction the function to call when the tag key has a type other than {@code - * String}, {@code long}, or {@code boolean}. - * @param The result type of the function. - * @return The result of calling the function that matches the tag key's type. + * @return the name of the key. */ - // TODO(sebright): Should we make this public in the first release? - public abstract T match( - Function stringFunction, - Function longFunction, - Function booleanFunction, - Function defaultFunction); + public abstract String getName(); /** * Determines whether the given {@code String} is a valid tag key. @@ -126,119 +75,4 @@ public abstract class TagKey { private static boolean isValid(String name) { return name.length() <= MAX_LENGTH && StringUtil.isPrintableString(name); } - - /** A {@code TagKey} for values of type {@code String}. */ - @Immutable - @AutoValue - public abstract static class TagKeyString extends TagKey { - - /** - * Constructs a {@code TagKeyString} with the given name. - * - *

The name must meet the following requirements: - * - *

    - *
  1. It cannot be longer than {@link #MAX_LENGTH}. - *
  2. It can only contain printable ASCII characters. - *
- * - * @param name the name of the key. - * @return a {@code TagKeyString} with the given name. - * @throws IllegalArgumentException if the name is not valid. - */ - public static TagKeyString create(String name) { - // TODO(sebright): Should we disallow an empty name? - checkArgument(isValid(name)); - return new AutoValue_TagKey_TagKeyString(name); - } - - @Override - public final T match( - Function stringFunction, - Function longFunction, - Function booleanFunction, - Function defaultFunction) { - return stringFunction.apply(this); - } - } - - /** - * A {@code TagKey} for values of type {@code long}. - * - *

Note that {@link TagKeyLong} isn't supported by the implementation yet, so the factory - * method isn't exposed. - */ - @Immutable - @AutoValue - public abstract static class TagKeyLong extends TagKey { - - /** - * Constructs a {@code TagKeyLong} with the given name. - * - *

The name must meet the following requirements: - * - *

    - *
  1. It cannot be longer than {@link #MAX_LENGTH}. - *
  2. It can only contain printable ASCII characters. - *
- * - * @param name the name of the key. - * @return a {@code TagKeyLong} with the given name. - * @throws IllegalArgumentException if the name is not valid. - */ - // TODO(sebright): Make this public once we support types other than String. - static TagKeyLong create(String name) { - checkArgument(isValid(name)); - return new AutoValue_TagKey_TagKeyLong(name); - } - - @Override - public final T match( - Function stringFunction, - Function longFunction, - Function booleanFunction, - Function defaultFunction) { - return longFunction.apply(this); - } - } - - /** - * A {@code TagKey} for values of type {@code boolean}. - * - *

Note that {@link TagKeyBoolean} isn't supported by the implementation yet, so the factory - * method isn't exposed. - */ - @Immutable - @AutoValue - public abstract static class TagKeyBoolean extends TagKey { - - /** - * Constructs a {@code TagKeyBoolean} with the given name. - * - *

The name must meet the following requirements: - * - *

    - *
  1. It cannot be longer than {@link #MAX_LENGTH}. - *
  2. It can only contain printable ASCII characters. - *
- * - * @param name the name of the key. - * @return a {@code TagKeyBoolean} with the given name. - * @throws IllegalArgumentException if the name is not valid. - */ - // TODO(sebright): Make this public once we support types other than String. - static TagKeyBoolean create(String name) { - checkArgument(isValid(name)); - return new AutoValue_TagKey_TagKeyBoolean(name); - } - - @Override - public final T match( - Function stringFunction, - Function longFunction, - Function booleanFunction, - Function defaultFunction) { - return booleanFunction.apply(this); - } - } } diff --git a/api/src/main/java/io/opencensus/tags/TagValue.java b/api/src/main/java/io/opencensus/tags/TagValue.java index 7da713c5..abd0bda4 100644 --- a/api/src/main/java/io/opencensus/tags/TagValue.java +++ b/api/src/main/java/io/opencensus/tags/TagValue.java @@ -18,165 +18,54 @@ package io.opencensus.tags; import com.google.auto.value.AutoValue; import com.google.common.base.Preconditions; -import io.opencensus.common.Function; import io.opencensus.internal.StringUtil; -import io.opencensus.tags.TagKey.TagKeyBoolean; -import io.opencensus.tags.TagKey.TagKeyLong; -import io.opencensus.tags.TagKey.TagKeyString; import javax.annotation.concurrent.Immutable; -/** A validated tag value. */ +/** + * A validated tag value. + * + *

Validation ensures that the {@code String} has a maximum length of {@link #MAX_LENGTH} and + * contains only printable ASCII characters. + */ @Immutable +@AutoValue public abstract class TagValue { + /** The maximum length for a tag value. The value is {@value #MAX_LENGTH}. */ + public static final int MAX_LENGTH = 256; TagValue() {} /** - * Applies a function to a tag value. The function that is called depends on the type of the - * value. This is similar to the visitor pattern. {@code match} also takes a function to handle - * the default case, for backwards compatibility when tag types are added. + * Constructs a {@code TagValue} from the given string. The string must meet the following + * requirements: + * + *

    + *
  1. It cannot be longer than {@link #MAX_LENGTH}. + *
  2. It can only contain printable ASCII characters. + *
* - * @param stringFunction the function to call when the tag value has type {@code String}. - * @param longFunction the function to call when the tag value has type {@code long}. - * @param booleanFunction the function to call when the tag value has type {@code boolean}. - * @param defaultFunction the function to call when the tag value has a type other than {@code - * String}, {@code long}, or {@code boolean}. - * @param The result type of the function. - * @return The result of calling the function that matches the tag value's type. + * @param value the tag value. + * @throws IllegalArgumentException if the {@code String} is not valid. */ - public abstract T match( - Function stringFunction, - Function longFunction, - Function booleanFunction, - Function defaultFunction); + public static TagValue create(String value) { + Preconditions.checkArgument(isValid(value)); + return new AutoValue_TagValue(value); + } /** - * A validated tag value associated with a {@link TagKeyString}. + * Returns the tag value as a {@code String}. * - *

Validation ensures that the {@code String} has a maximum length of {@link #MAX_LENGTH} and - * contains only printable ASCII characters. + * @return the tag value as a {@code String}. */ - @Immutable - @AutoValue - public abstract static class TagValueString extends TagValue { - /** The maximum length for a {@code String} tag value. The value is {@value #MAX_LENGTH}. */ - public static final int MAX_LENGTH = 256; - - TagValueString() {} - - /** - * Constructs a {@code TagValueString} from the given string. The string must meet the following - * requirements: - * - *

    - *
  1. It cannot be longer than {@link #MAX_LENGTH}. - *
  2. It can only contain printable ASCII characters. - *
- * - * @param value the tag value. - * @throws IllegalArgumentException if the {@code String} is not valid. - */ - public static TagValueString create(String value) { - Preconditions.checkArgument(isValid(value)); - return new AutoValue_TagValue_TagValueString(value); - } - - @Override - public final T match( - Function stringFunction, - Function longFunction, - Function booleanFunction, - Function defaultFunction) { - return stringFunction.apply(this); - } - - /** - * Returns the tag value as a {@code String}. - * - * @return the tag value as a {@code String}. - */ - public abstract String asString(); - - /** - * Determines whether the given {@code String} is a valid tag value. - * - * @param value the tag value to be validated. - * @return whether the value is valid. - */ - private static boolean isValid(String value) { - return value.length() <= MAX_LENGTH && StringUtil.isPrintableString(value); - } - } - - /** A tag value associated with a {@link TagKeyLong}. */ - @Immutable - @AutoValue - public abstract static class TagValueLong extends TagValue { - - TagValueLong() {} + public abstract String asString(); - /** - * Constructs a {@code TagValueLong} from the given {@code long}. - * - * @param value the tag value. - */ - public static TagValueLong create(long value) { - return new AutoValue_TagValue_TagValueLong(value); - } - - @Override - public final T match( - Function stringFunction, - Function longFunction, - Function booleanFunction, - Function defaultFunction) { - return longFunction.apply(this); - } - - /** - * Returns the tag value as a {@code long}. - * - * @return the tag value as a {@code long}. - */ - public abstract long asLong(); - } - - /** A tag value associated with a {@link TagKeyBoolean}. */ - @Immutable - @AutoValue - public abstract static class TagValueBoolean extends TagValue { - private static final TagValueBoolean TRUE_VALUE = createInternal(true); - private static final TagValueBoolean FALSE_VALUE = createInternal(false); - - TagValueBoolean() {} - - /** - * Constructs a {@code TagValueBoolean} from the given {@code boolean}. - * - * @param value the tag value. - */ - public static TagValueBoolean create(boolean value) { - return value ? TRUE_VALUE : FALSE_VALUE; - } - - private static TagValueBoolean createInternal(boolean value) { - return new AutoValue_TagValue_TagValueBoolean(value); - } - - @Override - public final T match( - Function stringFunction, - Function longFunction, - Function booleanFunction, - Function defaultFunction) { - return booleanFunction.apply(this); - } - - /** - * Returns the tag value as a {@code boolean}. - * - * @return the tag value as a {@code boolean}. - */ - public abstract boolean asBoolean(); + /** + * Determines whether the given {@code String} is a valid tag value. + * + * @param value the tag value to be validated. + * @return whether the value is valid. + */ + private static boolean isValid(String value) { + return value.length() <= MAX_LENGTH && StringUtil.isPrintableString(value); } } diff --git a/api/src/main/java/io/opencensus/tags/package-info.java b/api/src/main/java/io/opencensus/tags/package-info.java index 2a332f6d..e18c68d1 100644 --- a/api/src/main/java/io/opencensus/tags/package-info.java +++ b/api/src/main/java/io/opencensus/tags/package-info.java @@ -22,12 +22,11 @@ * io.opencensus.stats} package labels all stats with the current tags. * *

{@link io.opencensus.tags.Tag Tags} are key-value pairs. The {@link io.opencensus.tags.TagKey - * keys} are wrapped {@code String}s, but the values can have multiple types, such as {@code - * String}, {@code long}, and {@code boolean}. They are stored as a map in a {@link - * io.opencensus.tags.TagContext}. + * keys} and {@link io.opencensus.tags.TagValue values} are wrapped {@code String}s. They are + * stored as a map in a {@link io.opencensus.tags.TagContext}. * *

Note that tags are independent of the tracing data that is propagated in the {@code * io.grpc.Context}, such as trace ID. */ -// TODO(sebright): Add code examples after the API is updated to use a TagContext factory. +// TODO(sebright): Add code examples. package io.opencensus.tags; diff --git a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java index 9639ab94..dfd1136b 100644 --- a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java +++ b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java @@ -20,10 +20,9 @@ import static com.google.common.truth.Truth.assertThat; import io.opencensus.stats.Measure.MeasureDouble; import io.opencensus.tags.Tag; -import io.opencensus.tags.Tag.TagString; import io.opencensus.tags.TagContext; -import io.opencensus.tags.TagKey.TagKeyString; -import io.opencensus.tags.TagValue.TagValueString; +import io.opencensus.tags.TagKey; +import io.opencensus.tags.TagValue; import java.util.Collections; import java.util.Iterator; import org.junit.Rule; @@ -38,8 +37,7 @@ import org.junit.runners.JUnit4; */ @RunWith(JUnit4.class) public final class NoopStatsTest { - private static final TagString TAG = - TagString.create(TagKeyString.create("key"), TagValueString.create("value")); + private static final Tag TAG = Tag.create(TagKey.create("key"), TagValue.create("value")); private static final MeasureDouble MEASURE = Measure.MeasureDouble.create("my measure", "description", "s"); diff --git a/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java b/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java index 01196e1d..b70e49cc 100644 --- a/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java +++ b/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java @@ -27,7 +27,7 @@ import io.opencensus.stats.View.AggregationWindow.Interval; import io.opencensus.stats.View.Name; import io.opencensus.stats.ViewData.AggregationWindowData.CumulativeData; import io.opencensus.stats.ViewData.AggregationWindowData.IntervalData; -import io.opencensus.tags.TagKey.TagKeyString; +import io.opencensus.tags.TagKey; import java.util.Arrays; import org.junit.Rule; import org.junit.Test; @@ -40,7 +40,7 @@ import org.junit.runners.JUnit4; public final class NoopViewManagerTest { private static final MeasureDouble MEASURE = Measure.MeasureDouble.create("my measure", "description", "s"); - private static final TagKeyString KEY = TagKeyString.create("KEY"); + private static final TagKey KEY = TagKey.create("KEY"); private static final Name VIEW_NAME = Name.create("my view"); private static final String VIEW_DESCRIPTION = "view description"; private static final Sum AGGREGATION = Sum.create(); diff --git a/api/src/test/java/io/opencensus/stats/ViewDataTest.java b/api/src/test/java/io/opencensus/stats/ViewDataTest.java index 43cc956a..69313295 100644 --- a/api/src/test/java/io/opencensus/stats/ViewDataTest.java +++ b/api/src/test/java/io/opencensus/stats/ViewDataTest.java @@ -33,9 +33,8 @@ import io.opencensus.stats.View.AggregationWindow.Interval; import io.opencensus.stats.ViewData.AggregationWindowData; import io.opencensus.stats.ViewData.AggregationWindowData.CumulativeData; import io.opencensus.stats.ViewData.AggregationWindowData.IntervalData; -import io.opencensus.tags.TagKey.TagKeyString; +import io.opencensus.tags.TagKey; import io.opencensus.tags.TagValue; -import io.opencensus.tags.TagValue.TagValueString; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -184,15 +183,15 @@ public final class ViewDataTest { } // tag keys - private static final TagKeyString K1 = TagKeyString.create("k1"); - private static final TagKeyString K2 = TagKeyString.create("k2"); - private final List tagKeys = Arrays.asList(K1, K2); + private static final TagKey K1 = TagKey.create("k1"); + private static final TagKey K2 = TagKey.create("k2"); + private final List tagKeys = Arrays.asList(K1, K2); // tag values - private static final TagValueString V1 = TagValueString.create("v1"); - private static final TagValueString V2 = TagValueString.create("v2"); - private static final TagValueString V10 = TagValueString.create("v10"); - private static final TagValueString V20 = TagValueString.create("v20"); + private static final TagValue V1 = TagValue.create("v1"); + private static final TagValue V2 = TagValue.create("v2"); + private static final TagValue V10 = TagValue.create("v10"); + private static final TagValue V20 = TagValue.create("v20"); private static final AggregationWindow CUMULATIVE = Cumulative.create(); private static final AggregationWindow INTERVAL_HOUR = Interval.create(Duration.create(3600, 0)); @@ -202,7 +201,7 @@ public final class ViewDataTest { private static final Aggregation DISTRIBUTION = Distribution.create(BUCKET_BOUNDARIES); - private static final ImmutableMap, DistributionData> ENTRIES = + private static final ImmutableMap, DistributionData> ENTRIES = ImmutableMap.of( Arrays.asList(V1, V2), DistributionData.create(1, 1, 1, 1, 0, new long[]{0, 1, 0}), diff --git a/api/src/test/java/io/opencensus/stats/ViewTest.java b/api/src/test/java/io/opencensus/stats/ViewTest.java index 99215352..81584ef9 100644 --- a/api/src/test/java/io/opencensus/stats/ViewTest.java +++ b/api/src/test/java/io/opencensus/stats/ViewTest.java @@ -24,7 +24,7 @@ import io.opencensus.common.Duration; import io.opencensus.stats.Aggregation.Mean; import io.opencensus.stats.View.AggregationWindow.Cumulative; import io.opencensus.stats.View.AggregationWindow.Interval; -import io.opencensus.tags.TagKey.TagKeyString; +import io.opencensus.tags.TagKey; import java.util.Arrays; import java.util.List; import org.junit.Rule; @@ -100,7 +100,7 @@ public final class ViewTest { DESCRIPTION, MEASURE, MEAN, - Arrays.asList(TagKeyString.create("duplicate"), TagKeyString.create("duplicate")), + Arrays.asList(TagKey.create("duplicate"), TagKey.create("duplicate")), Cumulative.create()); } @@ -152,9 +152,9 @@ public final class ViewTest { private static final String DESCRIPTION = "test-view-name description"; private static final Measure MEASURE = Measure.MeasureDouble.create( "measure", "measure description", "1"); - private static final TagKeyString FOO = TagKeyString.create("foo"); - private static final TagKeyString BAR = TagKeyString.create("bar"); - private static final List keys = ImmutableList.of(FOO, BAR); + private static final TagKey FOO = TagKey.create("foo"); + private static final TagKey BAR = TagKey.create("bar"); + private static final List keys = ImmutableList.of(FOO, BAR); private static final Mean MEAN = Mean.create(); private static final Duration MINUTE = Duration.create(60, 0); private static final Duration TWO_MINUTES = Duration.create(120, 0); diff --git a/api/src/test/java/io/opencensus/tags/InternalUtilsTest.java b/api/src/test/java/io/opencensus/tags/InternalUtilsTest.java index ba69ef88..db5a2d9d 100644 --- a/api/src/test/java/io/opencensus/tags/InternalUtilsTest.java +++ b/api/src/test/java/io/opencensus/tags/InternalUtilsTest.java @@ -19,9 +19,6 @@ package io.opencensus.tags; import static com.google.common.truth.Truth.assertThat; import com.google.common.collect.Lists; -import io.opencensus.tags.Tag.TagString; -import io.opencensus.tags.TagKey.TagKeyString; -import io.opencensus.tags.TagValue.TagValueString; import java.util.Iterator; import org.junit.Test; import org.junit.runner.RunWith; @@ -35,7 +32,7 @@ public final class InternalUtilsTest { public void getTags() { final Iterator iterator = Lists.newArrayList( - TagString.create(TagKeyString.create("k"), TagValueString.create("v"))) + Tag.create(TagKey.create("k"), TagValue.create("v"))) .iterator(); TagContext ctx = new TagContext() { diff --git a/api/src/test/java/io/opencensus/tags/NoopTagsTest.java b/api/src/test/java/io/opencensus/tags/NoopTagsTest.java index 2ee1c8cc..d39c5d7f 100644 --- a/api/src/test/java/io/opencensus/tags/NoopTagsTest.java +++ b/api/src/test/java/io/opencensus/tags/NoopTagsTest.java @@ -20,13 +20,6 @@ import static com.google.common.truth.Truth.assertThat; import com.google.common.collect.Lists; import io.opencensus.internal.NoopScope; -import io.opencensus.tags.Tag.TagString; -import io.opencensus.tags.TagKey.TagKeyBoolean; -import io.opencensus.tags.TagKey.TagKeyLong; -import io.opencensus.tags.TagKey.TagKeyString; -import io.opencensus.tags.TagValue.TagValueBoolean; -import io.opencensus.tags.TagValue.TagValueLong; -import io.opencensus.tags.TagValue.TagValueString; import io.opencensus.tags.propagation.TagContextBinarySerializer; import io.opencensus.tags.propagation.TagContextParseException; import java.util.Arrays; @@ -40,19 +33,15 @@ import org.junit.runners.JUnit4; /** Unit tests for {@link NoopTags}. */ @RunWith(JUnit4.class) public final class NoopTagsTest { - private static final TagKeyString KEY_STRING = TagKeyString.create("key"); - private static final TagValueString VALUE_STRING = TagValueString.create("value"); - private static final TagKeyLong KEY_LONG = TagKeyLong.create("key"); - private static final TagValueLong VALUE_LONG = TagValueLong.create(1L); - private static final TagKeyBoolean KEY_BOOLEAN = TagKeyBoolean.create("key"); - private static final TagValueBoolean VALUE_BOOLEAN = TagValueBoolean.create(true); + private static final TagKey KEY = TagKey.create("key"); + private static final TagValue VALUE = TagValue.create("value"); private static final TagContext TAG_CONTEXT = new TagContext() { @Override protected Iterator getIterator() { - return Arrays.asList(TagString.create(KEY_STRING, VALUE_STRING)).iterator(); + return Arrays.asList(Tag.create(KEY, VALUE)).iterator(); } }; @@ -100,53 +89,25 @@ public final class NoopTagsTest { @Test public void noopTagContextBuilder() { assertThat(NoopTags.getNoopTagContextBuilder().build()).isSameAs(NoopTags.getNoopTagContext()); - assertThat(NoopTags.getNoopTagContextBuilder().put(KEY_STRING, VALUE_STRING).build()) + assertThat(NoopTags.getNoopTagContextBuilder().put(KEY, VALUE).build()) .isSameAs(NoopTags.getNoopTagContext()); assertThat(NoopTags.getNoopTagContextBuilder().buildScoped()).isSameAs(NoopScope.getInstance()); - assertThat(NoopTags.getNoopTagContextBuilder().put(KEY_STRING, VALUE_STRING).buildScoped()) + assertThat(NoopTags.getNoopTagContextBuilder().put(KEY, VALUE).buildScoped()) .isSameAs(NoopScope.getInstance()); } @Test - public void noopTagContextBuilder_PutString_DisallowsNullKey() { + public void noopTagContextBuilder_Put_DisallowsNullKey() { TagContextBuilder noopBuilder = NoopTags.getNoopTagContextBuilder(); thrown.expect(NullPointerException.class); - noopBuilder.put(null, VALUE_STRING); + noopBuilder.put(null, VALUE); } @Test - public void noopTagContextBuilder_PutString_DisallowsNullValue() { + public void noopTagContextBuilder_Put_DisallowsNullValue() { TagContextBuilder noopBuilder = NoopTags.getNoopTagContextBuilder(); thrown.expect(NullPointerException.class); - noopBuilder.put(KEY_STRING, null); - } - - @Test - public void noopTagContextBuilder_PutLong_DisallowsNullKey() { - TagContextBuilder noopBuilder = NoopTags.getNoopTagContextBuilder(); - thrown.expect(NullPointerException.class); - noopBuilder.put(null, VALUE_LONG); - } - - @Test - public void noopTagContextBuilder_PutLong_DisallowsNullValue() { - TagContextBuilder noopBuilder = NoopTags.getNoopTagContextBuilder(); - thrown.expect(NullPointerException.class); - noopBuilder.put(KEY_LONG, null); - } - - @Test - public void noopTagContextBuilder_PutBoolean_DisallowsNullKey() { - TagContextBuilder noopBuilder = NoopTags.getNoopTagContextBuilder(); - thrown.expect(NullPointerException.class); - noopBuilder.put(null, VALUE_BOOLEAN); - } - - @Test - public void noopTagContextBuilder_PutBoolean_DisallowsNullValue() { - TagContextBuilder noopBuilder = NoopTags.getNoopTagContextBuilder(); - thrown.expect(NullPointerException.class); - noopBuilder.put(KEY_BOOLEAN, null); + noopBuilder.put(KEY, null); } @Test diff --git a/api/src/test/java/io/opencensus/tags/TagContextTest.java b/api/src/test/java/io/opencensus/tags/TagContextTest.java index d6adfe12..0e229323 100644 --- a/api/src/test/java/io/opencensus/tags/TagContextTest.java +++ b/api/src/test/java/io/opencensus/tags/TagContextTest.java @@ -20,9 +20,6 @@ import static com.google.common.truth.Truth.assertThat; import com.google.common.collect.Lists; import com.google.common.testing.EqualsTester; -import io.opencensus.tags.Tag.TagString; -import io.opencensus.tags.TagKey.TagKeyString; -import io.opencensus.tags.TagValue.TagValueString; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -34,9 +31,9 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public final class TagContextTest { private static final Tag TAG1 = - TagString.create(TagKeyString.create("key"), TagValueString.create("val")); + Tag.create(TagKey.create("key"), TagValue.create("val")); private static final Tag TAG2 = - TagString.create(TagKeyString.create("key2"), TagValueString.create("val")); + Tag.create(TagKey.create("key2"), TagValue.create("val")); @Test public void equals_IgnoresTagOrderAndTagContextClass() { diff --git a/api/src/test/java/io/opencensus/tags/TagKeyTest.java b/api/src/test/java/io/opencensus/tags/TagKeyTest.java index 5b70ba7a..122c5baa 100644 --- a/api/src/test/java/io/opencensus/tags/TagKeyTest.java +++ b/api/src/test/java/io/opencensus/tags/TagKeyTest.java @@ -19,11 +19,6 @@ package io.opencensus.tags; import static com.google.common.truth.Truth.assertThat; import com.google.common.testing.EqualsTester; -import io.opencensus.common.Function; -import io.opencensus.common.Functions; -import io.opencensus.tags.TagKey.TagKeyBoolean; -import io.opencensus.tags.TagKey.TagKeyLong; -import io.opencensus.tags.TagKey.TagKeyString; import java.util.Arrays; import org.junit.Rule; import org.junit.Test; @@ -39,118 +34,35 @@ public final class TagKeyTest { @Test public void testGetName() { - assertThat(TagKeyString.create("foo").getName()).isEqualTo("foo"); + assertThat(TagKey.create("foo").getName()).isEqualTo("foo"); } @Test - public void createString_AllowTagKeyNameWithMaxLength() { + public void create_AllowTagKeyNameWithMaxLength() { char[] key = new char[TagKey.MAX_LENGTH]; Arrays.fill(key, 'k'); - TagKeyString.create(new String(key)); + TagKey.create(new String(key)); } @Test - public void createString_DisallowTagKeyNameOverMaxLength() { + public void create_DisallowTagKeyNameOverMaxLength() { char[] key = new char[TagKey.MAX_LENGTH + 1]; Arrays.fill(key, 'k'); thrown.expect(IllegalArgumentException.class); - TagKeyString.create(new String(key)); + TagKey.create(new String(key)); } @Test - public void createString_DisallowUnprintableChars() { + public void create_DisallowUnprintableChars() { thrown.expect(IllegalArgumentException.class); - TagKeyString.create("\2ab\3cd"); - } - - @Test - public void testMatchStringKey() { - assertThat( - TagKeyString.create("key") - .match( - new Function() { - @Override - public String apply(TagKeyString tag) { - return tag.getName(); - } - }, - new Function() { - @Override - public String apply(TagKeyLong tag) { - throw new AssertionError(); - } - }, - new Function() { - @Override - public String apply(TagKeyBoolean tag) { - throw new AssertionError(); - } - }, - Functions.throwIllegalArgumentException())) - .isEqualTo("key"); - } - - @Test - public void testMatchLongKey() { - assertThat( - TagKeyLong.create("key") - .match( - new Function() { - @Override - public String apply(TagKeyString tag) { - throw new AssertionError(); - } - }, - new Function() { - @Override - public String apply(TagKeyLong tag) { - return tag.getName(); - } - }, - new Function() { - @Override - public String apply(TagKeyBoolean tag) { - throw new AssertionError(); - } - }, - Functions.throwIllegalArgumentException())) - .isEqualTo("key"); - } - - @Test - public void testMatchBooleanKey() { - assertThat( - TagKeyBoolean.create("key") - .match( - new Function() { - @Override - public String apply(TagKeyString tag) { - throw new AssertionError(); - } - }, - new Function() { - @Override - public String apply(TagKeyLong tag) { - throw new AssertionError(); - } - }, - new Function() { - @Override - public String apply(TagKeyBoolean tag) { - return tag.getName(); - } - }, - Functions.throwIllegalArgumentException())) - .isEqualTo("key"); + TagKey.create("\2ab\3cd"); } @Test public void testTagKeyEquals() { new EqualsTester() - .addEqualityGroup(TagKeyString.create("foo"), TagKeyString.create("foo")) - .addEqualityGroup(TagKeyLong.create("foo")) - .addEqualityGroup(TagKeyBoolean.create("foo")) - .addEqualityGroup(TagKeyString.create("bar")) + .addEqualityGroup(TagKey.create("foo"), TagKey.create("foo")) + .addEqualityGroup(TagKey.create("bar")) .testEquals(); } } diff --git a/api/src/test/java/io/opencensus/tags/TagTest.java b/api/src/test/java/io/opencensus/tags/TagTest.java index 79b2eb4d..f3fe6dc4 100644 --- a/api/src/test/java/io/opencensus/tags/TagTest.java +++ b/api/src/test/java/io/opencensus/tags/TagTest.java @@ -19,17 +19,6 @@ package io.opencensus.tags; import static com.google.common.truth.Truth.assertThat; import com.google.common.testing.EqualsTester; -import io.opencensus.common.Function; -import io.opencensus.common.Functions; -import io.opencensus.tags.Tag.TagBoolean; -import io.opencensus.tags.Tag.TagLong; -import io.opencensus.tags.Tag.TagString; -import io.opencensus.tags.TagKey.TagKeyBoolean; -import io.opencensus.tags.TagKey.TagKeyLong; -import io.opencensus.tags.TagKey.TagKeyString; -import io.opencensus.tags.TagValue.TagValueBoolean; -import io.opencensus.tags.TagValue.TagValueLong; -import io.opencensus.tags.TagValue.TagValueString; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -39,120 +28,21 @@ import org.junit.runners.JUnit4; public final class TagTest { @Test - public void testGetStringKey() { - assertThat(TagString.create(TagKeyString.create("k"), TagValueString.create("v")).getKey()) - .isEqualTo(TagKeyString.create("k")); - } - - @Test - public void testGetLongKey() { - assertThat(TagLong.create(TagKeyLong.create("k"), TagValueLong.create(2L)).getKey()) - .isEqualTo(TagKeyLong.create("k")); - } - - @Test - public void testGetBooleanKey() { - assertThat(TagBoolean.create(TagKeyBoolean.create("k"), TagValueBoolean.create(false)).getKey()) - .isEqualTo(TagKeyBoolean.create("k")); - } - - @Test - public void testMatchStringTag() { - assertThat( - TagString.create(TagKeyString.create("k1"), TagValueString.create("value")) - .match( - new Function() { - @Override - public String apply(TagString tag) { - return tag.getValue().asString(); - } - }, - new Function() { - @Override - public String apply(TagLong tag) { - throw new AssertionError(); - } - }, - new Function() { - @Override - public String apply(TagBoolean tag) { - throw new AssertionError(); - } - }, - Functions.throwIllegalArgumentException())) - .isEqualTo("value"); - } - - @Test - public void testMatchLong() { - assertThat( - TagLong.create(TagKeyLong.create("k2"), TagValueLong.create(3L)) - .match( - new Function() { - @Override - public Long apply(TagString tag) { - throw new AssertionError(); - } - }, - new Function() { - @Override - public Long apply(TagLong tag) { - return tag.getValue().asLong(); - } - }, - new Function() { - @Override - public Long apply(TagBoolean tag) { - throw new AssertionError(); - } - }, - Functions.throwIllegalArgumentException())) - .isEqualTo(3L); - } - - @Test - public void testMatchBoolean() { - assertThat( - TagBoolean.create(TagKeyBoolean.create("k3"), TagValueBoolean.create(false)) - .match( - new Function() { - @Override - public Boolean apply(TagString tag) { - throw new AssertionError(); - } - }, - new Function() { - @Override - public Boolean apply(TagLong tag) { - throw new AssertionError(); - } - }, - new Function() { - @Override - public Boolean apply(TagBoolean tag) { - return tag.getValue().asBoolean(); - } - }, - Functions.throwIllegalArgumentException())) - .isEqualTo(false); + public void testGetKey() { + assertThat(Tag.create(TagKey.create("k"), TagValue.create("v")).getKey()) + .isEqualTo(TagKey.create("k")); } @Test public void testTagEquals() { new EqualsTester() .addEqualityGroup( - TagString.create(TagKeyString.create("Key1"), TagValueString.create("foo")), - TagString.create(TagKeyString.create("Key1"), TagValueString.create("foo"))) - .addEqualityGroup( - TagLong.create(TagKeyLong.create("Key1"), TagValueLong.create(100L)), - TagLong.create(TagKeyLong.create("Key1"), TagValueLong.create(100L))) - .addEqualityGroup( - TagBoolean.create(TagKeyBoolean.create("Key1"), TagValueBoolean.create(true)), - TagBoolean.create(TagKeyBoolean.create("Key1"), TagValueBoolean.create(true))) + Tag.create(TagKey.create("Key"), TagValue.create("foo")), + Tag.create(TagKey.create("Key"), TagValue.create("foo"))) .addEqualityGroup( - TagBoolean.create(TagKeyBoolean.create("Key2"), TagValueBoolean.create(true))) + Tag.create(TagKey.create("Key"), TagValue.create("bar"))) .addEqualityGroup( - TagBoolean.create(TagKeyBoolean.create("Key1"), TagValueBoolean.create(false))) + Tag.create(TagKey.create("Key2"), TagValue.create("foo"))) .testEquals(); } } diff --git a/api/src/test/java/io/opencensus/tags/TagValueTest.java b/api/src/test/java/io/opencensus/tags/TagValueTest.java index b1382312..7b4b68af 100644 --- a/api/src/test/java/io/opencensus/tags/TagValueTest.java +++ b/api/src/test/java/io/opencensus/tags/TagValueTest.java @@ -19,11 +19,6 @@ package io.opencensus.tags; import static com.google.common.truth.Truth.assertThat; import com.google.common.testing.EqualsTester; -import io.opencensus.common.Function; -import io.opencensus.common.Functions; -import io.opencensus.tags.TagValue.TagValueBoolean; -import io.opencensus.tags.TagValue.TagValueLong; -import io.opencensus.tags.TagValue.TagValueString; import java.util.Arrays; import org.junit.Rule; import org.junit.Test; @@ -34,121 +29,37 @@ import org.junit.runners.JUnit4; /** Tests for {@link TagValue}. */ @RunWith(JUnit4.class) public final class TagValueTest { - @Rule public final ExpectedException thrown = ExpectedException.none(); @Test - public void testMatchStringValue() { - assertThat( - TagValueString.create("value") - .match( - new Function() { - @Override - public String apply(TagValueString tag) { - return tag.asString(); - } - }, - new Function() { - @Override - public String apply(TagValueLong tag) { - throw new AssertionError(); - } - }, - new Function() { - @Override - public String apply(TagValueBoolean tag) { - throw new AssertionError(); - } - }, - Functions.throwIllegalArgumentException())) - .isEqualTo("value"); - } - - @Test - public void testMatchLongValue() { - assertThat( - TagValueLong.create(1234) - .match( - new Function() { - @Override - public Long apply(TagValueString tag) { - throw new AssertionError(); - } - }, - new Function() { - @Override - public Long apply(TagValueLong tag) { - return tag.asLong(); - } - }, - new Function() { - @Override - public Long apply(TagValueBoolean tag) { - throw new AssertionError(); - } - }, - Functions.throwIllegalArgumentException())) - .isEqualTo(1234); - } - - @Test - public void testMatchBooleanValue() { - assertThat( - TagValueBoolean.create(false) - .match( - new Function() { - @Override - public Boolean apply(TagValueString tag) { - throw new AssertionError(); - } - }, - new Function() { - @Override - public Boolean apply(TagValueLong tag) { - throw new AssertionError(); - } - }, - new Function() { - @Override - public Boolean apply(TagValueBoolean tag) { - return tag.asBoolean(); - } - }, - Functions.throwIllegalArgumentException())) - .isEqualTo(false); - } - - @Test - public void allowStringTagValueWithMaxLength() { - char[] chars = new char[TagValueString.MAX_LENGTH]; + public void allowTagValueWithMaxLength() { + char[] chars = new char[TagValue.MAX_LENGTH]; Arrays.fill(chars, 'v'); String value = new String(chars); - assertThat(TagValueString.create(value).asString()).isEqualTo(value); + assertThat(TagValue.create(value).asString()).isEqualTo(value); } @Test - public void disallowStringTagValueOverMaxLength() { - char[] chars = new char[TagValueString.MAX_LENGTH + 1]; + public void disallowTagValueOverMaxLength() { + char[] chars = new char[TagValue.MAX_LENGTH + 1]; Arrays.fill(chars, 'v'); String value = new String(chars); thrown.expect(IllegalArgumentException.class); - TagValueString.create(value); + TagValue.create(value); } @Test - public void disallowStringTagValueWithUnprintableChars() { + public void disallowTagValueWithUnprintableChars() { String value = "\2ab\3cd"; thrown.expect(IllegalArgumentException.class); - TagValueString.create(value); + TagValue.create(value); } @Test public void testTagValueEquals() { new EqualsTester() - .addEqualityGroup(TagValueString.create("foo"), TagValueString.create("foo")) - .addEqualityGroup(TagValueLong.create(2)) - .addEqualityGroup(TagValueBoolean.create(true)) - .addEqualityGroup(TagValueString.create("bar")) + .addEqualityGroup(TagValue.create("foo"), TagValue.create("foo")) + .addEqualityGroup(TagValue.create("bar")) .testEquals(); } } -- cgit v1.2.3 From fa2c722348bf38ed09879916ef459904f61b504b Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 17 Oct 2017 14:07:39 -0700 Subject: Remove an obsolete TODO. --- api/src/main/java/io/opencensus/tags/TagContextBuilder.java | 2 -- 1 file changed, 2 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/tags/TagContextBuilder.java b/api/src/main/java/io/opencensus/tags/TagContextBuilder.java index 2ac36455..c2828b34 100644 --- a/api/src/main/java/io/opencensus/tags/TagContextBuilder.java +++ b/api/src/main/java/io/opencensus/tags/TagContextBuilder.java @@ -19,8 +19,6 @@ package io.opencensus.tags; import io.opencensus.common.Scope; /** Builder for the {@link TagContext} class. */ -// TODO(sebright): Decide what to do when 'put' is called with a key that has the same name as an -// existing key, but a different type. We currently keep both keys. public abstract class TagContextBuilder { /** -- cgit v1.2.3 From 8b475cb9fc86c645d2ebe70a1f35437511da3b13 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 17 Oct 2017 14:08:08 -0700 Subject: Improve TagContextBuilder.put Javadoc. --- api/src/main/java/io/opencensus/tags/TagContextBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/tags/TagContextBuilder.java b/api/src/main/java/io/opencensus/tags/TagContextBuilder.java index c2828b34..c6c858c6 100644 --- a/api/src/main/java/io/opencensus/tags/TagContextBuilder.java +++ b/api/src/main/java/io/opencensus/tags/TagContextBuilder.java @@ -25,7 +25,7 @@ public abstract class TagContextBuilder { * Adds the key/value pair regardless of whether the key is present. * * @param key the {@code TagKey} which will be set. - * @param value the value to set for the given key. + * @param value the {@code TagValue} to set for the given key. * @return this */ public abstract TagContextBuilder put(TagKey key, TagValue value); -- cgit v1.2.3 From 25bc0f2954a43c989c03fc80db5f836b4140c37a Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 15 Aug 2017 17:01:43 -0700 Subject: Disallow empty tag keys. --- api/src/main/java/io/opencensus/tags/TagKey.java | 2 +- api/src/test/java/io/opencensus/tags/TagKeyTest.java | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/tags/TagKey.java b/api/src/main/java/io/opencensus/tags/TagKey.java index 7e532849..d68f0b75 100644 --- a/api/src/main/java/io/opencensus/tags/TagKey.java +++ b/api/src/main/java/io/opencensus/tags/TagKey.java @@ -73,6 +73,6 @@ public abstract class TagKey { * @return whether the name is valid. */ private static boolean isValid(String name) { - return name.length() <= MAX_LENGTH && StringUtil.isPrintableString(name); + return !name.isEmpty() && name.length() <= MAX_LENGTH && StringUtil.isPrintableString(name); } } diff --git a/api/src/test/java/io/opencensus/tags/TagKeyTest.java b/api/src/test/java/io/opencensus/tags/TagKeyTest.java index 122c5baa..0992cdb6 100644 --- a/api/src/test/java/io/opencensus/tags/TagKeyTest.java +++ b/api/src/test/java/io/opencensus/tags/TagKeyTest.java @@ -58,6 +58,12 @@ public final class TagKeyTest { TagKey.create("\2ab\3cd"); } + @Test + public void createString_DisallowEmpty() { + thrown.expect(IllegalArgumentException.class); + TagKey.create(""); + } + @Test public void testTagKeyEquals() { new EqualsTester() -- cgit v1.2.3 From 441080fc0da4e9cadf3f90c200ab8c2cfa6d1d6a Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Fri, 27 Oct 2017 15:46:42 -0700 Subject: Change TagValue.MAX_LENGTH to 255, to match TagKey.MAX_LENGTH. --- api/src/main/java/io/opencensus/tags/TagValue.java | 2 +- api/src/test/java/io/opencensus/tags/TagKeyTest.java | 5 +++++ api/src/test/java/io/opencensus/tags/TagValueTest.java | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/tags/TagValue.java b/api/src/main/java/io/opencensus/tags/TagValue.java index abd0bda4..71196051 100644 --- a/api/src/main/java/io/opencensus/tags/TagValue.java +++ b/api/src/main/java/io/opencensus/tags/TagValue.java @@ -31,7 +31,7 @@ import javax.annotation.concurrent.Immutable; @AutoValue public abstract class TagValue { /** The maximum length for a tag value. The value is {@value #MAX_LENGTH}. */ - public static final int MAX_LENGTH = 256; + public static final int MAX_LENGTH = 255; TagValue() {} diff --git a/api/src/test/java/io/opencensus/tags/TagKeyTest.java b/api/src/test/java/io/opencensus/tags/TagKeyTest.java index 0992cdb6..dd450aa3 100644 --- a/api/src/test/java/io/opencensus/tags/TagKeyTest.java +++ b/api/src/test/java/io/opencensus/tags/TagKeyTest.java @@ -32,6 +32,11 @@ public final class TagKeyTest { @Rule public final ExpectedException thrown = ExpectedException.none(); + @Test + public void testMaxLength() { + assertThat(TagKey.MAX_LENGTH).isEqualTo(255); + } + @Test public void testGetName() { assertThat(TagKey.create("foo").getName()).isEqualTo("foo"); diff --git a/api/src/test/java/io/opencensus/tags/TagValueTest.java b/api/src/test/java/io/opencensus/tags/TagValueTest.java index 7b4b68af..d1626373 100644 --- a/api/src/test/java/io/opencensus/tags/TagValueTest.java +++ b/api/src/test/java/io/opencensus/tags/TagValueTest.java @@ -31,6 +31,11 @@ import org.junit.runners.JUnit4; public final class TagValueTest { @Rule public final ExpectedException thrown = ExpectedException.none(); + @Test + public void testMaxLength() { + assertThat(TagValue.MAX_LENGTH).isEqualTo(255); + } + @Test public void allowTagValueWithMaxLength() { char[] chars = new char[TagValue.MAX_LENGTH]; -- cgit v1.2.3 From 80cf421f7049dd9ec602777f6dd5f767f8de67bb Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Fri, 27 Oct 2017 16:04:57 -0700 Subject: Make TagKey and TagValue tests consistent. This commit adds a test for TagValue.asString and ensures that only one method is called after ExpectedException.expect is called. --- api/src/test/java/io/opencensus/tags/TagKeyTest.java | 15 ++++++++------- api/src/test/java/io/opencensus/tags/TagValueTest.java | 9 +++++++-- 2 files changed, 15 insertions(+), 9 deletions(-) (limited to 'api') diff --git a/api/src/test/java/io/opencensus/tags/TagKeyTest.java b/api/src/test/java/io/opencensus/tags/TagKeyTest.java index dd450aa3..48cf9fd4 100644 --- a/api/src/test/java/io/opencensus/tags/TagKeyTest.java +++ b/api/src/test/java/io/opencensus/tags/TagKeyTest.java @@ -29,7 +29,6 @@ import org.junit.runners.JUnit4; /** Tests for {@link TagKey}. */ @RunWith(JUnit4.class) public final class TagKeyTest { - @Rule public final ExpectedException thrown = ExpectedException.none(); @Test @@ -44,17 +43,19 @@ public final class TagKeyTest { @Test public void create_AllowTagKeyNameWithMaxLength() { - char[] key = new char[TagKey.MAX_LENGTH]; - Arrays.fill(key, 'k'); - TagKey.create(new String(key)); + char[] chars = new char[TagKey.MAX_LENGTH]; + Arrays.fill(chars, 'k'); + String key = new String(chars); + assertThat(TagKey.create(key).getName()).isEqualTo(key); } @Test public void create_DisallowTagKeyNameOverMaxLength() { - char[] key = new char[TagKey.MAX_LENGTH + 1]; - Arrays.fill(key, 'k'); + char[] chars = new char[TagKey.MAX_LENGTH + 1]; + Arrays.fill(chars, 'k'); + String key = new String(chars); thrown.expect(IllegalArgumentException.class); - TagKey.create(new String(key)); + TagKey.create(key); } @Test diff --git a/api/src/test/java/io/opencensus/tags/TagValueTest.java b/api/src/test/java/io/opencensus/tags/TagValueTest.java index d1626373..9aa42c8c 100644 --- a/api/src/test/java/io/opencensus/tags/TagValueTest.java +++ b/api/src/test/java/io/opencensus/tags/TagValueTest.java @@ -37,7 +37,12 @@ public final class TagValueTest { } @Test - public void allowTagValueWithMaxLength() { + public void testAsString() { + assertThat(TagValue.create("foo").asString()).isEqualTo("foo"); + } + + @Test + public void create_AllowTagValueWithMaxLength() { char[] chars = new char[TagValue.MAX_LENGTH]; Arrays.fill(chars, 'v'); String value = new String(chars); @@ -45,7 +50,7 @@ public final class TagValueTest { } @Test - public void disallowTagValueOverMaxLength() { + public void create_DisallowTagValueOverMaxLength() { char[] chars = new char[TagValue.MAX_LENGTH + 1]; Arrays.fill(chars, 'v'); String value = new String(chars); -- cgit v1.2.3 From 6fd21d6685b42564946423a4f7dd3432c9e23fa3 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Fri, 27 Oct 2017 16:27:58 -0700 Subject: Returns null when getting unregistered views (#737) * Returns null when getting unregistered views * Improve java doc --- api/src/main/java/io/opencensus/stats/NoopStats.java | 2 +- api/src/main/java/io/opencensus/stats/ViewManager.java | 11 +++++++++++ .../test/java/io/opencensus/stats/NoopViewManagerTest.java | 7 ++----- 3 files changed, 14 insertions(+), 6 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/NoopStats.java b/api/src/main/java/io/opencensus/stats/NoopStats.java index 8a792c07..b7002102 100644 --- a/api/src/main/java/io/opencensus/stats/NoopStats.java +++ b/api/src/main/java/io/opencensus/stats/NoopStats.java @@ -165,7 +165,7 @@ final class NoopStats { synchronized (views) { View view = views.get(name); if (view == null) { - throw new IllegalArgumentException("View is not registered."); + return null; } else { return ViewData.create( view, diff --git a/api/src/main/java/io/opencensus/stats/ViewManager.java b/api/src/main/java/io/opencensus/stats/ViewManager.java index 16bf749e..908221c6 100644 --- a/api/src/main/java/io/opencensus/stats/ViewManager.java +++ b/api/src/main/java/io/opencensus/stats/ViewManager.java @@ -16,6 +16,8 @@ package io.opencensus.stats; +import javax.annotation.Nullable; + /** * Provides facilities to register {@link View}s for collecting stats and retrieving * stats data as a {@link ViewData}. @@ -24,11 +26,20 @@ public abstract class ViewManager { /** * Pull model for stats. Registers a {@link View} that will collect data to be accessed * via {@link #getView(View.Name)}. + * + * @param view the {@code View} to be registered. */ public abstract void registerView(View view); /** * Returns the current stats data, {@link ViewData}, associated with the given view name. + * + *

Returns {@code null} if the {@code View} is not registered. + * + * @param view the name of {@code View} for the current stats. + * @return {@code ViewData} for the {@code View}, or {@code null} if the {@code View} is not + * registered. */ + @Nullable public abstract ViewData getView(View.Name view); } diff --git a/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java b/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java index b70e49cc..24d1b14a 100644 --- a/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java +++ b/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java @@ -88,12 +88,9 @@ public final class NoopViewManagerTest { } @Test - public void noopViewManager_GetView_DisallowGettingNonExistentView() { + public void noopViewManager_GetView_GettingNonExistentViewReturnsNull() { ViewManager viewManager = NoopStats.newNoopViewManager(); - - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("View is not registered."); - viewManager.getView(VIEW_NAME); + assertThat(viewManager.getView(VIEW_NAME)).isNull(); } @Test -- cgit v1.2.3 From d118ce4c6bcc5d7f94f94b4e5f1b684b4d037b04 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Fri, 27 Oct 2017 16:34:24 -0700 Subject: Update max length of Measure name to 255 (#739) --- api/src/main/java/io/opencensus/stats/Measure.java | 10 ++++++---- api/src/test/java/io/opencensus/stats/MeasureTest.java | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/Measure.java b/api/src/main/java/io/opencensus/stats/Measure.java index e7a0ec96..062a35bf 100644 --- a/api/src/main/java/io/opencensus/stats/Measure.java +++ b/api/src/main/java/io/opencensus/stats/Measure.java @@ -28,7 +28,7 @@ import javax.annotation.concurrent.Immutable; @Immutable public abstract class Measure { - @VisibleForTesting static final int NAME_MAX_LENGTH = 256; + @VisibleForTesting static final int NAME_MAX_LENGTH = 255; /** * Applies the given match function to the underlying data type. @@ -40,7 +40,7 @@ public abstract class Measure { /** * Name of measure, as a {@code String}. Should be a ASCII string with a length no greater than - * 256 characters. + * 255 characters. * *

Suggested format for name: {@code /}. */ @@ -86,7 +86,8 @@ public abstract class Measure { */ public static MeasureDouble create(String name, String description, String unit) { checkArgument(StringUtil.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, - "Name should be a ASCII string with a length no greater than 256 characters."); + "Name should be a ASCII string with a length no greater than " + + NAME_MAX_LENGTH + " characters."); return new AutoValue_Measure_MeasureDouble(name, description, unit); } @@ -126,7 +127,8 @@ public abstract class Measure { */ public static MeasureLong create(String name, String description, String unit) { checkArgument(StringUtil.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, - "Name should be a ASCII string with a length no greater than 256 characters."); + "Name should be a ASCII string with a length no greater than " + + NAME_MAX_LENGTH + " characters."); return new AutoValue_Measure_MeasureLong(name, description, unit); } diff --git a/api/src/test/java/io/opencensus/stats/MeasureTest.java b/api/src/test/java/io/opencensus/stats/MeasureTest.java index d243637a..0c1e3867 100644 --- a/api/src/test/java/io/opencensus/stats/MeasureTest.java +++ b/api/src/test/java/io/opencensus/stats/MeasureTest.java @@ -41,7 +41,7 @@ public final class MeasureTest { @Test public void testConstants() { - assertThat(Measure.NAME_MAX_LENGTH).isEqualTo(256); + assertThat(Measure.NAME_MAX_LENGTH).isEqualTo(255); } @Test -- cgit v1.2.3 From ff43823476013f2131bd82bf7d566869afd12d17 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Tue, 31 Oct 2017 17:53:26 -0700 Subject: Rename StatsRecord to MeasureMap (#757) --- .../main/java/io/opencensus/stats/MeasureMap.java | 63 ++++++++++++++++++++++ .../main/java/io/opencensus/stats/NoopStats.java | 20 +++---- .../main/java/io/opencensus/stats/StatsRecord.java | 63 ---------------------- .../java/io/opencensus/stats/StatsRecorder.java | 2 +- .../java/io/opencensus/stats/NoopStatsTest.java | 8 +-- 5 files changed, 78 insertions(+), 78 deletions(-) create mode 100644 api/src/main/java/io/opencensus/stats/MeasureMap.java delete mode 100644 api/src/main/java/io/opencensus/stats/StatsRecord.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/MeasureMap.java b/api/src/main/java/io/opencensus/stats/MeasureMap.java new file mode 100644 index 00000000..03e55092 --- /dev/null +++ b/api/src/main/java/io/opencensus/stats/MeasureMap.java @@ -0,0 +1,63 @@ +/* + * 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.stats; + +import io.opencensus.stats.Measure.MeasureDouble; +import io.opencensus.stats.Measure.MeasureLong; +import io.opencensus.tags.TagContext; +import javax.annotation.concurrent.NotThreadSafe; + +/** A map from {@link Measure}s to measured values to be recorded at the same time. */ +@NotThreadSafe +public abstract class MeasureMap { + + /** + * Associates the {@link MeasureDouble} with the given value. Subsequent updates to the same + * {@link MeasureDouble} will overwrite the previous value. + * + * @param measure the {@link MeasureDouble} + * @param value the value to be associated with {@code measure} + * @return this + */ + public abstract MeasureMap put(MeasureDouble measure, double value); + + /** + * Associates the {@link MeasureLong} with the given value. Subsequent updates to the same {@link + * MeasureLong} will overwrite the previous value. + * + * @param measure the {@link MeasureLong} + * @param value the value to be associated with {@code measure} + * @return this + */ + public abstract MeasureMap put(MeasureLong measure, long value); + + /** + * Records all of the measures at the same time, with the current {@link TagContext}. + * + *

This method records all of the stats in the {@code MeasureMap} every time it is called. + */ + public abstract void record(); + + /** + * Records all of the measures at the same time, with an explicit {@link TagContext}. + * + *

This method records all of the stats in the {@code MeasureMap} every time it is called. + * + * @param tags the tags associated with the measurements. + */ + public abstract void record(TagContext tags); +} diff --git a/api/src/main/java/io/opencensus/stats/NoopStats.java b/api/src/main/java/io/opencensus/stats/NoopStats.java index b7002102..a016e2e9 100644 --- a/api/src/main/java/io/opencensus/stats/NoopStats.java +++ b/api/src/main/java/io/opencensus/stats/NoopStats.java @@ -61,12 +61,12 @@ final class NoopStats { } /** - * Returns a {@code StatsRecord} that ignores all calls to {@link StatsRecord#put}. + * Returns a {@code MeasureMap} that ignores all calls to {@link MeasureMap#put}. * - * @return a {@code StatsRecord} that ignores all calls to {@code StatsRecord#put}. + * @return a {@code MeasureMap} that ignores all calls to {@code MeasureMap#put}. */ - static StatsRecord getNoopStatsRecord() { - return NoopStatsRecord.INSTANCE; + static MeasureMap getNoopMeasureMap() { + return NoopMeasureMap.INSTANCE; } /** @@ -110,22 +110,22 @@ final class NoopStats { static final StatsRecorder INSTANCE = new NoopStatsRecorder(); @Override - public StatsRecord newRecord() { - return getNoopStatsRecord(); + public MeasureMap newMeasureMap() { + return getNoopMeasureMap(); } } @Immutable - private static final class NoopStatsRecord extends StatsRecord { - static final StatsRecord INSTANCE = new NoopStatsRecord(); + private static final class NoopMeasureMap extends MeasureMap { + static final MeasureMap INSTANCE = new NoopMeasureMap(); @Override - public StatsRecord put(MeasureDouble measure, double value) { + public MeasureMap put(MeasureDouble measure, double value) { return this; } @Override - public StatsRecord put(MeasureLong measure, long value) { + public MeasureMap put(MeasureLong measure, long value) { return this; } diff --git a/api/src/main/java/io/opencensus/stats/StatsRecord.java b/api/src/main/java/io/opencensus/stats/StatsRecord.java deleted file mode 100644 index 3f7658e1..00000000 --- a/api/src/main/java/io/opencensus/stats/StatsRecord.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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.stats; - -import io.opencensus.stats.Measure.MeasureDouble; -import io.opencensus.stats.Measure.MeasureLong; -import io.opencensus.tags.TagContext; -import javax.annotation.concurrent.NotThreadSafe; - -/** A map from {@link Measure}s to measured values to be recorded at the same time. */ -@NotThreadSafe -public abstract class StatsRecord { - - /** - * Associates the {@link MeasureDouble} with the given value. Subsequent updates to the same - * {@link MeasureDouble} will overwrite the previous value. - * - * @param measure the {@link MeasureDouble} - * @param value the value to be associated with {@code measure} - * @return this - */ - public abstract StatsRecord put(MeasureDouble measure, double value); - - /** - * Associates the {@link MeasureLong} with the given value. Subsequent updates to the same {@link - * MeasureLong} will overwrite the previous value. - * - * @param measure the {@link MeasureLong} - * @param value the value to be associated with {@code measure} - * @return this - */ - public abstract StatsRecord put(MeasureLong measure, long value); - - /** - * Records all of the measures at the same time, with the current {@link TagContext}. - * - *

This method records all of the stats in the {@code StatsRecord} every time it is called. - */ - public abstract void record(); - - /** - * Records all of the measures at the same time, with an explicit {@link TagContext}. - * - *

This method records all of the stats in the {@code StatsRecord} every time it is called. - * - * @param tags the tags associated with the measurements. - */ - public abstract void record(TagContext tags); -} diff --git a/api/src/main/java/io/opencensus/stats/StatsRecorder.java b/api/src/main/java/io/opencensus/stats/StatsRecorder.java index fcf2cb96..493d7ac1 100644 --- a/api/src/main/java/io/opencensus/stats/StatsRecorder.java +++ b/api/src/main/java/io/opencensus/stats/StatsRecorder.java @@ -25,5 +25,5 @@ public abstract class StatsRecorder { * * @return an object for recording multiple measurements. */ - public abstract StatsRecord newRecord(); + public abstract MeasureMap newMeasureMap(); } diff --git a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java index dfd1136b..9d686251 100644 --- a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java +++ b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java @@ -85,7 +85,7 @@ public final class NoopStatsTest { @Test public void noopStatsRecorder_Record() { NoopStats.getNoopStatsRecorder() - .newRecord() + .newMeasureMap() .put(MEASURE, 5) .record(tagContext); } @@ -94,13 +94,13 @@ public final class NoopStatsTest { // exception. @Test public void noopStatsRecorder_RecordWithCurrentContext() { - NoopStats.getNoopStatsRecorder().newRecord().put(MEASURE, 6).record(); + NoopStats.getNoopStatsRecorder().newMeasureMap().put(MEASURE, 6).record(); } @Test public void noopStatsRecorder_Record_DisallowNullTagContext() { - StatsRecord record = NoopStats.getNoopStatsRecorder().newRecord(); + MeasureMap measureMap = NoopStats.getNoopStatsRecorder().newMeasureMap(); thrown.expect(NullPointerException.class); - record.record(null); + measureMap.record(null); } } -- cgit v1.2.3 From ba5c5b1796d6dfd8ef09573dbcee8145dee5a872 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 31 Oct 2017 18:38:19 -0700 Subject: Make TagContextBinarySerializer.toByteArray throw a checked exception. The first version of the implementation will throw TagContextSerializationException when the serialized TagContext would be larger than 8192 bytes. --- .../propagation/TagContextBinarySerializer.java | 3 +- .../TagContextSerializationException.java | 43 +++++++++++++++++++++ .../test/java/io/opencensus/tags/NoopTagsTest.java | 7 +++- .../TagContextSerializationExceptionTest.java | 44 ++++++++++++++++++++++ 4 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 api/src/main/java/io/opencensus/tags/propagation/TagContextSerializationException.java create mode 100644 api/src/test/java/io/opencensus/tags/propagation/TagContextSerializationExceptionTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java b/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java index e54e5d3d..0baa7b2a 100644 --- a/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java +++ b/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java @@ -34,8 +34,9 @@ public abstract class TagContextBinarySerializer { * * @param tags the {@code TagContext} to serialize. * @return the on-the-wire representation of a {@code TagContext}. + * @throws TagContextSerializationException if the {@code TagContext} is too large to serialize. */ - public abstract byte[] toByteArray(TagContext tags); + public abstract byte[] toByteArray(TagContext tags) throws TagContextSerializationException; /** * Creates a {@code TagContext} from the given on-the-wire encoded representation. diff --git a/api/src/main/java/io/opencensus/tags/propagation/TagContextSerializationException.java b/api/src/main/java/io/opencensus/tags/propagation/TagContextSerializationException.java new file mode 100644 index 00000000..b702dd74 --- /dev/null +++ b/api/src/main/java/io/opencensus/tags/propagation/TagContextSerializationException.java @@ -0,0 +1,43 @@ +/* + * 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.tags.propagation; + +import io.opencensus.tags.TagContext; + +/** Exception thrown when a {@link TagContext} cannot be serialized. */ +public final class TagContextSerializationException extends Exception { + private static final long serialVersionUID = 0L; + + /** + * Constructs a new {@code TagContextSerializationException} with the given message. + * + * @param message a message describing the error. + */ + public TagContextSerializationException(String message) { + super(message); + } + + /** + * Constructs a new {@code TagContextSerializationException} with the given message and cause. + * + * @param message a message describing the error. + * @param cause the cause of the error. + */ + public TagContextSerializationException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/api/src/test/java/io/opencensus/tags/NoopTagsTest.java b/api/src/test/java/io/opencensus/tags/NoopTagsTest.java index d39c5d7f..551229a7 100644 --- a/api/src/test/java/io/opencensus/tags/NoopTagsTest.java +++ b/api/src/test/java/io/opencensus/tags/NoopTagsTest.java @@ -22,6 +22,7 @@ import com.google.common.collect.Lists; import io.opencensus.internal.NoopScope; import io.opencensus.tags.propagation.TagContextBinarySerializer; import io.opencensus.tags.propagation.TagContextParseException; +import io.opencensus.tags.propagation.TagContextSerializationException; import java.util.Arrays; import java.util.Iterator; import org.junit.Rule; @@ -129,7 +130,8 @@ public final class NoopTagsTest { } @Test - public void noopTagContextBinarySerializer() throws TagContextParseException { + public void noopTagContextBinarySerializer() + throws TagContextParseException, TagContextSerializationException { assertThat(NoopTags.getNoopTagContextBinarySerializer().toByteArray(TAG_CONTEXT)) .isEqualTo(new byte[0]); assertThat(NoopTags.getNoopTagContextBinarySerializer().fromByteArray(new byte[5])) @@ -137,7 +139,8 @@ public final class NoopTagsTest { } @Test - public void noopTagContextBinarySerializer_ToByteArray_DisallowsNull() { + public void noopTagContextBinarySerializer_ToByteArray_DisallowsNull() + throws TagContextSerializationException { TagContextBinarySerializer noopSerializer = NoopTags.getNoopTagContextBinarySerializer(); thrown.expect(NullPointerException.class); noopSerializer.toByteArray(null); diff --git a/api/src/test/java/io/opencensus/tags/propagation/TagContextSerializationExceptionTest.java b/api/src/test/java/io/opencensus/tags/propagation/TagContextSerializationExceptionTest.java new file mode 100644 index 00000000..54e9fab6 --- /dev/null +++ b/api/src/test/java/io/opencensus/tags/propagation/TagContextSerializationExceptionTest.java @@ -0,0 +1,44 @@ +/* + * 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.tags.propagation; + +import static com.google.common.truth.Truth.assertThat; + +import java.io.IOException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TagContextSerializationException}. */ +@RunWith(JUnit4.class) +public final class TagContextSerializationExceptionTest { + + @Test + public void createWithMessage() { + assertThat(new TagContextSerializationException("my message").getMessage()) + .isEqualTo("my message"); + } + + @Test + public void createWithMessageAndCause() { + IOException cause = new IOException(); + TagContextSerializationException exception = + new TagContextSerializationException("my message", cause); + assertThat(exception.getMessage()).isEqualTo("my message"); + assertThat(exception.getCause()).isEqualTo(cause); + } +} -- cgit v1.2.3 From 6f5b6617f150d04726960818758c1b48bd890373 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 31 Oct 2017 18:47:37 -0700 Subject: Add maximum serialized TagContext size to toByteArray Javadoc. --- .../java/io/opencensus/tags/propagation/TagContextBinarySerializer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java b/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java index 0baa7b2a..d3645e1a 100644 --- a/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java +++ b/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java @@ -34,7 +34,7 @@ public abstract class TagContextBinarySerializer { * * @param tags the {@code TagContext} to serialize. * @return the on-the-wire representation of a {@code TagContext}. - * @throws TagContextSerializationException if the {@code TagContext} is too large to serialize. + * @throws TagContextSerializationException if the result would be larger than 8192 bytes. */ public abstract byte[] toByteArray(TagContext tags) throws TagContextSerializationException; -- cgit v1.2.3 From 28f8581d5a6947250fc86e00dfe4cb538d01fa85 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 31 Oct 2017 19:00:32 -0700 Subject: Rename TagContextParseException to TagContextDeserializationException. The new name is more consistent with TagContextSerializationException. --- .../propagation/TagContextBinarySerializer.java | 6 +-- .../TagContextDeserializationException.java | 43 +++++++++++++++++++++ .../tags/propagation/TagContextParseException.java | 43 --------------------- .../test/java/io/opencensus/tags/NoopTagsTest.java | 6 +-- .../TagContextDeserializationExceptionTest.java | 44 ++++++++++++++++++++++ .../propagation/TagContextParseExceptionTest.java | 42 --------------------- 6 files changed, 93 insertions(+), 91 deletions(-) create mode 100644 api/src/main/java/io/opencensus/tags/propagation/TagContextDeserializationException.java delete mode 100644 api/src/main/java/io/opencensus/tags/propagation/TagContextParseException.java create mode 100644 api/src/test/java/io/opencensus/tags/propagation/TagContextDeserializationExceptionTest.java delete mode 100644 api/src/test/java/io/opencensus/tags/propagation/TagContextParseExceptionTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java b/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java index d3645e1a..0f5ea7ac 100644 --- a/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java +++ b/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java @@ -45,8 +45,8 @@ public abstract class TagContextBinarySerializer { * * @param bytes on-the-wire representation of a {@code TagContext}. * @return a {@code TagContext} deserialized from {@code bytes}. - * @throws TagContextParseException if there is a parse error or the serialized {@code TagContext} - * contains invalid tags. + * @throws TagContextDeserializationException if there is a parse error or the serialized {@code + * TagContext} contains invalid tags. */ - public abstract TagContext fromByteArray(byte[] bytes) throws TagContextParseException; + public abstract TagContext fromByteArray(byte[] bytes) throws TagContextDeserializationException; } diff --git a/api/src/main/java/io/opencensus/tags/propagation/TagContextDeserializationException.java b/api/src/main/java/io/opencensus/tags/propagation/TagContextDeserializationException.java new file mode 100644 index 00000000..aa84e495 --- /dev/null +++ b/api/src/main/java/io/opencensus/tags/propagation/TagContextDeserializationException.java @@ -0,0 +1,43 @@ +/* + * 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.tags.propagation; + +import io.opencensus.tags.TagContext; + +/** Exception thrown when a {@link TagContext} cannot be parsed. */ +public final class TagContextDeserializationException extends Exception { + private static final long serialVersionUID = 0L; + + /** + * Constructs a new {@code TagContextParseException} with the given message. + * + * @param message a message describing the parse error. + */ + public TagContextDeserializationException(String message) { + super(message); + } + + /** + * Constructs a new {@code TagContextParseException} with the given message and cause. + * + * @param message a message describing the parse error. + * @param cause the cause of the parse error. + */ + public TagContextDeserializationException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/api/src/main/java/io/opencensus/tags/propagation/TagContextParseException.java b/api/src/main/java/io/opencensus/tags/propagation/TagContextParseException.java deleted file mode 100644 index 0174c416..00000000 --- a/api/src/main/java/io/opencensus/tags/propagation/TagContextParseException.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.tags.propagation; - -import io.opencensus.tags.TagContext; - -/** Exception thrown when a {@link TagContext} cannot be parsed. */ -public final class TagContextParseException extends Exception { - private static final long serialVersionUID = 0L; - - /** - * Constructs a new {@code TagContextParseException} with the given message. - * - * @param message a message describing the parse error. - */ - public TagContextParseException(String message) { - super(message); - } - - /** - * Constructs a new {@code TagContextParseException} with the given message and cause. - * - * @param message a message describing the parse error. - * @param cause the cause of the parse error. - */ - public TagContextParseException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/api/src/test/java/io/opencensus/tags/NoopTagsTest.java b/api/src/test/java/io/opencensus/tags/NoopTagsTest.java index 551229a7..8434bd83 100644 --- a/api/src/test/java/io/opencensus/tags/NoopTagsTest.java +++ b/api/src/test/java/io/opencensus/tags/NoopTagsTest.java @@ -21,7 +21,7 @@ import static com.google.common.truth.Truth.assertThat; import com.google.common.collect.Lists; import io.opencensus.internal.NoopScope; import io.opencensus.tags.propagation.TagContextBinarySerializer; -import io.opencensus.tags.propagation.TagContextParseException; +import io.opencensus.tags.propagation.TagContextDeserializationException; import io.opencensus.tags.propagation.TagContextSerializationException; import java.util.Arrays; import java.util.Iterator; @@ -131,7 +131,7 @@ public final class NoopTagsTest { @Test public void noopTagContextBinarySerializer() - throws TagContextParseException, TagContextSerializationException { + throws TagContextDeserializationException, TagContextSerializationException { assertThat(NoopTags.getNoopTagContextBinarySerializer().toByteArray(TAG_CONTEXT)) .isEqualTo(new byte[0]); assertThat(NoopTags.getNoopTagContextBinarySerializer().fromByteArray(new byte[5])) @@ -148,7 +148,7 @@ public final class NoopTagsTest { @Test public void noopTagContextBinarySerializer_FromByteArray_DisallowsNull() - throws TagContextParseException { + throws TagContextDeserializationException { TagContextBinarySerializer noopSerializer = NoopTags.getNoopTagContextBinarySerializer(); thrown.expect(NullPointerException.class); noopSerializer.fromByteArray(null); diff --git a/api/src/test/java/io/opencensus/tags/propagation/TagContextDeserializationExceptionTest.java b/api/src/test/java/io/opencensus/tags/propagation/TagContextDeserializationExceptionTest.java new file mode 100644 index 00000000..750d5d45 --- /dev/null +++ b/api/src/test/java/io/opencensus/tags/propagation/TagContextDeserializationExceptionTest.java @@ -0,0 +1,44 @@ +/* + * 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.tags.propagation; + +import static com.google.common.truth.Truth.assertThat; + +import java.io.IOException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TagContextDeserializationException}. */ +@RunWith(JUnit4.class) +public final class TagContextDeserializationExceptionTest { + + @Test + public void createWithMessage() { + assertThat(new TagContextDeserializationException("my message").getMessage()) + .isEqualTo("my message"); + } + + @Test + public void createWithMessageAndCause() { + IOException cause = new IOException(); + TagContextDeserializationException exception = + new TagContextDeserializationException("my message", cause); + assertThat(exception.getMessage()).isEqualTo("my message"); + assertThat(exception.getCause()).isEqualTo(cause); + } +} diff --git a/api/src/test/java/io/opencensus/tags/propagation/TagContextParseExceptionTest.java b/api/src/test/java/io/opencensus/tags/propagation/TagContextParseExceptionTest.java deleted file mode 100644 index 0c2afadc..00000000 --- a/api/src/test/java/io/opencensus/tags/propagation/TagContextParseExceptionTest.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.tags.propagation; - -import static com.google.common.truth.Truth.assertThat; - -import java.io.IOException; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link TagContextParseException}. */ -@RunWith(JUnit4.class) -public final class TagContextParseExceptionTest { - - @Test - public void createWithMessage() { - assertThat(new TagContextParseException("my message").getMessage()).isEqualTo("my message"); - } - - @Test - public void createWithMessageAndCause() { - IOException cause = new IOException(); - TagContextParseException parseException = new TagContextParseException("my message", cause); - assertThat(parseException.getMessage()).isEqualTo("my message"); - assertThat(parseException.getCause()).isEqualTo(cause); - } -} -- cgit v1.2.3 From 1b68e740608d33c6039a4781fd7c523a0ad54c27 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 31 Oct 2017 19:19:21 -0700 Subject: Don't mention parsing in TagContextDeserializationException Javadoc. --- .../tags/propagation/TagContextDeserializationException.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/tags/propagation/TagContextDeserializationException.java b/api/src/main/java/io/opencensus/tags/propagation/TagContextDeserializationException.java index aa84e495..eb8d18ea 100644 --- a/api/src/main/java/io/opencensus/tags/propagation/TagContextDeserializationException.java +++ b/api/src/main/java/io/opencensus/tags/propagation/TagContextDeserializationException.java @@ -25,7 +25,7 @@ public final class TagContextDeserializationException extends Exception { /** * Constructs a new {@code TagContextParseException} with the given message. * - * @param message a message describing the parse error. + * @param message a message describing the error. */ public TagContextDeserializationException(String message) { super(message); @@ -34,8 +34,8 @@ public final class TagContextDeserializationException extends Exception { /** * Constructs a new {@code TagContextParseException} with the given message and cause. * - * @param message a message describing the parse error. - * @param cause the cause of the parse error. + * @param message a message describing the error. + * @param cause the cause of the error. */ public TagContextDeserializationException(String message, Throwable cause) { super(message, cause); -- cgit v1.2.3 From 38c7a2db7acaf72207cd401dd76204097a51dcf9 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 31 Oct 2017 19:23:11 -0700 Subject: Add maximum serialized TagContext size to fromByteArray Javadoc. --- .../io/opencensus/tags/propagation/TagContextBinarySerializer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java b/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java index 0f5ea7ac..5b354629 100644 --- a/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java +++ b/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java @@ -45,8 +45,8 @@ public abstract class TagContextBinarySerializer { * * @param bytes on-the-wire representation of a {@code TagContext}. * @return a {@code TagContext} deserialized from {@code bytes}. - * @throws TagContextDeserializationException if there is a parse error or the serialized {@code - * TagContext} contains invalid tags. + * @throws TagContextDeserializationException if there is a parse error, the input contains + * invalid tags, or the input is larger than 8192 bytes. */ public abstract TagContext fromByteArray(byte[] bytes) throws TagContextDeserializationException; } -- cgit v1.2.3 From 71478086c27da524ee1097cd40fbe7a2afdd9588 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 31 Oct 2017 19:29:33 -0700 Subject: Avoid specifying maximum size of serialized TagContext. The value will probably be configurable in a future version, and the default could change. --- .../io/opencensus/tags/propagation/TagContextBinarySerializer.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java b/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java index 5b354629..f89d7b0d 100644 --- a/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java +++ b/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java @@ -34,7 +34,8 @@ public abstract class TagContextBinarySerializer { * * @param tags the {@code TagContext} to serialize. * @return the on-the-wire representation of a {@code TagContext}. - * @throws TagContextSerializationException if the result would be larger than 8192 bytes. + * @throws TagContextSerializationException if the result would be larger than the maximum allowed + * serialized size. */ public abstract byte[] toByteArray(TagContext tags) throws TagContextSerializationException; @@ -46,7 +47,7 @@ public abstract class TagContextBinarySerializer { * @param bytes on-the-wire representation of a {@code TagContext}. * @return a {@code TagContext} deserialized from {@code bytes}. * @throws TagContextDeserializationException if there is a parse error, the input contains - * invalid tags, or the input is larger than 8192 bytes. + * invalid tags, or the input is larger than the maximum allowed serialized size. */ public abstract TagContext fromByteArray(byte[] bytes) throws TagContextDeserializationException; } -- cgit v1.2.3 From 91544bbe7da5b69e92ad49141b3579bd28b31e4a Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Tue, 31 Oct 2017 20:40:06 -0700 Subject: Start 0.9.0 development cycle --- .../main/java/io/opencensus/common/OpenCensusLibraryInformation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java index e2548651..1b1c75e4 100644 --- a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java +++ b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java @@ -25,5 +25,5 @@ public final class OpenCensusLibraryInformation { /** * The current version of the OpenCensus Java library. */ - public static final String VERSION = "0.8.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION + public static final String VERSION = "0.9.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION } -- cgit v1.2.3 From 3f946d748ea171c70c297cf3188e4b0dbadab1ad Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Wed, 1 Nov 2017 11:08:37 +0100 Subject: Use the current release version of Mockito. (#751) * Use the current release version of Mockito. * Fix errorprone's warnings about NonCanonicalStaticMemberImport. --- api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java | 2 +- api/src/test/java/io/opencensus/trace/SpanTest.java | 4 ++-- api/src/test/java/io/opencensus/trace/TracerTest.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'api') diff --git a/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java b/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java index a8c18819..36c8865d 100644 --- a/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java +++ b/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java @@ -17,7 +17,7 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Matchers.same; +import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.verify; import io.opencensus.common.Scope; diff --git a/api/src/test/java/io/opencensus/trace/SpanTest.java b/api/src/test/java/io/opencensus/trace/SpanTest.java index 327b9abe..5fce242e 100644 --- a/api/src/test/java/io/opencensus/trace/SpanTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanTest.java @@ -17,8 +17,8 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.same; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.verify; import java.util.Collections; diff --git a/api/src/test/java/io/opencensus/trace/TracerTest.java b/api/src/test/java/io/opencensus/trace/TracerTest.java index 7c65742e..4edf377d 100644 --- a/api/src/test/java/io/opencensus/trace/TracerTest.java +++ b/api/src/test/java/io/opencensus/trace/TracerTest.java @@ -17,7 +17,7 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Matchers.same; +import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.when; import io.grpc.Context; -- cgit v1.2.3 From 1807f485edfd3bdd4204aff1d8b4c062ae2e71f6 Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Wed, 1 Nov 2017 19:19:02 +0100 Subject: s/new new/new/ (#765) --- api/src/main/java/io/opencensus/trace/SpanBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java index 6567b649..f27d1bbb 100644 --- a/api/src/main/java/io/opencensus/trace/SpanBuilder.java +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -165,7 +165,7 @@ public abstract class SpanBuilder { public abstract Span startSpan(); /** - * Starts a new new span and sets it as the {@link Tracer#getCurrentSpan current span}. + * Starts a new span and sets it as the {@link Tracer#getCurrentSpan current span}. * *

Enters the scope of code where the newly created {@code Span} is in the current Context, and * returns an object that represents that scope. The scope is exited when the returned object is -- cgit v1.2.3 From 6cb4dd2cc949a2602783321da179cb11afb7fc7a Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Fri, 3 Nov 2017 09:25:12 +1100 Subject: Add gradle plugin for google java format. Enforce all files to be formatted. (#771) * Add gradle plugin for google java format. Enforce all files to be formatted. * Fix javadoc comments. * update to google-java-formatter 1.5 * Fix comments and run formatter only for java8. * Formatter works only on java8. --- .../main/java/io/opencensus/common/Duration.java | 4 +- .../java/io/opencensus/common/ExperimentalApi.java | 28 ++++---- .../common/OpenCensusLibraryInformation.java | 10 +-- .../main/java/io/opencensus/common/Timestamp.java | 4 +- .../java/io/opencensus/internal/NoopScope.java | 4 +- .../main/java/io/opencensus/stats/Aggregation.java | 28 +++----- .../java/io/opencensus/stats/AggregationData.java | 37 +++++----- .../java/io/opencensus/stats/BucketBoundaries.java | 4 +- api/src/main/java/io/opencensus/stats/Measure.java | 41 +++++------ .../main/java/io/opencensus/stats/Measurement.java | 19 ++---- api/src/main/java/io/opencensus/stats/View.java | 46 +++++-------- .../main/java/io/opencensus/stats/ViewData.java | 10 ++- .../main/java/io/opencensus/stats/ViewManager.java | 8 +-- .../java/io/opencensus/tags/InternalUtils.java | 4 +- .../main/java/io/opencensus/tags/package-info.java | 4 +- .../java/io/opencensus/trace/CurrentSpanUtils.java | 4 +- api/src/main/java/io/opencensus/trace/Sampler.java | 4 +- api/src/main/java/io/opencensus/trace/Span.java | 5 +- .../java/io/opencensus/trace/TraceComponent.java | 8 +-- .../java/io/opencensus/trace/TraceOptions.java | 3 +- .../opencensus/trace/export/ExportComponent.java | 8 +-- .../trace/propagation/PropagationComponent.java | 8 +-- .../java/io/opencensus/common/DurationTest.java | 1 - .../java/io/opencensus/common/TimestampTest.java | 2 +- .../io/opencensus/stats/AggregationDataTest.java | 70 +++++++------------ .../java/io/opencensus/stats/AggregationTest.java | 79 ++++++++++------------ .../io/opencensus/stats/BucketBoundariesTest.java | 7 +- .../test/java/io/opencensus/stats/MeasureTest.java | 52 ++++---------- .../java/io/opencensus/stats/NoopStatsTest.java | 5 +- .../test/java/io/opencensus/stats/StatsTest.java | 19 +++--- .../java/io/opencensus/stats/ViewDataTest.java | 37 ++++------ .../test/java/io/opencensus/stats/ViewTest.java | 34 ++++------ .../java/io/opencensus/tags/InternalUtilsTest.java | 4 +- .../java/io/opencensus/tags/TagContextTest.java | 6 +- api/src/test/java/io/opencensus/tags/TagTest.java | 6 +- .../io/opencensus/trace/AttributeValueTest.java | 9 ++- 36 files changed, 248 insertions(+), 374 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Duration.java b/api/src/main/java/io/opencensus/common/Duration.java index 77ba3db7..b4b59a57 100644 --- a/api/src/main/java/io/opencensus/common/Duration.java +++ b/api/src/main/java/io/opencensus/common/Duration.java @@ -92,8 +92,8 @@ public abstract class Duration implements Comparable { * Compares this {@code Duration} to the specified {@code Duration}. * * @param otherDuration the other {@code Duration} to compare to, not {@code null}. - * @return the comparator value: zero if equal, negative if this duration is smaller - * than otherDuration, positive if larger. + * @return the comparator value: zero if equal, negative if this duration is smaller than + * otherDuration, positive if larger. * @throws NullPointerException if otherDuration is {@code null}. */ @Override diff --git a/api/src/main/java/io/opencensus/common/ExperimentalApi.java b/api/src/main/java/io/opencensus/common/ExperimentalApi.java index 266da4e9..9906cbff 100644 --- a/api/src/main/java/io/opencensus/common/ExperimentalApi.java +++ b/api/src/main/java/io/opencensus/common/ExperimentalApi.java @@ -27,26 +27,26 @@ import java.lang.annotation.Target; * backward-compatibility. * *

Usage guidelines: + * *

    - *
  1. This annotation is used only on public API. Internal interfaces should not use it.
  2. - *
  3. After OpenCensus has gained API stability, this annotation can only be added to new API. - * Adding it to an existing API is considered API-breaking.
  4. - *
  5. Removing this annotation from an API gives it stable status.
  6. + *
  7. This annotation is used only on public API. Internal interfaces should not use it. + *
  8. After OpenCensus has gained API stability, this annotation can only be added to new API. + * Adding it to an existing API is considered API-breaking. + *
  9. Removing this annotation from an API gives it stable status. *
*/ @Internal @Retention(RetentionPolicy.SOURCE) @Target({ - ElementType.ANNOTATION_TYPE, - ElementType.CONSTRUCTOR, - ElementType.FIELD, - ElementType.METHOD, - ElementType.PACKAGE, - ElementType.TYPE}) + ElementType.ANNOTATION_TYPE, + ElementType.CONSTRUCTOR, + ElementType.FIELD, + ElementType.METHOD, + ElementType.PACKAGE, + ElementType.TYPE +}) @Documented public @interface ExperimentalApi { - /** - * Context information such as links to discussion thread, tracking issue etc. - */ + /** Context information such as links to discussion thread, tracking issue etc. */ String value() default ""; -} \ No newline at end of file +} diff --git a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java index 1b1c75e4..aa5d69d5 100644 --- a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java +++ b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java @@ -16,14 +16,10 @@ package io.opencensus.common; -/** - * Class holder for all common constants (such as the version) for the OpenCensus Java library. - */ +/** Class holder for all common constants (such as the version) for the OpenCensus Java library. */ @ExperimentalApi public final class OpenCensusLibraryInformation { - /** - * The current version of the OpenCensus Java library. - */ - public static final String VERSION = "0.9.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION + /** The current version of the OpenCensus Java library. */ + public static final String VERSION = "0.9.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION } diff --git a/api/src/main/java/io/opencensus/common/Timestamp.java b/api/src/main/java/io/opencensus/common/Timestamp.java index 0fa7c800..b62a1102 100644 --- a/api/src/main/java/io/opencensus/common/Timestamp.java +++ b/api/src/main/java/io/opencensus/common/Timestamp.java @@ -138,8 +138,8 @@ public abstract class Timestamp implements Comparable { * Compares this {@code Timestamp} to the specified {@code Timestamp}. * * @param otherTimestamp the other {@code Timestamp} to compare to, not {@code null}. - * @return the comparator value: zero if equal, negative if this timestamp happens - * before otherTimestamp, positive if after. + * @return the comparator value: zero if equal, negative if this timestamp happens before + * otherTimestamp, positive if after. * @throws NullPointerException if otherTimestamp is {@code null}. */ @Override diff --git a/api/src/main/java/io/opencensus/internal/NoopScope.java b/api/src/main/java/io/opencensus/internal/NoopScope.java index 1edac98e..f4a8da07 100644 --- a/api/src/main/java/io/opencensus/internal/NoopScope.java +++ b/api/src/main/java/io/opencensus/internal/NoopScope.java @@ -18,9 +18,7 @@ package io.opencensus.internal; import io.opencensus.common.Scope; -/** - * A {@link Scope} that does nothing when it is created or closed. - */ +/** A {@link Scope} that does nothing when it is created or closed. */ public final class NoopScope implements Scope { private static final Scope INSTANCE = new NoopScope(); diff --git a/api/src/main/java/io/opencensus/stats/Aggregation.java b/api/src/main/java/io/opencensus/stats/Aggregation.java index f12517c8..90341af4 100644 --- a/api/src/main/java/io/opencensus/stats/Aggregation.java +++ b/api/src/main/java/io/opencensus/stats/Aggregation.java @@ -23,10 +23,11 @@ import io.opencensus.common.Function; import javax.annotation.concurrent.Immutable; /** - * {@link Aggregation} is the process of combining a certain set of {@code MeasureValue}s - * for a given {@code Measure} into an {@link AggregationData}. + * {@link Aggregation} is the process of combining a certain set of {@code MeasureValue}s for a + * given {@code Measure} into an {@link AggregationData}. * *

{@link Aggregation} currently supports 4 types of basic aggregation: + * *

    *
  • Sum *
  • Count @@ -40,12 +41,9 @@ import javax.annotation.concurrent.Immutable; @Immutable public abstract class Aggregation { - private Aggregation() { - } + private Aggregation() {} - /** - * Applies the given match function to the underlying data type. - */ + /** Applies the given match function to the underlying data type. */ public abstract T match( Function p0, Function p1, @@ -58,8 +56,7 @@ public abstract class Aggregation { @AutoValue public abstract static class Sum extends Aggregation { - Sum() { - } + Sum() {} private static final Sum INSTANCE = new AutoValue_Aggregation_Sum(); @@ -88,8 +85,7 @@ public abstract class Aggregation { @AutoValue public abstract static class Count extends Aggregation { - Count() { - } + Count() {} private static final Count INSTANCE = new AutoValue_Aggregation_Count(); @@ -118,8 +114,7 @@ public abstract class Aggregation { @AutoValue public abstract static class Mean extends Aggregation { - Mean() { - } + Mean() {} private static final Mean INSTANCE = new AutoValue_Aggregation_Mean(); @@ -144,15 +139,14 @@ public abstract class Aggregation { } /** - * Calculate distribution stats on aggregated {@code MeasureValue}s. Distribution includes - * mean, count, histogram, min, max and sum of squared deviations. + * Calculate distribution stats on aggregated {@code MeasureValue}s. Distribution includes mean, + * count, histogram, min, max and sum of squared deviations. */ @Immutable @AutoValue public abstract static class Distribution extends Aggregation { - Distribution() { - } + Distribution() {} /** * Construct a {@code Distribution}. diff --git a/api/src/main/java/io/opencensus/stats/AggregationData.java b/api/src/main/java/io/opencensus/stats/AggregationData.java index b91d0d19..d5cacfc5 100644 --- a/api/src/main/java/io/opencensus/stats/AggregationData.java +++ b/api/src/main/java/io/opencensus/stats/AggregationData.java @@ -27,10 +27,11 @@ import java.util.List; import javax.annotation.concurrent.Immutable; /** - * {@link AggregationData} is the result of applying a given {@link Aggregation} to a set of - * {@code MeasureValue}s. + * {@link AggregationData} is the result of applying a given {@link Aggregation} to a set of {@code + * MeasureValue}s. * *

    {@link AggregationData} currently supports 5 types of basic aggregation values: + * *

      *
    • SumDataDouble *
    • SumDataLong @@ -39,18 +40,15 @@ import javax.annotation.concurrent.Immutable; *
    • DistributionData *
    * - *

    {@link ViewData} will contain one {@link AggregationData}, corresponding to its - * {@link Aggregation} definition in {@link View}. + *

    {@link ViewData} will contain one {@link AggregationData}, corresponding to its {@link + * Aggregation} definition in {@link View}. */ @Immutable public abstract class AggregationData { - private AggregationData() { - } + private AggregationData() {} - /** - * Applies the given match function to the underlying data type. - */ + /** Applies the given match function to the underlying data type. */ public abstract T match( Function p0, Function p1, @@ -64,8 +62,7 @@ public abstract class AggregationData { @AutoValue public abstract static class SumDataDouble extends AggregationData { - SumDataDouble() { - } + SumDataDouble() {} /** * Creates a {@code SumDataDouble}. @@ -101,8 +98,7 @@ public abstract class AggregationData { @AutoValue public abstract static class SumDataLong extends AggregationData { - SumDataLong() { - } + SumDataLong() {} /** * Creates a {@code SumDataLong}. @@ -138,8 +134,7 @@ public abstract class AggregationData { @AutoValue public abstract static class CountData extends AggregationData { - CountData() { - } + CountData() {} /** * Creates a {@code CountData}. @@ -175,8 +170,7 @@ public abstract class AggregationData { @AutoValue public abstract static class MeanData extends AggregationData { - MeanData() { - } + MeanData() {} /** * Creates a {@code MeanData}. @@ -223,8 +217,7 @@ public abstract class AggregationData { @AutoValue public abstract static class DistributionData extends AggregationData { - DistributionData() { - } + DistributionData() {} /** * Creates a {@code DistributionData}. @@ -238,7 +231,11 @@ public abstract class AggregationData { * @return a {@code DistributionData}. */ public static DistributionData create( - double mean, long count, double min, double max, double sumOfSquaredDeviations, + double mean, + long count, + double min, + double max, + double sumOfSquaredDeviations, List bucketCounts) { if (min != Double.POSITIVE_INFINITY || max != Double.NEGATIVE_INFINITY) { checkArgument(min <= max, "max should be greater or equal to min."); diff --git a/api/src/main/java/io/opencensus/stats/BucketBoundaries.java b/api/src/main/java/io/opencensus/stats/BucketBoundaries.java index b9a808f4..8af83a4e 100644 --- a/api/src/main/java/io/opencensus/stats/BucketBoundaries.java +++ b/api/src/main/java/io/opencensus/stats/BucketBoundaries.java @@ -38,7 +38,7 @@ public abstract class BucketBoundaries { */ public static final BucketBoundaries create(List bucketBoundaries) { checkNotNull(bucketBoundaries, "bucketBoundaries list should not be null."); - List bucketBoundariesCopy = new ArrayList(bucketBoundaries); // Deep copy. + List bucketBoundariesCopy = new ArrayList(bucketBoundaries); // Deep copy. // Check if sorted. if (bucketBoundariesCopy.size() > 1) { double lower = bucketBoundariesCopy.get(0); @@ -52,6 +52,8 @@ public abstract class BucketBoundaries { } /** + * Returns a list of histogram bucket boundaries. + * * @return a list of histogram bucket boundaries. */ public abstract List getBoundaries(); diff --git a/api/src/main/java/io/opencensus/stats/Measure.java b/api/src/main/java/io/opencensus/stats/Measure.java index 062a35bf..52fadfa0 100644 --- a/api/src/main/java/io/opencensus/stats/Measure.java +++ b/api/src/main/java/io/opencensus/stats/Measure.java @@ -30,9 +30,7 @@ public abstract class Measure { @VisibleForTesting static final int NAME_MAX_LENGTH = 255; - /** - * Applies the given match function to the underlying data type. - */ + /** Applies the given match function to the underlying data type. */ public abstract T match( Function p0, Function p1, @@ -46,35 +44,35 @@ public abstract class Measure { */ public abstract String getName(); - /** - * Detailed description of the measure, used in documentation. - */ + /** Detailed description of the measure, used in documentation. */ public abstract String getDescription(); /** * The units in which {@link Measure} values are measured. * *

    The suggested grammar for a unit is as follows: - * Expression = Component { "." Component } { "/" Component } ; - * Component = [ PREFIX ] UNIT [ Annotation ] | Annotation | "1" ; - * Annotation = "{" NAME "}" ; - * For example, string “MBy{transmitted}/ms” stands for megabytes per milliseconds, and the + * + *

      + *
    • Expression = Component { "." Component } {"/" Component }; + *
    • Component = [ PREFIX ] UNIT [ Annotation ] | Annotation | "1"; + *
    • Annotation = "{" NAME "}" ; + *
    + * + *

    For example, string “MBy{transmitted}/ms” stands for megabytes per milliseconds, and the * annotation transmitted inside {} is just a comment of the unit. */ // TODO(songya): determine whether we want to check the grammar on string unit. public abstract String getUnit(); // Prevents this class from being subclassed anywhere else. - private Measure() { - } + private Measure() {} /** {@link Measure} with {@code Double} typed values. */ @Immutable @AutoValue public abstract static class MeasureDouble extends Measure { - MeasureDouble() { - } + MeasureDouble() {} /** * Constructs a new {@link MeasureDouble}. @@ -85,9 +83,11 @@ public abstract class Measure { * @return a {@code MeasureDouble}. */ public static MeasureDouble create(String name, String description, String unit) { - checkArgument(StringUtil.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, + checkArgument( + StringUtil.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, "Name should be a ASCII string with a length no greater than " - + NAME_MAX_LENGTH + " characters."); + + NAME_MAX_LENGTH + + " characters."); return new AutoValue_Measure_MeasureDouble(name, description, unit); } @@ -114,8 +114,7 @@ public abstract class Measure { @AutoValue public abstract static class MeasureLong extends Measure { - MeasureLong() { - } + MeasureLong() {} /** * Constructs a new {@link MeasureLong}. @@ -126,9 +125,11 @@ public abstract class Measure { * @return a {@code MeasureLong}. */ public static MeasureLong create(String name, String description, String unit) { - checkArgument(StringUtil.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, + checkArgument( + StringUtil.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, "Name should be a ASCII string with a length no greater than " - + NAME_MAX_LENGTH + " characters."); + + NAME_MAX_LENGTH + + " characters."); return new AutoValue_Measure_MeasureLong(name, description, unit); } diff --git a/api/src/main/java/io/opencensus/stats/Measurement.java b/api/src/main/java/io/opencensus/stats/Measurement.java index 10fc5888..1bb746d8 100644 --- a/api/src/main/java/io/opencensus/stats/Measurement.java +++ b/api/src/main/java/io/opencensus/stats/Measurement.java @@ -26,22 +26,17 @@ import javax.annotation.concurrent.Immutable; @Immutable public abstract class Measurement { - /** - * Applies the given match function to the underlying data type. - */ + /** Applies the given match function to the underlying data type. */ public abstract T match( Function p0, Function p1, Function defaultFunction); - /** - * Extracts the measured {@link Measure}. - */ + /** Extracts the measured {@link Measure}. */ public abstract Measure getMeasure(); // Prevents this class from being subclassed anywhere else. - private Measurement() { - } + private Measurement() {} /** {@code Double} typed {@link Measurement}. */ @Immutable @@ -49,9 +44,7 @@ public abstract class Measurement { public abstract static class MeasurementDouble extends Measurement { MeasurementDouble() {} - /** - * Constructs a new {@link MeasurementDouble}. - */ + /** Constructs a new {@link MeasurementDouble}. */ public static MeasurementDouble create(MeasureDouble measure, double value) { return new AutoValue_Measurement_MeasurementDouble(measure, value); } @@ -76,9 +69,7 @@ public abstract class Measurement { public abstract static class MeasurementLong extends Measurement { MeasurementLong() {} - /** - * Constructs a new {@link MeasurementLong}. - */ + /** Constructs a new {@link MeasurementLong}. */ public static MeasurementLong create(MeasureLong measure, long value) { return new AutoValue_Measurement_MeasurementLong(measure, value); } diff --git a/api/src/main/java/io/opencensus/stats/View.java b/api/src/main/java/io/opencensus/stats/View.java index 26b1177f..c4b152e0 100644 --- a/api/src/main/java/io/opencensus/stats/View.java +++ b/api/src/main/java/io/opencensus/stats/View.java @@ -31,8 +31,8 @@ import java.util.List; import javax.annotation.concurrent.Immutable; /** - * A View specifies an aggregation and a set of tag keys. The aggregation will be broken - * down by the unique set of matching tag values for each measure. + * A View specifies an aggregation and a set of tag keys. The aggregation will be broken down by the + * unique set of matching tag values for each measure. */ @Immutable @AutoValue @@ -40,27 +40,18 @@ public abstract class View { @VisibleForTesting static final int NAME_MAX_LENGTH = 256; - View() { - } + View() {} - /** - * Name of view. Must be unique. - */ + /** Name of view. Must be unique. */ public abstract Name getName(); - /** - * More detailed description, for documentation purposes. - */ + /** More detailed description, for documentation purposes. */ public abstract String getDescription(); - /** - * Measure type of this view. - */ + /** Measure type of this view. */ public abstract Measure getMeasure(); - /** - * The {@link Aggregation} associated with this {@link View}. - */ + /** The {@link Aggregation} associated with this {@link View}. */ public abstract Aggregation getAggregation(); /** @@ -97,8 +88,7 @@ public abstract class View { Aggregation aggregation, List columns, AggregationWindow window) { - checkArgument(new HashSet(columns).size() == columns.size(), - "Columns have duplicate."); + checkArgument(new HashSet(columns).size() == columns.size(), "Columns have duplicate."); return new AutoValue_View( name, @@ -109,9 +99,7 @@ public abstract class View { window); } - /** - * The name of a {@code View}. - */ + /** The name of a {@code View}. */ // This type should be used as the key when associating data with Views. @Immutable @AutoValue @@ -127,8 +115,8 @@ public abstract class View { public abstract String asString(); /** - * Creates a {@code View.Name} from a {@code String}. Should be a ASCII string with a length - * no greater than 256 characters. + * Creates a {@code View.Name} from a {@code String}. Should be a ASCII string with a length no + * greater than 256 characters. * *

    Suggested format for name: {@code /}. * @@ -136,7 +124,8 @@ public abstract class View { * @return a {@code View.Name} with the given name {@code String}. */ public static Name create(String name) { - checkArgument(StringUtil.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, + checkArgument( + StringUtil.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, "Name should be a ASCII string with a length no greater than 256 characters."); return new AutoValue_View_Name(name); } @@ -148,9 +137,7 @@ public abstract class View { private AggregationWindow() {} - /** - * Applies the given match function to the underlying data type. - */ + /** Applies the given match function to the underlying data type. */ public abstract T match( Function p0, Function p1, @@ -182,7 +169,7 @@ public abstract class View { Function p0, Function p1, Function defaultFunction) { - return p0.apply(this); + return p0.apply(this); } } @@ -202,7 +189,6 @@ public abstract class View { */ public abstract Duration getDuration(); - /** * Constructs an interval {@code AggregationWindow} that has a finite explicit {@code * Duration}. @@ -222,7 +208,7 @@ public abstract class View { Function p0, Function p1, Function defaultFunction) { - return p1.apply(this); + return p1.apply(this); } } } diff --git a/api/src/main/java/io/opencensus/stats/ViewData.java b/api/src/main/java/io/opencensus/stats/ViewData.java index 007022e7..458b1f1a 100644 --- a/api/src/main/java/io/opencensus/stats/ViewData.java +++ b/api/src/main/java/io/opencensus/stats/ViewData.java @@ -41,8 +41,8 @@ public abstract class ViewData { public abstract View getView(); /** - * The {@link AggregationData} grouped by combination of tag values, associated with this - * {@link ViewData}. + * The {@link AggregationData} grouped by combination of tag values, associated with this {@link + * ViewData}. */ public abstract Map, AggregationData> getAggregationMap(); @@ -91,11 +91,9 @@ public abstract class ViewData { Functions.throwIllegalArgumentException()); Map, AggregationData> deepCopy = Maps.newHashMap(); - for (Entry, ? extends AggregationData> entry : map - .entrySet()) { + for (Entry, ? extends AggregationData> entry : map.entrySet()) { deepCopy.put( - Collections.unmodifiableList(new ArrayList(entry.getKey())), - entry.getValue()); + Collections.unmodifiableList(new ArrayList(entry.getKey())), entry.getValue()); } return new AutoValue_ViewData(view, Collections.unmodifiableMap(deepCopy), windowData); diff --git a/api/src/main/java/io/opencensus/stats/ViewManager.java b/api/src/main/java/io/opencensus/stats/ViewManager.java index 908221c6..f98e8058 100644 --- a/api/src/main/java/io/opencensus/stats/ViewManager.java +++ b/api/src/main/java/io/opencensus/stats/ViewManager.java @@ -19,13 +19,13 @@ package io.opencensus.stats; import javax.annotation.Nullable; /** - * Provides facilities to register {@link View}s for collecting stats and retrieving - * stats data as a {@link ViewData}. + * Provides facilities to register {@link View}s for collecting stats and retrieving stats data as a + * {@link ViewData}. */ public abstract class ViewManager { /** - * Pull model for stats. Registers a {@link View} that will collect data to be accessed - * via {@link #getView(View.Name)}. + * Pull model for stats. Registers a {@link View} that will collect data to be accessed via {@link + * #getView(View.Name)}. * * @param view the {@code View} to be registered. */ diff --git a/api/src/main/java/io/opencensus/tags/InternalUtils.java b/api/src/main/java/io/opencensus/tags/InternalUtils.java index c55ca7d4..734fcf98 100644 --- a/api/src/main/java/io/opencensus/tags/InternalUtils.java +++ b/api/src/main/java/io/opencensus/tags/InternalUtils.java @@ -18,9 +18,7 @@ package io.opencensus.tags; import java.util.Iterator; -/** - * Internal tagging utilities. - */ +/** Internal tagging utilities. */ @io.opencensus.common.Internal public final class InternalUtils { private InternalUtils() {} diff --git a/api/src/main/java/io/opencensus/tags/package-info.java b/api/src/main/java/io/opencensus/tags/package-info.java index e18c68d1..eb19ee77 100644 --- a/api/src/main/java/io/opencensus/tags/package-info.java +++ b/api/src/main/java/io/opencensus/tags/package-info.java @@ -22,8 +22,8 @@ * io.opencensus.stats} package labels all stats with the current tags. * *

    {@link io.opencensus.tags.Tag Tags} are key-value pairs. The {@link io.opencensus.tags.TagKey - * keys} and {@link io.opencensus.tags.TagValue values} are wrapped {@code String}s. They are - * stored as a map in a {@link io.opencensus.tags.TagContext}. + * keys} and {@link io.opencensus.tags.TagValue values} are wrapped {@code String}s. They are stored + * as a map in a {@link io.opencensus.tags.TagContext}. * *

    Note that tags are independent of the tracing data that is propagated in the {@code * io.grpc.Context}, such as trace ID. diff --git a/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java index ab8282de..dbbe3a33 100644 --- a/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java +++ b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java @@ -20,9 +20,7 @@ import io.grpc.Context; import io.opencensus.common.Scope; import io.opencensus.trace.unsafe.ContextUtils; -/** - * Util methods/functionality to interact with the {@link Span} in the {@link io.grpc.Context}. - */ +/** Util methods/functionality to interact with the {@link Span} in the {@link io.grpc.Context}. */ final class CurrentSpanUtils { // No instance of this class. private CurrentSpanUtils() {} diff --git a/api/src/main/java/io/opencensus/trace/Sampler.java b/api/src/main/java/io/opencensus/trace/Sampler.java index 429ffe92..e30b5fdd 100644 --- a/api/src/main/java/io/opencensus/trace/Sampler.java +++ b/api/src/main/java/io/opencensus/trace/Sampler.java @@ -44,8 +44,8 @@ public abstract class Sampler { List parentLinks); /** - * Returns the description of this {@code Sampler}. This may be displayed on debug pages or in - * the logs. + * Returns the description of this {@code Sampler}. This may be displayed on debug pages or in the + * logs. * *

    Example: "ProbabilitySampler{0.000100}" * diff --git a/api/src/main/java/io/opencensus/trace/Span.java b/api/src/main/java/io/opencensus/trace/Span.java index b58a1fde..3ede6686 100644 --- a/api/src/main/java/io/opencensus/trace/Span.java +++ b/api/src/main/java/io/opencensus/trace/Span.java @@ -77,8 +77,8 @@ public abstract class Span { } /** - * Sets an attribute to the {@code Span}. If the {@code Span} previously contained a mapping - * for the key, the old value is replaced by the specified value. + * Sets an attribute to the {@code Span}. If the {@code Span} previously contained a mapping for + * the key, the old value is replaced by the specified value. * * @param key the key for this attribute. * @param value the value for this attribute. @@ -103,7 +103,6 @@ public abstract class Span { addAttributes(attributes); } - /** * @deprecated Use {@link #putAttributes(Map)} * @param attributes the attributes that will be added and associated with the {@code Span}. diff --git a/api/src/main/java/io/opencensus/trace/TraceComponent.java b/api/src/main/java/io/opencensus/trace/TraceComponent.java index 4472ba26..e1806490 100644 --- a/api/src/main/java/io/opencensus/trace/TraceComponent.java +++ b/api/src/main/java/io/opencensus/trace/TraceComponent.java @@ -23,8 +23,8 @@ import io.opencensus.trace.export.ExportComponent; import io.opencensus.trace.propagation.PropagationComponent; /** - * Class that holds the implementation instances for {@link Tracer}, {@link - * PropagationComponent}, {@link Clock}, {@link ExportComponent} and {@link TraceConfig}. + * Class that holds the implementation instances for {@link Tracer}, {@link PropagationComponent}, + * {@link Clock}, {@link ExportComponent} and {@link TraceConfig}. * *

    Unless otherwise noted all methods (on component) results are cacheable. */ @@ -40,8 +40,8 @@ public abstract class TraceComponent { public abstract Tracer getTracer(); /** - * Returns the {@link PropagationComponent} with the provided implementation. If no - * implementation is provided then no-op implementation will be used. + * Returns the {@link PropagationComponent} with the provided implementation. If no implementation + * is provided then no-op implementation will be used. * * @return the {@code PropagationComponent} implementation. */ diff --git a/api/src/main/java/io/opencensus/trace/TraceOptions.java b/api/src/main/java/io/opencensus/trace/TraceOptions.java index 35181e28..fc594853 100644 --- a/api/src/main/java/io/opencensus/trace/TraceOptions.java +++ b/api/src/main/java/io/opencensus/trace/TraceOptions.java @@ -200,7 +200,8 @@ public final class TraceOptions { if (isSampled) { options = (byte) (options | IS_SAMPLED); } else { - options = (byte) (options & ~IS_SAMPLED);; + options = (byte) (options & ~IS_SAMPLED); + ; } return this; } diff --git a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java index abf5c531..9b7e1664 100644 --- a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java +++ b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java @@ -20,8 +20,8 @@ import io.opencensus.trace.TraceOptions; import javax.annotation.Nullable; /** - * Class that holds the implementation instances for {@link SpanExporter}, {@link - * RunningSpanStore} and {@link SampledSpanStore}. + * Class that holds the implementation instances for {@link SpanExporter}, {@link RunningSpanStore} + * and {@link SampledSpanStore}. * *

    Unless otherwise noted all methods (on component) results are cacheable. */ @@ -48,8 +48,8 @@ public abstract class ExportComponent { public abstract SpanExporter getSpanExporter(); /** - * Returns the {@link RunningSpanStore} that can be used to get useful debugging information - * about all the current active spans. + * Returns the {@link RunningSpanStore} that can be used to get useful debugging information about + * all the current active spans. * * @return the {@code RunningSpanStore} or {@code null} if not supported. */ diff --git a/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java b/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java index e8abda76..7dfa8202 100644 --- a/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java +++ b/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java @@ -17,16 +17,16 @@ package io.opencensus.trace.propagation; /** - * Container class for all the supported propagation formats. Currently supports only Binary - * format see {@link BinaryFormat} but more formats will be added. + * Container class for all the supported propagation formats. Currently supports only Binary format + * see {@link BinaryFormat} but more formats will be added. */ public abstract class PropagationComponent { private static final PropagationComponent NOOP_PROPAGATION_COMPONENT = new NoopPropagationComponent(); /** - * Returns the {@link BinaryFormat} with the provided implementations. If no implementation - * is provided then no-op implementation will be used. + * Returns the {@link BinaryFormat} with the provided implementations. If no implementation is + * provided then no-op implementation will be used. * * @return the {@code BinaryFormat} implementation. */ diff --git a/api/src/test/java/io/opencensus/common/DurationTest.java b/api/src/test/java/io/opencensus/common/DurationTest.java index 1aad997b..40682fc4 100644 --- a/api/src/test/java/io/opencensus/common/DurationTest.java +++ b/api/src/test/java/io/opencensus/common/DurationTest.java @@ -74,7 +74,6 @@ public class DurationTest { assertThat(Duration.create(-24, -45).compareTo(Duration.create(-24, -42))).isEqualTo(-1); assertThat(Duration.create(-24, -42).compareTo(Duration.create(-25, -42))).isEqualTo(1); assertThat(Duration.create(24, 42).compareTo(Duration.create(-24, -42))).isEqualTo(1); - } @Test diff --git a/api/src/test/java/io/opencensus/common/TimestampTest.java b/api/src/test/java/io/opencensus/common/TimestampTest.java index 68492cb2..776f5f12 100644 --- a/api/src/test/java/io/opencensus/common/TimestampTest.java +++ b/api/src/test/java/io/opencensus/common/TimestampTest.java @@ -83,7 +83,7 @@ public class TimestampTest { assertThat(timestamp.addNanos(Long.MIN_VALUE)) .isEqualTo(Timestamp.create(1234L - 9223372036L - 1, 223 + 145224192)); } - + @Test public void timestampAddDuration() { Timestamp timestamp = Timestamp.create(1234, 223); diff --git a/api/src/test/java/io/opencensus/stats/AggregationDataTest.java b/api/src/test/java/io/opencensus/stats/AggregationDataTest.java index d4403c93..3431d043 100644 --- a/api/src/test/java/io/opencensus/stats/AggregationDataTest.java +++ b/api/src/test/java/io/opencensus/stats/AggregationDataTest.java @@ -41,13 +41,12 @@ public class AggregationDataTest { private static final double TOLERANCE = 1e-6; - @Rule - public ExpectedException thrown = ExpectedException.none(); + @Rule public ExpectedException thrown = ExpectedException.none(); @Test public void testCreateDistributionData() { - DistributionData distributionData = DistributionData.create( - 7.7, 10, 1.1, 9.9, 32.2, Arrays.asList(4L, 1L, 5L)); + DistributionData distributionData = + DistributionData.create(7.7, 10, 1.1, 9.9, 32.2, Arrays.asList(4L, 1L, 5L)); assertThat(distributionData.getMean()).isWithin(TOLERANCE).of(7.7); assertThat(distributionData.getCount()).isEqualTo(10); assertThat(distributionData.getMin()).isWithin(TOLERANCE).of(1.1); @@ -80,53 +79,34 @@ public class AggregationDataTest { @Test public void testEquals() { new EqualsTester() - .addEqualityGroup( - SumDataDouble.create(10.0), - SumDataDouble.create(10.0)) - .addEqualityGroup( - SumDataDouble.create(20.0), - SumDataDouble.create(20.0)) - .addEqualityGroup( - SumDataLong.create(20), - SumDataLong.create(20)) - .addEqualityGroup( - CountData.create(40), - CountData.create(40)) - .addEqualityGroup( - CountData.create(80), - CountData.create(80)) + .addEqualityGroup(SumDataDouble.create(10.0), SumDataDouble.create(10.0)) + .addEqualityGroup(SumDataDouble.create(20.0), SumDataDouble.create(20.0)) + .addEqualityGroup(SumDataLong.create(20), SumDataLong.create(20)) + .addEqualityGroup(CountData.create(40), CountData.create(40)) + .addEqualityGroup(CountData.create(80), CountData.create(80)) .addEqualityGroup( DistributionData.create(10, 10, 1, 1, 0, Arrays.asList(0L, 10L, 0L)), DistributionData.create(10, 10, 1, 1, 0, Arrays.asList(0L, 10L, 0L))) - .addEqualityGroup( - DistributionData.create(10, 10, 1, 1, 0, Arrays.asList(0L, 10L, 100L))) - .addEqualityGroup( - DistributionData.create(110, 10, 1, 1, 0, Arrays.asList(0L, 10L, 0L))) - .addEqualityGroup( - DistributionData.create(10, 110, 1, 1, 0, Arrays.asList(0L, 10L, 0L))) - .addEqualityGroup( - DistributionData.create(10, 10, -1, 1, 0, Arrays.asList(0L, 10L, 0L))) - .addEqualityGroup( - DistributionData.create(10, 10, 1, 5, 0, Arrays.asList(0L, 10L, 0L))) - .addEqualityGroup( - DistributionData.create(10, 10, 1, 1, 55.5, Arrays.asList(0L, 10L, 0L))) - .addEqualityGroup( - MeanData.create(5.0, 1), - MeanData.create(5.0, 1)) - .addEqualityGroup( - MeanData.create(-5.0, 1), - MeanData.create(-5.0, 1)) + .addEqualityGroup(DistributionData.create(10, 10, 1, 1, 0, Arrays.asList(0L, 10L, 100L))) + .addEqualityGroup(DistributionData.create(110, 10, 1, 1, 0, Arrays.asList(0L, 10L, 0L))) + .addEqualityGroup(DistributionData.create(10, 110, 1, 1, 0, Arrays.asList(0L, 10L, 0L))) + .addEqualityGroup(DistributionData.create(10, 10, -1, 1, 0, Arrays.asList(0L, 10L, 0L))) + .addEqualityGroup(DistributionData.create(10, 10, 1, 5, 0, Arrays.asList(0L, 10L, 0L))) + .addEqualityGroup(DistributionData.create(10, 10, 1, 1, 55.5, Arrays.asList(0L, 10L, 0L))) + .addEqualityGroup(MeanData.create(5.0, 1), MeanData.create(5.0, 1)) + .addEqualityGroup(MeanData.create(-5.0, 1), MeanData.create(-5.0, 1)) .testEquals(); } @Test public void testMatchAndGet() { - List aggregations = Arrays.asList( - SumDataDouble.create(10.0), - SumDataLong.create(100000000), - CountData.create(40), - MeanData.create(5.0, 1), - DistributionData.create(1, 1, 1, 1, 0, Arrays.asList(0L, 10L, 0L))); + List aggregations = + Arrays.asList( + SumDataDouble.create(10.0), + SumDataLong.create(100000000), + CountData.create(40), + MeanData.create(5.0, 1), + DistributionData.create(1, 1, 1, 1, 0, Arrays.asList(0L, 10L, 0L))); final List actual = new ArrayList(); for (AggregationData aggregation : aggregations) { @@ -169,7 +149,7 @@ public class AggregationDataTest { Functions.throwIllegalArgumentException()); } - assertThat(actual).isEqualTo( - Arrays.asList(10.0, 100000000L, 40L, 5.0, Arrays.asList(0L, 10L, 0L))); + assertThat(actual) + .isEqualTo(Arrays.asList(10.0, 100000000L, 40L, 5.0, Arrays.asList(0L, 10L, 0L))); } } diff --git a/api/src/test/java/io/opencensus/stats/AggregationTest.java b/api/src/test/java/io/opencensus/stats/AggregationTest.java index 66376cbb..3ef131b8 100644 --- a/api/src/test/java/io/opencensus/stats/AggregationTest.java +++ b/api/src/test/java/io/opencensus/stats/AggregationTest.java @@ -38,8 +38,7 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public class AggregationTest { - @Rule - public ExpectedException thrown = ExpectedException.none(); + @Rule public ExpectedException thrown = ExpectedException.none(); @Test public void testCreateDistribution() { @@ -58,60 +57,56 @@ public class AggregationTest { @Test public void testEquals() { new EqualsTester() - .addEqualityGroup( - Sum.create(), - Sum.create()) - .addEqualityGroup( - Count.create(), - Count.create()) + .addEqualityGroup(Sum.create(), Sum.create()) + .addEqualityGroup(Count.create(), Count.create()) .addEqualityGroup( Distribution.create(BucketBoundaries.create(Arrays.asList(-10.0, 1.0, 5.0))), Distribution.create(BucketBoundaries.create(Arrays.asList(-10.0, 1.0, 5.0)))) .addEqualityGroup( Distribution.create(BucketBoundaries.create(Arrays.asList(0.0, 1.0, 5.0))), Distribution.create(BucketBoundaries.create(Arrays.asList(0.0, 1.0, 5.0)))) - .addEqualityGroup( - Mean.create(), - Mean.create()) + .addEqualityGroup(Mean.create(), Mean.create()) .testEquals(); } @Test public void testMatch() { - List aggregations = Arrays.asList( - Sum.create(), - Count.create(), - Mean.create(), - Distribution.create(BucketBoundaries.create(Arrays.asList(-10.0, 1.0, 5.0)))); + List aggregations = + Arrays.asList( + Sum.create(), + Count.create(), + Mean.create(), + Distribution.create(BucketBoundaries.create(Arrays.asList(-10.0, 1.0, 5.0)))); List actual = new ArrayList(); for (Aggregation aggregation : aggregations) { - actual.add(aggregation.match( - new Function() { - @Override - public String apply(Sum arg) { - return "SUM"; - } - }, - new Function() { - @Override - public String apply(Count arg) { - return "COUNT"; - } - }, - new Function() { - @Override - public String apply(Mean arg) { - return "MEAN"; - } - }, - new Function() { - @Override - public String apply(Distribution arg) { - return "DISTRIBUTION"; - } - }, - Functions.throwIllegalArgumentException())); + actual.add( + aggregation.match( + new Function() { + @Override + public String apply(Sum arg) { + return "SUM"; + } + }, + new Function() { + @Override + public String apply(Count arg) { + return "COUNT"; + } + }, + new Function() { + @Override + public String apply(Mean arg) { + return "MEAN"; + } + }, + new Function() { + @Override + public String apply(Distribution arg) { + return "DISTRIBUTION"; + } + }, + Functions.throwIllegalArgumentException())); } assertThat(actual).isEqualTo(Arrays.asList("SUM", "COUNT", "MEAN", "DISTRIBUTION")); diff --git a/api/src/test/java/io/opencensus/stats/BucketBoundariesTest.java b/api/src/test/java/io/opencensus/stats/BucketBoundariesTest.java index e3fd3222..36f2edb4 100644 --- a/api/src/test/java/io/opencensus/stats/BucketBoundariesTest.java +++ b/api/src/test/java/io/opencensus/stats/BucketBoundariesTest.java @@ -28,14 +28,11 @@ import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** - * Unit tests for {@link io.opencensus.stats.BucketBoundaries}. - */ +/** Unit tests for {@link io.opencensus.stats.BucketBoundaries}. */ @RunWith(JUnit4.class) public class BucketBoundariesTest { - @Rule - public final ExpectedException thrown = ExpectedException.none(); + @Rule public final ExpectedException thrown = ExpectedException.none(); @Test public void testConstructBoundaries() { diff --git a/api/src/test/java/io/opencensus/stats/MeasureTest.java b/api/src/test/java/io/opencensus/stats/MeasureTest.java index 0c1e3867..a9302425 100644 --- a/api/src/test/java/io/opencensus/stats/MeasureTest.java +++ b/api/src/test/java/io/opencensus/stats/MeasureTest.java @@ -36,8 +36,7 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public final class MeasureTest { - @Rule - public final ExpectedException thrown = ExpectedException.none(); + @Rule public final ExpectedException thrown = ExpectedException.none(); @Test public void testConstants() { @@ -61,10 +60,7 @@ public final class MeasureTest { @Test public void testMeasureDoubleComponents() { - Measure measurement = Measure.MeasureDouble.create( - "Foo", - "The description of Foo", - "Mbit/s"); + Measure measurement = Measure.MeasureDouble.create("Foo", "The description of Foo", "Mbit/s"); assertThat(measurement.getName()).isEqualTo("Foo"); assertThat(measurement.getDescription()).isEqualTo("The description of Foo"); assertThat(measurement.getUnit()).isEqualTo("Mbit/s"); @@ -72,10 +68,7 @@ public final class MeasureTest { @Test public void testMeasureLongComponents() { - Measure measurement = Measure.MeasureLong.create( - "Bar", - "The description of Bar", - "1"); + Measure measurement = Measure.MeasureLong.create("Bar", "The description of Bar", "1"); assertThat(measurement.getName()).isEqualTo("Bar"); assertThat(measurement.getDescription()).isEqualTo("The description of Bar"); assertThat(measurement.getUnit()).isEqualTo("1"); @@ -85,19 +78,9 @@ public final class MeasureTest { public void testMeasureDoubleEquals() { new EqualsTester() .addEqualityGroup( - Measure.MeasureDouble.create( - "name", - "description", - "bit/s"), - Measure.MeasureDouble.create( - "name", - "description", - "bit/s")) - .addEqualityGroup( - Measure.MeasureDouble.create( - "name", - "description 2", - "bit/s")) + Measure.MeasureDouble.create("name", "description", "bit/s"), + Measure.MeasureDouble.create("name", "description", "bit/s")) + .addEqualityGroup(Measure.MeasureDouble.create("name", "description 2", "bit/s")) .testEquals(); } @@ -105,27 +88,18 @@ public final class MeasureTest { public void testMeasureLongEquals() { new EqualsTester() .addEqualityGroup( - Measure.MeasureLong.create( - "name", - "description", - "bit/s"), - Measure.MeasureLong.create( - "name", - "description", - "bit/s")) - .addEqualityGroup( - Measure.MeasureLong.create( - "name", - "description 2", - "bit/s")) + Measure.MeasureLong.create("name", "description", "bit/s"), + Measure.MeasureLong.create("name", "description", "bit/s")) + .addEqualityGroup(Measure.MeasureLong.create("name", "description 2", "bit/s")) .testEquals(); } @Test public void testMatch() { - List measures = Arrays.asList( - MeasureDouble.create("measure1", "description", "1"), - MeasureLong.create("measure2", "description", "1")); + List measures = + Arrays.asList( + MeasureDouble.create("measure1", "description", "1"), + MeasureLong.create("measure2", "description", "1")); List outputs = Lists.newArrayList(); for (Measure measure : measures) { outputs.add( diff --git a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java index 9d686251..9a52b7db 100644 --- a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java +++ b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java @@ -84,10 +84,7 @@ public final class NoopStatsTest { // exception. @Test public void noopStatsRecorder_Record() { - NoopStats.getNoopStatsRecorder() - .newMeasureMap() - .put(MEASURE, 5) - .record(tagContext); + NoopStats.getNoopStatsRecorder().newMeasureMap().put(MEASURE, 5).record(tagContext); } // The NoopStatsRecorder should do nothing, so this test just checks that record doesn't throw an diff --git a/api/src/test/java/io/opencensus/stats/StatsTest.java b/api/src/test/java/io/opencensus/stats/StatsTest.java index cb2f3a23..cc60d6c0 100644 --- a/api/src/test/java/io/opencensus/stats/StatsTest.java +++ b/api/src/test/java/io/opencensus/stats/StatsTest.java @@ -45,16 +45,15 @@ public final class StatsTest { @Test public void loadStatsManager_IgnoresMissingClasses() { - assertThat( - Stats.loadStatsComponent( - new ClassLoader() { - @Override - public Class loadClass(String name) throws ClassNotFoundException { - throw new ClassNotFoundException(); - } - }) - .getClass() - .getName()) + ClassLoader classLoader = + new ClassLoader() { + @Override + public Class loadClass(String name) throws ClassNotFoundException { + throw new ClassNotFoundException(); + } + }; + + assertThat(Stats.loadStatsComponent(classLoader).getClass().getName()) .isEqualTo("io.opencensus.stats.NoopStats$NoopStatsComponent"); } diff --git a/api/src/test/java/io/opencensus/stats/ViewDataTest.java b/api/src/test/java/io/opencensus/stats/ViewDataTest.java index 285921db..028506fb 100644 --- a/api/src/test/java/io/opencensus/stats/ViewDataTest.java +++ b/api/src/test/java/io/opencensus/stats/ViewDataTest.java @@ -48,8 +48,7 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public final class ViewDataTest { - @Rule - public ExpectedException thrown = ExpectedException.none(); + @Rule public ExpectedException thrown = ExpectedException.none(); @Test public void testCumulativeViewData() { @@ -86,28 +85,19 @@ public final class ViewDataTest { ViewData.create( cumulativeView, ENTRIES, - CumulativeData.create( - Timestamp.fromMillis(1000), Timestamp.fromMillis(2000))), + CumulativeData.create(Timestamp.fromMillis(1000), Timestamp.fromMillis(2000))), ViewData.create( cumulativeView, ENTRIES, - CumulativeData.create( - Timestamp.fromMillis(1000), Timestamp.fromMillis(2000)))) + CumulativeData.create(Timestamp.fromMillis(1000), Timestamp.fromMillis(2000)))) .addEqualityGroup( ViewData.create( cumulativeView, ENTRIES, - CumulativeData.create( - Timestamp.fromMillis(1000), Timestamp.fromMillis(3000)))) + CumulativeData.create(Timestamp.fromMillis(1000), Timestamp.fromMillis(3000)))) .addEqualityGroup( - ViewData.create( - intervalView, - ENTRIES, - IntervalData.create(Timestamp.fromMillis(2000))), - ViewData.create( - intervalView, - ENTRIES, - IntervalData.create(Timestamp.fromMillis(2000)))) + ViewData.create(intervalView, ENTRIES, IntervalData.create(Timestamp.fromMillis(2000))), + ViewData.create(intervalView, ENTRIES, IntervalData.create(Timestamp.fromMillis(2000)))) .addEqualityGroup( ViewData.create( intervalView, @@ -163,8 +153,7 @@ public final class ViewDataTest { ViewData.create( View.create(NAME, DESCRIPTION, MEASURE, DISTRIBUTION, tagKeys, INTERVAL_HOUR), ENTRIES, - CumulativeData.create( - Timestamp.fromMillis(1000), Timestamp.fromMillis(2000))); + CumulativeData.create(Timestamp.fromMillis(1000), Timestamp.fromMillis(2000))); } @Test @@ -196,11 +185,11 @@ public final class ViewDataTest { private static final AggregationWindow CUMULATIVE = Cumulative.create(); private static final AggregationWindow INTERVAL_HOUR = Interval.create(Duration.create(3600, 0)); - private static final BucketBoundaries BUCKET_BOUNDARIES = BucketBoundaries.create( - Arrays.asList(10.0, 20.0, 30.0, 40.0)); + private static final BucketBoundaries BUCKET_BOUNDARIES = + BucketBoundaries.create(Arrays.asList(10.0, 20.0, 30.0, 40.0)); private static final Aggregation DISTRIBUTION = Distribution.create(BUCKET_BOUNDARIES); - + private static final ImmutableMap, DistributionData> ENTRIES = ImmutableMap.of( Arrays.asList(V1, V2), @@ -213,8 +202,6 @@ public final class ViewDataTest { // description private static final String DESCRIPTION = "test-view-descriptor description"; // measure - private static final Measure MEASURE = Measure.MeasureDouble.create( - "measure", - "measure description", - "1"); + private static final Measure MEASURE = + Measure.MeasureDouble.create("measure", "measure description", "1"); } diff --git a/api/src/test/java/io/opencensus/stats/ViewTest.java b/api/src/test/java/io/opencensus/stats/ViewTest.java index 81584ef9..c135713c 100644 --- a/api/src/test/java/io/opencensus/stats/ViewTest.java +++ b/api/src/test/java/io/opencensus/stats/ViewTest.java @@ -46,8 +46,7 @@ public final class ViewTest { @Test public void testDistributionView() { - final View view = View.create( - NAME, DESCRIPTION, MEASURE, MEAN, keys, Cumulative.create()); + final View view = View.create(NAME, DESCRIPTION, MEASURE, MEAN, keys, Cumulative.create()); assertThat(view.getName()).isEqualTo(NAME); assertThat(view.getDescription()).isEqualTo(DESCRIPTION); assertThat(view.getMeasure().getName()).isEqualTo(MEASURE.getName()); @@ -59,12 +58,10 @@ public final class ViewTest { @Test public void testIntervalView() { - final View view = View.create( - NAME, DESCRIPTION, MEASURE, MEAN, keys, Interval.create(MINUTE)); + final View view = View.create(NAME, DESCRIPTION, MEASURE, MEAN, keys, Interval.create(MINUTE)); assertThat(view.getName()).isEqualTo(NAME); assertThat(view.getDescription()).isEqualTo(DESCRIPTION); - assertThat(view.getMeasure().getName()) - .isEqualTo(MEASURE.getName()); + assertThat(view.getMeasure().getName()).isEqualTo(MEASURE.getName()); assertThat(view.getAggregation()).isEqualTo(MEAN); assertThat(view.getColumns()).hasSize(2); assertThat(view.getColumns()).containsExactly(FOO, BAR).inOrder(); @@ -75,21 +72,15 @@ public final class ViewTest { public void testViewEquals() { new EqualsTester() .addEqualityGroup( - View.create( - NAME, DESCRIPTION, MEASURE, MEAN, keys, Cumulative.create()), - View.create( - NAME, DESCRIPTION, MEASURE, MEAN, keys, Cumulative.create())) + View.create(NAME, DESCRIPTION, MEASURE, MEAN, keys, Cumulative.create()), + View.create(NAME, DESCRIPTION, MEASURE, MEAN, keys, Cumulative.create())) .addEqualityGroup( - View.create( - NAME, DESCRIPTION + 2, MEASURE, MEAN, keys, Cumulative.create())) + View.create(NAME, DESCRIPTION + 2, MEASURE, MEAN, keys, Cumulative.create())) .addEqualityGroup( - View.create( - NAME, DESCRIPTION, MEASURE, MEAN, keys, Interval.create(MINUTE)), - View.create( - NAME, DESCRIPTION, MEASURE, MEAN, keys, Interval.create(MINUTE))) + View.create(NAME, DESCRIPTION, MEASURE, MEAN, keys, Interval.create(MINUTE)), + View.create(NAME, DESCRIPTION, MEASURE, MEAN, keys, Interval.create(MINUTE))) .addEqualityGroup( - View.create( - NAME, DESCRIPTION, MEASURE, MEAN, keys, Interval.create(TWO_MINUTES))) + View.create(NAME, DESCRIPTION, MEASURE, MEAN, keys, Interval.create(TWO_MINUTES))) .testEquals(); } @@ -142,16 +133,15 @@ public final class ViewTest { @Test public void testViewNameEquals() { new EqualsTester() - .addEqualityGroup( - View.Name.create("view-1"), View.Name.create("view-1")) + .addEqualityGroup(View.Name.create("view-1"), View.Name.create("view-1")) .addEqualityGroup(View.Name.create("view-2")) .testEquals(); } private static final View.Name NAME = View.Name.create("test-view-name"); private static final String DESCRIPTION = "test-view-name description"; - private static final Measure MEASURE = Measure.MeasureDouble.create( - "measure", "measure description", "1"); + private static final Measure MEASURE = + Measure.MeasureDouble.create("measure", "measure description", "1"); private static final TagKey FOO = TagKey.create("foo"); private static final TagKey BAR = TagKey.create("bar"); private static final List keys = ImmutableList.of(FOO, BAR); diff --git a/api/src/test/java/io/opencensus/tags/InternalUtilsTest.java b/api/src/test/java/io/opencensus/tags/InternalUtilsTest.java index db5a2d9d..65482de1 100644 --- a/api/src/test/java/io/opencensus/tags/InternalUtilsTest.java +++ b/api/src/test/java/io/opencensus/tags/InternalUtilsTest.java @@ -31,9 +31,7 @@ public final class InternalUtilsTest { @Test public void getTags() { final Iterator iterator = - Lists.newArrayList( - Tag.create(TagKey.create("k"), TagValue.create("v"))) - .iterator(); + Lists.newArrayList(Tag.create(TagKey.create("k"), TagValue.create("v"))).iterator(); TagContext ctx = new TagContext() { @Override diff --git a/api/src/test/java/io/opencensus/tags/TagContextTest.java b/api/src/test/java/io/opencensus/tags/TagContextTest.java index 0e229323..813e1a76 100644 --- a/api/src/test/java/io/opencensus/tags/TagContextTest.java +++ b/api/src/test/java/io/opencensus/tags/TagContextTest.java @@ -30,10 +30,8 @@ import org.junit.runners.JUnit4; /** Tests for {@link TagContext}. */ @RunWith(JUnit4.class) public final class TagContextTest { - private static final Tag TAG1 = - Tag.create(TagKey.create("key"), TagValue.create("val")); - private static final Tag TAG2 = - Tag.create(TagKey.create("key2"), TagValue.create("val")); + private static final Tag TAG1 = Tag.create(TagKey.create("key"), TagValue.create("val")); + private static final Tag TAG2 = Tag.create(TagKey.create("key2"), TagValue.create("val")); @Test public void equals_IgnoresTagOrderAndTagContextClass() { diff --git a/api/src/test/java/io/opencensus/tags/TagTest.java b/api/src/test/java/io/opencensus/tags/TagTest.java index f3fe6dc4..3c899e65 100644 --- a/api/src/test/java/io/opencensus/tags/TagTest.java +++ b/api/src/test/java/io/opencensus/tags/TagTest.java @@ -39,10 +39,8 @@ public final class TagTest { .addEqualityGroup( Tag.create(TagKey.create("Key"), TagValue.create("foo")), Tag.create(TagKey.create("Key"), TagValue.create("foo"))) - .addEqualityGroup( - Tag.create(TagKey.create("Key"), TagValue.create("bar"))) - .addEqualityGroup( - Tag.create(TagKey.create("Key2"), TagValue.create("foo"))) + .addEqualityGroup(Tag.create(TagKey.create("Key"), TagValue.create("bar"))) + .addEqualityGroup(Tag.create(TagKey.create("Key2"), TagValue.create("foo"))) .testEquals(); } } diff --git a/api/src/test/java/io/opencensus/trace/AttributeValueTest.java b/api/src/test/java/io/opencensus/trace/AttributeValueTest.java index 01226d1b..b7e0afbd 100644 --- a/api/src/test/java/io/opencensus/trace/AttributeValueTest.java +++ b/api/src/test/java/io/opencensus/trace/AttributeValueTest.java @@ -53,7 +53,8 @@ public class AttributeValueTest { fail("Expected a String"); return null; } - }, Functions.throwIllegalArgumentException()); + }, + Functions.throwIllegalArgumentException()); } @Test @@ -80,7 +81,8 @@ public class AttributeValueTest { fail("Expected a Boolean"); return null; } - }, Functions.throwIllegalArgumentException()); + }, + Functions.throwIllegalArgumentException()); } @Test @@ -107,7 +109,8 @@ public class AttributeValueTest { assertThat(longValue).isEqualTo(123456L); return null; } - }, Functions.throwIllegalArgumentException()); + }, + Functions.throwIllegalArgumentException()); } @Test -- cgit v1.2.3 From cf49958f7ccd82cd801aca6f8ac87367e0d2ce36 Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Fri, 3 Nov 2017 17:25:48 +0100 Subject: No-op: Context.Key#get() is the same as Context.Key#get(Context.current()). (#776) * Context.Key#get() is the same as Context.Key#get(Context.current()). * Context.Key#get() is the same as Context.Key#get(Context.current()). --- api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java index dbbe3a33..291de53a 100644 --- a/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java +++ b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java @@ -31,7 +31,7 @@ final class CurrentSpanUtils { * @return The {@code Span} from the current context. */ static Span getCurrentSpan() { - return ContextUtils.CONTEXT_SPAN_KEY.get(Context.current()); + return ContextUtils.CONTEXT_SPAN_KEY.get(); } /** -- cgit v1.2.3 From 4833413b2a0e4fa6e4d4b7279f0b28e7e3479a56 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Tue, 7 Nov 2017 15:32:38 +1100 Subject: Add a setStatus method in the Span. (#779) * Add a setStatus method in the Span. * Update after feedback. * Run ./gradlew goJF * Update comment in EndSpanOptions. --- .../main/java/io/opencensus/trace/BlankSpan.java | 3 +++ .../java/io/opencensus/trace/EndSpanOptions.java | 25 +++++++++------------- api/src/main/java/io/opencensus/trace/Span.java | 18 +++++++++++++++- .../java/io/opencensus/trace/BlankSpanTest.java | 1 + .../io/opencensus/trace/EndSpanOptionsTest.java | 15 +++++++------ 5 files changed, 39 insertions(+), 23 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/BlankSpan.java b/api/src/main/java/io/opencensus/trace/BlankSpan.java index fcb3e546..0c35a885 100644 --- a/api/src/main/java/io/opencensus/trace/BlankSpan.java +++ b/api/src/main/java/io/opencensus/trace/BlankSpan.java @@ -58,6 +58,9 @@ public final class BlankSpan extends Span { @Override public void addLink(Link link) {} + @Override + public void setStatus(Status status) {} + /** No-op implementation of the {@link Span#end(EndSpanOptions)} method. */ @Override public void end(EndSpanOptions options) {} diff --git a/api/src/main/java/io/opencensus/trace/EndSpanOptions.java b/api/src/main/java/io/opencensus/trace/EndSpanOptions.java index 4323ffa8..10952e8a 100644 --- a/api/src/main/java/io/opencensus/trace/EndSpanOptions.java +++ b/api/src/main/java/io/opencensus/trace/EndSpanOptions.java @@ -16,11 +16,10 @@ package io.opencensus.trace; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.auto.value.AutoValue; import io.opencensus.common.ExperimentalApi; import java.util.Collection; +import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; /** @@ -39,9 +38,7 @@ public abstract class EndSpanOptions { * @return a new {@code Builder} with default options. */ public static Builder builder() { - return new AutoValue_EndSpanOptions.Builder() - .setStatus(Status.OK) - .setSampleToLocalSpanStore(false); + return new AutoValue_EndSpanOptions.Builder().setSampleToLocalSpanStore(false); } /** @@ -53,7 +50,8 @@ public abstract class EndSpanOptions { * io.opencensus.trace.export.SampledSpanStore#registerSpanNamesForCollection(Collection)} API * instead. * - * @return this. + * @return {@code true} if the name of the {@code Span} should be registered to the {@code + * io.opencensus.trace.export.SampledSpanStore}. */ @ExperimentalApi public abstract boolean getSampleToLocalSpanStore(); @@ -61,8 +59,12 @@ public abstract class EndSpanOptions { /** * Returns the status. * + *

    If {@code null} then the {@link Span} will record the {@link Status} set via {@link + * Span#setStatus(Status)} or the default {@link Status#OK} if no status was set. + * * @return the status. */ + @Nullable public abstract Status getStatus(); /** Builder class for {@link EndSpanOptions}. */ @@ -71,7 +73,7 @@ public abstract class EndSpanOptions { /** * Sets the status for the {@link Span}. * - *

    If set, this will override the default {@code Span} status. Default is {@link Status#OK}. + *

    If set, this will override the status set via {@link Span#setStatus(Status)}. * * @param status the status. * @return this. @@ -95,19 +97,12 @@ public abstract class EndSpanOptions { @ExperimentalApi public abstract Builder setSampleToLocalSpanStore(boolean sampleToLocalSpanStore); - abstract EndSpanOptions autoBuild(); // not public - /** * Builds and returns a {@code EndSpanOptions} with the desired settings. * * @return a {@code EndSpanOptions} with the desired settings. - * @throws NullPointerException if {@code status} is {@code null}. */ - public EndSpanOptions build() { - EndSpanOptions endSpanOptions = autoBuild(); - checkNotNull(endSpanOptions.getStatus(), "status"); - return endSpanOptions; - } + public abstract EndSpanOptions build(); Builder() {} } diff --git a/api/src/main/java/io/opencensus/trace/Span.java b/api/src/main/java/io/opencensus/trace/Span.java index 3ede6686..ec39f5c4 100644 --- a/api/src/main/java/io/opencensus/trace/Span.java +++ b/api/src/main/java/io/opencensus/trace/Span.java @@ -126,7 +126,7 @@ public abstract class Span { * * @param description the description of the annotation time event. * @param attributes the attributes that will be added; these are associated with this annotation, - * not the {@code Span} as for {@link #addAttributes(Map)}. + * not the {@code Span} as for {@link #putAttributes(Map)}. */ public abstract void addAnnotation(String description, Map attributes); @@ -157,6 +157,22 @@ public abstract class Span { */ public abstract void addLink(Link link); + /** + * Sets the {@link Status} to the {@code Span}. + * + *

    If used, this will override the default {@code Span} status. Default is {@link Status#OK}. + * + *

    Only the value of the last call will be recorded, and implementations are free to ignore + * previous calls. If the status is set via {@link EndSpanOptions.Builder#setStatus(Status)} that + * will always be the last call. + * + * @param status the {@link Status} to set. + */ + public void setStatus(Status status) { + // Implemented as no-op for backwards compatibility (for example gRPC extends Span in tests). + // Implementation must override this method. + } + /** * Marks the end of {@code Span} execution with the given options. * diff --git a/api/src/test/java/io/opencensus/trace/BlankSpanTest.java b/api/src/test/java/io/opencensus/trace/BlankSpanTest.java index 4e8342e2..b9760c2f 100644 --- a/api/src/test/java/io/opencensus/trace/BlankSpanTest.java +++ b/api/src/test/java/io/opencensus/trace/BlankSpanTest.java @@ -55,6 +55,7 @@ public class BlankSpanTest { BlankSpan.INSTANCE.addNetworkEvent(NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).build()); BlankSpan.INSTANCE.addLink( Link.fromSpanContext(SpanContext.INVALID, Link.Type.CHILD_LINKED_SPAN)); + BlankSpan.INSTANCE.setStatus(Status.OK); BlankSpan.INSTANCE.end(EndSpanOptions.DEFAULT); BlankSpan.INSTANCE.end(); } diff --git a/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java b/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java index cae21064..b6ab8e0e 100644 --- a/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java +++ b/api/src/test/java/io/opencensus/trace/EndSpanOptionsTest.java @@ -26,19 +26,20 @@ import org.junit.runners.JUnit4; /** Unit tests for {@link EndSpanOptions}. */ @RunWith(JUnit4.class) public class EndSpanOptionsTest { - @Test(expected = NullPointerException.class) - public void setNullStatus() { - EndSpanOptions.builder().setStatus(null).build(); - } - @Test public void endSpanOptions_DefaultOptions() { - assertThat(EndSpanOptions.DEFAULT.getStatus()).isEqualTo(Status.OK); + assertThat(EndSpanOptions.DEFAULT.getStatus()).isNull(); assertThat(EndSpanOptions.DEFAULT.getSampleToLocalSpanStore()).isFalse(); } @Test - public void setStatus() { + public void setStatus_Ok() { + EndSpanOptions endSpanOptions = EndSpanOptions.builder().setStatus(Status.OK).build(); + assertThat(endSpanOptions.getStatus()).isEqualTo(Status.OK); + } + + @Test + public void setStatus_Error() { EndSpanOptions endSpanOptions = EndSpanOptions.builder() .setStatus(Status.CANCELLED.withDescription("ThisIsAnError")) -- cgit v1.2.3 From 5edd6c2bf4a222bc241edfdb76a22082588d479d Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Tue, 7 Nov 2017 23:17:21 +0100 Subject: Slightly reword Javadoc on SpanBuilder#startScopedSpan. (#788) --- api/src/main/java/io/opencensus/trace/SpanBuilder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java index f27d1bbb..530af97e 100644 --- a/api/src/main/java/io/opencensus/trace/SpanBuilder.java +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -168,8 +168,8 @@ public abstract class SpanBuilder { * Starts a new span and sets it as the {@link Tracer#getCurrentSpan current span}. * *

    Enters the scope of code where the newly created {@code Span} is in the current Context, and - * returns an object that represents that scope. The scope is exited when the returned object is - * closed then the previous Context is restored and the newly created {@code Span} is ended using + * returns an object that represents that scope. When the returned object is closed, the scope is + * exited, the previous Context is restored, and the newly created {@code Span} is ended using * {@link Span#end}. * *

    Supports try-with-resource idiom. -- cgit v1.2.3 From b54b414a098c06022d58d7bd29cc0c547a057433 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Wed, 8 Nov 2017 12:01:49 -0800 Subject: Update Stats implementation to use Stats state (#789) * Add CurrentStatsState * Use stats state for register, record and getView * Throw IllegalStateException when setState is called after getState * Register views and return empty ViewData when Stats is disabled * Disable stats library will clear recorded stats * Re-enable StatsCollectionState will reset MutableViewData. Update CurrentStatsState. * Small updates --- api/src/main/java/io/opencensus/stats/StatsComponent.java | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/StatsComponent.java b/api/src/main/java/io/opencensus/stats/StatsComponent.java index 69fbcb5c..cdcfc3ee 100644 --- a/api/src/main/java/io/opencensus/stats/StatsComponent.java +++ b/api/src/main/java/io/opencensus/stats/StatsComponent.java @@ -35,6 +35,9 @@ public abstract class StatsComponent { *

    When no implementation is available, {@code getState} always returns {@link * StatsCollectionState#DISABLED}. * + *

    Once {@link #getState()} is called, subsequent calls to {@link + * #setState(StatsCollectionState)} will throw an {@code IllegalStateException}. + * * @return the current {@code StatsCollectionState}. */ public abstract StatsCollectionState getState(); @@ -44,6 +47,9 @@ public abstract class StatsComponent { * *

    When no implementation is available, {@code setState} has no effect. * + *

    If state is set to {@link StatsCollectionState#DISABLED}, all stats that are previously + * recorded will be cleared. + * * @param state the new {@code StatsCollectionState}. */ public abstract void setState(StatsCollectionState state); -- cgit v1.2.3 From 80b8b631b47e6db4cd3f543adeb4059b14d3033a Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Wed, 8 Nov 2017 13:00:03 -0800 Subject: Deprecate Tags.setState, and throw an exception when it is called after getState. This commit is related to #608. It deprecates Tags.setState and TagsComponent.setState and makes NoopTagsComponent.setState and TagsComponentImplBase.setState throw IllegalStateException when they are called after getState. --- api/src/main/java/io/opencensus/tags/NoopTags.java | 12 ++++++--- api/src/main/java/io/opencensus/tags/Tags.java | 13 ++++++++-- .../java/io/opencensus/tags/TagsComponent.java | 11 +++++++- .../test/java/io/opencensus/tags/NoopTagsTest.java | 29 +++++++++++++++++++--- api/src/test/java/io/opencensus/tags/TagsTest.java | 2 ++ 5 files changed, 57 insertions(+), 10 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/tags/NoopTags.java b/api/src/main/java/io/opencensus/tags/NoopTags.java index b7c86a2d..973a1b40 100644 --- a/api/src/main/java/io/opencensus/tags/NoopTags.java +++ b/api/src/main/java/io/opencensus/tags/NoopTags.java @@ -26,6 +26,7 @@ import io.opencensus.tags.propagation.TagPropagationComponent; import java.util.Collections; import java.util.Iterator; import javax.annotation.concurrent.Immutable; +import javax.annotation.concurrent.ThreadSafe; /** No-op implementations of tagging classes. */ final class NoopTags { @@ -37,8 +38,8 @@ final class NoopTags { * * @return a {@code TagsComponent} that has a no-op implementation for {@code Tagger}. */ - static TagsComponent getNoopTagsComponent() { - return NoopTagsComponent.INSTANCE; + static TagsComponent newNoopTagsComponent() { + return new NoopTagsComponent(); } /** @@ -81,9 +82,9 @@ final class NoopTags { return NoopTagContextBinarySerializer.INSTANCE; } - @Immutable + @ThreadSafe private static final class NoopTagsComponent extends TagsComponent { - static final TagsComponent INSTANCE = new NoopTagsComponent(); + private volatile boolean isRead; @Override public Tagger getTagger() { @@ -97,12 +98,15 @@ final class NoopTags { @Override public TaggingState getState() { + isRead = true; return TaggingState.DISABLED; } @Override + @Deprecated public void setState(TaggingState state) { Preconditions.checkNotNull(state, "state"); + Preconditions.checkState(!isRead, "State was already read, cannot set state."); } } diff --git a/api/src/main/java/io/opencensus/tags/Tags.java b/api/src/main/java/io/opencensus/tags/Tags.java index 5378fa5a..8772e8ec 100644 --- a/api/src/main/java/io/opencensus/tags/Tags.java +++ b/api/src/main/java/io/opencensus/tags/Tags.java @@ -55,6 +55,9 @@ public final class Tags { *

    When no implementation is available, {@code getState} always returns {@link * TaggingState#DISABLED}. * + *

    Once {@link #getState()} is called, subsequent calls to {@link #setState(TaggingState)} will + * throw an {@code IllegalStateException}. + * * @return the current {@code TaggingState}. */ public static TaggingState getState() { @@ -64,10 +67,16 @@ public final class Tags { /** * Sets the current {@code TaggingState}. * - *

    When no implementation is available, {@code setState} has no effect. + *

    When no implementation is available, {@code setState} does not change the state. * * @param state the new {@code TaggingState}. + * @throws IllegalStateException if {@link #getState()} was previously called. + * @deprecated This method is deprecated because other libraries could cache the result of {@link + * #getState()}, use a stale value, and behave incorrectly. It is only safe to call early in + * initialization. This method throws {@link IllegalStateException} after {@link #getState()} + * has been called, in order to prevent the result of {@code getState()} from changing. */ + @Deprecated public static void setState(TaggingState state) { tagsComponent.setState(state); } @@ -99,6 +108,6 @@ public final class Tags { + "default implementation for TagsComponent.", e); } - return NoopTags.getNoopTagsComponent(); + return NoopTags.newNoopTagsComponent(); } } diff --git a/api/src/main/java/io/opencensus/tags/TagsComponent.java b/api/src/main/java/io/opencensus/tags/TagsComponent.java index 755173d8..076fe48d 100644 --- a/api/src/main/java/io/opencensus/tags/TagsComponent.java +++ b/api/src/main/java/io/opencensus/tags/TagsComponent.java @@ -37,6 +37,9 @@ public abstract class TagsComponent { *

    When no implementation is available, {@code getState} always returns {@link * TaggingState#DISABLED}. * + *

    Once {@link #getState()} is called, subsequent calls to {@link #setState(TaggingState)} will + * throw an {@code IllegalStateException}. + * * @return the current {@code TaggingState}. */ public abstract TaggingState getState(); @@ -44,9 +47,15 @@ public abstract class TagsComponent { /** * Sets the current {@code TaggingState}. * - *

    When no implementation is available, {@code setState} has no effect. + *

    When no implementation is available, {@code setState} does not change the state. * * @param state the new {@code TaggingState}. + * @throws IllegalStateException if {@link #getState()} was previously called. + * @deprecated This method is deprecated because other libraries could cache the result of {@link + * #getState()}, use a stale value, and behave incorrectly. It is only safe to call early in + * initialization. This method throws {@link IllegalStateException} after {@code getState()} + * has been called, in order to prevent the result of {@code getState()} from changing. */ + @Deprecated public abstract void setState(TaggingState state); } diff --git a/api/src/test/java/io/opencensus/tags/NoopTagsTest.java b/api/src/test/java/io/opencensus/tags/NoopTagsTest.java index 8434bd83..db07520e 100644 --- a/api/src/test/java/io/opencensus/tags/NoopTagsTest.java +++ b/api/src/test/java/io/opencensus/tags/NoopTagsTest.java @@ -50,18 +50,41 @@ public final class NoopTagsTest { @Test public void noopTagsComponent() { - assertThat(NoopTags.getNoopTagsComponent().getTagger()).isSameAs(NoopTags.getNoopTagger()); - assertThat(NoopTags.getNoopTagsComponent().getTagPropagationComponent()) + assertThat(NoopTags.newNoopTagsComponent().getTagger()).isSameAs(NoopTags.getNoopTagger()); + assertThat(NoopTags.newNoopTagsComponent().getTagPropagationComponent()) .isSameAs(NoopTags.getNoopTagPropagationComponent()); } @Test + @SuppressWarnings("deprecation") public void noopTagsComponent_SetState_DisallowsNull() { - TagsComponent noopTagsComponent = NoopTags.getNoopTagsComponent(); + TagsComponent noopTagsComponent = NoopTags.newNoopTagsComponent(); thrown.expect(NullPointerException.class); noopTagsComponent.setState(null); } + @Test + @SuppressWarnings("deprecation") + public void preventSettingStateAfterGettingState_DifferentState() { + TagsComponent noopTagsComponent = NoopTags.newNoopTagsComponent(); + noopTagsComponent.setState(TaggingState.DISABLED); + noopTagsComponent.getState(); + thrown.expect(IllegalStateException.class); + thrown.expectMessage("State was already read, cannot set state."); + noopTagsComponent.setState(TaggingState.ENABLED); + } + + @Test + @SuppressWarnings("deprecation") + public void preventSettingStateAfterGettingState_SameState() { + TagsComponent noopTagsComponent = NoopTags.newNoopTagsComponent(); + noopTagsComponent.setState(TaggingState.DISABLED); + noopTagsComponent.getState(); + thrown.expect(IllegalStateException.class); + thrown.expectMessage("State was already read, cannot set state."); + noopTagsComponent.setState(TaggingState.DISABLED); + } + @Test public void noopTagger() { Tagger noopTagger = NoopTags.getNoopTagger(); diff --git a/api/src/test/java/io/opencensus/tags/TagsTest.java b/api/src/test/java/io/opencensus/tags/TagsTest.java index e87407db..5cab5b45 100644 --- a/api/src/test/java/io/opencensus/tags/TagsTest.java +++ b/api/src/test/java/io/opencensus/tags/TagsTest.java @@ -62,12 +62,14 @@ public class TagsTest { } @Test + @SuppressWarnings("deprecation") public void setState_IgnoresInput() { Tags.setState(TaggingState.ENABLED); assertThat(Tags.getState()).isEqualTo(TaggingState.DISABLED); } @Test(expected = NullPointerException.class) + @SuppressWarnings("deprecation") public void setState_DisallowsNull() { Tags.setState(null); } -- cgit v1.2.3 From 6cbf3adbc630774b341cd7958ceed8140696e71f Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Wed, 8 Nov 2017 14:45:46 -0800 Subject: Combine tests for Tags.getState and Tags.setState. These tests modify global state, so combining them into a single test prevents any order-dependent behavior. --- api/src/test/java/io/opencensus/tags/TagsTest.java | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'api') diff --git a/api/src/test/java/io/opencensus/tags/TagsTest.java b/api/src/test/java/io/opencensus/tags/TagsTest.java index 5cab5b45..dee517b6 100644 --- a/api/src/test/java/io/opencensus/tags/TagsTest.java +++ b/api/src/test/java/io/opencensus/tags/TagsTest.java @@ -56,22 +56,20 @@ public class TagsTest { .isEqualTo("io.opencensus.tags.NoopTags$NoopTagsComponent"); } - @Test - public void getState() { - assertThat(Tags.getState()).isEqualTo(TaggingState.DISABLED); - } - + // There is only one test that modifies tagging state in the Tags class, since the state is + // global, and it could affect other tests. NoopTagsTest has more thorough tests for tagging + // state. @Test @SuppressWarnings("deprecation") - public void setState_IgnoresInput() { + public void testState() { + // Test that setState ignores its input. Tags.setState(TaggingState.ENABLED); assertThat(Tags.getState()).isEqualTo(TaggingState.DISABLED); - } - @Test(expected = NullPointerException.class) - @SuppressWarnings("deprecation") - public void setState_DisallowsNull() { - Tags.setState(null); + // Test that setState cannot be called after getState. + thrown.expect(IllegalStateException.class); + thrown.expectMessage("State was already read, cannot set state."); + Tags.setState(TaggingState.ENABLED); } @Test -- cgit v1.2.3 From 7102022573c6e1c0e215ad1fccf8b1ec1d36818a Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Fri, 10 Nov 2017 12:30:23 -0800 Subject: Avoid guaranteeing that the result of Tags.getState() won't change. --- api/src/main/java/io/opencensus/tags/Tags.java | 2 +- api/src/main/java/io/opencensus/tags/TagsComponent.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/tags/Tags.java b/api/src/main/java/io/opencensus/tags/Tags.java index 8772e8ec..593312ae 100644 --- a/api/src/main/java/io/opencensus/tags/Tags.java +++ b/api/src/main/java/io/opencensus/tags/Tags.java @@ -74,7 +74,7 @@ public final class Tags { * @deprecated This method is deprecated because other libraries could cache the result of {@link * #getState()}, use a stale value, and behave incorrectly. It is only safe to call early in * initialization. This method throws {@link IllegalStateException} after {@link #getState()} - * has been called, in order to prevent the result of {@code getState()} from changing. + * has been called, in order to limit changes to the result of {@code getState()}. */ @Deprecated public static void setState(TaggingState state) { diff --git a/api/src/main/java/io/opencensus/tags/TagsComponent.java b/api/src/main/java/io/opencensus/tags/TagsComponent.java index 076fe48d..b0965077 100644 --- a/api/src/main/java/io/opencensus/tags/TagsComponent.java +++ b/api/src/main/java/io/opencensus/tags/TagsComponent.java @@ -54,7 +54,7 @@ public abstract class TagsComponent { * @deprecated This method is deprecated because other libraries could cache the result of {@link * #getState()}, use a stale value, and behave incorrectly. It is only safe to call early in * initialization. This method throws {@link IllegalStateException} after {@code getState()} - * has been called, in order to prevent the result of {@code getState()} from changing. + * has been called, in order to limit changes to the result of {@code getState()}. */ @Deprecated public abstract void setState(TaggingState state); -- cgit v1.2.3 From 23be8f0f3228c5c1142291a0dd779666793f47b6 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Fri, 10 Nov 2017 15:01:23 -0800 Subject: Revert "Use the current release version of Mockito. (#751)" This reverts commit 3f946d748ea171c70c297cf3188e4b0dbadab1ad. Reverting due to integration issues. --- api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java | 2 +- api/src/test/java/io/opencensus/trace/SpanTest.java | 4 ++-- api/src/test/java/io/opencensus/trace/TracerTest.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'api') diff --git a/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java b/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java index 36c8865d..a8c18819 100644 --- a/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java +++ b/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java @@ -17,7 +17,7 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Matchers.same; import static org.mockito.Mockito.verify; import io.opencensus.common.Scope; diff --git a/api/src/test/java/io/opencensus/trace/SpanTest.java b/api/src/test/java/io/opencensus/trace/SpanTest.java index 5fce242e..327b9abe 100644 --- a/api/src/test/java/io/opencensus/trace/SpanTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanTest.java @@ -17,8 +17,8 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.same; import static org.mockito.Mockito.verify; import java.util.Collections; diff --git a/api/src/test/java/io/opencensus/trace/TracerTest.java b/api/src/test/java/io/opencensus/trace/TracerTest.java index 4edf377d..7c65742e 100644 --- a/api/src/test/java/io/opencensus/trace/TracerTest.java +++ b/api/src/test/java/io/opencensus/trace/TracerTest.java @@ -17,7 +17,7 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Matchers.same; import static org.mockito.Mockito.when; import io.grpc.Context; -- cgit v1.2.3 From ba78379bcf98d4a5a1ee7a3230b5a25f27356edf Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Fri, 10 Nov 2017 18:28:44 -0800 Subject: com.google.errorprone:error_prone_core: 2.0.19 -> 2.1.2 Other changes: - Remove references to warnings that were removed from Error Prone. - Suppress occurrences of a new warning, JdkObsolete. All of the warnings are about uses of LinkedList. We need to decide whether to use a different class or continue suppressing the warnings. I left TODOs, since each occurrence may need to be handled differently. --- api/src/test/java/io/opencensus/trace/export/SpanDataTest.java | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'api') diff --git a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java index cb962121..ab8d8067 100644 --- a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java +++ b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java @@ -68,11 +68,21 @@ public class SpanDataTest { TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); private final SpanId parentSpanId = SpanId.generateRandomId(random); private final Map attributesMap = new HashMap(); + + // TODO: Decide whether to use a different class instead of LinkedList. + @SuppressWarnings("JdkObsolete") private final List> annotationsList = new LinkedList>(); + + // TODO: Decide whether to use a different class instead of LinkedList. + @SuppressWarnings("JdkObsolete") private final List> networkEventsList = new LinkedList>(); + + // TODO: Decide whether to use a different class instead of LinkedList. + @SuppressWarnings("JdkObsolete") private final List linksList = new LinkedList(); + private Attributes attributes; private TimedEvents annotations; private TimedEvents networkEvents; -- cgit v1.2.3 From 68bc92e4b11118919f623e9bda0284cee748a11a Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Sat, 11 Nov 2017 00:55:02 -0800 Subject: Use ArrayList instead of LinkedList in SpanDataTest.java to fix warning. --- .../java/io/opencensus/trace/export/SpanDataTest.java | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'api') diff --git a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java index ab8d8067..5c8097fa 100644 --- a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java +++ b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java @@ -34,9 +34,9 @@ import io.opencensus.trace.export.SpanData.Attributes; import io.opencensus.trace.export.SpanData.Links; import io.opencensus.trace.export.SpanData.TimedEvent; import io.opencensus.trace.export.SpanData.TimedEvents; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Random; @@ -68,20 +68,11 @@ public class SpanDataTest { TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); private final SpanId parentSpanId = SpanId.generateRandomId(random); private final Map attributesMap = new HashMap(); - - // TODO: Decide whether to use a different class instead of LinkedList. - @SuppressWarnings("JdkObsolete") private final List> annotationsList = - new LinkedList>(); - - // TODO: Decide whether to use a different class instead of LinkedList. - @SuppressWarnings("JdkObsolete") + new ArrayList>(); private final List> networkEventsList = - new LinkedList>(); - - // TODO: Decide whether to use a different class instead of LinkedList. - @SuppressWarnings("JdkObsolete") - private final List linksList = new LinkedList(); + new ArrayList>(); + private final List linksList = new ArrayList(); private Attributes attributes; private TimedEvents annotations; -- cgit v1.2.3 From e898e0388d04b91083ff8b63172fa075ec3ce13a Mon Sep 17 00:00:00 2001 From: Yang Song Date: Mon, 13 Nov 2017 16:57:16 -0800 Subject: Deprecate Stats.setState, and throw an exception when it is called after getState. (#792) * Throw IllegalStateException if setState is called after getState * Deprecate Stats.setState * Remove a test that has potential race condition. * Remove Deprecated from impl --- api/src/main/java/io/opencensus/stats/NoopStats.java | 5 +++++ api/src/main/java/io/opencensus/stats/Stats.java | 14 +++++++++++++- api/src/main/java/io/opencensus/stats/StatsComponent.java | 8 +++++++- api/src/test/java/io/opencensus/stats/NoopStatsTest.java | 13 +++++++++++++ api/src/test/java/io/opencensus/stats/StatsTest.java | 6 +++++- 5 files changed, 43 insertions(+), 3 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/NoopStats.java b/api/src/main/java/io/opencensus/stats/NoopStats.java index a016e2e9..ac9329f6 100644 --- a/api/src/main/java/io/opencensus/stats/NoopStats.java +++ b/api/src/main/java/io/opencensus/stats/NoopStats.java @@ -18,6 +18,7 @@ package io.opencensus.stats; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; import com.google.common.base.Preconditions; import com.google.common.collect.Maps; @@ -83,6 +84,7 @@ final class NoopStats { @ThreadSafe private static final class NoopStatsComponent extends StatsComponent { private final ViewManager viewManager = newNoopViewManager(); + private volatile boolean isRead; @Override public ViewManager getViewManager() { @@ -96,12 +98,15 @@ final class NoopStats { @Override public StatsCollectionState getState() { + isRead = true; return StatsCollectionState.DISABLED; } @Override + @Deprecated public void setState(StatsCollectionState state) { Preconditions.checkNotNull(state, "state"); + checkState(!isRead, "State was already read, cannot set state."); } } diff --git a/api/src/main/java/io/opencensus/stats/Stats.java b/api/src/main/java/io/opencensus/stats/Stats.java index 016455e9..3bc78640 100644 --- a/api/src/main/java/io/opencensus/stats/Stats.java +++ b/api/src/main/java/io/opencensus/stats/Stats.java @@ -44,6 +44,9 @@ public final class Stats { *

    When no implementation is available, {@code getState} always returns {@link * StatsCollectionState#DISABLED}. * + *

    Once {@link #getState()} is called, subsequent calls to {@link + * #setState(StatsCollectionState)} will throw an {@code IllegalStateException}. + * * @return the current {@code StatsCollectionState}. */ public static StatsCollectionState getState() { @@ -53,10 +56,19 @@ public final class Stats { /** * Sets the current {@code StatsCollectionState}. * - *

    When no implementation is available, {@code setState} has no effect. + *

    When no implementation is available, {@code setState} does not change the state. + * + *

    If state is set to {@link StatsCollectionState#DISABLED}, all stats that are previously + * recorded will be cleared. * * @param state the new {@code StatsCollectionState}. + * @throws IllegalStateException if {@link #getState()} was previously called. + * @deprecated This method is deprecated because other libraries could cache the result of {@link + * #getState()}, use a stale value, and behave incorrectly. It is only safe to call early in + * initialization. This method throws {@link IllegalStateException} after {@code getState()} + * has been called, in order to prevent the result of {@code getState()} from changing. */ + @Deprecated public static void setState(StatsCollectionState state) { statsComponent.setState(state); } diff --git a/api/src/main/java/io/opencensus/stats/StatsComponent.java b/api/src/main/java/io/opencensus/stats/StatsComponent.java index cdcfc3ee..30f56a91 100644 --- a/api/src/main/java/io/opencensus/stats/StatsComponent.java +++ b/api/src/main/java/io/opencensus/stats/StatsComponent.java @@ -45,12 +45,18 @@ public abstract class StatsComponent { /** * Sets the current {@code StatsCollectionState}. * - *

    When no implementation is available, {@code setState} has no effect. + *

    When no implementation is available, {@code setState} does not change the state. * *

    If state is set to {@link StatsCollectionState#DISABLED}, all stats that are previously * recorded will be cleared. * * @param state the new {@code StatsCollectionState}. + * @throws IllegalStateException if {@link #getState()} was previously called. + * @deprecated This method is deprecated because other libraries could cache the result of {@link + * #getState()}, use a stale value, and behave incorrectly. It is only safe to call early in + * initialization. This method throws {@link IllegalStateException} after {@code getState()} + * has been called, in order to prevent the result of {@code getState()} from changing. */ + @Deprecated public abstract void setState(StatsCollectionState state); } diff --git a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java index 9a52b7db..b3f81715 100644 --- a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java +++ b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java @@ -67,6 +67,7 @@ public final class NoopStatsTest { } @Test + @SuppressWarnings("deprecation") public void noopStatsComponent_SetState_IgnoresInput() { StatsComponent noopStatsComponent = NoopStats.newNoopStatsComponent(); noopStatsComponent.setState(StatsCollectionState.ENABLED); @@ -74,12 +75,24 @@ public final class NoopStatsTest { } @Test + @SuppressWarnings("deprecation") public void noopStatsComponent_SetState_DisallowsNull() { StatsComponent noopStatsComponent = NoopStats.newNoopStatsComponent(); thrown.expect(NullPointerException.class); noopStatsComponent.setState(null); } + @Test + @SuppressWarnings("deprecation") + public void noopStatsComponent_DisallowsSetStateAfterGetState() { + StatsComponent noopStatsComponent = NoopStats.newNoopStatsComponent(); + noopStatsComponent.setState(StatsCollectionState.DISABLED); + noopStatsComponent.getState(); + thrown.expect(IllegalStateException.class); + thrown.expectMessage("State was already read, cannot set state."); + noopStatsComponent.setState(StatsCollectionState.ENABLED); + } + // The NoopStatsRecorder should do nothing, so this test just checks that record doesn't throw an // exception. @Test diff --git a/api/src/test/java/io/opencensus/stats/StatsTest.java b/api/src/test/java/io/opencensus/stats/StatsTest.java index cc60d6c0..4219173a 100644 --- a/api/src/test/java/io/opencensus/stats/StatsTest.java +++ b/api/src/test/java/io/opencensus/stats/StatsTest.java @@ -69,13 +69,17 @@ public final class StatsTest { } @Test + @SuppressWarnings("deprecation") public void setState_IgnoresInput() { Stats.setState(StatsCollectionState.ENABLED); assertThat(Stats.getState()).isEqualTo(StatsCollectionState.DISABLED); } - @Test(expected = NullPointerException.class) + @Test + @SuppressWarnings("deprecation") public void setState_DisallowsNull() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("state"); Stats.setState(null); } } -- cgit v1.2.3 From c80a523e367669067729854ec0996a504c96f68e Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Mon, 13 Nov 2017 19:53:05 -0800 Subject: Hide constructor of io.opencensus.common.OpenCensusLibraryInformation. This class is a public utility class, and it shouldn't be instantiated. --- .../main/java/io/opencensus/common/OpenCensusLibraryInformation.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java index aa5d69d5..91771644 100644 --- a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java +++ b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java @@ -22,4 +22,6 @@ public final class OpenCensusLibraryInformation { /** The current version of the OpenCensus Java library. */ public static final String VERSION = "0.9.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION + + private OpenCensusLibraryInformation() {} } -- cgit v1.2.3 From 8b849436310c298b3293211f748f3bb6d227ff63 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Mon, 13 Nov 2017 18:57:32 -0800 Subject: Enable PrivateConstructorForUtilityClass Error Prone warning. This commit also adds some private constructors to utility and example classes. --- api/src/main/java/io/opencensus/common/TimeUtil.java | 2 ++ api/src/main/java/io/opencensus/internal/Provider.java | 1 + 2 files changed, 3 insertions(+) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/TimeUtil.java b/api/src/main/java/io/opencensus/common/TimeUtil.java index ab64c5df..09b3ddf9 100644 --- a/api/src/main/java/io/opencensus/common/TimeUtil.java +++ b/api/src/main/java/io/opencensus/common/TimeUtil.java @@ -23,4 +23,6 @@ final class TimeUtil { static final long MILLIS_PER_SECOND = 1000L; static final long NANOS_PER_MILLI = 1000 * 1000; static final long NANOS_PER_SECOND = NANOS_PER_MILLI * MILLIS_PER_SECOND; + + private TimeUtil() {} } diff --git a/api/src/main/java/io/opencensus/internal/Provider.java b/api/src/main/java/io/opencensus/internal/Provider.java index 25cb82b0..8cfb7294 100644 --- a/api/src/main/java/io/opencensus/internal/Provider.java +++ b/api/src/main/java/io/opencensus/internal/Provider.java @@ -28,6 +28,7 @@ import java.util.ServiceConfigurationError; * } */ public final class Provider { + private Provider() {} /** * Tries to create an instance of the given rawClass as a subclass of the given superclass. -- cgit v1.2.3 From c39d244ca356ee2bbbb9a2eaf7323d3d468dbee7 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Mon, 13 Nov 2017 19:01:47 -0800 Subject: Enable new ReturnMissingNullable Error Prone experimental suggestion. I also added some missing Nullable annotations. --- api/src/main/java/io/opencensus/stats/NoopStats.java | 2 ++ api/src/test/java/io/opencensus/tags/TagContextTest.java | 2 ++ api/src/test/java/io/opencensus/trace/AttributeValueTest.java | 10 ++++++++++ 3 files changed, 14 insertions(+) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/NoopStats.java b/api/src/main/java/io/opencensus/stats/NoopStats.java index a016e2e9..84d2cf86 100644 --- a/api/src/main/java/io/opencensus/stats/NoopStats.java +++ b/api/src/main/java/io/opencensus/stats/NoopStats.java @@ -33,6 +33,7 @@ import io.opencensus.tags.TagValue; import java.util.Collections; import java.util.List; import java.util.Map; +import javax.annotation.Nullable; import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.ThreadSafe; @@ -160,6 +161,7 @@ final class NoopStats { } @Override + @Nullable public ViewData getView(View.Name name) { checkNotNull(name, "name"); synchronized (views) { diff --git a/api/src/test/java/io/opencensus/tags/TagContextTest.java b/api/src/test/java/io/opencensus/tags/TagContextTest.java index 813e1a76..7243720c 100644 --- a/api/src/test/java/io/opencensus/tags/TagContextTest.java +++ b/api/src/test/java/io/opencensus/tags/TagContextTest.java @@ -23,6 +23,7 @@ import com.google.common.testing.EqualsTester; import java.util.Collections; import java.util.Iterator; import java.util.List; +import javax.annotation.Nullable; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -94,6 +95,7 @@ public final class TagContextTest { } @Override + @Nullable protected Iterator getIterator() { return tags == null ? null : tags.iterator(); } diff --git a/api/src/test/java/io/opencensus/trace/AttributeValueTest.java b/api/src/test/java/io/opencensus/trace/AttributeValueTest.java index b7e0afbd..e505c59b 100644 --- a/api/src/test/java/io/opencensus/trace/AttributeValueTest.java +++ b/api/src/test/java/io/opencensus/trace/AttributeValueTest.java @@ -22,6 +22,7 @@ import static org.junit.Assert.fail; import com.google.common.testing.EqualsTester; import io.opencensus.common.Function; import io.opencensus.common.Functions; +import javax.annotation.Nullable; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -35,6 +36,7 @@ public class AttributeValueTest { attribute.match( new Function() { @Override + @Nullable public Object apply(String stringValue) { assertThat(stringValue).isEqualTo("MyStringAttributeValue"); return null; @@ -42,6 +44,7 @@ public class AttributeValueTest { }, new Function() { @Override + @Nullable public Object apply(Boolean booleanValue) { fail("Expected a String"); return null; @@ -49,6 +52,7 @@ public class AttributeValueTest { }, new Function() { @Override + @Nullable public Object apply(Long longValue) { fail("Expected a String"); return null; @@ -63,6 +67,7 @@ public class AttributeValueTest { attribute.match( new Function() { @Override + @Nullable public Object apply(String stringValue) { fail("Expected a Boolean"); return null; @@ -70,6 +75,7 @@ public class AttributeValueTest { }, new Function() { @Override + @Nullable public Object apply(Boolean booleanValue) { assertThat(booleanValue).isTrue(); return null; @@ -77,6 +83,7 @@ public class AttributeValueTest { }, new Function() { @Override + @Nullable public Object apply(Long longValue) { fail("Expected a Boolean"); return null; @@ -91,6 +98,7 @@ public class AttributeValueTest { attribute.match( new Function() { @Override + @Nullable public Object apply(String stringValue) { fail("Expected a Long"); return null; @@ -98,6 +106,7 @@ public class AttributeValueTest { }, new Function() { @Override + @Nullable public Object apply(Boolean booleanValue) { fail("Expected a Long"); return null; @@ -105,6 +114,7 @@ public class AttributeValueTest { }, new Function() { @Override + @Nullable public Object apply(Long longValue) { assertThat(longValue).isEqualTo(123456L); return null; -- cgit v1.2.3 From e086f07b5708ad1ffddbc186cf7965a21e852ba7 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Mon, 13 Nov 2017 19:05:17 -0800 Subject: Update lists of enabled Error Prone warnings with the latest bug patterns. I used the latest list of bug patterns from http://errorprone.info/bugpatterns. I had to turn off FieldMissingNullable because of an Error Prone bug and suppress two instances of other warnings in the code. I removed NonRuntimeAnnotation and ProtocolBufferOrdinal from the list because they were promoted to errors. I also enabled two previously disabled warnings because they seemed to no longer cause any problems in this project. --- api/src/test/java/io/opencensus/tags/TagContextTest.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'api') diff --git a/api/src/test/java/io/opencensus/tags/TagContextTest.java b/api/src/test/java/io/opencensus/tags/TagContextTest.java index 7243720c..b5c44b15 100644 --- a/api/src/test/java/io/opencensus/tags/TagContextTest.java +++ b/api/src/test/java/io/opencensus/tags/TagContextTest.java @@ -86,6 +86,9 @@ public final class TagContextTest { private static final class SimpleTagContext extends TagContext { private final List tags; + // This Error Prone warning doesn't seem correct, because the constructor is just calling + // another constructor. + @SuppressWarnings("ConstructorLeaksThis") SimpleTagContext(Tag... tags) { this(Lists.newArrayList(tags)); } -- cgit v1.2.3 From 1c58c313c0b13d9ef781436572645f699a2c286d Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Wed, 8 Nov 2017 18:03:44 -0800 Subject: Add ViewManager.getAllExportedViews(). This method currently returns all registered cumulative views. We could add a way to specify which views should be exported later. The API is currently needed for the StackDriver exporter. The NoopViewManager also returns all cumulative views. However, the exporter could choose to not export data when stats collection isn't enabled. --- .../main/java/io/opencensus/stats/NoopStats.java | 16 ++++++ .../main/java/io/opencensus/stats/ViewManager.java | 12 +++++ .../io/opencensus/stats/NoopViewManagerTest.java | 63 ++++++++++++++++++++++ 3 files changed, 91 insertions(+) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/NoopStats.java b/api/src/main/java/io/opencensus/stats/NoopStats.java index 55c424c7..c087a19f 100644 --- a/api/src/main/java/io/opencensus/stats/NoopStats.java +++ b/api/src/main/java/io/opencensus/stats/NoopStats.java @@ -22,10 +22,12 @@ import static com.google.common.base.Preconditions.checkState; import com.google.common.base.Preconditions; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import io.opencensus.common.Functions; import io.opencensus.common.Timestamp; import io.opencensus.stats.Measure.MeasureDouble; import io.opencensus.stats.Measure.MeasureLong; +import io.opencensus.stats.View.AggregationWindow; import io.opencensus.stats.ViewData.AggregationWindowData; import io.opencensus.stats.ViewData.AggregationWindowData.CumulativeData; import io.opencensus.stats.ViewData.AggregationWindowData.IntervalData; @@ -34,6 +36,7 @@ import io.opencensus.tags.TagValue; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Set; import javax.annotation.Nullable; import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.Immutable; @@ -187,5 +190,18 @@ final class NoopStats { } } } + + @Override + public Set getAllExportedViews() { + synchronized (views) { + Set exportedViews = Sets.newHashSet(); + for (View view : views.values()) { + if (view.getWindow() instanceof AggregationWindow.Cumulative) { + exportedViews.add(view); + } + } + return Collections.unmodifiableSet(exportedViews); + } + } } } diff --git a/api/src/main/java/io/opencensus/stats/ViewManager.java b/api/src/main/java/io/opencensus/stats/ViewManager.java index f98e8058..a6e18b89 100644 --- a/api/src/main/java/io/opencensus/stats/ViewManager.java +++ b/api/src/main/java/io/opencensus/stats/ViewManager.java @@ -16,6 +16,7 @@ package io.opencensus.stats; +import java.util.Set; import javax.annotation.Nullable; /** @@ -42,4 +43,15 @@ public abstract class ViewManager { */ @Nullable public abstract ViewData getView(View.Name view); + + /** + * Returns all registered views that should be exported. + * + *

    This method should be used by any stats exporter that automatically exports data for views + * registered with the {@link ViewManager}. + * + * @return all registered views that should be exported. + * @since 0.9 + */ + public abstract Set getAllExportedViews(); } diff --git a/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java b/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java index 24d1b14a..4aaa60dc 100644 --- a/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java +++ b/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java @@ -29,6 +29,7 @@ import io.opencensus.stats.ViewData.AggregationWindowData.CumulativeData; import io.opencensus.stats.ViewData.AggregationWindowData.IntervalData; import io.opencensus.tags.TagKey; import java.util.Arrays; +import java.util.Set; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -128,4 +129,66 @@ public final class NoopViewManagerTest { thrown.expect(NullPointerException.class); viewManager.getView(null); } + + @Test + public void getAllExportedViews() { + ViewManager viewManager = NoopStats.newNoopViewManager(); + assertThat(viewManager.getAllExportedViews()).isEmpty(); + View cumulativeView1 = + View.create( + View.Name.create("View 1"), + VIEW_DESCRIPTION, + MEASURE, + AGGREGATION, + Arrays.asList(KEY), + CUMULATIVE); + View cumulativeView2 = + View.create( + View.Name.create("View 2"), + VIEW_DESCRIPTION, + MEASURE, + AGGREGATION, + Arrays.asList(KEY), + CUMULATIVE); + View intervalView = + View.create( + View.Name.create("View 3"), + VIEW_DESCRIPTION, + MEASURE, + AGGREGATION, + Arrays.asList(KEY), + INTERVAL); + viewManager.registerView(cumulativeView1); + viewManager.registerView(cumulativeView2); + viewManager.registerView(intervalView); + + // Only cumulative views should be exported. + assertThat(viewManager.getAllExportedViews()).containsExactly(cumulativeView1, cumulativeView2); + } + + @Test + public void getAllExportedViews_ResultIsUnmodifiable() { + ViewManager viewManager = NoopStats.newNoopViewManager(); + View view1 = + View.create( + View.Name.create("View 1"), + VIEW_DESCRIPTION, + MEASURE, + AGGREGATION, + Arrays.asList(KEY), + CUMULATIVE); + viewManager.registerView(view1); + Set exported = viewManager.getAllExportedViews(); + + View view2 = + View.create( + View.Name.create("View 2"), + VIEW_DESCRIPTION, + MEASURE, + AGGREGATION, + Arrays.asList(KEY), + CUMULATIVE); + thrown.expect(UnsupportedOperationException.class); + exported.add(view2); + } } -- cgit v1.2.3 From 5a2ad707e6a046a4035727ce0d20321839294b03 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 14 Nov 2017 14:16:42 -0800 Subject: Cache the set of views returned from NoopViewManager.getAllExportedViews. --- .../main/java/io/opencensus/stats/NoopStats.java | 43 +++++++++++++++------- 1 file changed, 29 insertions(+), 14 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/NoopStats.java b/api/src/main/java/io/opencensus/stats/NoopStats.java index c087a19f..74f8f660 100644 --- a/api/src/main/java/io/opencensus/stats/NoopStats.java +++ b/api/src/main/java/io/opencensus/stats/NoopStats.java @@ -33,6 +33,7 @@ import io.opencensus.stats.ViewData.AggregationWindowData.CumulativeData; import io.opencensus.stats.ViewData.AggregationWindowData.IntervalData; import io.opencensus.tags.TagContext; import io.opencensus.tags.TagValue; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; @@ -151,19 +152,24 @@ final class NoopStats { private static final class NoopViewManager extends ViewManager { private static final Timestamp ZERO_TIMESTAMP = Timestamp.create(0, 0); - @GuardedBy("views") - private final Map views = Maps.newHashMap(); + @GuardedBy("registeredViews") + private final Map registeredViews = Maps.newHashMap(); + + // Cached set of exported views. It must be set to null whenever a view is registered or + // unregistered. + @Nullable private volatile Set exportedViews; @Override public void registerView(View newView) { checkNotNull(newView, "newView"); - synchronized (views) { - View existing = views.get(newView.getName()); + synchronized (registeredViews) { + exportedViews = null; + View existing = registeredViews.get(newView.getName()); checkArgument( existing == null || newView.equals(existing), "A different view with the same name already exists."); if (existing == null) { - views.put(newView.getName(), newView); + registeredViews.put(newView.getName(), newView); } } } @@ -172,8 +178,8 @@ final class NoopStats { @Nullable public ViewData getView(View.Name name) { checkNotNull(name, "name"); - synchronized (views) { - View view = views.get(name); + synchronized (registeredViews) { + View view = registeredViews.get(name); if (view == null) { return null; } else { @@ -193,15 +199,24 @@ final class NoopStats { @Override public Set getAllExportedViews() { - synchronized (views) { - Set exportedViews = Sets.newHashSet(); - for (View view : views.values()) { - if (view.getWindow() instanceof AggregationWindow.Cumulative) { - exportedViews.add(view); - } + Set views = exportedViews; + if (views == null) { + synchronized (registeredViews) { + exportedViews = views = filterExportedViews(registeredViews.values()); + } + } + return views; + } + + // Returns the subset of the given views that should be exported + private static Set filterExportedViews(Collection allViews) { + Set views = Sets.newHashSet(); + for (View view : allViews) { + if (view.getWindow() instanceof AggregationWindow.Cumulative) { + views.add(view); } - return Collections.unmodifiableSet(exportedViews); } + return Collections.unmodifiableSet(views); } } } -- cgit v1.2.3 From 00ba25261867427e3a742bae64600c9f8de69b6d Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Fri, 17 Nov 2017 09:59:27 -0800 Subject: Use consistent wording in stats and tags 'setState' Javadocs. This commit updates the Javadocs for Stats.setState and StatsComponent.setState to avoid guaranteeing that the state won't change. It is consistent with Tags and TagsComponent. --- api/src/main/java/io/opencensus/stats/Stats.java | 2 +- api/src/main/java/io/opencensus/stats/StatsComponent.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/Stats.java b/api/src/main/java/io/opencensus/stats/Stats.java index 3bc78640..d02780f8 100644 --- a/api/src/main/java/io/opencensus/stats/Stats.java +++ b/api/src/main/java/io/opencensus/stats/Stats.java @@ -66,7 +66,7 @@ public final class Stats { * @deprecated This method is deprecated because other libraries could cache the result of {@link * #getState()}, use a stale value, and behave incorrectly. It is only safe to call early in * initialization. This method throws {@link IllegalStateException} after {@code getState()} - * has been called, in order to prevent the result of {@code getState()} from changing. + * has been called, in order to limit changes to the result of {@code getState()}. */ @Deprecated public static void setState(StatsCollectionState state) { diff --git a/api/src/main/java/io/opencensus/stats/StatsComponent.java b/api/src/main/java/io/opencensus/stats/StatsComponent.java index 30f56a91..6d95d4e3 100644 --- a/api/src/main/java/io/opencensus/stats/StatsComponent.java +++ b/api/src/main/java/io/opencensus/stats/StatsComponent.java @@ -55,7 +55,7 @@ public abstract class StatsComponent { * @deprecated This method is deprecated because other libraries could cache the result of {@link * #getState()}, use a stale value, and behave incorrectly. It is only safe to call early in * initialization. This method throws {@link IllegalStateException} after {@code getState()} - * has been called, in order to prevent the result of {@code getState()} from changing. + * has been called, in order to limit changes to the result of {@code getState()}. */ @Deprecated public abstract void setState(StatsCollectionState state); -- cgit v1.2.3 From 933817d0b9cb0cc4b90d750d3ac4aa5e5e96a59a Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Fri, 17 Nov 2017 12:57:48 -0800 Subject: Remove an obsolete TODO from TagKey.java. We decided not to allow empty tag key names in https://github.com/census-instrumentation/opencensus-specs/issues/12. --- api/src/main/java/io/opencensus/tags/TagKey.java | 1 - 1 file changed, 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/tags/TagKey.java b/api/src/main/java/io/opencensus/tags/TagKey.java index d68f0b75..f1304b33 100644 --- a/api/src/main/java/io/opencensus/tags/TagKey.java +++ b/api/src/main/java/io/opencensus/tags/TagKey.java @@ -54,7 +54,6 @@ public abstract class TagKey { * @throws IllegalArgumentException if the name is not valid. */ public static TagKey create(String name) { - // TODO(sebright): Should we disallow an empty name? checkArgument(isValid(name)); return new AutoValue_TagKey(name); } -- cgit v1.2.3 From d6536a7ac22b5f0fed111c0b5a76fabd831e93c2 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Sat, 18 Nov 2017 11:00:39 +1100 Subject: Start 0.10.0 development cycle (#816) --- .../main/java/io/opencensus/common/OpenCensusLibraryInformation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java index 91771644..e156a1df 100644 --- a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java +++ b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java @@ -21,7 +21,7 @@ package io.opencensus.common; public final class OpenCensusLibraryInformation { /** The current version of the OpenCensus Java library. */ - public static final String VERSION = "0.9.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION + public static final String VERSION = "0.10.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION private OpenCensusLibraryInformation() {} } -- cgit v1.2.3 From d89b938b29497ad234a466c97dedd3002c7aa414 Mon Sep 17 00:00:00 2001 From: Hailong Wen Date: Mon, 20 Nov 2017 17:21:01 -0800 Subject: Add NoopRunningSpanStore and NoopSampledSpanStore. --- .../java/io/opencensus/trace/TraceComponent.java | 7 +- api/src/main/java/io/opencensus/trace/Tracing.java | 2 +- .../opencensus/trace/export/ExportComponent.java | 15 +--- .../opencensus/trace/export/RunningSpanStore.java | 25 ++++++ .../opencensus/trace/export/SampledSpanStore.java | 69 +++++++++++++++ .../io/opencensus/trace/TraceComponentTest.java | 12 +-- .../test/java/io/opencensus/trace/TracingTest.java | 3 +- .../trace/export/ExportComponentTest.java | 8 +- .../trace/export/NoopRunningSpanStoreTest.java | 55 ++++++++++++ .../trace/export/NoopSampledSpanStoreTest.java | 97 ++++++++++++++++++++++ 10 files changed, 267 insertions(+), 26 deletions(-) create mode 100644 api/src/test/java/io/opencensus/trace/export/NoopRunningSpanStoreTest.java create mode 100644 api/src/test/java/io/opencensus/trace/export/NoopSampledSpanStoreTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/TraceComponent.java b/api/src/main/java/io/opencensus/trace/TraceComponent.java index e1806490..424ea180 100644 --- a/api/src/main/java/io/opencensus/trace/TraceComponent.java +++ b/api/src/main/java/io/opencensus/trace/TraceComponent.java @@ -29,7 +29,6 @@ import io.opencensus.trace.propagation.PropagationComponent; *

    Unless otherwise noted all methods (on component) results are cacheable. */ public abstract class TraceComponent { - private static final NoopTraceComponent noopTraceComponent = new NoopTraceComponent(); /** * Returns the {@link Tracer} with the provided implementations. If no implementation is provided @@ -75,8 +74,8 @@ public abstract class TraceComponent { * * @return an instance that contains no-op implementations for all the instances. */ - static TraceComponent getNoopTraceComponent() { - return noopTraceComponent; + static TraceComponent newNoopTraceComponent() { + return new NoopTraceComponent(); } private static final class NoopTraceComponent extends TraceComponent { @@ -97,7 +96,7 @@ public abstract class TraceComponent { @Override public ExportComponent getExportComponent() { - return ExportComponent.getNoopExportComponent(); + return ExportComponent.newNoopExportComponent(); } @Override diff --git a/api/src/main/java/io/opencensus/trace/Tracing.java b/api/src/main/java/io/opencensus/trace/Tracing.java index f370e014..c68f66ad 100644 --- a/api/src/main/java/io/opencensus/trace/Tracing.java +++ b/api/src/main/java/io/opencensus/trace/Tracing.java @@ -103,7 +103,7 @@ public final class Tracing { + "default implementation for TraceComponent.", e); } - return TraceComponent.getNoopTraceComponent(); + return TraceComponent.newNoopTraceComponent(); } // No instance of this class. diff --git a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java index 9b7e1664..742b0d9a 100644 --- a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java +++ b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java @@ -17,7 +17,6 @@ package io.opencensus.trace.export; import io.opencensus.trace.TraceOptions; -import javax.annotation.Nullable; /** * Class that holds the implementation instances for {@link SpanExporter}, {@link RunningSpanStore} @@ -27,15 +26,13 @@ import javax.annotation.Nullable; */ public abstract class ExportComponent { - private static final NoopExportComponent NOOP_EXPORT_COMPONENT = new NoopExportComponent(); - /** * Returns the no-op implementation of the {@code ExportComponent}. * * @return the no-op implementation of the {@code ExportComponent}. */ - public static ExportComponent getNoopExportComponent() { - return NOOP_EXPORT_COMPONENT; + public static ExportComponent newNoopExportComponent() { + return new NoopExportComponent(); } /** @@ -53,7 +50,6 @@ public abstract class ExportComponent { * * @return the {@code RunningSpanStore} or {@code null} if not supported. */ - @Nullable public abstract RunningSpanStore getRunningSpanStore(); /** @@ -62,7 +58,6 @@ public abstract class ExportComponent { * * @return the {@code SampledSpanStore} or {@code null} if not supported. */ - @Nullable public abstract SampledSpanStore getSampledSpanStore(); private static final class NoopExportComponent extends ExportComponent { @@ -71,16 +66,14 @@ public abstract class ExportComponent { return SpanExporter.getNoopSpanExporter(); } - @Nullable @Override public RunningSpanStore getRunningSpanStore() { - return null; + return RunningSpanStore.getNoopRunningSpanStore(); } - @Nullable @Override public SampledSpanStore getSampledSpanStore() { - return null; + return SampledSpanStore.newNoopSampledSpanStore(); } } } diff --git a/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java b/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java index bee65027..bf13c769 100644 --- a/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java @@ -37,8 +37,19 @@ import javax.annotation.concurrent.ThreadSafe; @ThreadSafe public abstract class RunningSpanStore { + private static final RunningSpanStore NOOP_RUNNING_SPAN_STORE = new NoopRunningSpanStore(); + protected RunningSpanStore() {} + /** + * Returns the no-op implementation of the {@code RunningSpanStore}. + * + * @return the no-op implementation of the {@code RunningSpanStore}. + */ + public static RunningSpanStore getNoopRunningSpanStore() { + return NOOP_RUNNING_SPAN_STORE; + } + /** * Returns the summary of all available data such, as number of running spans. * @@ -151,4 +162,18 @@ public abstract class RunningSpanStore { */ public abstract int getMaxSpansToReturn(); } + + private static final class NoopRunningSpanStore extends RunningSpanStore { + + @Override + public Summary getSummary() { + return Summary.create(Collections.emptyMap()); + } + + @Override + public Collection getRunningSpans(Filter filter) { + checkNotNull(filter, "filter"); + return Collections.emptyList(); + } + } } diff --git a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java index b19ad3a1..f34f2e26 100644 --- a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java @@ -21,6 +21,8 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import io.opencensus.trace.Span; import io.opencensus.trace.Status; import io.opencensus.trace.Status.CanonicalCode; @@ -31,6 +33,7 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.ThreadSafe; @@ -48,6 +51,17 @@ public abstract class SampledSpanStore { protected SampledSpanStore() {} + /** + * Returns a {@code SampledSpanStore} that maintains a map of span names, but always returns an + * empty list of {@link SpanData}. + * + * @return a {@code SampledSpanStore} that maintains a map of span names, but always returns an + * empty list of {@code SpanData}. + */ + static SampledSpanStore newNoopSampledSpanStore() { + return new NoopSampledSpanStore(); + } + /** * Returns the summary of all available data, such as number of sampled spans in the latency based * samples or error based samples. @@ -370,4 +384,59 @@ public abstract class SampledSpanStore { */ public abstract int getMaxSpansToReturn(); } + + @ThreadSafe + private static final class NoopSampledSpanStore extends SampledSpanStore { + + @GuardedBy("registeredSpanNames") + private final Set registeredSpanNames = Sets.newHashSet(); + + @Override + public Summary getSummary() { + Map result = Maps.newHashMap(); + synchronized (registeredSpanNames) { + for (String registeredSpanName : registeredSpanNames) { + result.put( + registeredSpanName, + PerSpanNameSummary.create( + Collections.emptyMap(), + Collections.emptyMap())); + } + } + return Summary.create(result); + } + + @Override + public Collection getLatencySampledSpans(LatencyFilter filter) { + return Collections.emptyList(); + } + + @Override + public Collection getErrorSampledSpans(ErrorFilter filter) { + return Collections.emptyList(); + } + + @Override + public void registerSpanNamesForCollection(Collection spanNames) { + checkNotNull(spanNames); + synchronized (registeredSpanNames) { + registeredSpanNames.addAll(spanNames); + } + } + + @Override + public void unregisterSpanNamesForCollection(Collection spanNames) { + checkNotNull(spanNames); + synchronized (registeredSpanNames) { + registeredSpanNames.removeAll(spanNames); + } + } + + @Override + public Set getRegisteredSpanNamesForCollection() { + synchronized (registeredSpanNames) { + return registeredSpanNames; + } + } + } } diff --git a/api/src/test/java/io/opencensus/trace/TraceComponentTest.java b/api/src/test/java/io/opencensus/trace/TraceComponentTest.java index a086efe3..1c3f07d5 100644 --- a/api/src/test/java/io/opencensus/trace/TraceComponentTest.java +++ b/api/src/test/java/io/opencensus/trace/TraceComponentTest.java @@ -31,29 +31,29 @@ import org.junit.runners.JUnit4; public class TraceComponentTest { @Test public void defaultTracer() { - assertThat(TraceComponent.getNoopTraceComponent().getTracer()).isSameAs(Tracer.getNoopTracer()); + assertThat(TraceComponent.newNoopTraceComponent().getTracer()).isSameAs(Tracer.getNoopTracer()); } @Test public void defaultBinaryPropagationHandler() { - assertThat(TraceComponent.getNoopTraceComponent().getPropagationComponent()) + assertThat(TraceComponent.newNoopTraceComponent().getPropagationComponent()) .isSameAs(PropagationComponent.getNoopPropagationComponent()); } @Test public void defaultClock() { - assertThat(TraceComponent.getNoopTraceComponent().getClock()).isInstanceOf(ZeroTimeClock.class); + assertThat(TraceComponent.newNoopTraceComponent().getClock()).isInstanceOf(ZeroTimeClock.class); } @Test public void defaultTraceExporter() { - assertThat(TraceComponent.getNoopTraceComponent().getExportComponent()) - .isSameAs(ExportComponent.getNoopExportComponent()); + assertThat(TraceComponent.newNoopTraceComponent().getExportComponent()) + .isInstanceOf(ExportComponent.newNoopExportComponent().getClass()); } @Test public void defaultTraceConfig() { - assertThat(TraceComponent.getNoopTraceComponent().getTraceConfig()) + assertThat(TraceComponent.newNoopTraceComponent().getTraceConfig()) .isSameAs(TraceConfig.getNoopTraceConfig()); } } diff --git a/api/src/test/java/io/opencensus/trace/TracingTest.java b/api/src/test/java/io/opencensus/trace/TracingTest.java index a4245e6f..e7c93a95 100644 --- a/api/src/test/java/io/opencensus/trace/TracingTest.java +++ b/api/src/test/java/io/opencensus/trace/TracingTest.java @@ -72,7 +72,8 @@ public class TracingTest { @Test public void defaultTraceExporter() { - assertThat(Tracing.getExportComponent()).isSameAs(ExportComponent.getNoopExportComponent()); + assertThat(Tracing.getExportComponent()) + .isInstanceOf(ExportComponent.newNoopExportComponent().getClass()); } @Test diff --git a/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java b/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java index 01c1a086..d7f385d0 100644 --- a/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java +++ b/api/src/test/java/io/opencensus/trace/export/ExportComponentTest.java @@ -25,7 +25,7 @@ import org.junit.runners.JUnit4; /** Unit tests for {@link ExportComponent}. */ @RunWith(JUnit4.class) public class ExportComponentTest { - private final ExportComponent exportComponent = ExportComponent.getNoopExportComponent(); + private final ExportComponent exportComponent = ExportComponent.newNoopExportComponent(); @Test public void implementationOfSpanExporter() { @@ -34,11 +34,13 @@ public class ExportComponentTest { @Test public void implementationOfActiveSpans() { - assertThat(exportComponent.getRunningSpanStore()).isNull(); + assertThat(exportComponent.getRunningSpanStore()) + .isEqualTo(RunningSpanStore.getNoopRunningSpanStore()); } @Test public void implementationOfSampledSpanStore() { - assertThat(exportComponent.getSampledSpanStore()).isNull(); + assertThat(exportComponent.getSampledSpanStore()) + .isInstanceOf(SampledSpanStore.newNoopSampledSpanStore().getClass()); } } diff --git a/api/src/test/java/io/opencensus/trace/export/NoopRunningSpanStoreTest.java b/api/src/test/java/io/opencensus/trace/export/NoopRunningSpanStoreTest.java new file mode 100644 index 00000000..960da27c --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/export/NoopRunningSpanStoreTest.java @@ -0,0 +1,55 @@ +/* + * 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.export; + +import static com.google.common.truth.Truth.assertThat; + +import java.util.Collection; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link NoopRunningSpanStore}. */ +@RunWith(JUnit4.class) +public final class NoopRunningSpanStoreTest { + + private final RunningSpanStore runningSpanStore = + ExportComponent.newNoopExportComponent().getRunningSpanStore(); + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void noopRunningSpanStore_GetSummary() { + RunningSpanStore.Summary summary = runningSpanStore.getSummary(); + assertThat(summary.getPerSpanNameSummary()).isEmpty(); + } + + @Test + public void noopRunningSpanStore_GetRunningSpans_DisallowsNull() { + thrown.expect(NullPointerException.class); + runningSpanStore.getRunningSpans(null); + } + + @Test + public void noopRunningSpanStore_GetRunningSpans() { + Collection runningSpans = + runningSpanStore.getRunningSpans(RunningSpanStore.Filter.create("TestSpan", 0)); + assertThat(runningSpans).isEmpty(); + } +} diff --git a/api/src/test/java/io/opencensus/trace/export/NoopSampledSpanStoreTest.java b/api/src/test/java/io/opencensus/trace/export/NoopSampledSpanStoreTest.java new file mode 100644 index 00000000..97bc6ea9 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/export/NoopSampledSpanStoreTest.java @@ -0,0 +1,97 @@ +/* + * 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.export; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.collect.Lists; +import io.opencensus.trace.Status.CanonicalCode; +import java.util.Collection; +import java.util.Collections; +import java.util.Set; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link NoopSampledSpanStore}. */ +@RunWith(JUnit4.class) +public final class NoopSampledSpanStoreTest { + + @Rule public final ExpectedException thrown = ExpectedException.none(); + private final SampledSpanStore.PerSpanNameSummary emptyPerSpanNameSummary = + SampledSpanStore.PerSpanNameSummary.create( + Collections.emptyMap(), + Collections.emptyMap()); + + @Test + public void noopSampledSpanStore_RegisterUnregisterAndGetSummary() { + // should return empty before register + SampledSpanStore sampledSpanStore = + ExportComponent.newNoopExportComponent().getSampledSpanStore(); + SampledSpanStore.Summary summary = sampledSpanStore.getSummary(); + assertThat(summary.getPerSpanNameSummary()).isEmpty(); + + // should return non-empty summaries with zero latency/error sampled spans after register + sampledSpanStore.registerSpanNamesForCollection( + Collections.unmodifiableList(Lists.newArrayList("TestSpan1", "TestSpan2", "TestSpan3"))); + summary = sampledSpanStore.getSummary(); + assertThat(summary.getPerSpanNameSummary()) + .containsExactly( + "TestSpan1", emptyPerSpanNameSummary, + "TestSpan2", emptyPerSpanNameSummary, + "TestSpan3", emptyPerSpanNameSummary); + + // should unregister specific spanNames + sampledSpanStore.unregisterSpanNamesForCollection( + Collections.unmodifiableList(Lists.newArrayList("TestSpan1", "TestSpan3"))); + summary = sampledSpanStore.getSummary(); + assertThat(summary.getPerSpanNameSummary()) + .containsExactly("TestSpan2", emptyPerSpanNameSummary); + } + + @Test + public void noopSampledSpanStore_GetLatencySampledSpans() { + SampledSpanStore sampledSpanStore = + ExportComponent.newNoopExportComponent().getSampledSpanStore(); + Collection latencySampledSpans = + sampledSpanStore.getLatencySampledSpans( + SampledSpanStore.LatencyFilter.create("TestLatencyFilter", 0, 0, 0)); + assertThat(latencySampledSpans).isEmpty(); + } + + @Test + public void noopSampledSpanStore_GetErrorSampledSpans() { + SampledSpanStore sampledSpanStore = + ExportComponent.newNoopExportComponent().getSampledSpanStore(); + Collection errorSampledSpans = + sampledSpanStore.getErrorSampledSpans( + SampledSpanStore.ErrorFilter.create("TestErrorFilter", null, 0)); + assertThat(errorSampledSpans).isEmpty(); + } + + @Test + public void noopSampledSpanStore_GetRegisteredSpanNamesForCollection() { + SampledSpanStore sampledSpanStore = + ExportComponent.newNoopExportComponent().getSampledSpanStore(); + sampledSpanStore.registerSpanNamesForCollection( + Collections.unmodifiableList(Lists.newArrayList("TestSpan3", "TestSpan4"))); + Set registeredSpanNames = sampledSpanStore.getRegisteredSpanNamesForCollection(); + assertThat(registeredSpanNames).containsExactly("TestSpan3", "TestSpan4"); + } +} -- cgit v1.2.3 From 5f5afe8f305fddc74170c91428e6ab372b572705 Mon Sep 17 00:00:00 2001 From: Hailong Wen Date: Mon, 20 Nov 2017 22:03:09 -0800 Subject: Addressing sebright's comments. 1. Returns the same NoopExportComponent and NoopSampledSpanStore. 2. Correct outdated javadoc. 3. Change visibility of getNoopRunningSpanStore(). 4. Make empty Summary constant. 5. Returns immutable copy of registeredSpanNames when calling getRegisteredSpanNamesForCollection(). --- .../main/java/io/opencensus/trace/TraceComponent.java | 4 +++- .../io/opencensus/trace/export/ExportComponent.java | 9 ++++++--- .../io/opencensus/trace/export/RunningSpanStore.java | 7 +++++-- .../io/opencensus/trace/export/SampledSpanStore.java | 17 ++++++++++------- .../trace/export/NoopSampledSpanStoreTest.java | 10 +++++----- 5 files changed, 29 insertions(+), 18 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/TraceComponent.java b/api/src/main/java/io/opencensus/trace/TraceComponent.java index 424ea180..a781f045 100644 --- a/api/src/main/java/io/opencensus/trace/TraceComponent.java +++ b/api/src/main/java/io/opencensus/trace/TraceComponent.java @@ -79,6 +79,8 @@ public abstract class TraceComponent { } private static final class NoopTraceComponent extends TraceComponent { + private final ExportComponent noopExportComponent = ExportComponent.newNoopExportComponent(); + @Override public Tracer getTracer() { return Tracer.getNoopTracer(); @@ -96,7 +98,7 @@ public abstract class TraceComponent { @Override public ExportComponent getExportComponent() { - return ExportComponent.newNoopExportComponent(); + return noopExportComponent; } @Override diff --git a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java index 742b0d9a..7e2eb88e 100644 --- a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java +++ b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java @@ -48,7 +48,7 @@ public abstract class ExportComponent { * Returns the {@link RunningSpanStore} that can be used to get useful debugging information about * all the current active spans. * - * @return the {@code RunningSpanStore} or {@code null} if not supported. + * @return the {@code RunningSpanStore}. */ public abstract RunningSpanStore getRunningSpanStore(); @@ -56,11 +56,14 @@ public abstract class ExportComponent { * Returns the {@link SampledSpanStore} that can be used to get useful debugging information, such * as latency based sampled spans, error based sampled spans. * - * @return the {@code SampledSpanStore} or {@code null} if not supported. + * @return the {@code SampledSpanStore}. */ public abstract SampledSpanStore getSampledSpanStore(); private static final class NoopExportComponent extends ExportComponent { + private final SampledSpanStore noopSampledSpanStore = + SampledSpanStore.newNoopSampledSpanStore(); + @Override public SpanExporter getSpanExporter() { return SpanExporter.getNoopSpanExporter(); @@ -73,7 +76,7 @@ public abstract class ExportComponent { @Override public SampledSpanStore getSampledSpanStore() { - return SampledSpanStore.newNoopSampledSpanStore(); + return noopSampledSpanStore; } } } diff --git a/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java b/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java index bf13c769..8d736aab 100644 --- a/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java @@ -46,7 +46,7 @@ public abstract class RunningSpanStore { * * @return the no-op implementation of the {@code RunningSpanStore}. */ - public static RunningSpanStore getNoopRunningSpanStore() { + static RunningSpanStore getNoopRunningSpanStore() { return NOOP_RUNNING_SPAN_STORE; } @@ -165,9 +165,12 @@ public abstract class RunningSpanStore { private static final class NoopRunningSpanStore extends RunningSpanStore { + private static final Summary EMPTY_SUMMARY = + Summary.create(Collections.emptyMap()); + @Override public Summary getSummary() { - return Summary.create(Collections.emptyMap()); + return EMPTY_SUMMARY; } @Override diff --git a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java index f34f2e26..89509933 100644 --- a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java @@ -21,6 +21,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import io.opencensus.trace.Span; @@ -387,6 +388,10 @@ public abstract class SampledSpanStore { @ThreadSafe private static final class NoopSampledSpanStore extends SampledSpanStore { + private static final PerSpanNameSummary EMPTY_PER_SPAN_NAME_SUMMARY = + PerSpanNameSummary.create( + Collections.emptyMap(), + Collections.emptyMap()); @GuardedBy("registeredSpanNames") private final Set registeredSpanNames = Sets.newHashSet(); @@ -396,11 +401,7 @@ public abstract class SampledSpanStore { Map result = Maps.newHashMap(); synchronized (registeredSpanNames) { for (String registeredSpanName : registeredSpanNames) { - result.put( - registeredSpanName, - PerSpanNameSummary.create( - Collections.emptyMap(), - Collections.emptyMap())); + result.put(registeredSpanName, EMPTY_PER_SPAN_NAME_SUMMARY); } } return Summary.create(result); @@ -408,17 +409,19 @@ public abstract class SampledSpanStore { @Override public Collection getLatencySampledSpans(LatencyFilter filter) { + checkNotNull(filter, "latencyFilter"); return Collections.emptyList(); } @Override public Collection getErrorSampledSpans(ErrorFilter filter) { + checkNotNull(filter, "errorFilter"); return Collections.emptyList(); } @Override public void registerSpanNamesForCollection(Collection spanNames) { - checkNotNull(spanNames); + checkNotNull(spanNames, "spanNames"); synchronized (registeredSpanNames) { registeredSpanNames.addAll(spanNames); } @@ -435,7 +438,7 @@ public abstract class SampledSpanStore { @Override public Set getRegisteredSpanNamesForCollection() { synchronized (registeredSpanNames) { - return registeredSpanNames; + return ImmutableSet.copyOf(registeredSpanNames); } } } diff --git a/api/src/test/java/io/opencensus/trace/export/NoopSampledSpanStoreTest.java b/api/src/test/java/io/opencensus/trace/export/NoopSampledSpanStoreTest.java index 97bc6ea9..e18621ac 100644 --- a/api/src/test/java/io/opencensus/trace/export/NoopSampledSpanStoreTest.java +++ b/api/src/test/java/io/opencensus/trace/export/NoopSampledSpanStoreTest.java @@ -34,7 +34,7 @@ import org.junit.runners.JUnit4; public final class NoopSampledSpanStoreTest { @Rule public final ExpectedException thrown = ExpectedException.none(); - private final SampledSpanStore.PerSpanNameSummary emptyPerSpanNameSummary = + private static final SampledSpanStore.PerSpanNameSummary EMPTY_PER_SPAN_NAME_SUMMARY = SampledSpanStore.PerSpanNameSummary.create( Collections.emptyMap(), Collections.emptyMap()); @@ -53,16 +53,16 @@ public final class NoopSampledSpanStoreTest { summary = sampledSpanStore.getSummary(); assertThat(summary.getPerSpanNameSummary()) .containsExactly( - "TestSpan1", emptyPerSpanNameSummary, - "TestSpan2", emptyPerSpanNameSummary, - "TestSpan3", emptyPerSpanNameSummary); + "TestSpan1", EMPTY_PER_SPAN_NAME_SUMMARY, + "TestSpan2", EMPTY_PER_SPAN_NAME_SUMMARY, + "TestSpan3", EMPTY_PER_SPAN_NAME_SUMMARY); // should unregister specific spanNames sampledSpanStore.unregisterSpanNamesForCollection( Collections.unmodifiableList(Lists.newArrayList("TestSpan1", "TestSpan3"))); summary = sampledSpanStore.getSummary(); assertThat(summary.getPerSpanNameSummary()) - .containsExactly("TestSpan2", emptyPerSpanNameSummary); + .containsExactly("TestSpan2", EMPTY_PER_SPAN_NAME_SUMMARY); } @Test -- cgit v1.2.3 From 690a1fe0342b2783ce86602f51d4ca5e92466f94 Mon Sep 17 00:00:00 2001 From: Hailong Wen Date: Tue, 21 Nov 2017 10:03:55 -0800 Subject: Use unmodifiableSet instead of ImmutableSet to get rid of build error. Refine javadoc of newNoopSampledSpanStore(). --- api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java index 89509933..e1339090 100644 --- a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java @@ -21,7 +21,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import io.opencensus.trace.Span; @@ -53,10 +52,10 @@ public abstract class SampledSpanStore { protected SampledSpanStore() {} /** - * Returns a {@code SampledSpanStore} that maintains a map of span names, but always returns an + * Returns a {@code SampledSpanStore} that maintains a set of span names, but always returns an * empty list of {@link SpanData}. * - * @return a {@code SampledSpanStore} that maintains a map of span names, but always returns an + * @return a {@code SampledSpanStore} that maintains a set of span names, but always returns an * empty list of {@code SpanData}. */ static SampledSpanStore newNoopSampledSpanStore() { @@ -438,7 +437,7 @@ public abstract class SampledSpanStore { @Override public Set getRegisteredSpanNamesForCollection() { synchronized (registeredSpanNames) { - return ImmutableSet.copyOf(registeredSpanNames); + return Collections.unmodifiableSet(Sets.newHashSet(registeredSpanNames)); } } } -- cgit v1.2.3 From 7106a4737b44f4e55be6c4e397a4cf01e64ba220 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Tue, 21 Nov 2017 15:55:55 -0800 Subject: Update length limit for View.Name (#834) --- api/src/main/java/io/opencensus/stats/View.java | 6 +++--- api/src/test/java/io/opencensus/stats/ViewTest.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/View.java b/api/src/main/java/io/opencensus/stats/View.java index c4b152e0..a773ec1f 100644 --- a/api/src/main/java/io/opencensus/stats/View.java +++ b/api/src/main/java/io/opencensus/stats/View.java @@ -38,7 +38,7 @@ import javax.annotation.concurrent.Immutable; @AutoValue public abstract class View { - @VisibleForTesting static final int NAME_MAX_LENGTH = 256; + @VisibleForTesting static final int NAME_MAX_LENGTH = 255; View() {} @@ -116,7 +116,7 @@ public abstract class View { /** * Creates a {@code View.Name} from a {@code String}. Should be a ASCII string with a length no - * greater than 256 characters. + * greater than 255 characters. * *

    Suggested format for name: {@code /}. * @@ -126,7 +126,7 @@ public abstract class View { public static Name create(String name) { checkArgument( StringUtil.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, - "Name should be a ASCII string with a length no greater than 256 characters."); + "Name should be a ASCII string with a length no greater than 255 characters."); return new AutoValue_View_Name(name); } } diff --git a/api/src/test/java/io/opencensus/stats/ViewTest.java b/api/src/test/java/io/opencensus/stats/ViewTest.java index c135713c..4781854c 100644 --- a/api/src/test/java/io/opencensus/stats/ViewTest.java +++ b/api/src/test/java/io/opencensus/stats/ViewTest.java @@ -41,7 +41,7 @@ public final class ViewTest { @Test public void testConstants() { - assertThat(View.NAME_MAX_LENGTH).isEqualTo(256); + assertThat(View.NAME_MAX_LENGTH).isEqualTo(255); } @Test -- cgit v1.2.3 From 1cec10ed55408d525619d8c712e1d092def114ec Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Wed, 29 Nov 2017 18:44:36 -0800 Subject: Remove ScopedSpanHandle and make SpanInScope able to close the Span. (#848) * Remove ScopedSpanHandle and make SpanInScope able to close the Span. * Fix extra ";". * Fix comments. --- .../java/io/opencensus/trace/CurrentSpanUtils.java | 22 +++++---- .../java/io/opencensus/trace/ScopedSpanHandle.java | 50 -------------------- .../main/java/io/opencensus/trace/SpanBuilder.java | 2 +- api/src/main/java/io/opencensus/trace/Tracer.java | 2 +- .../io/opencensus/trace/CurrentSpanUtilsTest.java | 23 +++++++-- .../io/opencensus/trace/ScopedSpanHandleTest.java | 54 ---------------------- 6 files changed, 36 insertions(+), 117 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java delete mode 100644 api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java index 291de53a..713c8816 100644 --- a/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java +++ b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java @@ -41,31 +41,37 @@ final class CurrentSpanUtils { *

    Supports try-with-resource idiom. * * @param span The {@code Span} to be set to the current context. + * @param endSpan if {@code true} the returned {@code Scope} will close the {@code Span}. * @return An object that defines a scope where the given {@code Span} is set to the current * context. */ - static Scope withSpan(Span span) { - return new WithSpan(span, ContextUtils.CONTEXT_SPAN_KEY); + static Scope withSpan(Span span, boolean endSpan) { + return new ScopeInSpan(span, endSpan); } // Defines an arbitrary scope of code as a traceable operation. Supports try-with-resources idiom. - private static final class WithSpan implements Scope { + private static final class ScopeInSpan implements Scope { private final Context origContext; + private final Span span; + private boolean endSpan; /** - * Constructs a new {@link WithSpan}. + * Constructs a new {@link ScopeInSpan}. * * @param span is the {@code Span} to be added to the current {@code io.grpc.Context}. - * @param contextKey is the {@code Context.Key} used to set/get {@code Span} from the {@code - * Context}. */ - WithSpan(Span span, Context.Key contextKey) { - origContext = Context.current().withValue(contextKey, span).attach(); + ScopeInSpan(Span span, boolean endSpan) { + this.span = span; + this.endSpan = endSpan; + origContext = Context.current().withValue(ContextUtils.CONTEXT_SPAN_KEY, span).attach(); } @Override public void close() { Context.current().detach(origContext); + if (endSpan) { + span.end(); + } } } } diff --git a/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java b/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java deleted file mode 100644 index b5beb4aa..00000000 --- a/api/src/main/java/io/opencensus/trace/ScopedSpanHandle.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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; - -import io.opencensus.common.Scope; - -/** - * Defines a scope of code where the given {@link Span} is in the current context. The scope is - * exited when the object is closed and the previous context is restored. When the scope exits the - * given {@code Span} will be ended using {@link Span#end}. - * - *

    Supports try-with-resource idiom. - */ -final class ScopedSpanHandle implements Scope { - private final Span span; - private final Scope withSpan; - - /** - * Creates a {@code ScopedSpanHandle} - * - * @param span The span that will be installed in the current context. - */ - ScopedSpanHandle(Span span) { - this.span = span; - this.withSpan = CurrentSpanUtils.withSpan(span); - } - - /** - * Uninstalls the {@code Span} from the current context and ends it by calling {@link Span#end()}. - */ - @Override - public void close() { - withSpan.close(); - span.end(); - } -} diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java index 530af97e..4c28147e 100644 --- a/api/src/main/java/io/opencensus/trace/SpanBuilder.java +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -220,7 +220,7 @@ public abstract class SpanBuilder { */ @MustBeClosed public final Scope startScopedSpan() { - return new ScopedSpanHandle(startSpan()); + return CurrentSpanUtils.withSpan(startSpan(), true); } static final class NoopSpanBuilder extends SpanBuilder { diff --git a/api/src/main/java/io/opencensus/trace/Tracer.java b/api/src/main/java/io/opencensus/trace/Tracer.java index 24853fbc..8215f7b1 100644 --- a/api/src/main/java/io/opencensus/trace/Tracer.java +++ b/api/src/main/java/io/opencensus/trace/Tracer.java @@ -147,7 +147,7 @@ public abstract class Tracer { */ @MustBeClosed public final Scope withSpan(Span span) { - return CurrentSpanUtils.withSpan(checkNotNull(span, "span")); + return CurrentSpanUtils.withSpan(checkNotNull(span, "span"), false); } /** diff --git a/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java b/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java index afc7db63..8ba910b0 100644 --- a/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java +++ b/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java @@ -17,6 +17,9 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.same; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; import io.grpc.Context; import io.opencensus.common.Scope; @@ -57,21 +60,35 @@ public class CurrentSpanUtilsTest { } @Test - public void withSpan() { + public void withSpan_CloseDetaches() { assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); - Scope ws = CurrentSpanUtils.withSpan(span); + Scope ws = CurrentSpanUtils.withSpan(span, false); try { assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); } finally { ws.close(); } assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + verifyZeroInteractions(span); + } + + @Test + public void withSpan_CloseDetachesAndEndsSpan() { + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Scope ss = CurrentSpanUtils.withSpan(span, true); + try { + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + } finally { + ss.close(); + } + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + verify(span).end(same(EndSpanOptions.DEFAULT)); } @Test public void propagationViaRunnable() { Runnable runnable = null; - Scope ws = CurrentSpanUtils.withSpan(span); + Scope ws = CurrentSpanUtils.withSpan(span, false); try { assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); runnable = diff --git a/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java b/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java deleted file mode 100644 index a8c18819..00000000 --- a/api/src/test/java/io/opencensus/trace/ScopedSpanHandleTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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; - -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Matchers.same; -import static org.mockito.Mockito.verify; - -import io.opencensus.common.Scope; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** Unit tests for {@link ScopedSpanHandle}. */ -@RunWith(JUnit4.class) -public class ScopedSpanHandleTest { - private static final Tracer tracer = Tracer.getNoopTracer(); - @Mock private Span span; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void initAttachesSpan_CloseDetachesAndEndsSpan() { - assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); - Scope ss = new ScopedSpanHandle(span); - try { - assertThat(tracer.getCurrentSpan()).isSameAs(span); - } finally { - ss.close(); - } - assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); - verify(span).end(same(EndSpanOptions.DEFAULT)); - } -} -- cgit v1.2.3 From a12419151e072df03fc1de5f5fba6926c5005579 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Fri, 1 Dec 2017 16:45:46 -0800 Subject: Update project name in api/README.md. --- api/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'api') diff --git a/api/README.md b/api/README.md index 797ebe0a..83891d4d 100644 --- a/api/README.md +++ b/api/README.md @@ -3,4 +3,4 @@ OpenCensus API * Java 6 and Android compatible. * The abstract classes in this directory can be subclassed to create alternative - implementations of the Instrumentation library. + implementations of the OpenCensus library. -- cgit v1.2.3 From 70b2c031f216cb5ce6b5cdcb0c3a48ce61f18f69 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Mon, 4 Dec 2017 16:59:53 -0800 Subject: Start 0.11.0 development cycle (#874) --- .../main/java/io/opencensus/common/OpenCensusLibraryInformation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java index e156a1df..91151212 100644 --- a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java +++ b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java @@ -21,7 +21,7 @@ package io.opencensus.common; public final class OpenCensusLibraryInformation { /** The current version of the OpenCensus Java library. */ - public static final String VERSION = "0.10.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION + public static final String VERSION = "0.11.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION private OpenCensusLibraryInformation() {} } -- cgit v1.2.3 From 28d023af35ef516fb472092edff3de224fc79e03 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Wed, 6 Dec 2017 13:04:38 -0800 Subject: 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. --- .../opencensus/trace/propagation/TextFormat.java | 189 +++++++++++++++++++++ .../propagation/PropagationComponentTest.java | 2 +- .../trace/propagation/TextFormatTest.java | 75 ++++++++ 3 files changed, 265 insertions(+), 1 deletion(-) create mode 100644 api/src/main/java/io/opencensus/trace/propagation/TextFormat.java create mode 100644 api/src/test/java/io/opencensus/trace/propagation/TextFormatTest.java (limited to 'api') 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. + * + *

    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. + * + *

    Example of usage on the client: + * + *

    {@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() {
    + *   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.
    + * }
    + * }
    + * + *

    Example of usage on the server: + * + *

    {@code
    + * private static final Tracer tracer = Tracing.getTracer();
    + * private static final TextFormat textFormat = Tracing.getPropagationComponent().getTextFormat();
    + * private static final TextFormat.Getter 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()
    + * }
    + * }
    + */ +@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)}. + * + *

    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 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 void inject(SpanContext spanContext, C carrier, Setter setter); + + /** + * Class that allows a {@code TextFormat} to set propagated fields into a carrier. + * + *

    {@code Setter} is stateless and allows to be saved as a constant to avoid runtime + * allocations. + * + * @param carrier of propagation fields, such as an http request + */ + public abstract static class Setter { + + /** + * Replaces a propagated field with the given value. + * + *

    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 SpanContext extract(C carrier, Getter getter) + throws SpanContextParseException; + + /** + * Class that allows a {@code TextFormat} to read propagated fields from a carrier. + * + *

    {@code Getter} is stateless and allows to be saved as a constant to avoid runtime + * allocations. + * + * @param carrier of propagation fields, such as an http request + */ + public abstract static class Getter { + + /** + * 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 fields() { + return Collections.emptyList(); + } + + @Override + public void inject(SpanContext spanContext, C carrier, Setter setter) { + checkNotNull(spanContext, "spanContext"); + checkNotNull(carrier, "carrier"); + checkNotNull(setter, "setter"); + } + + @Override + public SpanContext extract(C carrier, Getter 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() { + @Override + public void put(Object carrier, String key, String value) {} + }); + } + + @Test + public void inject_NotNullSpanContext_DoesNotFail() { + textFormat.inject( + SpanContext.INVALID, + new Object(), + new Setter() { + @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() { + @Nullable + @Override + public String get(Object carrier, String key) { + return null; + } + })) + .isSameAs(SpanContext.INVALID); + } +} -- cgit v1.2.3 From 381e11c5168e5d31e09ec92840f908b42be647e6 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Mon, 11 Dec 2017 16:12:53 -0800 Subject: Add initial support for b3-propagation headers. (#889) * Add initial support for b3-propagation headers. * Update tests and throw exception when missing span_id or trace_id. * Cleanup and add more tests. * Update comments. Update tests. --- api/src/main/java/io/opencensus/trace/SpanId.java | 25 ++++++++++++++++++++++ api/src/main/java/io/opencensus/trace/TraceId.java | 25 ++++++++++++++++++++++ .../test/java/io/opencensus/trace/SpanIdTest.java | 18 ++++++++++++++-- .../test/java/io/opencensus/trace/TraceIdTest.java | 19 ++++++++++++++-- .../test/java/io/opencensus/trace/TracerTest.java | 3 --- 5 files changed, 83 insertions(+), 7 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/SpanId.java b/api/src/main/java/io/opencensus/trace/SpanId.java index 446a228e..a986d013 100644 --- a/api/src/main/java/io/opencensus/trace/SpanId.java +++ b/api/src/main/java/io/opencensus/trace/SpanId.java @@ -83,6 +83,22 @@ public final class SpanId implements Comparable { return new SpanId(bytes); } + /** + * Returns a {@code SpanId} built from a lowercase base16 representation. + * + * @param src the lowercase base16 representation. + * @return a {@code SpanId} built from a lowercase base16 representation. + * @throws NullPointerException if {@code src} is null. + * @throws IllegalArgumentException if {@code src.length} is not {@code 2 * SpanId.SIZE} OR if the + * {@code str} has invalid characters. + */ + public static SpanId fromLowerBase16(String src) { + checkArgument( + src.length() == 2 * SIZE, "Invalid size: expected %s, got %s", 2 * SIZE, src.length()); + byte[] bytes = BaseEncoding.base16().lowerCase().decode(src); + return new SpanId(bytes); + } + /** * Generates a new random {@code SpanId}. * @@ -136,6 +152,15 @@ public final class SpanId implements Comparable { return !Arrays.equals(bytes, INVALID.bytes); } + /** + * Returns the lowercase base16 encoding of this {@code SpanId}. + * + * @return the lowercase base16 encoding of this {@code SpanId}. + */ + public String toLowerBase16() { + return BaseEncoding.base16().lowerCase().encode(bytes); + } + @Override public boolean equals(Object obj) { if (obj == this) { diff --git a/api/src/main/java/io/opencensus/trace/TraceId.java b/api/src/main/java/io/opencensus/trace/TraceId.java index 6badf6e5..44b80a66 100644 --- a/api/src/main/java/io/opencensus/trace/TraceId.java +++ b/api/src/main/java/io/opencensus/trace/TraceId.java @@ -84,6 +84,22 @@ public final class TraceId implements Comparable { return new TraceId(bytes); } + /** + * Returns a {@code TraceId} built from a lowercase base16 representation. + * + * @param src the lowercase base16 representation. + * @return a {@code TraceId} built from a lowercase base16 representation. + * @throws NullPointerException if {@code src} is null. + * @throws IllegalArgumentException if {@code src.length} is not {@code 2 * TraceId.SIZE} OR if + * the {@code str} has invalid characters. + */ + public static TraceId fromLowerBase16(String src) { + checkArgument( + src.length() == 2 * SIZE, "Invalid size: expected %s, got %s", 2 * SIZE, src.length()); + byte[] bytes = BaseEncoding.base16().lowerCase().decode(src); + return new TraceId(bytes); + } + /** * Generates a new random {@code TraceId}. * @@ -137,6 +153,15 @@ public final class TraceId implements Comparable { return !Arrays.equals(bytes, INVALID.bytes); } + /** + * Returns the lowercase base16 encoding of this {@code TraceId}. + * + * @return the lowercase base16 encoding of this {@code TraceId}. + */ + public String toLowerBase16() { + return BaseEncoding.base16().lowerCase().encode(bytes); + } + /** * Returns the lower 8 bytes of the trace-id as a long value, assuming little-endian order. This * is used in ProbabilitySampler. diff --git a/api/src/test/java/io/opencensus/trace/SpanIdTest.java b/api/src/test/java/io/opencensus/trace/SpanIdTest.java index 36226da5..4a5bc2ae 100644 --- a/api/src/test/java/io/opencensus/trace/SpanIdTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanIdTest.java @@ -28,7 +28,7 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public class SpanIdTest { private static final byte[] firstBytes = new byte[] {0, 0, 0, 0, 0, 0, 0, 'a'}; - private static final byte[] secondBytes = new byte[] {(byte) 0xFF, 0, 0, 0, 0, 0, 0, 0}; + private static final byte[] secondBytes = new byte[] {(byte) 0xFF, 0, 0, 0, 0, 0, 0, 'A'}; private static final SpanId first = SpanId.fromBytes(firstBytes); private static final SpanId second = SpanId.fromBytes(secondBytes); @@ -44,6 +44,20 @@ public class SpanIdTest { assertThat(second.isValid()).isTrue(); } + @Test + public void fromLowerBase16() { + assertThat(SpanId.fromLowerBase16("0000000000000000")).isEqualTo(SpanId.INVALID); + assertThat(SpanId.fromLowerBase16("0000000000000061")).isEqualTo(first); + assertThat(SpanId.fromLowerBase16("ff00000000000041")).isEqualTo(second); + } + + @Test + public void toLowerBase16() { + assertThat(SpanId.INVALID.toLowerBase16()).isEqualTo("0000000000000000"); + assertThat(first.toLowerBase16()).isEqualTo("0000000000000061"); + assertThat(second.toLowerBase16()).isEqualTo("ff00000000000041"); + } + @Test public void getBytes() { assertThat(first.getBytes()).isEqualTo(firstBytes); @@ -71,6 +85,6 @@ public class SpanIdTest { public void traceId_ToString() { assertThat(SpanId.INVALID.toString()).contains("0000000000000000"); assertThat(first.toString()).contains("0000000000000061"); - assertThat(second.toString()).contains("ff00000000000000"); + assertThat(second.toString()).contains("ff00000000000041"); } } diff --git a/api/src/test/java/io/opencensus/trace/TraceIdTest.java b/api/src/test/java/io/opencensus/trace/TraceIdTest.java index 8c1a1004..c8b5dc8f 100644 --- a/api/src/test/java/io/opencensus/trace/TraceIdTest.java +++ b/api/src/test/java/io/opencensus/trace/TraceIdTest.java @@ -30,7 +30,7 @@ public class TraceIdTest { private static final byte[] firstBytes = new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'a'}; private static final byte[] secondBytes = - new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'A'}; + new byte[] {(byte) 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'A'}; private static final TraceId first = TraceId.fromBytes(firstBytes); private static final TraceId second = TraceId.fromBytes(secondBytes); @@ -52,6 +52,21 @@ public class TraceIdTest { assertThat(second.getBytes()).isEqualTo(secondBytes); } + @Test + public void fromLowerBase16() { + assertThat(TraceId.fromLowerBase16("00000000000000000000000000000000")) + .isEqualTo(TraceId.INVALID); + assertThat(TraceId.fromLowerBase16("00000000000000000000000000000061")).isEqualTo(first); + assertThat(TraceId.fromLowerBase16("ff000000000000000000000000000041")).isEqualTo(second); + } + + @Test + public void toLowerBase16() { + assertThat(TraceId.INVALID.toLowerBase16()).isEqualTo("00000000000000000000000000000000"); + assertThat(first.toLowerBase16()).isEqualTo("00000000000000000000000000000061"); + assertThat(second.toLowerBase16()).isEqualTo("ff000000000000000000000000000041"); + } + @Test public void traceId_CompareTo() { assertThat(first.compareTo(second)).isGreaterThan(0); @@ -73,6 +88,6 @@ public class TraceIdTest { public void traceId_ToString() { assertThat(TraceId.INVALID.toString()).contains("00000000000000000000000000000000"); assertThat(first.toString()).contains("00000000000000000000000000000061"); - assertThat(second.toString()).contains("00000000000000000000000000000041"); + assertThat(second.toString()).contains("ff000000000000000000000000000041"); } } diff --git a/api/src/test/java/io/opencensus/trace/TracerTest.java b/api/src/test/java/io/opencensus/trace/TracerTest.java index 7c65742e..8f0ac64f 100644 --- a/api/src/test/java/io/opencensus/trace/TracerTest.java +++ b/api/src/test/java/io/opencensus/trace/TracerTest.java @@ -23,9 +23,7 @@ import static org.mockito.Mockito.when; import io.grpc.Context; import io.opencensus.common.Scope; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.Mock; @@ -38,7 +36,6 @@ import org.mockito.MockitoAnnotations; public class TracerTest { private static final Tracer noopTracer = Tracer.getNoopTracer(); private static final String SPAN_NAME = "MySpanName"; - @Rule public ExpectedException thrown = ExpectedException.none(); @Mock private Tracer tracer; @Mock private SpanBuilder spanBuilder; @Mock private Span span; -- cgit v1.2.3 From 456400af2088da6519607bfeee8cec93c613bee6 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Mon, 11 Dec 2017 19:27:33 -0800 Subject: Change fromHex methods to accept CharSequence. (#897) --- api/src/main/java/io/opencensus/trace/SpanId.java | 2 +- api/src/main/java/io/opencensus/trace/TraceId.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/SpanId.java b/api/src/main/java/io/opencensus/trace/SpanId.java index a986d013..cf0c7d46 100644 --- a/api/src/main/java/io/opencensus/trace/SpanId.java +++ b/api/src/main/java/io/opencensus/trace/SpanId.java @@ -92,7 +92,7 @@ public final class SpanId implements Comparable { * @throws IllegalArgumentException if {@code src.length} is not {@code 2 * SpanId.SIZE} OR if the * {@code str} has invalid characters. */ - public static SpanId fromLowerBase16(String src) { + public static SpanId fromLowerBase16(CharSequence src) { checkArgument( src.length() == 2 * SIZE, "Invalid size: expected %s, got %s", 2 * SIZE, src.length()); byte[] bytes = BaseEncoding.base16().lowerCase().decode(src); diff --git a/api/src/main/java/io/opencensus/trace/TraceId.java b/api/src/main/java/io/opencensus/trace/TraceId.java index 44b80a66..20f81393 100644 --- a/api/src/main/java/io/opencensus/trace/TraceId.java +++ b/api/src/main/java/io/opencensus/trace/TraceId.java @@ -93,7 +93,7 @@ public final class TraceId implements Comparable { * @throws IllegalArgumentException if {@code src.length} is not {@code 2 * TraceId.SIZE} OR if * the {@code str} has invalid characters. */ - public static TraceId fromLowerBase16(String src) { + public static TraceId fromLowerBase16(CharSequence src) { checkArgument( src.length() == 2 * SIZE, "Invalid size: expected %s, got %s", 2 * SIZE, src.length()); byte[] bytes = BaseEncoding.base16().lowerCase().decode(src); -- cgit v1.2.3 From 65398bb0c56beccc0b3058b5b1137aabcbe76cd5 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Wed, 13 Dec 2017 23:25:04 -0800 Subject: Add methods to wrap Runnable and Callbacks and to run them. (#778) * Add methods to wrap Runnable and Callbacks and to run them. * Fix more comments. * Fix use of Assert.fail(). * Improve javadocs for the start and wrap methods. * Remove startSpanAndWrap API for the moment. * Change wrap to withSpan. * Fix examples in SpanBuilders. --- .../java/io/opencensus/trace/CurrentSpanUtils.java | 98 ++++++++- .../main/java/io/opencensus/trace/SpanBuilder.java | 63 ++++++ api/src/main/java/io/opencensus/trace/Tracer.java | 131 ++++++++++++ .../io/opencensus/trace/CurrentSpanUtilsTest.java | 224 +++++++++++++++++++-- .../java/io/opencensus/trace/SpanBuilderTest.java | 91 +++++++++ .../test/java/io/opencensus/trace/TracerTest.java | 51 +++-- 6 files changed, 620 insertions(+), 38 deletions(-) create mode 100644 api/src/test/java/io/opencensus/trace/SpanBuilderTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java index 713c8816..539339bc 100644 --- a/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java +++ b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java @@ -16,9 +16,11 @@ package io.opencensus.trace; +import com.google.common.base.Throwables; import io.grpc.Context; import io.opencensus.common.Scope; import io.opencensus.trace.unsafe.ContextUtils; +import java.util.concurrent.Callable; /** Util methods/functionality to interact with the {@link Span} in the {@link io.grpc.Context}. */ final class CurrentSpanUtils { @@ -49,6 +51,30 @@ final class CurrentSpanUtils { return new ScopeInSpan(span, endSpan); } + /** + * Wraps a {@link Runnable} so that it executes with the {@code span} as the current {@code Span}. + * + * @param span the {@code Span} to be set as current. + * @param endSpan if {@code true} the returned {@code Runnable} will close the {@code Span}. + * @param runnable the {@code Runnable} to run in the {@code Span}. + * @return the wrapped {@code Runnable}. + */ + static Runnable withSpan(Span span, boolean endSpan, Runnable runnable) { + return new RunnableInSpan(span, runnable, endSpan); + } + + /** + * Wraps a {@link Callable} so that it executes with the {@code span} as the current {@code Span}. + * + * @param span the {@code Span} to be set as current. + * @param endSpan if {@code true} the returned {@code Runnable} will close the {@code Span}. + * @param callable the {@code Callable} to run in the {@code Span}. + * @return the wrapped {@code Callable}. + */ + static Callable withSpan(Span span, boolean endSpan, Callable callable) { + return new CallableInSpan(span, callable, endSpan); + } + // Defines an arbitrary scope of code as a traceable operation. Supports try-with-resources idiom. private static final class ScopeInSpan implements Scope { private final Context origContext; @@ -60,7 +86,7 @@ final class CurrentSpanUtils { * * @param span is the {@code Span} to be added to the current {@code io.grpc.Context}. */ - ScopeInSpan(Span span, boolean endSpan) { + private ScopeInSpan(Span span, boolean endSpan) { this.span = span; this.endSpan = endSpan; origContext = Context.current().withValue(ContextUtils.CONTEXT_SPAN_KEY, span).attach(); @@ -74,4 +100,74 @@ final class CurrentSpanUtils { } } } + + private static final class RunnableInSpan implements Runnable { + // TODO(bdrutu): Investigate if the extra private visibility increases the generated bytecode. + private final Span span; + private final Runnable runnable; + private final boolean endSpan; + + private RunnableInSpan(Span span, Runnable runnable, boolean endSpan) { + this.span = span; + this.runnable = runnable; + this.endSpan = endSpan; + } + + @Override + public void run() { + Context origContext = + Context.current().withValue(ContextUtils.CONTEXT_SPAN_KEY, span).attach(); + try { + runnable.run(); + } catch (Throwable t) { + setErrorStatus(span, t); + Throwables.propagateIfPossible(t); + throw new RuntimeException("unexpected", t); + } finally { + Context.current().detach(origContext); + if (endSpan) { + span.end(); + } + } + } + } + + private static final class CallableInSpan implements Callable { + private final Span span; + private final Callable callable; + private final boolean endSpan; + + private CallableInSpan(Span span, Callable callable, boolean endSpan) { + this.span = span; + this.callable = callable; + this.endSpan = endSpan; + } + + @Override + public V call() throws Exception { + Context origContext = + Context.current().withValue(ContextUtils.CONTEXT_SPAN_KEY, span).attach(); + try { + return callable.call(); + } catch (Exception e) { + setErrorStatus(span, e); + throw e; + } catch (Throwable t) { + setErrorStatus(span, t); + Throwables.propagateIfPossible(t); + throw new RuntimeException("unexpected", t); + } finally { + Context.current().detach(origContext); + if (endSpan) { + span.end(); + } + } + } + } + + private static void setErrorStatus(Span span, Throwable t) { + span.setStatus( + Status.UNKNOWN.withDescription( + t.getMessage() == null ? t.getClass().getSimpleName() : t.getMessage())); + } } diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java index 4c28147e..0a7c9177 100644 --- a/api/src/main/java/io/opencensus/trace/SpanBuilder.java +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -21,6 +21,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.errorprone.annotations.MustBeClosed; import io.opencensus.common.Scope; import java.util.List; +import java.util.concurrent.Callable; import javax.annotation.Nullable; /** @@ -223,6 +224,68 @@ public abstract class SpanBuilder { return CurrentSpanUtils.withSpan(startSpan(), true); } + /** + * Starts a new span and runs the given {@code Runnable} with the newly created {@code Span} as + * the current {@code Span}, and ends the {@code Span} after the {@code Runnable} is run. + * + *

    Any error will end up as a {@link Status#UNKNOWN}. + * + *

    
    +   * tracer.spanBuilder("MyRunnableSpan").startSpanAndRun(myRunnable);
    +   * 
    + * + *

    It is equivalent with the following code: + * + *

    
    +   * Span span = tracer.spanBuilder("MyRunnableSpan").startSpan();
    +   * Runnable newRunnable = tracer.withSpan(span, myRunnable);
    +   * try {
    +   *   newRunnable.run();
    +   * } finally {
    +   *   span.end();
    +   * }
    +   * 
    + * + * @param runnable the {@code Runnable} to run in the {@code Span}. + * @since 0.11.0 + */ + public final void startSpanAndRun(final Runnable runnable) { + final Span span = startSpan(); + CurrentSpanUtils.withSpan(span, true, runnable).run(); + } + + /** + * Starts a new span and calls the given {@code Callable} with the newly created {@code Span} as + * the current {@code Span}, and ends the {@code Span} after the {@code Callable} is called. + * + *

    Any error will end up as a {@link Status#UNKNOWN}. + * + *

    
    +   * MyResult myResult = tracer.spanBuilder("MyCallableSpan").startSpanAndCall(myCallable);
    +   * 
    + * + *

    It is equivalent with the following code: + * + *

    
    +   * Span span = tracer.spanBuilder("MyCallableSpan").startSpan();
    +   * {@code Callable} newCallable = tracer.withSpan(span, myCallable);
    +   * MyResult myResult = null;
    +   * try {
    +   *   myResult = newCallable.call();
    +   * } finally {
    +   *   span.end();
    +   * }
    +   * );
    +   * 
    + * + * @param callable the {@code Callable} to run in the {@code Span}. + * @since 0.11.0 + */ + public final V startSpanAndCall(Callable callable) throws Exception { + final Span span = startSpan(); + return CurrentSpanUtils.withSpan(span, true, callable).call(); + } + static final class NoopSpanBuilder extends SpanBuilder { static NoopSpanBuilder createWithParent(String spanName, @Nullable Span parent) { return new NoopSpanBuilder(spanName); diff --git a/api/src/main/java/io/opencensus/trace/Tracer.java b/api/src/main/java/io/opencensus/trace/Tracer.java index 8215f7b1..cd4fc822 100644 --- a/api/src/main/java/io/opencensus/trace/Tracer.java +++ b/api/src/main/java/io/opencensus/trace/Tracer.java @@ -21,6 +21,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.errorprone.annotations.MustBeClosed; import io.opencensus.common.Scope; import io.opencensus.trace.SpanBuilder.NoopSpanBuilder; +import java.util.concurrent.Callable; import javax.annotation.Nullable; /** @@ -150,6 +151,136 @@ public abstract class Tracer { return CurrentSpanUtils.withSpan(checkNotNull(span, "span"), false); } + /** + * Returns a {@link Runnable} that runs the given task with the given {@code Span} in the current + * context. + * + *

    Users may consider to use {@link SpanBuilder#startSpanAndRun(Runnable)}. + * + *

    Any error will end up as a {@link Status#UNKNOWN}. + * + *

    IMPORTANT: Caller must manually propagate the entire {@code io.grpc.Context} when wraps a + * {@code Runnable}, see the examples. + * + *

    IMPORTANT: Caller must manually end the {@code Span} within the {@code Runnable}, or after + * the {@code Runnable} is executed. + * + *

    Example with Executor wrapped with {@link io.grpc.Context#currentContextExecutor}: + * + *

    
    +   * class MyClass {
    +   *   private static Tracer tracer = Tracing.getTracer();
    +   *   void handleRequest(Executor executor) {
    +   *     Span span = new Tracer.spanBuilder("MyRunnableSpan");
    +   *     executor.execute(tracer.withSpan(span, new Runnable() {
    +   *      {@literal @}Override
    +   *       public void run() {
    +   *         try {
    +   *           sendResult();
    +   *         } finally {
    +   *           span.end();
    +   *         }
    +   *       }
    +   *     }));
    +   *   }
    +   * }
    +   * 
    + * + *

    Example without Executor wrapped with {@link io.grpc.Context#currentContextExecutor}: + * + *

    
    +   * class MyClass {
    +   *   private static Tracer tracer = Tracing.getTracer();
    +   *   void handleRequest(Executor executor) {
    +   *     Span span = new Tracer.spanBuilder("MyRunnableSpan");
    +   *     executor.execute(Context.wrap(tracer.withSpan(span, new Runnable() {
    +   *      {@literal @}Override
    +   *       public void run() {
    +   *         try {
    +   *           sendResult();
    +   *         } finally {
    +   *           span.end();
    +   *         }
    +   *       }
    +   *     })));
    +   *   }
    +   * }
    +   * 
    + * + * @param span the {@code Span} to be set as current. + * @param runnable the {@code Runnable} to withSpan in the {@code Span}. + * @return the {@code Runnable}. + * @since 0.11.0 + */ + public final Runnable withSpan(Span span, Runnable runnable) { + return CurrentSpanUtils.withSpan(span, false, runnable); + } + + /** + * Returns a {@link Callable} that runs the given task with the given {@code Span} in the current + * context. + * + *

    Users may consider to use {@link SpanBuilder#startSpanAndCall(Callable)}. + * + *

    Any error will end up as a {@link Status#UNKNOWN}. + * + *

    IMPORTANT: Caller must manually propagate the entire {@code io.grpc.Context} when wraps a + * {@code Callable}, see the examples. + * + *

    IMPORTANT: Caller must manually end the {@code Span} within the {@code Callable}, or after + * the {@code Callable} is executed. + * + *

    Example with Executor wrapped with {@link io.grpc.Context#currentContextExecutor}: + * + *

    
    +   * class MyClass {
    +   *   private static Tracer tracer = Tracing.getTracer();
    +   *   void handleRequest(Executor executor) {
    +   *     Span span = new Tracer.spanBuilder("MyRunnableSpan");
    +   *     executor.execute(tracer.withSpan(span, {@code new Callable()} {
    +   *      {@literal @}Override
    +   *       public MyResult call() throws Exception {
    +   *         try {
    +   *           return sendResult();
    +   *         } finally {
    +   *           span.end();
    +   *         }
    +   *       }
    +   *     }));
    +   *   }
    +   * }
    +   * 
    + * + *

    Example without Executor wrapped with {@link io.grpc.Context#currentContextExecutor}: + * + *

    
    +   * class MyClass {
    +   *   private static Tracer tracer = Tracing.getTracer();
    +   *   void handleRequest(Executor executor) {
    +   *     Span span = new Tracer.spanBuilder("MyRunnableSpan");
    +   *     executor.execute(Context.wrap(tracer.withSpan(span, {@code new Callable()} {
    +   *      {@literal @}Override
    +   *       public MyResult call() throws Exception {
    +   *         try {
    +   *           return sendResult();
    +   *         } finally {
    +   *           span.end();
    +   *         }
    +   *       }
    +   *     })));
    +   *   }
    +   * }
    +   * 
    + * + * @param span the {@code Span} to be set as current. + * @param callable the {@code Callable} to run in the {@code Span}. + * @return the {@code Callable}. + * @since 0.11.0 + */ + public final Callable withSpan(Span span, final Callable callable) { + return CurrentSpanUtils.withSpan(span, false, callable); + } + /** * Returns a {@link SpanBuilder} to create and start a new child {@link Span} as a child of to the * current {@code Span} if any, otherwise creates a root {@code Span}. diff --git a/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java b/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java index 8ba910b0..6b16c3d0 100644 --- a/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java +++ b/api/src/test/java/io/opencensus/trace/CurrentSpanUtilsTest.java @@ -24,6 +24,7 @@ import static org.mockito.Mockito.verifyZeroInteractions; import io.grpc.Context; import io.opencensus.common.Scope; import io.opencensus.trace.unsafe.ContextUtils; +import java.util.concurrent.Callable; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -41,6 +42,30 @@ public class CurrentSpanUtilsTest { MockitoAnnotations.initMocks(this); } + // TODO(bdrutu): When update to junit 4.13 use assertThrows instead of this. + private void executeRunnableAndExpectError(Runnable runnable, Throwable error) { + boolean called = false; + try { + CurrentSpanUtils.withSpan(span, true, runnable).run(); + } catch (Throwable e) { + assertThat(e).isEqualTo(error); + called = true; + } + assertThat(called).isTrue(); + } + + // TODO(bdrutu): When update to junit 4.13 use assertThrows instead of this. + private void executeCallableAndExpectError(Callable callable, Throwable error) { + boolean called = false; + try { + CurrentSpanUtils.withSpan(span, true, callable).call(); + } catch (Throwable e) { + assertThat(e).isEqualTo(error); + called = true; + } + assertThat(called).isTrue(); + } + @Test public void getCurrentSpan_WhenNoContext() { assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); @@ -86,25 +111,184 @@ public class CurrentSpanUtilsTest { } @Test - public void propagationViaRunnable() { - Runnable runnable = null; - Scope ws = CurrentSpanUtils.withSpan(span, false); - try { - assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); - runnable = - Context.current() - .wrap( - new Runnable() { - @Override - public void run() { - assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); - } - }); - } finally { - ws.close(); - } - assertThat(CurrentSpanUtils.getCurrentSpan()).isNotSameAs(span); - // When we run the runnable we will have the span in the current Context. - runnable.run(); + public void withSpanRunnable() { + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Runnable runnable = + new Runnable() { + @Override + public void run() { + // When we run the runnable we will have the span in the current Context. + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + } + }; + CurrentSpanUtils.withSpan(span, false, runnable).run(); + verifyZeroInteractions(span); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void withSpanRunnable_EndSpan() { + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Runnable runnable = + new Runnable() { + @Override + public void run() { + // When we run the runnable we will have the span in the current Context. + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + } + }; + CurrentSpanUtils.withSpan(span, true, runnable).run(); + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void withSpanRunnable_WithError() { + final AssertionError error = new AssertionError("MyError"); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Runnable runnable = + new Runnable() { + @Override + public void run() { + // When we run the runnable we will have the span in the current Context. + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + throw error; + } + }; + executeRunnableAndExpectError(runnable, error); + verify(span).setStatus(Status.UNKNOWN.withDescription("MyError")); + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void withSpanRunnable_WithErrorNoMessage() { + final AssertionError error = new AssertionError(); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Runnable runnable = + new Runnable() { + @Override + public void run() { + // When we run the runnable we will have the span in the current Context. + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + throw error; + } + }; + executeRunnableAndExpectError(runnable, error); + verify(span).setStatus(Status.UNKNOWN.withDescription("AssertionError")); + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void withSpanCallable() throws Exception { + final Object ret = new Object(); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Callable callable = + new Callable() { + @Override + public Object call() throws Exception { + // When we run the runnable we will have the span in the current Context. + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + return ret; + } + }; + assertThat(CurrentSpanUtils.withSpan(span, false, callable).call()).isEqualTo(ret); + verifyZeroInteractions(span); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void withSpanCallable_EndSpan() throws Exception { + final Object ret = new Object(); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Callable callable = + new Callable() { + @Override + public Object call() throws Exception { + // When we run the runnable we will have the span in the current Context. + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + return ret; + } + }; + assertThat(CurrentSpanUtils.withSpan(span, true, callable).call()).isEqualTo(ret); + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void withSpanCallable_WithException() { + final Exception exception = new Exception("MyException"); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Callable callable = + new Callable() { + @Override + public Object call() throws Exception { + // When we run the runnable we will have the span in the current Context. + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + throw exception; + } + }; + executeCallableAndExpectError(callable, exception); + verify(span).setStatus(Status.UNKNOWN.withDescription("MyException")); + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void withSpanCallable_WithExceptionNoMessage() { + final Exception exception = new Exception(); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Callable callable = + new Callable() { + @Override + public Object call() throws Exception { + // When we run the runnable we will have the span in the current Context. + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + throw exception; + } + }; + executeCallableAndExpectError(callable, exception); + verify(span).setStatus(Status.UNKNOWN.withDescription("Exception")); + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void withSpanCallable_WithError() { + final AssertionError error = new AssertionError("MyError"); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Callable callable = + new Callable() { + @Override + public Object call() throws Exception { + // When we run the runnable we will have the span in the current Context. + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + throw error; + } + }; + executeCallableAndExpectError(callable, error); + verify(span).setStatus(Status.UNKNOWN.withDescription("MyError")); + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + } + + @Test + public void withSpanCallable_WithErrorNoMessage() { + final AssertionError error = new AssertionError(); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); + Callable callable = + new Callable() { + @Override + public Object call() throws Exception { + // When we run the runnable we will have the span in the current Context. + assertThat(CurrentSpanUtils.getCurrentSpan()).isSameAs(span); + throw error; + } + }; + executeCallableAndExpectError(callable, error); + verify(span).setStatus(Status.UNKNOWN.withDescription("AssertionError")); + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(CurrentSpanUtils.getCurrentSpan()).isNull(); } } diff --git a/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java b/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java new file mode 100644 index 00000000..1403db15 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java @@ -0,0 +1,91 @@ +/* + * 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; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.opencensus.common.Scope; +import java.util.concurrent.Callable; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** Unit tests for {@link SpanBuilder}. */ +@RunWith(JUnit4.class) +// Need to suppress warnings for MustBeClosed because Java-6 does not support try-with-resources. +@SuppressWarnings("MustBeClosedChecker") +public class SpanBuilderTest { + private Tracer tracer = Tracing.getTracer(); + @Mock private SpanBuilder spanBuilder; + @Mock private Span span; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + when(spanBuilder.startSpan()).thenReturn(span); + } + + @Test + public void startScopedSpan() { + assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + Scope scope = spanBuilder.startScopedSpan(); + try { + assertThat(tracer.getCurrentSpan()).isSameAs(span); + } finally { + scope.close(); + } + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + } + + @Test + public void startSpanAndRun() { + assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + spanBuilder.startSpanAndRun( + new Runnable() { + @Override + public void run() { + assertThat(tracer.getCurrentSpan()).isSameAs(span); + } + }); + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + } + + @Test + public void startSpanAndCall() throws Exception { + final Object ret = new Object(); + assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + assertThat( + spanBuilder.startSpanAndCall( + new Callable() { + @Override + public Object call() throws Exception { + assertThat(tracer.getCurrentSpan()).isSameAs(span); + return ret; + } + })) + .isEqualTo(ret); + verify(span).end(EndSpanOptions.DEFAULT); + assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + } +} diff --git a/api/src/test/java/io/opencensus/trace/TracerTest.java b/api/src/test/java/io/opencensus/trace/TracerTest.java index 8f0ac64f..58dd4bbe 100644 --- a/api/src/test/java/io/opencensus/trace/TracerTest.java +++ b/api/src/test/java/io/opencensus/trace/TracerTest.java @@ -18,10 +18,11 @@ package io.opencensus.trace; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Matchers.same; +import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; -import io.grpc.Context; import io.opencensus.common.Scope; +import java.util.concurrent.Callable; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -68,26 +69,42 @@ public class TracerTest { } @Test - public void propagationViaRunnable() { + public void wrapRunnable() { Runnable runnable; - Scope ws = noopTracer.withSpan(span); - try { - assertThat(noopTracer.getCurrentSpan()).isSameAs(span); - runnable = - Context.current() - .wrap( - new Runnable() { - @Override - public void run() { - assertThat(noopTracer.getCurrentSpan()).isSameAs(span); - } - }); - } finally { - ws.close(); - } assertThat(noopTracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + runnable = + tracer.withSpan( + span, + new Runnable() { + @Override + public void run() { + assertThat(noopTracer.getCurrentSpan()).isSameAs(span); + } + }); // When we run the runnable we will have the span in the current Context. runnable.run(); + verifyZeroInteractions(span); + assertThat(noopTracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + } + + @Test + public void wrapCallable() throws Exception { + final Object ret = new Object(); + Callable callable; + assertThat(noopTracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); + callable = + tracer.withSpan( + span, + new Callable() { + @Override + public Object call() throws Exception { + assertThat(noopTracer.getCurrentSpan()).isSameAs(span); + return ret; + } + }); + // When we call the callable we will have the span in the current Context. + assertThat(callable.call()).isEqualTo(ret); + verifyZeroInteractions(span); assertThat(noopTracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); } -- cgit v1.2.3 From 2ca42d812c7c01f229635d35c26c854f621ef962 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Tue, 19 Dec 2017 09:40:03 -0800 Subject: Validate types of Aggregation and AggregationData when creating ViewData (#839) --- .../main/java/io/opencensus/stats/ViewData.java | 162 ++++++++++++++++----- .../java/io/opencensus/stats/ViewDataTest.java | 84 +++++++++-- 2 files changed, 203 insertions(+), 43 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/ViewData.java b/api/src/main/java/io/opencensus/stats/ViewData.java index 458b1f1a..8c056521 100644 --- a/api/src/main/java/io/opencensus/stats/ViewData.java +++ b/api/src/main/java/io/opencensus/stats/ViewData.java @@ -16,11 +16,25 @@ package io.opencensus.stats; +import static com.google.common.base.Preconditions.checkArgument; + import com.google.auto.value.AutoValue; import com.google.common.collect.Maps; import io.opencensus.common.Function; import io.opencensus.common.Functions; import io.opencensus.common.Timestamp; +import io.opencensus.stats.Aggregation.Count; +import io.opencensus.stats.Aggregation.Distribution; +import io.opencensus.stats.Aggregation.Mean; +import io.opencensus.stats.Aggregation.Sum; +import io.opencensus.stats.AggregationData.CountData; +import io.opencensus.stats.AggregationData.DistributionData; +import io.opencensus.stats.AggregationData.MeanData; +import io.opencensus.stats.AggregationData.SumDataDouble; +import io.opencensus.stats.AggregationData.SumDataLong; +import io.opencensus.stats.Measure.MeasureDouble; +import io.opencensus.stats.Measure.MeasureLong; +import io.opencensus.stats.View.AggregationWindow; import io.opencensus.tags.TagValue; import java.util.ArrayList; import java.util.Collections; @@ -53,52 +67,132 @@ public abstract class ViewData { */ public abstract AggregationWindowData getWindowData(); - /** Constructs a new {@link ViewData}. */ + /** + * Constructs a new {@link ViewData}. + * + * @param view the {@link View} associated with this {@link ViewData}. + * @param map the mapping from {@link TagValue} list to {@link AggregationData}. + * @param windowData the {@link AggregationWindowData}. + * @return a {@code ViewData}. + * @throws IllegalArgumentException if the types of {@code Aggregation} and {@code + * AggregationData} don't match, or the types of {@code Window} and {@code WindowData} don't + * match. + */ public static ViewData create( View view, Map, ? extends AggregationData> map, final AggregationWindowData windowData) { - view.getWindow() - .match( - new Function() { - @Override - public Void apply(View.AggregationWindow.Cumulative arg) { - if (!(windowData instanceof AggregationWindowData.CumulativeData)) { - throw new IllegalArgumentException( - "AggregationWindow and AggregationWindowData types mismatch. " - + "AggregationWindow: " - + arg - + " AggregationWindowData: " - + windowData); - } - return null; - } - }, - new Function() { - @Override - public Void apply(View.AggregationWindow.Interval arg) { - if (!(windowData instanceof AggregationWindowData.IntervalData)) { - throw new IllegalArgumentException( - "AggregationWindow and AggregationWindowData types mismatch. " - + "AggregationWindow: " - + arg - + " AggregationWindowData: " - + windowData); - } - return null; - } - }, - Functions.throwIllegalArgumentException()); - + checkWindow(view.getWindow(), windowData); Map, AggregationData> deepCopy = Maps.newHashMap(); for (Entry, ? extends AggregationData> entry : map.entrySet()) { + checkAggregation(view.getAggregation(), entry.getValue(), view.getMeasure()); deepCopy.put( Collections.unmodifiableList(new ArrayList(entry.getKey())), entry.getValue()); } - return new AutoValue_ViewData(view, Collections.unmodifiableMap(deepCopy), windowData); } + private static void checkWindow( + AggregationWindow window, final AggregationWindowData windowData) { + window.match( + new Function() { + @Override + public Void apply(View.AggregationWindow.Cumulative arg) { + checkArgument( + windowData instanceof AggregationWindowData.CumulativeData, + createErrorMessageForWindow(arg, windowData)); + return null; + } + }, + new Function() { + @Override + public Void apply(View.AggregationWindow.Interval arg) { + checkArgument( + windowData instanceof AggregationWindowData.IntervalData, + createErrorMessageForWindow(arg, windowData)); + return null; + } + }, + Functions.throwIllegalArgumentException()); + } + + private static String createErrorMessageForWindow( + AggregationWindow window, AggregationWindowData windowData) { + return "AggregationWindow and AggregationWindowData types mismatch. " + + "AggregationWindow: " + + window + + " AggregationWindowData: " + + windowData; + } + + private static void checkAggregation( + final Aggregation aggregation, final AggregationData aggregationData, final Measure measure) { + aggregation.match( + new Function() { + @Override + public Void apply(Sum arg) { + measure.match( + new Function() { + @Override + public Void apply(MeasureDouble arg) { + checkArgument( + aggregationData instanceof SumDataDouble, + createErrorMessageForAggregation(aggregation, aggregationData)); + return null; + } + }, + new Function() { + @Override + public Void apply(MeasureLong arg) { + checkArgument( + aggregationData instanceof SumDataLong, + createErrorMessageForAggregation(aggregation, aggregationData)); + return null; + } + }, + Functions.throwAssertionError()); + return null; + } + }, + new Function() { + @Override + public Void apply(Count arg) { + checkArgument( + aggregationData instanceof CountData, + createErrorMessageForAggregation(aggregation, aggregationData)); + return null; + } + }, + new Function() { + @Override + public Void apply(Mean arg) { + checkArgument( + aggregationData instanceof MeanData, + createErrorMessageForAggregation(aggregation, aggregationData)); + return null; + } + }, + new Function() { + @Override + public Void apply(Distribution arg) { + checkArgument( + aggregationData instanceof DistributionData, + createErrorMessageForAggregation(aggregation, aggregationData)); + return null; + } + }, + Functions.throwAssertionError()); + } + + private static String createErrorMessageForAggregation( + Aggregation aggregation, AggregationData aggregationData) { + return "Aggregation and AggregationData types mismatch. " + + "Aggregation: " + + aggregation + + " AggregationData: " + + aggregationData; + } + /** The {@code AggregationWindowData} for a {@link ViewData}. */ @Immutable public abstract static class AggregationWindowData { diff --git a/api/src/test/java/io/opencensus/stats/ViewDataTest.java b/api/src/test/java/io/opencensus/stats/ViewDataTest.java index 028506fb..0dc78e33 100644 --- a/api/src/test/java/io/opencensus/stats/ViewDataTest.java +++ b/api/src/test/java/io/opencensus/stats/ViewDataTest.java @@ -25,8 +25,14 @@ import io.opencensus.common.Duration; import io.opencensus.common.Function; import io.opencensus.common.Functions; import io.opencensus.common.Timestamp; +import io.opencensus.stats.Aggregation.Count; import io.opencensus.stats.Aggregation.Distribution; +import io.opencensus.stats.Aggregation.Mean; +import io.opencensus.stats.Aggregation.Sum; +import io.opencensus.stats.AggregationData.CountData; import io.opencensus.stats.AggregationData.DistributionData; +import io.opencensus.stats.AggregationData.SumDataDouble; +import io.opencensus.stats.AggregationData.SumDataLong; import io.opencensus.stats.View.AggregationWindow; import io.opencensus.stats.View.AggregationWindow.Cumulative; import io.opencensus.stats.View.AggregationWindow.Interval; @@ -38,6 +44,7 @@ import io.opencensus.tags.TagValue; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Map; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -52,7 +59,7 @@ public final class ViewDataTest { @Test public void testCumulativeViewData() { - View view = View.create(NAME, DESCRIPTION, MEASURE, DISTRIBUTION, tagKeys, CUMULATIVE); + View view = View.create(NAME, DESCRIPTION, MEASURE_DOUBLE, DISTRIBUTION, TAG_KEYS, CUMULATIVE); Timestamp start = Timestamp.fromMillis(1000); Timestamp end = Timestamp.fromMillis(2000); AggregationWindowData windowData = CumulativeData.create(start, end); @@ -64,7 +71,8 @@ public final class ViewDataTest { @Test public void testIntervalViewData() { - View view = View.create(NAME, DESCRIPTION, MEASURE, DISTRIBUTION, tagKeys, INTERVAL_HOUR); + View view = + View.create(NAME, DESCRIPTION, MEASURE_DOUBLE, DISTRIBUTION, TAG_KEYS, INTERVAL_HOUR); Timestamp end = Timestamp.fromMillis(2000); AggregationWindowData windowData = IntervalData.create(end); ViewData viewData = ViewData.create(view, ENTRIES, windowData); @@ -76,9 +84,9 @@ public final class ViewDataTest { @Test public void testViewDataEquals() { View cumulativeView = - View.create(NAME, DESCRIPTION, MEASURE, DISTRIBUTION, tagKeys, CUMULATIVE); + View.create(NAME, DESCRIPTION, MEASURE_DOUBLE, DISTRIBUTION, TAG_KEYS, CUMULATIVE); View intervalView = - View.create(NAME, DESCRIPTION, MEASURE, DISTRIBUTION, tagKeys, INTERVAL_HOUR); + View.create(NAME, DESCRIPTION, MEASURE_DOUBLE, DISTRIBUTION, TAG_KEYS, INTERVAL_HOUR); new EqualsTester() .addEqualityGroup( @@ -150,8 +158,9 @@ public final class ViewDataTest { @Test public void preventWindowAndAggregationWindowDataMismatch() { thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("AggregationWindow and AggregationWindowData types mismatch. "); ViewData.create( - View.create(NAME, DESCRIPTION, MEASURE, DISTRIBUTION, tagKeys, INTERVAL_HOUR), + View.create(NAME, DESCRIPTION, MEASURE_DOUBLE, DISTRIBUTION, TAG_KEYS, INTERVAL_HOUR), ENTRIES, CumulativeData.create(Timestamp.fromMillis(1000), Timestamp.fromMillis(2000))); } @@ -159,8 +168,9 @@ public final class ViewDataTest { @Test public void preventWindowAndAggregationWindowDataMismatch2() { thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("AggregationWindow and AggregationWindowData types mismatch. "); ViewData.create( - View.create(NAME, DESCRIPTION, MEASURE, DISTRIBUTION, tagKeys, CUMULATIVE), + View.create(NAME, DESCRIPTION, MEASURE_DOUBLE, DISTRIBUTION, TAG_KEYS, CUMULATIVE), ENTRIES, IntervalData.create(Timestamp.fromMillis(1000))); } @@ -171,10 +181,64 @@ public final class ViewDataTest { CumulativeData.create(Timestamp.fromMillis(3000), Timestamp.fromMillis(2000)); } + @Test + public void preventAggregationAndAggregationDataMismatch_SumDouble_SumLong() { + aggregationAndAggregationDataMismatch( + createView(Sum.create(), MEASURE_DOUBLE), + ImmutableMap., AggregationData>of( + Arrays.asList(V1, V2), SumDataLong.create(100))); + } + + @Test + public void preventAggregationAndAggregationDataMismatch_SumLong_SumDouble() { + aggregationAndAggregationDataMismatch( + createView(Sum.create(), MEASURE_LONG), + ImmutableMap., AggregationData>of( + Arrays.asList(V1, V2), SumDataDouble.create(100))); + } + + @Test + public void preventAggregationAndAggregationDataMismatch_Count_Distribution() { + aggregationAndAggregationDataMismatch(createView(Count.create()), ENTRIES); + } + + @Test + public void preventAggregationAndAggregationDataMismatch_Mean_Distribution() { + aggregationAndAggregationDataMismatch(createView(Mean.create()), ENTRIES); + } + + @Test + public void preventAggregationAndAggregationDataMismatch_Distribution_Count() { + aggregationAndAggregationDataMismatch( + createView(DISTRIBUTION), + ImmutableMap.of( + Arrays.asList(V1, V2), + DistributionData.create(1, 1, 1, 1, 0, Arrays.asList(0L, 1L, 0L)), + Arrays.asList(V10, V20), + CountData.create(100))); + } + + private static View createView(Aggregation aggregation) { + return createView(aggregation, MEASURE_DOUBLE); + } + + private static View createView(Aggregation aggregation, Measure measure) { + return View.create(NAME, DESCRIPTION, measure, aggregation, TAG_KEYS, CUMULATIVE); + } + + private void aggregationAndAggregationDataMismatch( + View view, Map, ? extends AggregationData> entries) { + CumulativeData cumulativeData = + CumulativeData.create(Timestamp.fromMillis(1000), Timestamp.fromMillis(2000)); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Aggregation and AggregationData types mismatch. "); + ViewData.create(view, entries, cumulativeData); + } + // tag keys private static final TagKey K1 = TagKey.create("k1"); private static final TagKey K2 = TagKey.create("k2"); - private final List tagKeys = Arrays.asList(K1, K2); + private static final List TAG_KEYS = Arrays.asList(K1, K2); // tag values private static final TagValue V1 = TagValue.create("v1"); @@ -202,6 +266,8 @@ public final class ViewDataTest { // description private static final String DESCRIPTION = "test-view-descriptor description"; // measure - private static final Measure MEASURE = - Measure.MeasureDouble.create("measure", "measure description", "1"); + private static final Measure MEASURE_DOUBLE = + Measure.MeasureDouble.create("measure1", "measure description", "1"); + private static final Measure MEASURE_LONG = + Measure.MeasureLong.create("measure2", "measure description", "1"); } -- cgit v1.2.3 From dc0ed0bba9d2adc1f3bee8558746560fbdb0f8a8 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Mon, 18 Dec 2017 22:21:10 -0800 Subject: Add more null annotations (issue #359). This commit adds some Nullable annotations that are required by the Checker Framework, but it doesn't change any other code. It also suppresses some Error Prone and FindBugs warnings that conflict with the Checker Framework, since the three tools use different algorithms. --- api/src/main/java/io/opencensus/tags/TagContext.java | 3 ++- api/src/main/java/io/opencensus/trace/SpanContext.java | 3 ++- api/src/main/java/io/opencensus/trace/SpanId.java | 3 ++- api/src/main/java/io/opencensus/trace/Status.java | 5 +++-- api/src/main/java/io/opencensus/trace/TraceId.java | 3 ++- api/src/main/java/io/opencensus/trace/TraceOptions.java | 3 ++- 6 files changed, 13 insertions(+), 7 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/tags/TagContext.java b/api/src/main/java/io/opencensus/tags/TagContext.java index 8147906b..13fde2ac 100644 --- a/api/src/main/java/io/opencensus/tags/TagContext.java +++ b/api/src/main/java/io/opencensus/tags/TagContext.java @@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableMultiset; import com.google.common.collect.Lists; import com.google.common.collect.Multiset; import java.util.Iterator; +import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; /** @@ -59,7 +60,7 @@ public abstract class TagContext { * performance. */ @Override - public boolean equals(Object other) { + public boolean equals(@Nullable Object other) { if (!(other instanceof TagContext)) { return false; } diff --git a/api/src/main/java/io/opencensus/trace/SpanContext.java b/api/src/main/java/io/opencensus/trace/SpanContext.java index 5e88b9fd..6084c674 100644 --- a/api/src/main/java/io/opencensus/trace/SpanContext.java +++ b/api/src/main/java/io/opencensus/trace/SpanContext.java @@ -18,6 +18,7 @@ package io.opencensus.trace; import com.google.common.base.MoreObjects; import com.google.common.base.Objects; +import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; /** @@ -85,7 +86,7 @@ public final class SpanContext { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj == this) { return true; } diff --git a/api/src/main/java/io/opencensus/trace/SpanId.java b/api/src/main/java/io/opencensus/trace/SpanId.java index cf0c7d46..76747acf 100644 --- a/api/src/main/java/io/opencensus/trace/SpanId.java +++ b/api/src/main/java/io/opencensus/trace/SpanId.java @@ -23,6 +23,7 @@ import com.google.common.base.MoreObjects; import com.google.common.io.BaseEncoding; import java.util.Arrays; import java.util.Random; +import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; /** @@ -162,7 +163,7 @@ public final class SpanId implements Comparable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj == this) { return true; } diff --git a/api/src/main/java/io/opencensus/trace/Status.java b/api/src/main/java/io/opencensus/trace/Status.java index f34ab693..d5807ef5 100644 --- a/api/src/main/java/io/opencensus/trace/Status.java +++ b/api/src/main/java/io/opencensus/trace/Status.java @@ -249,8 +249,9 @@ public final class Status { // The canonical code of this message. private final CanonicalCode canonicalCode; + // An additional error message. - private final String description; + @Nullable private final String description; private Status(CanonicalCode canonicalCode, @Nullable String description) { this.canonicalCode = checkNotNull(canonicalCode, "canonicalCode"); @@ -304,7 +305,7 @@ public final class Status { * additional fields may be added to Status in the future. */ @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj == this) { return true; } diff --git a/api/src/main/java/io/opencensus/trace/TraceId.java b/api/src/main/java/io/opencensus/trace/TraceId.java index 20f81393..2fad8949 100644 --- a/api/src/main/java/io/opencensus/trace/TraceId.java +++ b/api/src/main/java/io/opencensus/trace/TraceId.java @@ -24,6 +24,7 @@ import com.google.common.io.BaseEncoding; import io.opencensus.common.Internal; import java.util.Arrays; import java.util.Random; +import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; /** @@ -184,7 +185,7 @@ public final class TraceId implements Comparable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj == this) { return true; } diff --git a/api/src/main/java/io/opencensus/trace/TraceOptions.java b/api/src/main/java/io/opencensus/trace/TraceOptions.java index fc594853..2f57f3a7 100644 --- a/api/src/main/java/io/opencensus/trace/TraceOptions.java +++ b/api/src/main/java/io/opencensus/trace/TraceOptions.java @@ -23,6 +23,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; import com.google.common.base.Objects; +import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; /** @@ -150,7 +151,7 @@ public final class TraceOptions { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj == this) { return true; } -- cgit v1.2.3 From 5c151c5f0f813ce88346681d14075001ad229b19 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 19 Dec 2017 17:16:04 -0800 Subject: Add type variables for Checker Framework null analysis (issue #359). --- api/src/main/java/io/opencensus/tags/TagContext.java | 4 ++-- api/src/main/java/io/opencensus/trace/Span.java | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/tags/TagContext.java b/api/src/main/java/io/opencensus/tags/TagContext.java index 13fde2ac..bc2a1630 100644 --- a/api/src/main/java/io/opencensus/tags/TagContext.java +++ b/api/src/main/java/io/opencensus/tags/TagContext.java @@ -70,11 +70,11 @@ public abstract class TagContext { Multiset tags1 = iter1 == null ? ImmutableMultiset.of() - : HashMultiset.create(Lists.newArrayList(iter1)); + : HashMultiset.create(Lists.newArrayList(iter1)); Multiset tags2 = iter2 == null ? ImmutableMultiset.of() - : HashMultiset.create(Lists.newArrayList(iter2)); + : HashMultiset.create(Lists.newArrayList(iter2)); return tags1.equals(tags2); } diff --git a/api/src/main/java/io/opencensus/trace/Span.java b/api/src/main/java/io/opencensus/trace/Span.java index ec39f5c4..16aac33f 100644 --- a/api/src/main/java/io/opencensus/trace/Span.java +++ b/api/src/main/java/io/opencensus/trace/Span.java @@ -70,7 +70,9 @@ public abstract class Span { protected Span(SpanContext context, @Nullable EnumSet options) { this.context = checkNotNull(context, "context"); this.options = - options == null ? DEFAULT_OPTIONS : Collections.unmodifiableSet(EnumSet.copyOf(options)); + options == null + ? DEFAULT_OPTIONS + : Collections.unmodifiableSet(EnumSet.copyOf(options)); checkArgument( !context.getTraceOptions().isSampled() || (this.options.contains(Options.RECORD_EVENTS)), "Span is sampled, but does not have RECORD_EVENTS set."); -- cgit v1.2.3 From 6fb84f495a4862cd2dc510609daa7400b58d2037 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 19 Dec 2017 17:19:32 -0800 Subject: Add missing null checks (issue #359). --- .../java/io/opencensus/trace/samplers/ProbabilitySampler.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java index d6247344..21d4d6ca 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java +++ b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java @@ -83,10 +83,12 @@ abstract class ProbabilitySampler extends Sampler { if (parentContext != null && parentContext.getTraceOptions().isSampled()) { return true; } - // If any parent link is sampled keep the sampling decision. - for (Span parentLink : parentLinks) { - if (parentLink.getContext().getTraceOptions().isSampled()) { - return true; + if (parentLinks != null) { + // If any parent link is sampled keep the sampling decision. + for (Span parentLink : parentLinks) { + if (parentLink.getContext().getTraceOptions().isSampled()) { + return true; + } } } // Always sample if we are within probability range. This is true even for child spans (that -- cgit v1.2.3 From bbe6b10f7c6b622b4ffd18e98f58d96a8eba3854 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 19 Dec 2017 20:02:00 -0800 Subject: Suppress warnings about missing @Nullable in AutoValue equals methods (#359). The Checker Framework treats Object.equals as having a Nullable annotation on its argument. AutoValue doesn't add any annotations to its generated equals methods, so the Checker Framework produces warnings. I couldn't find a way to suppress Checker Framework warnings in generated code, so I added @SuppressWarnings("nullness") to the abstract classes and used @AutoValue.CopyAnnotations to copy the annotations to the generated classes. --- api/src/main/java/io/opencensus/common/Duration.java | 3 +++ api/src/main/java/io/opencensus/common/Timestamp.java | 3 +++ api/src/main/java/io/opencensus/stats/Aggregation.java | 12 ++++++++++++ .../main/java/io/opencensus/stats/AggregationData.java | 15 +++++++++++++++ .../main/java/io/opencensus/stats/BucketBoundaries.java | 3 +++ api/src/main/java/io/opencensus/stats/Measure.java | 6 ++++++ api/src/main/java/io/opencensus/stats/Measurement.java | 6 ++++++ api/src/main/java/io/opencensus/stats/View.java | 12 ++++++++++++ api/src/main/java/io/opencensus/stats/ViewData.java | 9 +++++++++ api/src/main/java/io/opencensus/tags/Tag.java | 3 +++ api/src/main/java/io/opencensus/tags/TagKey.java | 3 +++ api/src/main/java/io/opencensus/tags/TagValue.java | 3 +++ api/src/main/java/io/opencensus/trace/Annotation.java | 3 +++ api/src/main/java/io/opencensus/trace/AttributeValue.java | 9 +++++++++ api/src/main/java/io/opencensus/trace/EndSpanOptions.java | 3 +++ api/src/main/java/io/opencensus/trace/Link.java | 3 +++ api/src/main/java/io/opencensus/trace/NetworkEvent.java | 3 +++ .../main/java/io/opencensus/trace/config/TraceParams.java | 3 +++ .../java/io/opencensus/trace/export/RunningSpanStore.java | 9 +++++++++ .../java/io/opencensus/trace/export/SampledSpanStore.java | 12 ++++++++++++ .../main/java/io/opencensus/trace/export/SpanData.java | 15 +++++++++++++++ .../io/opencensus/trace/samplers/ProbabilitySampler.java | 3 +++ 22 files changed, 141 insertions(+) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Duration.java b/api/src/main/java/io/opencensus/common/Duration.java index b4b59a57..178e9cf3 100644 --- a/api/src/main/java/io/opencensus/common/Duration.java +++ b/api/src/main/java/io/opencensus/common/Duration.java @@ -32,6 +32,9 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue +// Suppress Checker Framework warning about missing @Nullable in generated equals method. +@AutoValue.CopyAnnotations +@SuppressWarnings("nullness") public abstract class Duration implements Comparable { private static final Duration ZERO = create(0, 0); diff --git a/api/src/main/java/io/opencensus/common/Timestamp.java b/api/src/main/java/io/opencensus/common/Timestamp.java index b62a1102..04fed453 100644 --- a/api/src/main/java/io/opencensus/common/Timestamp.java +++ b/api/src/main/java/io/opencensus/common/Timestamp.java @@ -37,6 +37,9 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue +// Suppress Checker Framework warning about missing @Nullable in generated equals method. +@AutoValue.CopyAnnotations +@SuppressWarnings("nullness") public abstract class Timestamp implements Comparable { private static final Timestamp EPOCH = new AutoValue_Timestamp(0, 0); diff --git a/api/src/main/java/io/opencensus/stats/Aggregation.java b/api/src/main/java/io/opencensus/stats/Aggregation.java index 90341af4..0fe905ce 100644 --- a/api/src/main/java/io/opencensus/stats/Aggregation.java +++ b/api/src/main/java/io/opencensus/stats/Aggregation.java @@ -54,6 +54,9 @@ public abstract class Aggregation { /** Calculate sum on aggregated {@code MeasureValue}s. */ @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class Sum extends Aggregation { Sum() {} @@ -83,6 +86,9 @@ public abstract class Aggregation { /** Calculate count on aggregated {@code MeasureValue}s. */ @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class Count extends Aggregation { Count() {} @@ -112,6 +118,9 @@ public abstract class Aggregation { /** Calculate mean on aggregated {@code MeasureValue}s. */ @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class Mean extends Aggregation { Mean() {} @@ -144,6 +153,9 @@ public abstract class Aggregation { */ @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class Distribution extends Aggregation { Distribution() {} diff --git a/api/src/main/java/io/opencensus/stats/AggregationData.java b/api/src/main/java/io/opencensus/stats/AggregationData.java index d5cacfc5..822c9296 100644 --- a/api/src/main/java/io/opencensus/stats/AggregationData.java +++ b/api/src/main/java/io/opencensus/stats/AggregationData.java @@ -60,6 +60,9 @@ public abstract class AggregationData { /** The sum value of aggregated {@code MeasureValueDouble}s. */ @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class SumDataDouble extends AggregationData { SumDataDouble() {} @@ -96,6 +99,9 @@ public abstract class AggregationData { /** The sum value of aggregated {@code MeasureValueLong}s. */ @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class SumDataLong extends AggregationData { SumDataLong() {} @@ -132,6 +138,9 @@ public abstract class AggregationData { /** The count value of aggregated {@code MeasureValue}s. */ @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class CountData extends AggregationData { CountData() {} @@ -168,6 +177,9 @@ public abstract class AggregationData { /** The mean value of aggregated {@code MeasureValue}s. */ @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class MeanData extends AggregationData { MeanData() {} @@ -215,6 +227,9 @@ public abstract class AggregationData { */ @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class DistributionData extends AggregationData { DistributionData() {} diff --git a/api/src/main/java/io/opencensus/stats/BucketBoundaries.java b/api/src/main/java/io/opencensus/stats/BucketBoundaries.java index 8af83a4e..664c821f 100644 --- a/api/src/main/java/io/opencensus/stats/BucketBoundaries.java +++ b/api/src/main/java/io/opencensus/stats/BucketBoundaries.java @@ -28,6 +28,9 @@ import javax.annotation.concurrent.Immutable; /** The bucket boundaries for a histogram. */ @Immutable @AutoValue +// Suppress Checker Framework warning about missing @Nullable in generated equals method. +@AutoValue.CopyAnnotations +@SuppressWarnings("nullness") public abstract class BucketBoundaries { /** diff --git a/api/src/main/java/io/opencensus/stats/Measure.java b/api/src/main/java/io/opencensus/stats/Measure.java index 52fadfa0..209e946f 100644 --- a/api/src/main/java/io/opencensus/stats/Measure.java +++ b/api/src/main/java/io/opencensus/stats/Measure.java @@ -70,6 +70,9 @@ public abstract class Measure { /** {@link Measure} with {@code Double} typed values. */ @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class MeasureDouble extends Measure { MeasureDouble() {} @@ -112,6 +115,9 @@ public abstract class Measure { /** {@link Measure} with {@code Long} typed values. */ @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class MeasureLong extends Measure { MeasureLong() {} diff --git a/api/src/main/java/io/opencensus/stats/Measurement.java b/api/src/main/java/io/opencensus/stats/Measurement.java index 1bb746d8..6e4b6597 100644 --- a/api/src/main/java/io/opencensus/stats/Measurement.java +++ b/api/src/main/java/io/opencensus/stats/Measurement.java @@ -41,6 +41,9 @@ public abstract class Measurement { /** {@code Double} typed {@link Measurement}. */ @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class MeasurementDouble extends Measurement { MeasurementDouble() {} @@ -66,6 +69,9 @@ public abstract class Measurement { /** {@code Long} typed {@link Measurement}. */ @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class MeasurementLong extends Measurement { MeasurementLong() {} diff --git a/api/src/main/java/io/opencensus/stats/View.java b/api/src/main/java/io/opencensus/stats/View.java index a773ec1f..e077baf4 100644 --- a/api/src/main/java/io/opencensus/stats/View.java +++ b/api/src/main/java/io/opencensus/stats/View.java @@ -36,6 +36,9 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue +// Suppress Checker Framework warning about missing @Nullable in generated equals method. +@AutoValue.CopyAnnotations +@SuppressWarnings("nullness") public abstract class View { @VisibleForTesting static final int NAME_MAX_LENGTH = 255; @@ -103,6 +106,9 @@ public abstract class View { // This type should be used as the key when associating data with Views. @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class Name { Name() {} @@ -146,6 +152,9 @@ public abstract class View { /** Cumulative (infinite interval) time {@code AggregationWindow}. */ @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class Cumulative extends AggregationWindow { private static final Cumulative CUMULATIVE = @@ -176,6 +185,9 @@ public abstract class View { /** Interval (finite interval) time {@code AggregationWindow.} */ @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class Interval extends AggregationWindow { private static final Duration ZERO = Duration.create(0, 0); diff --git a/api/src/main/java/io/opencensus/stats/ViewData.java b/api/src/main/java/io/opencensus/stats/ViewData.java index 8c056521..c711e6f3 100644 --- a/api/src/main/java/io/opencensus/stats/ViewData.java +++ b/api/src/main/java/io/opencensus/stats/ViewData.java @@ -46,6 +46,9 @@ import javax.annotation.concurrent.Immutable; /** The aggregated data for a particular {@link View}. */ @Immutable @AutoValue +// Suppress Checker Framework warning about missing @Nullable in generated equals method. +@AutoValue.CopyAnnotations +@SuppressWarnings("nullness") public abstract class ViewData { // Prevents this class from being subclassed anywhere else. @@ -208,6 +211,9 @@ public abstract class ViewData { /** Cumulative {@code AggregationWindowData.} */ @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class CumulativeData extends AggregationWindowData { CumulativeData() {} @@ -246,6 +252,9 @@ public abstract class ViewData { /** Interval {@code AggregationWindowData.} */ @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class IntervalData extends AggregationWindowData { IntervalData() {} diff --git a/api/src/main/java/io/opencensus/tags/Tag.java b/api/src/main/java/io/opencensus/tags/Tag.java index 18a56547..90b050d5 100644 --- a/api/src/main/java/io/opencensus/tags/Tag.java +++ b/api/src/main/java/io/opencensus/tags/Tag.java @@ -22,6 +22,9 @@ import javax.annotation.concurrent.Immutable; /** {@link TagKey} paired with a {@link TagValue}. */ @Immutable @AutoValue +// Suppress Checker Framework warning about missing @Nullable in generated equals method. +@AutoValue.CopyAnnotations +@SuppressWarnings("nullness") public abstract class Tag { Tag() {} diff --git a/api/src/main/java/io/opencensus/tags/TagKey.java b/api/src/main/java/io/opencensus/tags/TagKey.java index f1304b33..a6eb802f 100644 --- a/api/src/main/java/io/opencensus/tags/TagKey.java +++ b/api/src/main/java/io/opencensus/tags/TagKey.java @@ -33,6 +33,9 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue +// Suppress Checker Framework warning about missing @Nullable in generated equals method. +@AutoValue.CopyAnnotations +@SuppressWarnings("nullness") public abstract class TagKey { /** The maximum length for a tag key name. The value is {@value #MAX_LENGTH}. */ public static final int MAX_LENGTH = 255; diff --git a/api/src/main/java/io/opencensus/tags/TagValue.java b/api/src/main/java/io/opencensus/tags/TagValue.java index 71196051..bd2894a7 100644 --- a/api/src/main/java/io/opencensus/tags/TagValue.java +++ b/api/src/main/java/io/opencensus/tags/TagValue.java @@ -29,6 +29,9 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue +// Suppress Checker Framework warning about missing @Nullable in generated equals method. +@AutoValue.CopyAnnotations +@SuppressWarnings("nullness") public abstract class TagValue { /** The maximum length for a tag value. The value is {@value #MAX_LENGTH}. */ public static final int MAX_LENGTH = 255; diff --git a/api/src/main/java/io/opencensus/trace/Annotation.java b/api/src/main/java/io/opencensus/trace/Annotation.java index f6482bd0..3a893647 100644 --- a/api/src/main/java/io/opencensus/trace/Annotation.java +++ b/api/src/main/java/io/opencensus/trace/Annotation.java @@ -27,6 +27,9 @@ import javax.annotation.concurrent.Immutable; /** A text annotation with a set of attributes. */ @Immutable @AutoValue +// Suppress Checker Framework warning about missing @Nullable in generated equals method. +@AutoValue.CopyAnnotations +@SuppressWarnings("nullness") public abstract class Annotation { private static final Map EMPTY_ATTRIBUTES = Collections.unmodifiableMap(Collections.emptyMap()); diff --git a/api/src/main/java/io/opencensus/trace/AttributeValue.java b/api/src/main/java/io/opencensus/trace/AttributeValue.java index ef0d37ed..6c938bd6 100644 --- a/api/src/main/java/io/opencensus/trace/AttributeValue.java +++ b/api/src/main/java/io/opencensus/trace/AttributeValue.java @@ -82,6 +82,9 @@ public abstract class AttributeValue { @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") abstract static class AttributeValueString extends AttributeValue { AttributeValueString() {} @@ -105,6 +108,9 @@ public abstract class AttributeValue { @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") abstract static class AttributeValueBoolean extends AttributeValue { AttributeValueBoolean() {} @@ -128,6 +134,9 @@ public abstract class AttributeValue { @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") abstract static class AttributeValueLong extends AttributeValue { AttributeValueLong() {} diff --git a/api/src/main/java/io/opencensus/trace/EndSpanOptions.java b/api/src/main/java/io/opencensus/trace/EndSpanOptions.java index 10952e8a..5c46e06f 100644 --- a/api/src/main/java/io/opencensus/trace/EndSpanOptions.java +++ b/api/src/main/java/io/opencensus/trace/EndSpanOptions.java @@ -28,6 +28,9 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue +// Suppress Checker Framework warning about missing @Nullable in generated equals method. +@AutoValue.CopyAnnotations +@SuppressWarnings("nullness") public abstract class EndSpanOptions { /** The default {@code EndSpanOptions}. */ public static final EndSpanOptions DEFAULT = builder().build(); diff --git a/api/src/main/java/io/opencensus/trace/Link.java b/api/src/main/java/io/opencensus/trace/Link.java index 716c2d72..77b17206 100644 --- a/api/src/main/java/io/opencensus/trace/Link.java +++ b/api/src/main/java/io/opencensus/trace/Link.java @@ -33,6 +33,9 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue +// Suppress Checker Framework warning about missing @Nullable in generated equals method. +@AutoValue.CopyAnnotations +@SuppressWarnings("nullness") public abstract class Link { private static final Map EMPTY_ATTRIBUTES = Collections.emptyMap(); diff --git a/api/src/main/java/io/opencensus/trace/NetworkEvent.java b/api/src/main/java/io/opencensus/trace/NetworkEvent.java index 08b7dc66..a38bbdb8 100644 --- a/api/src/main/java/io/opencensus/trace/NetworkEvent.java +++ b/api/src/main/java/io/opencensus/trace/NetworkEvent.java @@ -30,6 +30,9 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue +// Suppress Checker Framework warning about missing @Nullable in generated equals method. +@AutoValue.CopyAnnotations +@SuppressWarnings("nullness") public abstract class NetworkEvent { /** Available types for a {@code NetworkEvent}. */ public enum Type { diff --git a/api/src/main/java/io/opencensus/trace/config/TraceParams.java b/api/src/main/java/io/opencensus/trace/config/TraceParams.java index 234cc74d..c56cc9f7 100644 --- a/api/src/main/java/io/opencensus/trace/config/TraceParams.java +++ b/api/src/main/java/io/opencensus/trace/config/TraceParams.java @@ -30,6 +30,9 @@ import javax.annotation.concurrent.Immutable; /** Class that holds global trace parameters. */ @AutoValue @Immutable +// Suppress Checker Framework warning about missing @Nullable in generated equals method. +@AutoValue.CopyAnnotations +@SuppressWarnings("nullness") public abstract class TraceParams { // These values are the default values for all the global parameters. private static final double DEFAULT_PROBABILITY = 1e-4; diff --git a/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java b/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java index 8d736aab..209afe05 100644 --- a/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java @@ -68,6 +68,9 @@ public abstract class RunningSpanStore { /** The summary of all available data. */ @AutoValue @Immutable + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class Summary { Summary() {} @@ -97,6 +100,9 @@ public abstract class RunningSpanStore { /** Summary of all available data for a span name. */ @AutoValue @Immutable + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class PerSpanNameSummary { PerSpanNameSummary() {} @@ -127,6 +133,9 @@ public abstract class RunningSpanStore { */ @AutoValue @Immutable + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class Filter { Filter() {} diff --git a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java index e1339090..c04b19f6 100644 --- a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java @@ -130,6 +130,9 @@ public abstract class SampledSpanStore { /** The summary of all available data. */ @AutoValue @Immutable + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class Summary { Summary() {} @@ -159,6 +162,9 @@ public abstract class SampledSpanStore { /** Summary of all available data for a span name. */ @AutoValue @Immutable + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class PerSpanNameSummary { PerSpanNameSummary() {} @@ -269,6 +275,9 @@ public abstract class SampledSpanStore { */ @AutoValue @Immutable + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class LatencyFilter { LatencyFilter() {} @@ -332,6 +341,9 @@ public abstract class SampledSpanStore { */ @AutoValue @Immutable + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class ErrorFilter { ErrorFilter() {} diff --git a/api/src/main/java/io/opencensus/trace/export/SpanData.java b/api/src/main/java/io/opencensus/trace/export/SpanData.java index ab88b532..c268d6b4 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanData.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanData.java @@ -39,6 +39,9 @@ import javax.annotation.concurrent.Immutable; /** Immutable representation of all data collected by the {@link Span} class. */ @Immutable @AutoValue +// Suppress Checker Framework warning about missing @Nullable in generated equals method. +@AutoValue.CopyAnnotations +@SuppressWarnings("nullness") public abstract class SpanData { /** @@ -193,6 +196,9 @@ public abstract class SpanData { */ @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class TimedEvent { /** * Returns a new immutable {@code TimedEvent}. @@ -230,6 +236,9 @@ public abstract class SpanData { */ @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class TimedEvents { /** * Returns a new immutable {@code TimedEvents}. @@ -266,6 +275,9 @@ public abstract class SpanData { /** A set of attributes and the number of dropped attributes representation. */ @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class Attributes { /** * Returns a new immutable {@code Attributes}. @@ -304,6 +316,9 @@ public abstract class SpanData { /** A list of links and the number of dropped links representation. */ @Immutable @AutoValue + // Suppress Checker Framework warning about missing @Nullable in generated equals method. + @AutoValue.CopyAnnotations + @SuppressWarnings("nullness") public abstract static class Links { /** * Returns a new immutable {@code Links}. diff --git a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java index 21d4d6ca..8d8be354 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java +++ b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java @@ -37,6 +37,9 @@ import javax.annotation.concurrent.Immutable; */ @AutoValue @Immutable +// Suppress Checker Framework warning about missing @Nullable in generated equals method. +@AutoValue.CopyAnnotations +@SuppressWarnings("nullness") abstract class ProbabilitySampler extends Sampler { ProbabilitySampler() {} -- cgit v1.2.3 From 18cf999ddea65775db2a482e00cea05d52961077 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 19 Dec 2017 20:02:00 -0800 Subject: Work around a possible bug in the Checker Framework (issue #359). The issue https://github.com/typetools/checker-framework/issues/1712 affects all uses of the visitor pattern in this project. This commit adds utility methods for working around the issue and calls them from all "match" methods. --- .../java/io/opencensus/internal/NullnessUtils.java | 40 ++++++++++++++++++++++ .../main/java/io/opencensus/stats/Aggregation.java | 9 ++--- .../java/io/opencensus/stats/AggregationData.java | 12 ++++--- api/src/main/java/io/opencensus/stats/Measure.java | 5 +-- .../main/java/io/opencensus/stats/Measurement.java | 6 ++-- api/src/main/java/io/opencensus/stats/View.java | 5 +-- .../main/java/io/opencensus/stats/ViewData.java | 6 ++-- .../java/io/opencensus/trace/AttributeValue.java | 10 ++++-- 8 files changed, 73 insertions(+), 20 deletions(-) create mode 100644 api/src/main/java/io/opencensus/internal/NullnessUtils.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/NullnessUtils.java b/api/src/main/java/io/opencensus/internal/NullnessUtils.java new file mode 100644 index 00000000..ca3419cd --- /dev/null +++ b/api/src/main/java/io/opencensus/internal/NullnessUtils.java @@ -0,0 +1,40 @@ +/* + * 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.internal; + +import io.opencensus.common.Function; + +/*>>> +import org.checkerframework.checker.nullness.qual.KeyForBottom; +*/ + +/** Utility methods for working around Checker Framework issues. */ +public final class NullnessUtils { + private NullnessUtils() {} + + /** + * Work around https://github.com/typetools/checker-framework/issues/1712 by removing {@code ? + * super} from a {@code Function}'s argument type. + */ + // TODO(sebright): Remove this method once the issue is fixed. + public static Function removeSuperFromFunctionParameterType( + Function function) { + @SuppressWarnings("unchecked") + Function castFunction = (Function) function; + return castFunction; + } +} diff --git a/api/src/main/java/io/opencensus/stats/Aggregation.java b/api/src/main/java/io/opencensus/stats/Aggregation.java index 0fe905ce..7a612313 100644 --- a/api/src/main/java/io/opencensus/stats/Aggregation.java +++ b/api/src/main/java/io/opencensus/stats/Aggregation.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; import io.opencensus.common.Function; +import io.opencensus.internal.NullnessUtils; import javax.annotation.concurrent.Immutable; /** @@ -79,7 +80,7 @@ public abstract class Aggregation { Function p2, Function p3, Function defaultFunction) { - return p0.apply(this); + return NullnessUtils.removeSuperFromFunctionParameterType(p0).apply(this); } } @@ -111,7 +112,7 @@ public abstract class Aggregation { Function p2, Function p3, Function defaultFunction) { - return p1.apply(this); + return NullnessUtils.removeSuperFromFunctionParameterType(p1).apply(this); } } @@ -143,7 +144,7 @@ public abstract class Aggregation { Function p2, Function p3, Function defaultFunction) { - return p2.apply(this); + return NullnessUtils.removeSuperFromFunctionParameterType(p2).apply(this); } } @@ -179,7 +180,7 @@ public abstract class Aggregation { Function p2, Function p3, Function defaultFunction) { - return p3.apply(this); + return NullnessUtils.removeSuperFromFunctionParameterType(p3).apply(this); } } } diff --git a/api/src/main/java/io/opencensus/stats/AggregationData.java b/api/src/main/java/io/opencensus/stats/AggregationData.java index 822c9296..bdf618bc 100644 --- a/api/src/main/java/io/opencensus/stats/AggregationData.java +++ b/api/src/main/java/io/opencensus/stats/AggregationData.java @@ -22,6 +22,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; import com.google.common.collect.Lists; import io.opencensus.common.Function; +import io.opencensus.internal.NullnessUtils; import java.util.Collections; import java.util.List; import javax.annotation.concurrent.Immutable; @@ -92,7 +93,7 @@ public abstract class AggregationData { Function p3, Function p4, Function defaultFunction) { - return p0.apply(this); + return NullnessUtils.removeSuperFromFunctionParameterType(p0).apply(this); } } @@ -131,7 +132,7 @@ public abstract class AggregationData { Function p3, Function p4, Function defaultFunction) { - return p1.apply(this); + return NullnessUtils.removeSuperFromFunctionParameterType(p1).apply(this); } } @@ -170,7 +171,7 @@ public abstract class AggregationData { Function p3, Function p4, Function defaultFunction) { - return p2.apply(this); + return NullnessUtils.removeSuperFromFunctionParameterType(p2).apply(this); } } @@ -217,7 +218,7 @@ public abstract class AggregationData { Function p3, Function p4, Function defaultFunction) { - return p3.apply(this); + return NullnessUtils.removeSuperFromFunctionParameterType(p3).apply(this); } } @@ -317,7 +318,8 @@ public abstract class AggregationData { Function p3, Function p4, Function defaultFunction) { - return p4.apply(this); + return NullnessUtils.removeSuperFromFunctionParameterType(p4) + .apply(this); } } } diff --git a/api/src/main/java/io/opencensus/stats/Measure.java b/api/src/main/java/io/opencensus/stats/Measure.java index 209e946f..70210f4e 100644 --- a/api/src/main/java/io/opencensus/stats/Measure.java +++ b/api/src/main/java/io/opencensus/stats/Measure.java @@ -21,6 +21,7 @@ import static com.google.common.base.Preconditions.checkArgument; import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; import io.opencensus.common.Function; +import io.opencensus.internal.NullnessUtils; import io.opencensus.internal.StringUtil; import javax.annotation.concurrent.Immutable; @@ -99,7 +100,7 @@ public abstract class Measure { Function p0, Function p1, Function defaultFunction) { - return p0.apply(this); + return NullnessUtils.removeSuperFromFunctionParameterType(p0).apply(this); } @Override @@ -144,7 +145,7 @@ public abstract class Measure { Function p0, Function p1, Function defaultFunction) { - return p1.apply(this); + return NullnessUtils.removeSuperFromFunctionParameterType(p1).apply(this); } @Override diff --git a/api/src/main/java/io/opencensus/stats/Measurement.java b/api/src/main/java/io/opencensus/stats/Measurement.java index 6e4b6597..954cf43a 100644 --- a/api/src/main/java/io/opencensus/stats/Measurement.java +++ b/api/src/main/java/io/opencensus/stats/Measurement.java @@ -18,6 +18,7 @@ package io.opencensus.stats; import com.google.auto.value.AutoValue; import io.opencensus.common.Function; +import io.opencensus.internal.NullnessUtils; import io.opencensus.stats.Measure.MeasureDouble; import io.opencensus.stats.Measure.MeasureLong; import javax.annotation.concurrent.Immutable; @@ -62,7 +63,8 @@ public abstract class Measurement { Function p0, Function p1, Function defaultFunction) { - return p0.apply(this); + return NullnessUtils.removeSuperFromFunctionParameterType(p0) + .apply(this); } } @@ -90,7 +92,7 @@ public abstract class Measurement { Function p0, Function p1, Function defaultFunction) { - return p1.apply(this); + return NullnessUtils.removeSuperFromFunctionParameterType(p1).apply(this); } } } diff --git a/api/src/main/java/io/opencensus/stats/View.java b/api/src/main/java/io/opencensus/stats/View.java index e077baf4..4f852c77 100644 --- a/api/src/main/java/io/opencensus/stats/View.java +++ b/api/src/main/java/io/opencensus/stats/View.java @@ -22,6 +22,7 @@ import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; import io.opencensus.common.Duration; import io.opencensus.common.Function; +import io.opencensus.internal.NullnessUtils; import io.opencensus.internal.StringUtil; import io.opencensus.tags.TagKey; import java.util.ArrayList; @@ -178,7 +179,7 @@ public abstract class View { Function p0, Function p1, Function defaultFunction) { - return p0.apply(this); + return NullnessUtils.removeSuperFromFunctionParameterType(p0).apply(this); } } @@ -220,7 +221,7 @@ public abstract class View { Function p0, Function p1, Function defaultFunction) { - return p1.apply(this); + return NullnessUtils.removeSuperFromFunctionParameterType(p1).apply(this); } } } diff --git a/api/src/main/java/io/opencensus/stats/ViewData.java b/api/src/main/java/io/opencensus/stats/ViewData.java index c711e6f3..dc8fd555 100644 --- a/api/src/main/java/io/opencensus/stats/ViewData.java +++ b/api/src/main/java/io/opencensus/stats/ViewData.java @@ -23,6 +23,7 @@ import com.google.common.collect.Maps; import io.opencensus.common.Function; import io.opencensus.common.Functions; import io.opencensus.common.Timestamp; +import io.opencensus.internal.NullnessUtils; import io.opencensus.stats.Aggregation.Count; import io.opencensus.stats.Aggregation.Distribution; import io.opencensus.stats.Aggregation.Mean; @@ -237,7 +238,8 @@ public abstract class ViewData { Function p0, Function p1, Function defaultFunction) { - return p0.apply(this); + return NullnessUtils.removeSuperFromFunctionParameterType(p0) + .apply(this); } /** Constructs a new {@link CumulativeData}. */ @@ -271,7 +273,7 @@ public abstract class ViewData { Function p0, Function p1, Function defaultFunction) { - return p1.apply(this); + return NullnessUtils.removeSuperFromFunctionParameterType(p1).apply(this); } /** Constructs a new {@link IntervalData}. */ diff --git a/api/src/main/java/io/opencensus/trace/AttributeValue.java b/api/src/main/java/io/opencensus/trace/AttributeValue.java index 6c938bd6..2de8fc91 100644 --- a/api/src/main/java/io/opencensus/trace/AttributeValue.java +++ b/api/src/main/java/io/opencensus/trace/AttributeValue.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; import io.opencensus.common.Function; +import io.opencensus.internal.NullnessUtils; import javax.annotation.concurrent.Immutable; /** @@ -100,7 +101,8 @@ public abstract class AttributeValue { Function booleanFunction, Function longFunction, Function defaultFunction) { - return stringFunction.apply(getStringValue()); + return NullnessUtils.removeSuperFromFunctionParameterType(stringFunction) + .apply(getStringValue()); } abstract String getStringValue(); @@ -126,7 +128,8 @@ public abstract class AttributeValue { Function booleanFunction, Function longFunction, Function defaultFunction) { - return booleanFunction.apply(getBooleanValue()); + return NullnessUtils.removeSuperFromFunctionParameterType(booleanFunction) + .apply(getBooleanValue()); } abstract Boolean getBooleanValue(); @@ -152,7 +155,8 @@ public abstract class AttributeValue { Function booleanFunction, Function longFunction, Function defaultFunction) { - return longFunction.apply(getLongValue()); + return NullnessUtils.removeSuperFromFunctionParameterType(longFunction) + .apply(getLongValue()); } abstract Long getLongValue(); -- cgit v1.2.3 From 2fc0d4dd057ca28e1e9c37d18ebcfac6d2136de9 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 19 Dec 2017 20:02:00 -0800 Subject: Suppress some Checker Framework warnings and add TODOs (issue #359). Fixing these warnings will require significant refactoring. --- api/src/main/java/io/opencensus/internal/NullnessUtils.java | 12 +++++++++++- api/src/main/java/io/opencensus/stats/Stats.java | 3 ++- api/src/main/java/io/opencensus/tags/Tags.java | 3 ++- api/src/main/java/io/opencensus/trace/Tracing.java | 3 ++- 4 files changed, 17 insertions(+), 4 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/NullnessUtils.java b/api/src/main/java/io/opencensus/internal/NullnessUtils.java index ca3419cd..0301b798 100644 --- a/api/src/main/java/io/opencensus/internal/NullnessUtils.java +++ b/api/src/main/java/io/opencensus/internal/NullnessUtils.java @@ -17,15 +17,25 @@ package io.opencensus.internal; import io.opencensus.common.Function; +import javax.annotation.Nullable; /*>>> import org.checkerframework.checker.nullness.qual.KeyForBottom; */ -/** Utility methods for working around Checker Framework issues. */ +/** + * Utility methods for suppressing nullness warnings and working around Checker Framework issues. + */ public final class NullnessUtils { private NullnessUtils() {} + /** Suppress warnings about a nullable value. */ + // TODO(sebright): Try to remove all uses of this method. + @SuppressWarnings("nullness") + public static T castNonNull(@Nullable T arg) { + return arg; + } + /** * Work around https://github.com/typetools/checker-framework/issues/1712 by removing {@code ? * super} from a {@code Function}'s argument type. diff --git a/api/src/main/java/io/opencensus/stats/Stats.java b/api/src/main/java/io/opencensus/stats/Stats.java index d02780f8..0830313a 100644 --- a/api/src/main/java/io/opencensus/stats/Stats.java +++ b/api/src/main/java/io/opencensus/stats/Stats.java @@ -17,6 +17,7 @@ package io.opencensus.stats; import com.google.common.annotations.VisibleForTesting; +import io.opencensus.internal.NullnessUtils; import io.opencensus.internal.Provider; import java.util.logging.Level; import java.util.logging.Logger; @@ -26,7 +27,7 @@ public final class Stats { private static final Logger logger = Logger.getLogger(Stats.class.getName()); private static final StatsComponent statsComponent = - loadStatsComponent(StatsComponent.class.getClassLoader()); + loadStatsComponent(NullnessUtils.castNonNull(StatsComponent.class.getClassLoader())); /** Returns the default {@link StatsRecorder}. */ public static StatsRecorder getStatsRecorder() { diff --git a/api/src/main/java/io/opencensus/tags/Tags.java b/api/src/main/java/io/opencensus/tags/Tags.java index 593312ae..f480714d 100644 --- a/api/src/main/java/io/opencensus/tags/Tags.java +++ b/api/src/main/java/io/opencensus/tags/Tags.java @@ -17,6 +17,7 @@ package io.opencensus.tags; import com.google.common.annotations.VisibleForTesting; +import io.opencensus.internal.NullnessUtils; import io.opencensus.internal.Provider; import io.opencensus.tags.propagation.TagPropagationComponent; import java.util.logging.Level; @@ -27,7 +28,7 @@ public final class Tags { private static final Logger logger = Logger.getLogger(Tags.class.getName()); private static final TagsComponent tagsComponent = - loadTagsComponent(TagsComponent.class.getClassLoader()); + loadTagsComponent(NullnessUtils.castNonNull(TagsComponent.class.getClassLoader())); private Tags() {} diff --git a/api/src/main/java/io/opencensus/trace/Tracing.java b/api/src/main/java/io/opencensus/trace/Tracing.java index c68f66ad..8e575265 100644 --- a/api/src/main/java/io/opencensus/trace/Tracing.java +++ b/api/src/main/java/io/opencensus/trace/Tracing.java @@ -18,6 +18,7 @@ package io.opencensus.trace; import com.google.common.annotations.VisibleForTesting; import io.opencensus.common.Clock; +import io.opencensus.internal.NullnessUtils; import io.opencensus.internal.Provider; import io.opencensus.trace.config.TraceConfig; import io.opencensus.trace.export.ExportComponent; @@ -29,7 +30,7 @@ import java.util.logging.Logger; public final class Tracing { private static final Logger logger = Logger.getLogger(Tracing.class.getName()); private static final TraceComponent traceComponent = - loadTraceComponent(TraceComponent.class.getClassLoader()); + loadTraceComponent(NullnessUtils.castNonNull(TraceComponent.class.getClassLoader())); /** * Returns the global {@link Tracer}. -- cgit v1.2.3 From 6e53b74c4325ed2a80caf5f162614ba6fbec4c3c Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 19 Dec 2017 20:02:00 -0800 Subject: Add Checker Framework annotations in comments (issue #359). Putting the annotations in comments allows us to use Java 8 syntax and avoid depending on the Checker Framework library. Note that we need to use org.checkerframework.checker.nullness.qual.Nullable for marking types nullable, because javax.annotation.Nullable can't be applied to types. --- api/src/main/java/io/opencensus/stats/ViewData.java | 6 +++++- api/src/main/java/io/opencensus/trace/Status.java | 5 +++++ api/src/main/java/io/opencensus/trace/export/SpanData.java | 8 ++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/ViewData.java b/api/src/main/java/io/opencensus/stats/ViewData.java index dc8fd555..fe2510bc 100644 --- a/api/src/main/java/io/opencensus/stats/ViewData.java +++ b/api/src/main/java/io/opencensus/stats/ViewData.java @@ -44,6 +44,10 @@ import java.util.Map; import java.util.Map.Entry; import javax.annotation.concurrent.Immutable; +/*>>> +import org.checkerframework.checker.nullness.qual.Nullable; +*/ + /** The aggregated data for a particular {@link View}. */ @Immutable @AutoValue @@ -117,7 +121,7 @@ public abstract class ViewData { return null; } }, - Functions.throwIllegalArgumentException()); + Functions.throwIllegalArgumentException()); } private static String createErrorMessageForWindow( diff --git a/api/src/main/java/io/opencensus/trace/Status.java b/api/src/main/java/io/opencensus/trace/Status.java index d5807ef5..f5a275bf 100644 --- a/api/src/main/java/io/opencensus/trace/Status.java +++ b/api/src/main/java/io/opencensus/trace/Status.java @@ -28,6 +28,10 @@ import java.util.TreeMap; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; +/*>>> +import org.checkerframework.dataflow.qual.Deterministic; +*/ + /** * Defines the status of a {@link Span} by providing a standard {@link CanonicalCode} in conjunction * with an optional descriptive message. Instances of {@code Status} are created by starting with @@ -286,6 +290,7 @@ public final class Status { * @return the description of this {@code Status}. */ @Nullable + /*@Deterministic*/ public String getDescription() { return description; } diff --git a/api/src/main/java/io/opencensus/trace/export/SpanData.java b/api/src/main/java/io/opencensus/trace/export/SpanData.java index c268d6b4..498c142e 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanData.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanData.java @@ -36,6 +36,10 @@ import java.util.Map; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; +/*>>> +import org.checkerframework.dataflow.qual.Deterministic; +*/ + /** Immutable representation of all data collected by the {@link Span} class. */ @Immutable @AutoValue @@ -106,6 +110,7 @@ public abstract class SpanData { * @return the parent {@code SpanId} or {@code null} if the {@code Span} is a root {@code Span}. */ @Nullable + /*@Deterministic*/ public abstract SpanId getParentSpanId(); /** @@ -177,6 +182,7 @@ public abstract class SpanData { * @return the {@code Status} or {@code null} if {@code Span} is still active. */ @Nullable + /*@Deterministic*/ public abstract Status getStatus(); /** @@ -185,6 +191,7 @@ public abstract class SpanData { * @return the end {@code Timestamp} or {@code null} if the {@code Span} is still active. */ @Nullable + /*@Deterministic*/ public abstract Timestamp getEndTimestamp(); SpanData() {} @@ -224,6 +231,7 @@ public abstract class SpanData { * * @return the event. */ + /*@Deterministic*/ public abstract T getEvent(); TimedEvent() {} -- cgit v1.2.3 From a2241dd72616869db521cc18724f7beab85be168 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Wed, 20 Dec 2017 10:46:38 -0800 Subject: Rename NullnessUtils to CheckerFrameworkUtils. --- .../opencensus/internal/CheckerFrameworkUtils.java | 50 ++++++++++++++++++++++ .../java/io/opencensus/internal/NullnessUtils.java | 50 ---------------------- .../main/java/io/opencensus/stats/Aggregation.java | 11 ++--- .../java/io/opencensus/stats/AggregationData.java | 16 ++++--- api/src/main/java/io/opencensus/stats/Measure.java | 8 ++-- .../main/java/io/opencensus/stats/Measurement.java | 7 +-- api/src/main/java/io/opencensus/stats/Stats.java | 4 +- api/src/main/java/io/opencensus/stats/View.java | 8 ++-- .../main/java/io/opencensus/stats/ViewData.java | 7 +-- api/src/main/java/io/opencensus/tags/Tags.java | 4 +- .../java/io/opencensus/trace/AttributeValue.java | 8 ++-- api/src/main/java/io/opencensus/trace/Tracing.java | 4 +- 12 files changed, 94 insertions(+), 83 deletions(-) create mode 100644 api/src/main/java/io/opencensus/internal/CheckerFrameworkUtils.java delete mode 100644 api/src/main/java/io/opencensus/internal/NullnessUtils.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/CheckerFrameworkUtils.java b/api/src/main/java/io/opencensus/internal/CheckerFrameworkUtils.java new file mode 100644 index 00000000..34f69b1e --- /dev/null +++ b/api/src/main/java/io/opencensus/internal/CheckerFrameworkUtils.java @@ -0,0 +1,50 @@ +/* + * 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.internal; + +import io.opencensus.common.Function; +import javax.annotation.Nullable; + +/*>>> +import org.checkerframework.checker.nullness.qual.KeyForBottom; +*/ + +/** + * Utility methods for suppressing nullness warnings and working around Checker Framework issues. + */ +public final class CheckerFrameworkUtils { + private CheckerFrameworkUtils() {} + + /** Suppress warnings about a nullable value. */ + // TODO(sebright): Try to remove all uses of this method. + @SuppressWarnings("nullness") + public static T castNonNull(@Nullable T arg) { + return arg; + } + + /** + * Work around https://github.com/typetools/checker-framework/issues/1712 by removing {@code ? + * super} from a {@code Function}'s argument type. + */ + // TODO(sebright): Remove this method once the issue is fixed. + public static Function removeSuperFromFunctionParameterType( + Function function) { + @SuppressWarnings("unchecked") + Function castFunction = (Function) function; + return castFunction; + } +} diff --git a/api/src/main/java/io/opencensus/internal/NullnessUtils.java b/api/src/main/java/io/opencensus/internal/NullnessUtils.java deleted file mode 100644 index 0301b798..00000000 --- a/api/src/main/java/io/opencensus/internal/NullnessUtils.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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.internal; - -import io.opencensus.common.Function; -import javax.annotation.Nullable; - -/*>>> -import org.checkerframework.checker.nullness.qual.KeyForBottom; -*/ - -/** - * Utility methods for suppressing nullness warnings and working around Checker Framework issues. - */ -public final class NullnessUtils { - private NullnessUtils() {} - - /** Suppress warnings about a nullable value. */ - // TODO(sebright): Try to remove all uses of this method. - @SuppressWarnings("nullness") - public static T castNonNull(@Nullable T arg) { - return arg; - } - - /** - * Work around https://github.com/typetools/checker-framework/issues/1712 by removing {@code ? - * super} from a {@code Function}'s argument type. - */ - // TODO(sebright): Remove this method once the issue is fixed. - public static Function removeSuperFromFunctionParameterType( - Function function) { - @SuppressWarnings("unchecked") - Function castFunction = (Function) function; - return castFunction; - } -} diff --git a/api/src/main/java/io/opencensus/stats/Aggregation.java b/api/src/main/java/io/opencensus/stats/Aggregation.java index 7a612313..f9d2590c 100644 --- a/api/src/main/java/io/opencensus/stats/Aggregation.java +++ b/api/src/main/java/io/opencensus/stats/Aggregation.java @@ -20,7 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; import io.opencensus.common.Function; -import io.opencensus.internal.NullnessUtils; +import io.opencensus.internal.CheckerFrameworkUtils; import javax.annotation.concurrent.Immutable; /** @@ -80,7 +80,7 @@ public abstract class Aggregation { Function p2, Function p3, Function defaultFunction) { - return NullnessUtils.removeSuperFromFunctionParameterType(p0).apply(this); + return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p0).apply(this); } } @@ -112,7 +112,7 @@ public abstract class Aggregation { Function p2, Function p3, Function defaultFunction) { - return NullnessUtils.removeSuperFromFunctionParameterType(p1).apply(this); + return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p1).apply(this); } } @@ -144,7 +144,7 @@ public abstract class Aggregation { Function p2, Function p3, Function defaultFunction) { - return NullnessUtils.removeSuperFromFunctionParameterType(p2).apply(this); + return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p2).apply(this); } } @@ -180,7 +180,8 @@ public abstract class Aggregation { Function p2, Function p3, Function defaultFunction) { - return NullnessUtils.removeSuperFromFunctionParameterType(p3).apply(this); + return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p3) + .apply(this); } } } diff --git a/api/src/main/java/io/opencensus/stats/AggregationData.java b/api/src/main/java/io/opencensus/stats/AggregationData.java index bdf618bc..1ab7681c 100644 --- a/api/src/main/java/io/opencensus/stats/AggregationData.java +++ b/api/src/main/java/io/opencensus/stats/AggregationData.java @@ -22,7 +22,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; import com.google.common.collect.Lists; import io.opencensus.common.Function; -import io.opencensus.internal.NullnessUtils; +import io.opencensus.internal.CheckerFrameworkUtils; import java.util.Collections; import java.util.List; import javax.annotation.concurrent.Immutable; @@ -93,7 +93,8 @@ public abstract class AggregationData { Function p3, Function p4, Function defaultFunction) { - return NullnessUtils.removeSuperFromFunctionParameterType(p0).apply(this); + return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p0) + .apply(this); } } @@ -132,7 +133,8 @@ public abstract class AggregationData { Function p3, Function p4, Function defaultFunction) { - return NullnessUtils.removeSuperFromFunctionParameterType(p1).apply(this); + return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p1) + .apply(this); } } @@ -171,7 +173,8 @@ public abstract class AggregationData { Function p3, Function p4, Function defaultFunction) { - return NullnessUtils.removeSuperFromFunctionParameterType(p2).apply(this); + return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p2) + .apply(this); } } @@ -218,7 +221,8 @@ public abstract class AggregationData { Function p3, Function p4, Function defaultFunction) { - return NullnessUtils.removeSuperFromFunctionParameterType(p3).apply(this); + return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p3) + .apply(this); } } @@ -318,7 +322,7 @@ public abstract class AggregationData { Function p3, Function p4, Function defaultFunction) { - return NullnessUtils.removeSuperFromFunctionParameterType(p4) + return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p4) .apply(this); } } diff --git a/api/src/main/java/io/opencensus/stats/Measure.java b/api/src/main/java/io/opencensus/stats/Measure.java index 70210f4e..b7b6c187 100644 --- a/api/src/main/java/io/opencensus/stats/Measure.java +++ b/api/src/main/java/io/opencensus/stats/Measure.java @@ -21,7 +21,7 @@ import static com.google.common.base.Preconditions.checkArgument; import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; import io.opencensus.common.Function; -import io.opencensus.internal.NullnessUtils; +import io.opencensus.internal.CheckerFrameworkUtils; import io.opencensus.internal.StringUtil; import javax.annotation.concurrent.Immutable; @@ -100,7 +100,8 @@ public abstract class Measure { Function p0, Function p1, Function defaultFunction) { - return NullnessUtils.removeSuperFromFunctionParameterType(p0).apply(this); + return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p0) + .apply(this); } @Override @@ -145,7 +146,8 @@ public abstract class Measure { Function p0, Function p1, Function defaultFunction) { - return NullnessUtils.removeSuperFromFunctionParameterType(p1).apply(this); + return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p1) + .apply(this); } @Override diff --git a/api/src/main/java/io/opencensus/stats/Measurement.java b/api/src/main/java/io/opencensus/stats/Measurement.java index 954cf43a..2d9dcf02 100644 --- a/api/src/main/java/io/opencensus/stats/Measurement.java +++ b/api/src/main/java/io/opencensus/stats/Measurement.java @@ -18,7 +18,7 @@ package io.opencensus.stats; import com.google.auto.value.AutoValue; import io.opencensus.common.Function; -import io.opencensus.internal.NullnessUtils; +import io.opencensus.internal.CheckerFrameworkUtils; import io.opencensus.stats.Measure.MeasureDouble; import io.opencensus.stats.Measure.MeasureLong; import javax.annotation.concurrent.Immutable; @@ -63,7 +63,7 @@ public abstract class Measurement { Function p0, Function p1, Function defaultFunction) { - return NullnessUtils.removeSuperFromFunctionParameterType(p0) + return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p0) .apply(this); } } @@ -92,7 +92,8 @@ public abstract class Measurement { Function p0, Function p1, Function defaultFunction) { - return NullnessUtils.removeSuperFromFunctionParameterType(p1).apply(this); + return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p1) + .apply(this); } } } diff --git a/api/src/main/java/io/opencensus/stats/Stats.java b/api/src/main/java/io/opencensus/stats/Stats.java index 0830313a..18b1cf34 100644 --- a/api/src/main/java/io/opencensus/stats/Stats.java +++ b/api/src/main/java/io/opencensus/stats/Stats.java @@ -17,7 +17,7 @@ package io.opencensus.stats; import com.google.common.annotations.VisibleForTesting; -import io.opencensus.internal.NullnessUtils; +import io.opencensus.internal.CheckerFrameworkUtils; import io.opencensus.internal.Provider; import java.util.logging.Level; import java.util.logging.Logger; @@ -27,7 +27,7 @@ public final class Stats { private static final Logger logger = Logger.getLogger(Stats.class.getName()); private static final StatsComponent statsComponent = - loadStatsComponent(NullnessUtils.castNonNull(StatsComponent.class.getClassLoader())); + loadStatsComponent(CheckerFrameworkUtils.castNonNull(StatsComponent.class.getClassLoader())); /** Returns the default {@link StatsRecorder}. */ public static StatsRecorder getStatsRecorder() { diff --git a/api/src/main/java/io/opencensus/stats/View.java b/api/src/main/java/io/opencensus/stats/View.java index 4f852c77..0ab29e5e 100644 --- a/api/src/main/java/io/opencensus/stats/View.java +++ b/api/src/main/java/io/opencensus/stats/View.java @@ -22,7 +22,7 @@ import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; import io.opencensus.common.Duration; import io.opencensus.common.Function; -import io.opencensus.internal.NullnessUtils; +import io.opencensus.internal.CheckerFrameworkUtils; import io.opencensus.internal.StringUtil; import io.opencensus.tags.TagKey; import java.util.ArrayList; @@ -179,7 +179,8 @@ public abstract class View { Function p0, Function p1, Function defaultFunction) { - return NullnessUtils.removeSuperFromFunctionParameterType(p0).apply(this); + return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p0) + .apply(this); } } @@ -221,7 +222,8 @@ public abstract class View { Function p0, Function p1, Function defaultFunction) { - return NullnessUtils.removeSuperFromFunctionParameterType(p1).apply(this); + return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p1) + .apply(this); } } } diff --git a/api/src/main/java/io/opencensus/stats/ViewData.java b/api/src/main/java/io/opencensus/stats/ViewData.java index fe2510bc..f383fff5 100644 --- a/api/src/main/java/io/opencensus/stats/ViewData.java +++ b/api/src/main/java/io/opencensus/stats/ViewData.java @@ -23,7 +23,7 @@ import com.google.common.collect.Maps; import io.opencensus.common.Function; import io.opencensus.common.Functions; import io.opencensus.common.Timestamp; -import io.opencensus.internal.NullnessUtils; +import io.opencensus.internal.CheckerFrameworkUtils; import io.opencensus.stats.Aggregation.Count; import io.opencensus.stats.Aggregation.Distribution; import io.opencensus.stats.Aggregation.Mean; @@ -242,7 +242,7 @@ public abstract class ViewData { Function p0, Function p1, Function defaultFunction) { - return NullnessUtils.removeSuperFromFunctionParameterType(p0) + return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p0) .apply(this); } @@ -277,7 +277,8 @@ public abstract class ViewData { Function p0, Function p1, Function defaultFunction) { - return NullnessUtils.removeSuperFromFunctionParameterType(p1).apply(this); + return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p1) + .apply(this); } /** Constructs a new {@link IntervalData}. */ diff --git a/api/src/main/java/io/opencensus/tags/Tags.java b/api/src/main/java/io/opencensus/tags/Tags.java index f480714d..b2162264 100644 --- a/api/src/main/java/io/opencensus/tags/Tags.java +++ b/api/src/main/java/io/opencensus/tags/Tags.java @@ -17,7 +17,7 @@ package io.opencensus.tags; import com.google.common.annotations.VisibleForTesting; -import io.opencensus.internal.NullnessUtils; +import io.opencensus.internal.CheckerFrameworkUtils; import io.opencensus.internal.Provider; import io.opencensus.tags.propagation.TagPropagationComponent; import java.util.logging.Level; @@ -28,7 +28,7 @@ public final class Tags { private static final Logger logger = Logger.getLogger(Tags.class.getName()); private static final TagsComponent tagsComponent = - loadTagsComponent(NullnessUtils.castNonNull(TagsComponent.class.getClassLoader())); + loadTagsComponent(CheckerFrameworkUtils.castNonNull(TagsComponent.class.getClassLoader())); private Tags() {} diff --git a/api/src/main/java/io/opencensus/trace/AttributeValue.java b/api/src/main/java/io/opencensus/trace/AttributeValue.java index 2de8fc91..619d94ad 100644 --- a/api/src/main/java/io/opencensus/trace/AttributeValue.java +++ b/api/src/main/java/io/opencensus/trace/AttributeValue.java @@ -20,7 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; import io.opencensus.common.Function; -import io.opencensus.internal.NullnessUtils; +import io.opencensus.internal.CheckerFrameworkUtils; import javax.annotation.concurrent.Immutable; /** @@ -101,7 +101,7 @@ public abstract class AttributeValue { Function booleanFunction, Function longFunction, Function defaultFunction) { - return NullnessUtils.removeSuperFromFunctionParameterType(stringFunction) + return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(stringFunction) .apply(getStringValue()); } @@ -128,7 +128,7 @@ public abstract class AttributeValue { Function booleanFunction, Function longFunction, Function defaultFunction) { - return NullnessUtils.removeSuperFromFunctionParameterType(booleanFunction) + return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(booleanFunction) .apply(getBooleanValue()); } @@ -155,7 +155,7 @@ public abstract class AttributeValue { Function booleanFunction, Function longFunction, Function defaultFunction) { - return NullnessUtils.removeSuperFromFunctionParameterType(longFunction) + return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(longFunction) .apply(getLongValue()); } diff --git a/api/src/main/java/io/opencensus/trace/Tracing.java b/api/src/main/java/io/opencensus/trace/Tracing.java index 8e575265..ba79fd08 100644 --- a/api/src/main/java/io/opencensus/trace/Tracing.java +++ b/api/src/main/java/io/opencensus/trace/Tracing.java @@ -18,7 +18,7 @@ package io.opencensus.trace; import com.google.common.annotations.VisibleForTesting; import io.opencensus.common.Clock; -import io.opencensus.internal.NullnessUtils; +import io.opencensus.internal.CheckerFrameworkUtils; import io.opencensus.internal.Provider; import io.opencensus.trace.config.TraceConfig; import io.opencensus.trace.export.ExportComponent; @@ -30,7 +30,7 @@ import java.util.logging.Logger; public final class Tracing { private static final Logger logger = Logger.getLogger(Tracing.class.getName()); private static final TraceComponent traceComponent = - loadTraceComponent(NullnessUtils.castNonNull(TraceComponent.class.getClassLoader())); + loadTraceComponent(CheckerFrameworkUtils.castNonNull(TraceComponent.class.getClassLoader())); /** * Returns the global {@link Tracer}. -- cgit v1.2.3 From 377ad8252c59180d3abd53f18b06b10e4d1a3ce8 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Wed, 20 Dec 2017 10:53:46 -0800 Subject: Minor Javadoc update. --- api/src/main/java/io/opencensus/internal/CheckerFrameworkUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/CheckerFrameworkUtils.java b/api/src/main/java/io/opencensus/internal/CheckerFrameworkUtils.java index 34f69b1e..8edcafbb 100644 --- a/api/src/main/java/io/opencensus/internal/CheckerFrameworkUtils.java +++ b/api/src/main/java/io/opencensus/internal/CheckerFrameworkUtils.java @@ -29,7 +29,7 @@ import org.checkerframework.checker.nullness.qual.KeyForBottom; public final class CheckerFrameworkUtils { private CheckerFrameworkUtils() {} - /** Suppress warnings about a nullable value. */ + /** Suppresses warnings about a nullable value. */ // TODO(sebright): Try to remove all uses of this method. @SuppressWarnings("nullness") public static T castNonNull(@Nullable T arg) { @@ -37,7 +37,7 @@ public final class CheckerFrameworkUtils { } /** - * Work around https://github.com/typetools/checker-framework/issues/1712 by removing {@code ? + * Works around https://github.com/typetools/checker-framework/issues/1712 by removing {@code ? * super} from a {@code Function}'s argument type. */ // TODO(sebright): Remove this method once the issue is fixed. -- cgit v1.2.3 From fbe01af5eb386508617a91906253e5b5f19fa1be Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Wed, 20 Dec 2017 12:06:50 -0800 Subject: Remove warning suppression related to null ClassLoaders. Class.forName can take a null ClassLoader, so the methods that instantiate the stats, tags, and tracing components can also take null ClassLoaders. --- .../java/io/opencensus/internal/CheckerFrameworkUtils.java | 12 +----------- api/src/main/java/io/opencensus/stats/Stats.java | 6 +++--- api/src/main/java/io/opencensus/tags/Tags.java | 6 +++--- api/src/main/java/io/opencensus/trace/Tracing.java | 6 +++--- 4 files changed, 10 insertions(+), 20 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/CheckerFrameworkUtils.java b/api/src/main/java/io/opencensus/internal/CheckerFrameworkUtils.java index 8edcafbb..599c2fd3 100644 --- a/api/src/main/java/io/opencensus/internal/CheckerFrameworkUtils.java +++ b/api/src/main/java/io/opencensus/internal/CheckerFrameworkUtils.java @@ -17,25 +17,15 @@ package io.opencensus.internal; import io.opencensus.common.Function; -import javax.annotation.Nullable; /*>>> import org.checkerframework.checker.nullness.qual.KeyForBottom; */ -/** - * Utility methods for suppressing nullness warnings and working around Checker Framework issues. - */ +/** Utility methods for working around Checker Framework issues. */ public final class CheckerFrameworkUtils { private CheckerFrameworkUtils() {} - /** Suppresses warnings about a nullable value. */ - // TODO(sebright): Try to remove all uses of this method. - @SuppressWarnings("nullness") - public static T castNonNull(@Nullable T arg) { - return arg; - } - /** * Works around https://github.com/typetools/checker-framework/issues/1712 by removing {@code ? * super} from a {@code Function}'s argument type. diff --git a/api/src/main/java/io/opencensus/stats/Stats.java b/api/src/main/java/io/opencensus/stats/Stats.java index 18b1cf34..185b9e33 100644 --- a/api/src/main/java/io/opencensus/stats/Stats.java +++ b/api/src/main/java/io/opencensus/stats/Stats.java @@ -17,17 +17,17 @@ package io.opencensus.stats; import com.google.common.annotations.VisibleForTesting; -import io.opencensus.internal.CheckerFrameworkUtils; import io.opencensus.internal.Provider; import java.util.logging.Level; import java.util.logging.Logger; +import javax.annotation.Nullable; /** Class for accessing the default {@link StatsComponent}. */ public final class Stats { private static final Logger logger = Logger.getLogger(Stats.class.getName()); private static final StatsComponent statsComponent = - loadStatsComponent(CheckerFrameworkUtils.castNonNull(StatsComponent.class.getClassLoader())); + loadStatsComponent(StatsComponent.class.getClassLoader()); /** Returns the default {@link StatsRecorder}. */ public static StatsRecorder getStatsRecorder() { @@ -76,7 +76,7 @@ public final class Stats { // Any provider that may be used for StatsComponent can be added here. @VisibleForTesting - static StatsComponent loadStatsComponent(ClassLoader classLoader) { + static StatsComponent loadStatsComponent(@Nullable ClassLoader classLoader) { try { // Call Class.forName with literal string name of the class to help shading tools. return Provider.createInstance( diff --git a/api/src/main/java/io/opencensus/tags/Tags.java b/api/src/main/java/io/opencensus/tags/Tags.java index b2162264..5832ca5d 100644 --- a/api/src/main/java/io/opencensus/tags/Tags.java +++ b/api/src/main/java/io/opencensus/tags/Tags.java @@ -17,18 +17,18 @@ package io.opencensus.tags; import com.google.common.annotations.VisibleForTesting; -import io.opencensus.internal.CheckerFrameworkUtils; import io.opencensus.internal.Provider; import io.opencensus.tags.propagation.TagPropagationComponent; import java.util.logging.Level; import java.util.logging.Logger; +import javax.annotation.Nullable; /** Class for accessing the default {@link TagsComponent}. */ public final class Tags { private static final Logger logger = Logger.getLogger(Tags.class.getName()); private static final TagsComponent tagsComponent = - loadTagsComponent(CheckerFrameworkUtils.castNonNull(TagsComponent.class.getClassLoader())); + loadTagsComponent(TagsComponent.class.getClassLoader()); private Tags() {} @@ -84,7 +84,7 @@ public final class Tags { // Any provider that may be used for TagsComponent can be added here. @VisibleForTesting - static TagsComponent loadTagsComponent(ClassLoader classLoader) { + static TagsComponent loadTagsComponent(@Nullable ClassLoader classLoader) { try { // Call Class.forName with literal string name of the class to help shading tools. return Provider.createInstance( diff --git a/api/src/main/java/io/opencensus/trace/Tracing.java b/api/src/main/java/io/opencensus/trace/Tracing.java index ba79fd08..31d8cdc2 100644 --- a/api/src/main/java/io/opencensus/trace/Tracing.java +++ b/api/src/main/java/io/opencensus/trace/Tracing.java @@ -18,19 +18,19 @@ package io.opencensus.trace; import com.google.common.annotations.VisibleForTesting; import io.opencensus.common.Clock; -import io.opencensus.internal.CheckerFrameworkUtils; import io.opencensus.internal.Provider; import io.opencensus.trace.config.TraceConfig; import io.opencensus.trace.export.ExportComponent; import io.opencensus.trace.propagation.PropagationComponent; import java.util.logging.Level; import java.util.logging.Logger; +import javax.annotation.Nullable; /** Class that manages a global instance of the {@link TraceComponent}. */ public final class Tracing { private static final Logger logger = Logger.getLogger(Tracing.class.getName()); private static final TraceComponent traceComponent = - loadTraceComponent(CheckerFrameworkUtils.castNonNull(TraceComponent.class.getClassLoader())); + loadTraceComponent(TraceComponent.class.getClassLoader()); /** * Returns the global {@link Tracer}. @@ -79,7 +79,7 @@ public final class Tracing { // Any provider that may be used for TraceComponent can be added here. @VisibleForTesting - static TraceComponent loadTraceComponent(ClassLoader classLoader) { + static TraceComponent loadTraceComponent(@Nullable ClassLoader classLoader) { try { // Call Class.forName with literal string name of the class to help shading tools. return Provider.createInstance( -- cgit v1.2.3 From 26232c4d43e7351bef06ffb2e1c20c5b90f6cf4c Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Wed, 17 Jan 2018 10:03:55 -0800 Subject: Update errorprone, google cloud java, grpc versions. (#931) --- api/src/main/java/io/opencensus/trace/SpanBuilder.java | 6 +++--- api/src/main/java/io/opencensus/trace/Tracer.java | 6 +++--- api/src/test/java/io/opencensus/tags/TagContextTest.java | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java index 0a7c9177..04c339ff 100644 --- a/api/src/main/java/io/opencensus/trace/SpanBuilder.java +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -221,7 +221,7 @@ public abstract class SpanBuilder { */ @MustBeClosed public final Scope startScopedSpan() { - return CurrentSpanUtils.withSpan(startSpan(), true); + return CurrentSpanUtils.withSpan(startSpan(), /* endSpan= */ true); } /** @@ -251,7 +251,7 @@ public abstract class SpanBuilder { */ public final void startSpanAndRun(final Runnable runnable) { final Span span = startSpan(); - CurrentSpanUtils.withSpan(span, true, runnable).run(); + CurrentSpanUtils.withSpan(span, /* endSpan= */ true, runnable).run(); } /** @@ -283,7 +283,7 @@ public abstract class SpanBuilder { */ public final V startSpanAndCall(Callable callable) throws Exception { final Span span = startSpan(); - return CurrentSpanUtils.withSpan(span, true, callable).call(); + return CurrentSpanUtils.withSpan(span, /* endSpan= */ true, callable).call(); } static final class NoopSpanBuilder extends SpanBuilder { diff --git a/api/src/main/java/io/opencensus/trace/Tracer.java b/api/src/main/java/io/opencensus/trace/Tracer.java index cd4fc822..22b98da5 100644 --- a/api/src/main/java/io/opencensus/trace/Tracer.java +++ b/api/src/main/java/io/opencensus/trace/Tracer.java @@ -148,7 +148,7 @@ public abstract class Tracer { */ @MustBeClosed public final Scope withSpan(Span span) { - return CurrentSpanUtils.withSpan(checkNotNull(span, "span"), false); + return CurrentSpanUtils.withSpan(checkNotNull(span, "span"), /* endSpan= */ false); } /** @@ -213,7 +213,7 @@ public abstract class Tracer { * @since 0.11.0 */ public final Runnable withSpan(Span span, Runnable runnable) { - return CurrentSpanUtils.withSpan(span, false, runnable); + return CurrentSpanUtils.withSpan(span, /* endSpan= */ false, runnable); } /** @@ -278,7 +278,7 @@ public abstract class Tracer { * @since 0.11.0 */ public final Callable withSpan(Span span, final Callable callable) { - return CurrentSpanUtils.withSpan(span, false, callable); + return CurrentSpanUtils.withSpan(span, /* endSpan= */ false, callable); } /** diff --git a/api/src/test/java/io/opencensus/tags/TagContextTest.java b/api/src/test/java/io/opencensus/tags/TagContextTest.java index b5c44b15..05473255 100644 --- a/api/src/test/java/io/opencensus/tags/TagContextTest.java +++ b/api/src/test/java/io/opencensus/tags/TagContextTest.java @@ -84,7 +84,7 @@ public final class TagContextTest { } private static final class SimpleTagContext extends TagContext { - private final List tags; + @Nullable private final List tags; // This Error Prone warning doesn't seem correct, because the constructor is just calling // another constructor. -- cgit v1.2.3 From 3b59ca22ca27239039f023919d546c137f867774 Mon Sep 17 00:00:00 2001 From: Hailong Wen Date: Wed, 17 Jan 2018 15:03:49 -0800 Subject: Add http propagation APIs. (#930) * Add http propagation APIs. * Add an API in `PropagationComponent` for B3 format access. * Add contrib-http-util, with initial SD format support. --- .../trace/propagation/PropagationComponent.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java b/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java index 7dfa8202..9839517e 100644 --- a/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java +++ b/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java @@ -18,7 +18,8 @@ package io.opencensus.trace.propagation; /** * Container class for all the supported propagation formats. Currently supports only Binary format - * see {@link BinaryFormat} but more formats will be added. + * (see {@link BinaryFormat}) and B3 Text format (see {@link TextFormat}) but more formats will be + * added. */ public abstract class PropagationComponent { private static final PropagationComponent NOOP_PROPAGATION_COMPONENT = @@ -32,6 +33,16 @@ public abstract class PropagationComponent { */ public abstract BinaryFormat getBinaryFormat(); + /** + * Returns the B3 {@link TextFormat} with the provided implementations. See b3-propagation for more information. If + * no implementation is provided then no-op implementation will be used. + * + * @since 0.11.0 + * @return the B3 {@code TextFormat} implementation for B3. + */ + public abstract TextFormat getB3Format(); + /** * Returns an instance that contains no-op implementations for all the instances. * @@ -46,5 +57,10 @@ public abstract class PropagationComponent { public BinaryFormat getBinaryFormat() { return BinaryFormat.getNoopBinaryFormat(); } + + @Override + public TextFormat getB3Format() { + return TextFormat.getNoopTextFormat(); + } } } -- cgit v1.2.3 From 7720668b0fce41dda06f15bd50e1025f062bbdad Mon Sep 17 00:00:00 2001 From: Hailong Wen Date: Wed, 17 Jan 2018 16:40:20 -0800 Subject: Annotate `PropagationComponent#getB3Format()` with `ExperimentalApi`. (#934) --- .../java/io/opencensus/trace/propagation/PropagationComponent.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java b/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java index 9839517e..a56c6d13 100644 --- a/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java +++ b/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java @@ -16,6 +16,8 @@ package io.opencensus.trace.propagation; +import io.opencensus.common.ExperimentalApi; + /** * Container class for all the supported propagation formats. Currently supports only Binary format * (see {@link BinaryFormat}) and B3 Text format (see {@link TextFormat}) but more formats will be @@ -41,6 +43,7 @@ public abstract class PropagationComponent { * @since 0.11.0 * @return the B3 {@code TextFormat} implementation for B3. */ + @ExperimentalApi public abstract TextFormat getB3Format(); /** -- cgit v1.2.3 From 3c1819a03134139b4fef41508f7bb802305c3302 Mon Sep 17 00:00:00 2001 From: Hailong Wen Date: Thu, 18 Jan 2018 18:41:16 -0800 Subject: Start 0.12.0 development cycle (#937) --- .../main/java/io/opencensus/common/OpenCensusLibraryInformation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java index 91151212..38ec8d32 100644 --- a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java +++ b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java @@ -21,7 +21,7 @@ package io.opencensus.common; public final class OpenCensusLibraryInformation { /** The current version of the OpenCensus Java library. */ - public static final String VERSION = "0.11.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION + public static final String VERSION = "0.12.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION private OpenCensusLibraryInformation() {} } -- cgit v1.2.3 From 33dcccc9279ffc2fdd8206f5d1be40188dd26c82 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Wed, 31 Jan 2018 09:34:02 -0800 Subject: Add '@since' Javadoc tag to all tagging APIs (issue #864). This commit also adds missing Javadocs. --- api/src/main/java/io/opencensus/tags/InternalUtils.java | 11 ++++++++++- api/src/main/java/io/opencensus/tags/Tag.java | 9 ++++++++- api/src/main/java/io/opencensus/tags/TagContext.java | 3 +++ .../main/java/io/opencensus/tags/TagContextBuilder.java | 10 +++++++++- api/src/main/java/io/opencensus/tags/TagKey.java | 10 +++++++++- api/src/main/java/io/opencensus/tags/TagValue.java | 10 +++++++++- api/src/main/java/io/opencensus/tags/Tagger.java | 8 ++++++++ api/src/main/java/io/opencensus/tags/TaggingState.java | 10 +++++++++- api/src/main/java/io/opencensus/tags/Tags.java | 10 +++++++++- api/src/main/java/io/opencensus/tags/TagsComponent.java | 16 ++++++++++++++-- .../tags/propagation/TagContextBinarySerializer.java | 4 ++++ .../propagation/TagContextDeserializationException.java | 8 +++++++- .../propagation/TagContextSerializationException.java | 8 +++++++- .../tags/propagation/TagPropagationComponent.java | 7 ++++++- .../java/io/opencensus/tags/unsafe/ContextUtils.java | 4 ++++ 15 files changed, 116 insertions(+), 12 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/tags/InternalUtils.java b/api/src/main/java/io/opencensus/tags/InternalUtils.java index 734fcf98..944122e1 100644 --- a/api/src/main/java/io/opencensus/tags/InternalUtils.java +++ b/api/src/main/java/io/opencensus/tags/InternalUtils.java @@ -18,11 +18,20 @@ package io.opencensus.tags; import java.util.Iterator; -/** Internal tagging utilities. */ +/** + * Internal tagging utilities. + * + * @since 0.8 + */ @io.opencensus.common.Internal public final class InternalUtils { private InternalUtils() {} + /** + * Internal tag accessor. + * + * @since 0.8 + */ public static Iterator getTags(TagContext tags) { return tags.getIterator(); } diff --git a/api/src/main/java/io/opencensus/tags/Tag.java b/api/src/main/java/io/opencensus/tags/Tag.java index 90b050d5..d5415e02 100644 --- a/api/src/main/java/io/opencensus/tags/Tag.java +++ b/api/src/main/java/io/opencensus/tags/Tag.java @@ -19,7 +19,11 @@ package io.opencensus.tags; import com.google.auto.value.AutoValue; import javax.annotation.concurrent.Immutable; -/** {@link TagKey} paired with a {@link TagValue}. */ +/** + * {@link TagKey} paired with a {@link TagValue}. + * + * @since 0.8 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -35,6 +39,7 @@ public abstract class Tag { * @param key the tag key. * @param value the tag value. * @return a {@code Tag} with the given key and value. + * @since 0.8 */ public static Tag create(TagKey key, TagValue value) { return new AutoValue_Tag(key, value); @@ -44,6 +49,7 @@ public abstract class Tag { * Returns the tag's key. * * @return the tag's key. + * @since 0.8 */ public abstract TagKey getKey(); @@ -51,6 +57,7 @@ public abstract class Tag { * Returns the tag's value. * * @return the tag's value. + * @since 0.8 */ public abstract TagValue getValue(); } diff --git a/api/src/main/java/io/opencensus/tags/TagContext.java b/api/src/main/java/io/opencensus/tags/TagContext.java index bc2a1630..841c8ab5 100644 --- a/api/src/main/java/io/opencensus/tags/TagContext.java +++ b/api/src/main/java/io/opencensus/tags/TagContext.java @@ -30,6 +30,8 @@ import javax.annotation.concurrent.Immutable; * *

    For example, {@code TagContext}s can be used to label stats, log messages, or debugging * information. + * + * @since 0.8 */ @Immutable public abstract class TagContext { @@ -38,6 +40,7 @@ public abstract class TagContext { * Returns an iterator over the tags in this {@code TagContext}. * * @return an iterator over the tags in this {@code TagContext}. + * @since 0.8 */ // This method is protected to prevent client code from accessing the tags of any TagContext. We // don't currently support efficient access to tags. However, every TagContext subclass needs to diff --git a/api/src/main/java/io/opencensus/tags/TagContextBuilder.java b/api/src/main/java/io/opencensus/tags/TagContextBuilder.java index c6c858c6..f4268968 100644 --- a/api/src/main/java/io/opencensus/tags/TagContextBuilder.java +++ b/api/src/main/java/io/opencensus/tags/TagContextBuilder.java @@ -18,7 +18,11 @@ package io.opencensus.tags; import io.opencensus.common.Scope; -/** Builder for the {@link TagContext} class. */ +/** + * Builder for the {@link TagContext} class. + * + * @since 0.8 + */ public abstract class TagContextBuilder { /** @@ -27,6 +31,7 @@ public abstract class TagContextBuilder { * @param key the {@code TagKey} which will be set. * @param value the {@code TagValue} to set for the given key. * @return this + * @since 0.8 */ public abstract TagContextBuilder put(TagKey key, TagValue value); @@ -35,6 +40,7 @@ public abstract class TagContextBuilder { * * @param key the {@code TagKey} which will be removed. * @return this + * @since 0.8 */ public abstract TagContextBuilder remove(TagKey key); @@ -42,6 +48,7 @@ public abstract class TagContextBuilder { * Creates a {@code TagContext} from this builder. * * @return a {@code TagContext} with the same tags as this builder. + * @since 0.8 */ public abstract TagContext build(); @@ -52,6 +59,7 @@ public abstract class TagContextBuilder { * * @return an object that defines a scope where the {@code TagContext} created from this builder * is set to the current context. + * @since 0.8 */ public abstract Scope buildScoped(); } diff --git a/api/src/main/java/io/opencensus/tags/TagKey.java b/api/src/main/java/io/opencensus/tags/TagKey.java index a6eb802f..bad2fec3 100644 --- a/api/src/main/java/io/opencensus/tags/TagKey.java +++ b/api/src/main/java/io/opencensus/tags/TagKey.java @@ -30,6 +30,8 @@ import javax.annotation.concurrent.Immutable; * *

    {@code TagKey}s are designed to be used as constants. Declaring each key as a constant * prevents key names from being validated multiple times. + * + * @since 0.8 */ @Immutable @AutoValue @@ -37,7 +39,11 @@ import javax.annotation.concurrent.Immutable; @AutoValue.CopyAnnotations @SuppressWarnings("nullness") public abstract class TagKey { - /** The maximum length for a tag key name. The value is {@value #MAX_LENGTH}. */ + /** + * The maximum length for a tag key name. The value is {@value #MAX_LENGTH}. + * + * @since 0.8 + */ public static final int MAX_LENGTH = 255; TagKey() {} @@ -55,6 +61,7 @@ public abstract class TagKey { * @param name the name of the key. * @return a {@code TagKey} with the given name. * @throws IllegalArgumentException if the name is not valid. + * @since 0.8 */ public static TagKey create(String name) { checkArgument(isValid(name)); @@ -65,6 +72,7 @@ public abstract class TagKey { * Returns the name of the key. * * @return the name of the key. + * @since 0.8 */ public abstract String getName(); diff --git a/api/src/main/java/io/opencensus/tags/TagValue.java b/api/src/main/java/io/opencensus/tags/TagValue.java index bd2894a7..07ccc2cc 100644 --- a/api/src/main/java/io/opencensus/tags/TagValue.java +++ b/api/src/main/java/io/opencensus/tags/TagValue.java @@ -26,6 +26,8 @@ import javax.annotation.concurrent.Immutable; * *

    Validation ensures that the {@code String} has a maximum length of {@link #MAX_LENGTH} and * contains only printable ASCII characters. + * + * @since 0.8 */ @Immutable @AutoValue @@ -33,7 +35,11 @@ import javax.annotation.concurrent.Immutable; @AutoValue.CopyAnnotations @SuppressWarnings("nullness") public abstract class TagValue { - /** The maximum length for a tag value. The value is {@value #MAX_LENGTH}. */ + /** + * The maximum length for a tag value. The value is {@value #MAX_LENGTH}. + * + * @since 0.8 + */ public static final int MAX_LENGTH = 255; TagValue() {} @@ -49,6 +55,7 @@ public abstract class TagValue { * * @param value the tag value. * @throws IllegalArgumentException if the {@code String} is not valid. + * @since 0.8 */ public static TagValue create(String value) { Preconditions.checkArgument(isValid(value)); @@ -59,6 +66,7 @@ public abstract class TagValue { * Returns the tag value as a {@code String}. * * @return the tag value as a {@code String}. + * @since 0.8 */ public abstract String asString(); diff --git a/api/src/main/java/io/opencensus/tags/Tagger.java b/api/src/main/java/io/opencensus/tags/Tagger.java index 1d786f71..f3ba0f5b 100644 --- a/api/src/main/java/io/opencensus/tags/Tagger.java +++ b/api/src/main/java/io/opencensus/tags/Tagger.java @@ -27,6 +27,8 @@ import io.opencensus.common.Scope; *

    Implementations may have different constraints and are free to convert tag contexts to their * own subtypes. This means callers cannot assume the {@link #getCurrentTagContext() current * context} is the same instance as the one {@link #withTagContext(TagContext) placed into scope}. + * + * @since 0.8 */ public abstract class Tagger { @@ -34,6 +36,7 @@ public abstract class Tagger { * Returns an empty {@code TagContext}. * * @return an empty {@code TagContext}. + * @since 0.8 */ public abstract TagContext empty(); @@ -41,6 +44,7 @@ public abstract class Tagger { * Returns the current {@code TagContext}. * * @return the current {@code TagContext}. + * @since 0.8 */ public abstract TagContext getCurrentTagContext(); @@ -48,6 +52,7 @@ public abstract class Tagger { * Returns a new empty {@code Builder}. * * @return a new empty {@code Builder}. + * @since 0.8 */ public abstract TagContextBuilder emptyBuilder(); @@ -55,6 +60,7 @@ public abstract class Tagger { * Returns a builder based on this {@code TagContext}. * * @return a builder based on this {@code TagContext}. + * @since 0.8 */ public abstract TagContextBuilder toBuilder(TagContext tags); @@ -62,6 +68,7 @@ public abstract class Tagger { * Returns a new builder created from the current {@code TagContext}. * * @return a new builder created from the current {@code TagContext}. + * @since 0.8 */ public abstract TagContextBuilder currentBuilder(); @@ -73,6 +80,7 @@ public abstract class Tagger { * @param tags the {@code TagContext} to be set to the current context. * @return an object that defines a scope where the given {@code TagContext} is set to the current * context. + * @since 0.8 */ public abstract Scope withTagContext(TagContext tags); } diff --git a/api/src/main/java/io/opencensus/tags/TaggingState.java b/api/src/main/java/io/opencensus/tags/TaggingState.java index 861aca74..88970361 100644 --- a/api/src/main/java/io/opencensus/tags/TaggingState.java +++ b/api/src/main/java/io/opencensus/tags/TaggingState.java @@ -16,7 +16,11 @@ package io.opencensus.tags; -/** State of the {@link TagsComponent}. */ +/** + * State of the {@link TagsComponent}. + * + * @since 0.8 + */ public enum TaggingState { // TODO(sebright): Should we add a state that propagates the tags, but doesn't allow // modifications? @@ -26,6 +30,8 @@ public enum TaggingState { * *

    The {@link TagsComponent} can add tags to {@link TagContext}s, propagate {@code TagContext}s * in the current context, and serialize {@code TagContext}s. + * + * @since 0.8 */ ENABLED, @@ -34,6 +40,8 @@ public enum TaggingState { * *

    The {@link TagsComponent} may not add tags to {@link TagContext}s, propagate {@code * TagContext}s in the current context, or serialize {@code TagContext}s. + * + * @since 0.8 */ // TODO(sebright): Document how this interacts with stats collection. DISABLED diff --git a/api/src/main/java/io/opencensus/tags/Tags.java b/api/src/main/java/io/opencensus/tags/Tags.java index 5832ca5d..b784b5f5 100644 --- a/api/src/main/java/io/opencensus/tags/Tags.java +++ b/api/src/main/java/io/opencensus/tags/Tags.java @@ -23,7 +23,11 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; -/** Class for accessing the default {@link TagsComponent}. */ +/** + * Class for accessing the default {@link TagsComponent}. + * + * @since 0.8 + */ public final class Tags { private static final Logger logger = Logger.getLogger(Tags.class.getName()); @@ -36,6 +40,7 @@ public final class Tags { * Returns the default {@code Tagger}. * * @return the default {@code Tagger}. + * @since 0.8 */ public static Tagger getTagger() { return tagsComponent.getTagger(); @@ -45,6 +50,7 @@ public final class Tags { * Returns the default {@code TagPropagationComponent}. * * @return the default {@code TagPropagationComponent}. + * @since 0.8 */ public static TagPropagationComponent getTagPropagationComponent() { return tagsComponent.getTagPropagationComponent(); @@ -60,6 +66,7 @@ public final class Tags { * throw an {@code IllegalStateException}. * * @return the current {@code TaggingState}. + * @since 0.8 */ public static TaggingState getState() { return tagsComponent.getState(); @@ -76,6 +83,7 @@ public final class Tags { * #getState()}, use a stale value, and behave incorrectly. It is only safe to call early in * initialization. This method throws {@link IllegalStateException} after {@link #getState()} * has been called, in order to limit changes to the result of {@code getState()}. + * @since 0.8 */ @Deprecated public static void setState(TaggingState state) { diff --git a/api/src/main/java/io/opencensus/tags/TagsComponent.java b/api/src/main/java/io/opencensus/tags/TagsComponent.java index b0965077..d34f1951 100644 --- a/api/src/main/java/io/opencensus/tags/TagsComponent.java +++ b/api/src/main/java/io/opencensus/tags/TagsComponent.java @@ -22,13 +22,23 @@ import io.opencensus.tags.propagation.TagPropagationComponent; * Class that holds the implementation for {@link Tagger} and {@link TagPropagationComponent}. * *

    All objects returned by methods on {@code TagsComponent} are cacheable. + * + * @since 0.8 */ public abstract class TagsComponent { - /** Returns the {@link Tagger} for this implementation. */ + /** + * Returns the {@link Tagger} for this implementation. + * + * @since 0.8 + */ public abstract Tagger getTagger(); - /** Returns the {@link TagPropagationComponent} for this implementation. */ + /** + * Returns the {@link TagPropagationComponent} for this implementation. + * + * @since 0.8 + */ public abstract TagPropagationComponent getTagPropagationComponent(); /** @@ -41,6 +51,7 @@ public abstract class TagsComponent { * throw an {@code IllegalStateException}. * * @return the current {@code TaggingState}. + * @since 0.8 */ public abstract TaggingState getState(); @@ -55,6 +66,7 @@ public abstract class TagsComponent { * #getState()}, use a stale value, and behave incorrectly. It is only safe to call early in * initialization. This method throws {@link IllegalStateException} after {@code getState()} * has been called, in order to limit changes to the result of {@code getState()}. + * @since 0.8 */ @Deprecated public abstract void setState(TaggingState state); diff --git a/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java b/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java index f89d7b0d..39eb8cee 100644 --- a/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java +++ b/api/src/main/java/io/opencensus/tags/propagation/TagContextBinarySerializer.java @@ -24,6 +24,8 @@ import io.opencensus.tags.TagContext; *

    See opencensus-specs * for the specification of the cross-language binary serialization format. + * + * @since 0.8 */ public abstract class TagContextBinarySerializer { @@ -36,6 +38,7 @@ public abstract class TagContextBinarySerializer { * @return the on-the-wire representation of a {@code TagContext}. * @throws TagContextSerializationException if the result would be larger than the maximum allowed * serialized size. + * @since 0.8 */ public abstract byte[] toByteArray(TagContext tags) throws TagContextSerializationException; @@ -48,6 +51,7 @@ public abstract class TagContextBinarySerializer { * @return a {@code TagContext} deserialized from {@code bytes}. * @throws TagContextDeserializationException if there is a parse error, the input contains * invalid tags, or the input is larger than the maximum allowed serialized size. + * @since 0.8 */ public abstract TagContext fromByteArray(byte[] bytes) throws TagContextDeserializationException; } diff --git a/api/src/main/java/io/opencensus/tags/propagation/TagContextDeserializationException.java b/api/src/main/java/io/opencensus/tags/propagation/TagContextDeserializationException.java index eb8d18ea..11dcb59f 100644 --- a/api/src/main/java/io/opencensus/tags/propagation/TagContextDeserializationException.java +++ b/api/src/main/java/io/opencensus/tags/propagation/TagContextDeserializationException.java @@ -18,7 +18,11 @@ package io.opencensus.tags.propagation; import io.opencensus.tags.TagContext; -/** Exception thrown when a {@link TagContext} cannot be parsed. */ +/** + * Exception thrown when a {@link TagContext} cannot be parsed. + * + * @since 0.8 + */ public final class TagContextDeserializationException extends Exception { private static final long serialVersionUID = 0L; @@ -26,6 +30,7 @@ public final class TagContextDeserializationException extends Exception { * Constructs a new {@code TagContextParseException} with the given message. * * @param message a message describing the error. + * @since 0.8 */ public TagContextDeserializationException(String message) { super(message); @@ -36,6 +41,7 @@ public final class TagContextDeserializationException extends Exception { * * @param message a message describing the error. * @param cause the cause of the error. + * @since 0.8 */ public TagContextDeserializationException(String message, Throwable cause) { super(message, cause); diff --git a/api/src/main/java/io/opencensus/tags/propagation/TagContextSerializationException.java b/api/src/main/java/io/opencensus/tags/propagation/TagContextSerializationException.java index b702dd74..bb3c9b74 100644 --- a/api/src/main/java/io/opencensus/tags/propagation/TagContextSerializationException.java +++ b/api/src/main/java/io/opencensus/tags/propagation/TagContextSerializationException.java @@ -18,7 +18,11 @@ package io.opencensus.tags.propagation; import io.opencensus.tags.TagContext; -/** Exception thrown when a {@link TagContext} cannot be serialized. */ +/** + * Exception thrown when a {@link TagContext} cannot be serialized. + * + * @since 0.8 + */ public final class TagContextSerializationException extends Exception { private static final long serialVersionUID = 0L; @@ -26,6 +30,7 @@ public final class TagContextSerializationException extends Exception { * Constructs a new {@code TagContextSerializationException} with the given message. * * @param message a message describing the error. + * @since 0.8 */ public TagContextSerializationException(String message) { super(message); @@ -36,6 +41,7 @@ public final class TagContextSerializationException extends Exception { * * @param message a message describing the error. * @param cause the cause of the error. + * @since 0.8 */ public TagContextSerializationException(String message, Throwable cause) { super(message, cause); diff --git a/api/src/main/java/io/opencensus/tags/propagation/TagPropagationComponent.java b/api/src/main/java/io/opencensus/tags/propagation/TagPropagationComponent.java index c51a845c..6ececa79 100644 --- a/api/src/main/java/io/opencensus/tags/propagation/TagPropagationComponent.java +++ b/api/src/main/java/io/opencensus/tags/propagation/TagPropagationComponent.java @@ -18,7 +18,11 @@ package io.opencensus.tags.propagation; import io.opencensus.tags.TagContext; -/** Object containing all supported {@link TagContext} propagation formats. */ +/** + * Object containing all supported {@link TagContext} propagation formats. + * + * @since 0.8 + */ // TODO(sebright): Add an HTTP serializer. public abstract class TagPropagationComponent { @@ -26,6 +30,7 @@ public abstract class TagPropagationComponent { * Returns the {@link TagContextBinarySerializer} for this implementation. * * @return the {@code TagContextBinarySerializer} for this implementation. + * @since 0.8 */ public abstract TagContextBinarySerializer getBinarySerializer(); } diff --git a/api/src/main/java/io/opencensus/tags/unsafe/ContextUtils.java b/api/src/main/java/io/opencensus/tags/unsafe/ContextUtils.java index 2baf1a2a..8936bbbb 100644 --- a/api/src/main/java/io/opencensus/tags/unsafe/ContextUtils.java +++ b/api/src/main/java/io/opencensus/tags/unsafe/ContextUtils.java @@ -28,6 +28,8 @@ import javax.annotation.concurrent.Immutable; * *

    Most code should interact with the current context via the public APIs in {@link * io.opencensus.tags.TagContext} and avoid accessing {@link #TAG_CONTEXT_KEY} directly. + * + * @since 0.8 */ public final class ContextUtils { private static final TagContext EMPTY_TAG_CONTEXT = new EmptyTagContext(); @@ -37,6 +39,8 @@ public final class ContextUtils { /** * The {@link io.grpc.Context.Key} used to interact with the {@code TagContext} contained in the * {@link io.grpc.Context}. + * + * @since 0.8 */ public static final Context.Key TAG_CONTEXT_KEY = Context.keyWithDefault("opencensus-tag-context-key", EMPTY_TAG_CONTEXT); -- cgit v1.2.3 From 2a7386c27a841bd73b0e1d5bbb897f21038fe1a1 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Wed, 31 Jan 2018 09:34:02 -0800 Subject: Add '@since' Javadoc tag to all stats APIs (issue #864). This commit also adds missing Javadocs. --- .../main/java/io/opencensus/stats/Aggregation.java | 38 +++++++++++-- .../java/io/opencensus/stats/AggregationData.java | 50 +++++++++++++++-- .../java/io/opencensus/stats/BucketBoundaries.java | 8 ++- api/src/main/java/io/opencensus/stats/Measure.java | 36 ++++++++++-- .../main/java/io/opencensus/stats/MeasureMap.java | 11 +++- .../main/java/io/opencensus/stats/Measurement.java | 54 +++++++++++++++--- api/src/main/java/io/opencensus/stats/Stats.java | 20 ++++++- .../io/opencensus/stats/StatsCollectionState.java | 10 +++- .../java/io/opencensus/stats/StatsComponent.java | 16 +++++- .../java/io/opencensus/stats/StatsRecorder.java | 7 ++- api/src/main/java/io/opencensus/stats/View.java | 65 +++++++++++++++++++--- .../main/java/io/opencensus/stats/ViewData.java | 55 +++++++++++++++--- .../main/java/io/opencensus/stats/ViewManager.java | 4 ++ 13 files changed, 327 insertions(+), 47 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/Aggregation.java b/api/src/main/java/io/opencensus/stats/Aggregation.java index f9d2590c..1983b908 100644 --- a/api/src/main/java/io/opencensus/stats/Aggregation.java +++ b/api/src/main/java/io/opencensus/stats/Aggregation.java @@ -38,13 +38,19 @@ import javax.annotation.concurrent.Immutable; * *

    When creating a {@link View}, one {@link Aggregation} needs to be specified as how to * aggregate {@code MeasureValue}s. + * + * @since 0.8 */ @Immutable public abstract class Aggregation { private Aggregation() {} - /** Applies the given match function to the underlying data type. */ + /** + * Applies the given match function to the underlying data type. + * + * @since 0.8 + */ public abstract T match( Function p0, Function p1, @@ -52,7 +58,11 @@ public abstract class Aggregation { Function p3, Function defaultFunction); - /** Calculate sum on aggregated {@code MeasureValue}s. */ + /** + * Calculate sum on aggregated {@code MeasureValue}s. + * + * @since 0.8 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -68,6 +78,7 @@ public abstract class Aggregation { * Construct a {@code Sum}. * * @return a new {@code Sum}. + * @since 0.8 */ public static Sum create() { return INSTANCE; @@ -84,7 +95,11 @@ public abstract class Aggregation { } } - /** Calculate count on aggregated {@code MeasureValue}s. */ + /** + * Calculate count on aggregated {@code MeasureValue}s. + * + * @since 0.8 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -100,6 +115,7 @@ public abstract class Aggregation { * Construct a {@code Count}. * * @return a new {@code Count}. + * @since 0.8 */ public static Count create() { return INSTANCE; @@ -116,7 +132,11 @@ public abstract class Aggregation { } } - /** Calculate mean on aggregated {@code MeasureValue}s. */ + /** + * Calculate mean on aggregated {@code MeasureValue}s. + * + * @since 0.8 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -132,6 +152,7 @@ public abstract class Aggregation { * Construct a {@code Mean}. * * @return a new {@code Mean}. + * @since 0.8 */ public static Mean create() { return INSTANCE; @@ -151,6 +172,8 @@ public abstract class Aggregation { /** * Calculate distribution stats on aggregated {@code MeasureValue}s. Distribution includes mean, * count, histogram, min, max and sum of squared deviations. + * + * @since 0.8 */ @Immutable @AutoValue @@ -165,12 +188,19 @@ public abstract class Aggregation { * Construct a {@code Distribution}. * * @return a new {@code Distribution}. + * @since 0.8 */ public static Distribution create(BucketBoundaries bucketBoundaries) { checkNotNull(bucketBoundaries, "bucketBoundaries should not be null."); return new AutoValue_Aggregation_Distribution(bucketBoundaries); } + /** + * Returns the {@code Distribution}'s bucket boundaries. + * + * @return the {@code Distribution}'s bucket boundaries. + * @since 0.8 + */ public abstract BucketBoundaries getBucketBoundaries(); @Override diff --git a/api/src/main/java/io/opencensus/stats/AggregationData.java b/api/src/main/java/io/opencensus/stats/AggregationData.java index 1ab7681c..be0df5e0 100644 --- a/api/src/main/java/io/opencensus/stats/AggregationData.java +++ b/api/src/main/java/io/opencensus/stats/AggregationData.java @@ -43,13 +43,19 @@ import javax.annotation.concurrent.Immutable; * *

    {@link ViewData} will contain one {@link AggregationData}, corresponding to its {@link * Aggregation} definition in {@link View}. + * + * @since 0.8 */ @Immutable public abstract class AggregationData { private AggregationData() {} - /** Applies the given match function to the underlying data type. */ + /** + * Applies the given match function to the underlying data type. + * + * @since 0.8 + */ public abstract T match( Function p0, Function p1, @@ -58,7 +64,11 @@ public abstract class AggregationData { Function p4, Function defaultFunction); - /** The sum value of aggregated {@code MeasureValueDouble}s. */ + /** + * The sum value of aggregated {@code MeasureValueDouble}s. + * + * @since 0.8 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -73,6 +83,7 @@ public abstract class AggregationData { * * @param sum the aggregated sum. * @return a {@code SumDataDouble}. + * @since 0.8 */ public static SumDataDouble create(double sum) { return new AutoValue_AggregationData_SumDataDouble(sum); @@ -82,6 +93,7 @@ public abstract class AggregationData { * Returns the aggregated sum. * * @return the aggregated sum. + * @since 0.8 */ public abstract double getSum(); @@ -98,7 +110,11 @@ public abstract class AggregationData { } } - /** The sum value of aggregated {@code MeasureValueLong}s. */ + /** + * The sum value of aggregated {@code MeasureValueLong}s. + * + * @since 0.8 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -113,6 +129,7 @@ public abstract class AggregationData { * * @param sum the aggregated sum. * @return a {@code SumDataLong}. + * @since 0.8 */ public static SumDataLong create(long sum) { return new AutoValue_AggregationData_SumDataLong(sum); @@ -122,6 +139,7 @@ public abstract class AggregationData { * Returns the aggregated sum. * * @return the aggregated sum. + * @since 0.8 */ public abstract long getSum(); @@ -138,7 +156,11 @@ public abstract class AggregationData { } } - /** The count value of aggregated {@code MeasureValue}s. */ + /** + * The count value of aggregated {@code MeasureValue}s. + * + * @since 0.8 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -153,6 +175,7 @@ public abstract class AggregationData { * * @param count the aggregated count. * @return a {@code CountData}. + * @since 0.8 */ public static CountData create(long count) { return new AutoValue_AggregationData_CountData(count); @@ -162,6 +185,7 @@ public abstract class AggregationData { * Returns the aggregated count. * * @return the aggregated count. + * @since 0.8 */ public abstract long getCount(); @@ -178,7 +202,11 @@ public abstract class AggregationData { } } - /** The mean value of aggregated {@code MeasureValue}s. */ + /** + * The mean value of aggregated {@code MeasureValue}s. + * + * @since 0.8 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -194,6 +222,7 @@ public abstract class AggregationData { * @param mean the aggregated mean. * @param count the aggregated count. * @return a {@code MeanData}. + * @since 0.8 */ public static MeanData create(double mean, long count) { return new AutoValue_AggregationData_MeanData(mean, count); @@ -203,6 +232,7 @@ public abstract class AggregationData { * Returns the aggregated mean. * * @return the aggregated mean. + * @since 0.8 */ public abstract double getMean(); @@ -210,6 +240,7 @@ public abstract class AggregationData { * Returns the aggregated count. * * @return the aggregated count. + * @since 0.8 */ public abstract long getCount(); @@ -229,6 +260,8 @@ public abstract class AggregationData { /** * The distribution stats of aggregated {@code MeasureValue}s. Distribution stats include mean, * count, histogram, min, max and sum of squared deviations. + * + * @since 0.8 */ @Immutable @AutoValue @@ -249,6 +282,7 @@ public abstract class AggregationData { * @param sumOfSquaredDeviations sum of squared deviations. * @param bucketCounts histogram bucket counts. * @return a {@code DistributionData}. + * @since 0.8 */ public static DistributionData create( double mean, @@ -275,6 +309,7 @@ public abstract class AggregationData { * Returns the aggregated mean. * * @return the aggregated mean. + * @since 0.8 */ public abstract double getMean(); @@ -282,6 +317,7 @@ public abstract class AggregationData { * Returns the aggregated count. * * @return the aggregated count. + * @since 0.8 */ public abstract long getCount(); @@ -289,6 +325,7 @@ public abstract class AggregationData { * Returns the minimum of the population values. * * @return the minimum of the population values. + * @since 0.8 */ public abstract double getMin(); @@ -296,6 +333,7 @@ public abstract class AggregationData { * Returns the maximum of the population values. * * @return the maximum of the population values. + * @since 0.8 */ public abstract double getMax(); @@ -303,6 +341,7 @@ public abstract class AggregationData { * Returns the aggregated sum of squared deviations. * * @return the aggregated sum of squared deviations. + * @since 0.8 */ public abstract double getSumOfSquaredDeviations(); @@ -311,6 +350,7 @@ public abstract class AggregationData { * will throw an {@code UnsupportedOperationException}. * * @return the aggregated bucket counts. + * @since 0.8 */ public abstract List getBucketCounts(); diff --git a/api/src/main/java/io/opencensus/stats/BucketBoundaries.java b/api/src/main/java/io/opencensus/stats/BucketBoundaries.java index 664c821f..01ec6db7 100644 --- a/api/src/main/java/io/opencensus/stats/BucketBoundaries.java +++ b/api/src/main/java/io/opencensus/stats/BucketBoundaries.java @@ -25,7 +25,11 @@ import java.util.Collections; import java.util.List; import javax.annotation.concurrent.Immutable; -/** The bucket boundaries for a histogram. */ +/** + * The bucket boundaries for a histogram. + * + * @since 0.8 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -38,6 +42,7 @@ public abstract class BucketBoundaries { * @return a new {@code BucketBoundaries} with the specified boundaries. * @throws NullPointerException if {@code bucketBoundaries} is null. * @throws IllegalArgumentException if {@code bucketBoundaries} is not sorted. + * @since 0.8 */ public static final BucketBoundaries create(List bucketBoundaries) { checkNotNull(bucketBoundaries, "bucketBoundaries list should not be null."); @@ -58,6 +63,7 @@ public abstract class BucketBoundaries { * Returns a list of histogram bucket boundaries. * * @return a list of histogram bucket boundaries. + * @since 0.8 */ public abstract List getBoundaries(); } diff --git a/api/src/main/java/io/opencensus/stats/Measure.java b/api/src/main/java/io/opencensus/stats/Measure.java index b7b6c187..3cbbedef 100644 --- a/api/src/main/java/io/opencensus/stats/Measure.java +++ b/api/src/main/java/io/opencensus/stats/Measure.java @@ -25,13 +25,21 @@ import io.opencensus.internal.CheckerFrameworkUtils; import io.opencensus.internal.StringUtil; import javax.annotation.concurrent.Immutable; -/** The definition of the {@link Measurement} that is taken by OpenCensus library. */ +/** + * The definition of the {@link Measurement} that is taken by OpenCensus library. + * + * @since 0.8 + */ @Immutable public abstract class Measure { @VisibleForTesting static final int NAME_MAX_LENGTH = 255; - /** Applies the given match function to the underlying data type. */ + /** + * Applies the given match function to the underlying data type. + * + * @since 0.8 + */ public abstract T match( Function p0, Function p1, @@ -42,10 +50,16 @@ public abstract class Measure { * 255 characters. * *

    Suggested format for name: {@code /}. + * + * @since 0.8 */ public abstract String getName(); - /** Detailed description of the measure, used in documentation. */ + /** + * Detailed description of the measure, used in documentation. + * + * @since 0.8 + */ public abstract String getDescription(); /** @@ -61,6 +75,8 @@ public abstract class Measure { * *

    For example, string “MBy{transmitted}/ms” stands for megabytes per milliseconds, and the * annotation transmitted inside {} is just a comment of the unit. + * + * @since 0.8 */ // TODO(songya): determine whether we want to check the grammar on string unit. public abstract String getUnit(); @@ -68,7 +84,11 @@ public abstract class Measure { // Prevents this class from being subclassed anywhere else. private Measure() {} - /** {@link Measure} with {@code Double} typed values. */ + /** + * {@link Measure} with {@code Double} typed values. + * + * @since 0.8 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -85,6 +105,7 @@ public abstract class Measure { * @param description description of {@code Measure}. * @param unit unit of {@code Measure}. * @return a {@code MeasureDouble}. + * @since 0.8 */ public static MeasureDouble create(String name, String description, String unit) { checkArgument( @@ -114,7 +135,11 @@ public abstract class Measure { public abstract String getUnit(); } - /** {@link Measure} with {@code Long} typed values. */ + /** + * {@link Measure} with {@code Long} typed values. + * + * @since 0.8 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -131,6 +156,7 @@ public abstract class Measure { * @param description description of {@code Measure}. * @param unit unit of {@code Measure}. * @return a {@code MeasureLong}. + * @since 0.8 */ public static MeasureLong create(String name, String description, String unit) { checkArgument( diff --git a/api/src/main/java/io/opencensus/stats/MeasureMap.java b/api/src/main/java/io/opencensus/stats/MeasureMap.java index 03e55092..a7430537 100644 --- a/api/src/main/java/io/opencensus/stats/MeasureMap.java +++ b/api/src/main/java/io/opencensus/stats/MeasureMap.java @@ -21,7 +21,11 @@ import io.opencensus.stats.Measure.MeasureLong; import io.opencensus.tags.TagContext; import javax.annotation.concurrent.NotThreadSafe; -/** A map from {@link Measure}s to measured values to be recorded at the same time. */ +/** + * A map from {@link Measure}s to measured values to be recorded at the same time. + * + * @since 0.8 + */ @NotThreadSafe public abstract class MeasureMap { @@ -32,6 +36,7 @@ public abstract class MeasureMap { * @param measure the {@link MeasureDouble} * @param value the value to be associated with {@code measure} * @return this + * @since 0.8 */ public abstract MeasureMap put(MeasureDouble measure, double value); @@ -42,6 +47,7 @@ public abstract class MeasureMap { * @param measure the {@link MeasureLong} * @param value the value to be associated with {@code measure} * @return this + * @since 0.8 */ public abstract MeasureMap put(MeasureLong measure, long value); @@ -49,6 +55,8 @@ public abstract class MeasureMap { * Records all of the measures at the same time, with the current {@link TagContext}. * *

    This method records all of the stats in the {@code MeasureMap} every time it is called. + * + * @since 0.8 */ public abstract void record(); @@ -58,6 +66,7 @@ public abstract class MeasureMap { *

    This method records all of the stats in the {@code MeasureMap} every time it is called. * * @param tags the tags associated with the measurements. + * @since 0.8 */ public abstract void record(TagContext tags); } diff --git a/api/src/main/java/io/opencensus/stats/Measurement.java b/api/src/main/java/io/opencensus/stats/Measurement.java index 2d9dcf02..2f2421cd 100644 --- a/api/src/main/java/io/opencensus/stats/Measurement.java +++ b/api/src/main/java/io/opencensus/stats/Measurement.java @@ -23,23 +23,39 @@ import io.opencensus.stats.Measure.MeasureDouble; import io.opencensus.stats.Measure.MeasureLong; import javax.annotation.concurrent.Immutable; -/** Immutable representation of a Measurement. */ +/** + * Immutable representation of a Measurement. + * + * @since 0.8 + */ @Immutable public abstract class Measurement { - /** Applies the given match function to the underlying data type. */ + /** + * Applies the given match function to the underlying data type. + * + * @since 0.8 + */ public abstract T match( Function p0, Function p1, Function defaultFunction); - /** Extracts the measured {@link Measure}. */ + /** + * Extracts the measured {@link Measure}. + * + * @since 0.8 + */ public abstract Measure getMeasure(); // Prevents this class from being subclassed anywhere else. private Measurement() {} - /** {@code Double} typed {@link Measurement}. */ + /** + * {@code Double} typed {@link Measurement}. + * + * @since 0.8 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -48,7 +64,11 @@ public abstract class Measurement { public abstract static class MeasurementDouble extends Measurement { MeasurementDouble() {} - /** Constructs a new {@link MeasurementDouble}. */ + /** + * Constructs a new {@link MeasurementDouble}. + * + * @since 0.8 + */ public static MeasurementDouble create(MeasureDouble measure, double value) { return new AutoValue_Measurement_MeasurementDouble(measure, value); } @@ -56,6 +76,12 @@ public abstract class Measurement { @Override public abstract MeasureDouble getMeasure(); + /** + * Returns the value for the measure. + * + * @return the value for the measure. + * @since 0.8 + */ public abstract double getValue(); @Override @@ -68,7 +94,11 @@ public abstract class Measurement { } } - /** {@code Long} typed {@link Measurement}. */ + /** + * {@code Long} typed {@link Measurement}. + * + * @since 0.8 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -77,7 +107,11 @@ public abstract class Measurement { public abstract static class MeasurementLong extends Measurement { MeasurementLong() {} - /** Constructs a new {@link MeasurementLong}. */ + /** + * Constructs a new {@link MeasurementLong}. + * + * @since 0.8 + */ public static MeasurementLong create(MeasureLong measure, long value) { return new AutoValue_Measurement_MeasurementLong(measure, value); } @@ -85,6 +119,12 @@ public abstract class Measurement { @Override public abstract MeasureLong getMeasure(); + /** + * Returns the value for the measure. + * + * @return the value for the measure. + * @since 0.8 + */ public abstract long getValue(); @Override diff --git a/api/src/main/java/io/opencensus/stats/Stats.java b/api/src/main/java/io/opencensus/stats/Stats.java index 185b9e33..4b7852ce 100644 --- a/api/src/main/java/io/opencensus/stats/Stats.java +++ b/api/src/main/java/io/opencensus/stats/Stats.java @@ -22,19 +22,31 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; -/** Class for accessing the default {@link StatsComponent}. */ +/** + * Class for accessing the default {@link StatsComponent}. + * + * @since 0.8 + */ public final class Stats { private static final Logger logger = Logger.getLogger(Stats.class.getName()); private static final StatsComponent statsComponent = loadStatsComponent(StatsComponent.class.getClassLoader()); - /** Returns the default {@link StatsRecorder}. */ + /** + * Returns the default {@link StatsRecorder}. + * + * @since 0.8 + */ public static StatsRecorder getStatsRecorder() { return statsComponent.getStatsRecorder(); } - /** Returns the default {@link ViewManager}. */ + /** + * Returns the default {@link ViewManager}. + * + * @since 0.8 + */ public static ViewManager getViewManager() { return statsComponent.getViewManager(); } @@ -49,6 +61,7 @@ public final class Stats { * #setState(StatsCollectionState)} will throw an {@code IllegalStateException}. * * @return the current {@code StatsCollectionState}. + * @since 0.8 */ public static StatsCollectionState getState() { return statsComponent.getState(); @@ -68,6 +81,7 @@ public final class Stats { * #getState()}, use a stale value, and behave incorrectly. It is only safe to call early in * initialization. This method throws {@link IllegalStateException} after {@code getState()} * has been called, in order to limit changes to the result of {@code getState()}. + * @since 0.8 */ @Deprecated public static void setState(StatsCollectionState state) { diff --git a/api/src/main/java/io/opencensus/stats/StatsCollectionState.java b/api/src/main/java/io/opencensus/stats/StatsCollectionState.java index 7e5641b1..6b2f2409 100644 --- a/api/src/main/java/io/opencensus/stats/StatsCollectionState.java +++ b/api/src/main/java/io/opencensus/stats/StatsCollectionState.java @@ -16,13 +16,19 @@ package io.opencensus.stats; -/** State of the {@link StatsComponent}. */ +/** + * State of the {@link StatsComponent}. + * + * @since 0.8 + */ public enum StatsCollectionState { /** * State that fully enables stats collection. * *

    The {@link StatsComponent} collects stats for registered views. + * + * @since 0.8 */ ENABLED, @@ -31,6 +37,8 @@ public enum StatsCollectionState { * *

    The {@link StatsComponent} does not need to collect stats for registered views and may * return empty {@link ViewData}s from {@link ViewManager#getView(View.Name)}. + * + * @since 0.8 */ DISABLED } diff --git a/api/src/main/java/io/opencensus/stats/StatsComponent.java b/api/src/main/java/io/opencensus/stats/StatsComponent.java index 6d95d4e3..9764fce5 100644 --- a/api/src/main/java/io/opencensus/stats/StatsComponent.java +++ b/api/src/main/java/io/opencensus/stats/StatsComponent.java @@ -20,13 +20,23 @@ package io.opencensus.stats; * Class that holds the implementations for {@link ViewManager} and {@link StatsRecorder}. * *

    All objects returned by methods on {@code StatsComponent} are cacheable. + * + * @since 0.8 */ public abstract class StatsComponent { - /** Returns the default {@link ViewManager}. */ + /** + * Returns the default {@link ViewManager}. + * + * @since 0.8 + */ public abstract ViewManager getViewManager(); - /** Returns the default {@link StatsRecorder}. */ + /** + * Returns the default {@link StatsRecorder}. + * + * @since 0.8 + */ public abstract StatsRecorder getStatsRecorder(); /** @@ -39,6 +49,7 @@ public abstract class StatsComponent { * #setState(StatsCollectionState)} will throw an {@code IllegalStateException}. * * @return the current {@code StatsCollectionState}. + * @since 0.8 */ public abstract StatsCollectionState getState(); @@ -56,6 +67,7 @@ public abstract class StatsComponent { * #getState()}, use a stale value, and behave incorrectly. It is only safe to call early in * initialization. This method throws {@link IllegalStateException} after {@code getState()} * has been called, in order to limit changes to the result of {@code getState()}. + * @since 0.8 */ @Deprecated public abstract void setState(StatsCollectionState state); diff --git a/api/src/main/java/io/opencensus/stats/StatsRecorder.java b/api/src/main/java/io/opencensus/stats/StatsRecorder.java index 493d7ac1..87b8c8b0 100644 --- a/api/src/main/java/io/opencensus/stats/StatsRecorder.java +++ b/api/src/main/java/io/opencensus/stats/StatsRecorder.java @@ -16,7 +16,11 @@ package io.opencensus.stats; -/** Provides methods to record stats against tags. */ +/** + * Provides methods to record stats against tags. + * + * @since 0.8 + */ public abstract class StatsRecorder { // TODO(sebright): Should we provide convenience methods for only recording one measure? @@ -24,6 +28,7 @@ public abstract class StatsRecorder { * Returns an object for recording multiple measurements. * * @return an object for recording multiple measurements. + * @since 0.8 */ public abstract MeasureMap newMeasureMap(); } diff --git a/api/src/main/java/io/opencensus/stats/View.java b/api/src/main/java/io/opencensus/stats/View.java index 0ab29e5e..78eff4ef 100644 --- a/api/src/main/java/io/opencensus/stats/View.java +++ b/api/src/main/java/io/opencensus/stats/View.java @@ -34,6 +34,8 @@ import javax.annotation.concurrent.Immutable; /** * A View specifies an aggregation and a set of tag keys. The aggregation will be broken down by the * unique set of matching tag values for each measure. + * + * @since 0.8 */ @Immutable @AutoValue @@ -46,16 +48,32 @@ public abstract class View { View() {} - /** Name of view. Must be unique. */ + /** + * Name of view. Must be unique. + * + * @since 0.8 + */ public abstract Name getName(); - /** More detailed description, for documentation purposes. */ + /** + * More detailed description, for documentation purposes. + * + * @since 0.8 + */ public abstract String getDescription(); - /** Measure type of this view. */ + /** + * Measure type of this view. + * + * @since 0.8 + */ public abstract Measure getMeasure(); - /** The {@link Aggregation} associated with this {@link View}. */ + /** + * The {@link Aggregation} associated with this {@link View}. + * + * @since 0.8 + */ public abstract Aggregation getAggregation(); /** @@ -63,6 +81,8 @@ public abstract class View { * *

    {@link Measure} will be recorded in a "greedy" way. That is, every view aggregates every * measure. This is similar to doing a GROUPBY on view’s columns. Columns must be unique. + * + * @since 0.8 */ public abstract List getColumns(); @@ -70,6 +90,7 @@ public abstract class View { * Returns the time {@link AggregationWindow} for this {@code View}. * * @return the time {@link AggregationWindow}. + * @since 0.8 */ public abstract AggregationWindow getWindow(); @@ -84,6 +105,7 @@ public abstract class View { * duplicates. * @param window the {@link AggregationWindow} of view. * @return a new {@link View}. + * @since 0.8 */ public static View create( Name name, @@ -103,7 +125,11 @@ public abstract class View { window); } - /** The name of a {@code View}. */ + /** + * The name of a {@code View}. + * + * @since 0.8 + */ // This type should be used as the key when associating data with Views. @Immutable @AutoValue @@ -118,6 +144,7 @@ public abstract class View { * Returns the name as a {@code String}. * * @return the name as a {@code String}. + * @since 0.8 */ public abstract String asString(); @@ -129,6 +156,7 @@ public abstract class View { * * @param name the name {@code String}. * @return a {@code View.Name} with the given name {@code String}. + * @since 0.8 */ public static Name create(String name) { checkArgument( @@ -138,19 +166,31 @@ public abstract class View { } } - /** The time window for a {@code View}. */ + /** + * The time window for a {@code View}. + * + * @since 0.8 + */ @Immutable public abstract static class AggregationWindow { private AggregationWindow() {} - /** Applies the given match function to the underlying data type. */ + /** + * Applies the given match function to the underlying data type. + * + * @since 0.8 + */ public abstract T match( Function p0, Function p1, Function defaultFunction); - /** Cumulative (infinite interval) time {@code AggregationWindow}. */ + /** + * Cumulative (infinite interval) time {@code AggregationWindow}. + * + * @since 0.8 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -169,6 +209,7 @@ public abstract class View { * {@code Duration}. * * @return a cumulative {@code AggregationWindow}. + * @since 0.8 */ public static Cumulative create() { return CUMULATIVE; @@ -184,7 +225,11 @@ public abstract class View { } } - /** Interval (finite interval) time {@code AggregationWindow.} */ + /** + * Interval (finite interval) time {@code AggregationWindow}. + * + * @since 0.8 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -200,6 +245,7 @@ public abstract class View { * Returns the {@code Duration} associated with this {@code Interval}. * * @return a {@code Duration}. + * @since 0.8 */ public abstract Duration getDuration(); @@ -211,6 +257,7 @@ public abstract class View { * cannot have smaller {@code Duration} such as microseconds or nanoseconds. * * @return an interval {@code AggregationWindow}. + * @since 0.8 */ public static Interval create(Duration duration) { checkArgument(duration.compareTo(ZERO) > 0, "Duration must be positive"); diff --git a/api/src/main/java/io/opencensus/stats/ViewData.java b/api/src/main/java/io/opencensus/stats/ViewData.java index f383fff5..2e5e4a42 100644 --- a/api/src/main/java/io/opencensus/stats/ViewData.java +++ b/api/src/main/java/io/opencensus/stats/ViewData.java @@ -48,7 +48,11 @@ import javax.annotation.concurrent.Immutable; import org.checkerframework.checker.nullness.qual.Nullable; */ -/** The aggregated data for a particular {@link View}. */ +/** + * The aggregated data for a particular {@link View}. + * + * @since 0.8 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -59,12 +63,18 @@ public abstract class ViewData { // Prevents this class from being subclassed anywhere else. ViewData() {} - /** The {@link View} associated with this {@link ViewData}. */ + /** + * The {@link View} associated with this {@link ViewData}. + * + * @since 0.8 + */ public abstract View getView(); /** * The {@link AggregationData} grouped by combination of tag values, associated with this {@link * ViewData}. + * + * @since 0.8 */ public abstract Map, AggregationData> getAggregationMap(); @@ -72,6 +82,7 @@ public abstract class ViewData { * Returns the {@link AggregationWindowData} associated with this {@link ViewData}. * * @return the {@code AggregationWindowData}. + * @since 0.8 */ public abstract AggregationWindowData getWindowData(); @@ -85,6 +96,7 @@ public abstract class ViewData { * @throws IllegalArgumentException if the types of {@code Aggregation} and {@code * AggregationData} don't match, or the types of {@code Window} and {@code WindowData} don't * match. + * @since 0.8 */ public static ViewData create( View view, @@ -201,19 +213,31 @@ public abstract class ViewData { + aggregationData; } - /** The {@code AggregationWindowData} for a {@link ViewData}. */ + /** + * The {@code AggregationWindowData} for a {@link ViewData}. + * + * @since 0.8 + */ @Immutable public abstract static class AggregationWindowData { private AggregationWindowData() {} - /** Applies the given match function to the underlying data type. */ + /** + * Applies the given match function to the underlying data type. + * + * @since 0.8 + */ public abstract T match( Function p0, Function p1, Function defaultFunction); - /** Cumulative {@code AggregationWindowData.} */ + /** + * Cumulative {@code AggregationWindowData}. + * + * @since 0.8 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -227,6 +251,7 @@ public abstract class ViewData { * Returns the start {@code Timestamp} for a {@link CumulativeData}. * * @return the start {@code Timestamp}. + * @since 0.8 */ public abstract Timestamp getStart(); @@ -234,6 +259,7 @@ public abstract class ViewData { * Returns the end {@code Timestamp} for a {@link CumulativeData}. * * @return the end {@code Timestamp}. + * @since 0.8 */ public abstract Timestamp getEnd(); @@ -246,7 +272,11 @@ public abstract class ViewData { .apply(this); } - /** Constructs a new {@link CumulativeData}. */ + /** + * Constructs a new {@link CumulativeData}. + * + * @since 0.8 + */ public static CumulativeData create(Timestamp start, Timestamp end) { if (start.compareTo(end) > 0) { throw new IllegalArgumentException("Start time is later than end time."); @@ -255,7 +285,11 @@ public abstract class ViewData { } } - /** Interval {@code AggregationWindowData.} */ + /** + * Interval {@code AggregationWindowData}. + * + * @since 0.8 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -269,6 +303,7 @@ public abstract class ViewData { * Returns the end {@code Timestamp} for an {@link IntervalData}. * * @return the end {@code Timestamp}. + * @since 0.8 */ public abstract Timestamp getEnd(); @@ -281,7 +316,11 @@ public abstract class ViewData { .apply(this); } - /** Constructs a new {@link IntervalData}. */ + /** + * Constructs a new {@link IntervalData}. + * + * @since 0.8 + */ public static IntervalData create(Timestamp end) { return new AutoValue_ViewData_AggregationWindowData_IntervalData(end); } diff --git a/api/src/main/java/io/opencensus/stats/ViewManager.java b/api/src/main/java/io/opencensus/stats/ViewManager.java index a6e18b89..a00165cc 100644 --- a/api/src/main/java/io/opencensus/stats/ViewManager.java +++ b/api/src/main/java/io/opencensus/stats/ViewManager.java @@ -22,6 +22,8 @@ import javax.annotation.Nullable; /** * Provides facilities to register {@link View}s for collecting stats and retrieving stats data as a * {@link ViewData}. + * + * @since 0.8 */ public abstract class ViewManager { /** @@ -29,6 +31,7 @@ public abstract class ViewManager { * #getView(View.Name)}. * * @param view the {@code View} to be registered. + * @since 0.8 */ public abstract void registerView(View view); @@ -40,6 +43,7 @@ public abstract class ViewManager { * @param view the name of {@code View} for the current stats. * @return {@code ViewData} for the {@code View}, or {@code null} if the {@code View} is not * registered. + * @since 0.8 */ @Nullable public abstract ViewData getView(View.Name view); -- cgit v1.2.3 From 86a09513f3a3f981c75948a3da346b13888a3184 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Thu, 1 Feb 2018 12:28:26 -0800 Subject: Checker Framework: 2.3.0 -> 2.3.2 The new version fixes https://github.com/typetools/checker-framework/issues/1712, so this commit also removes the workaround. --- .../opencensus/internal/CheckerFrameworkUtils.java | 40 ---------------------- .../main/java/io/opencensus/stats/Aggregation.java | 10 +++--- .../java/io/opencensus/stats/AggregationData.java | 16 +++------ api/src/main/java/io/opencensus/stats/Measure.java | 7 ++-- .../main/java/io/opencensus/stats/Measurement.java | 7 ++-- api/src/main/java/io/opencensus/stats/View.java | 7 ++-- .../main/java/io/opencensus/stats/ViewData.java | 7 ++-- .../java/io/opencensus/trace/AttributeValue.java | 10 ++---- 8 files changed, 20 insertions(+), 84 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/internal/CheckerFrameworkUtils.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/CheckerFrameworkUtils.java b/api/src/main/java/io/opencensus/internal/CheckerFrameworkUtils.java deleted file mode 100644 index 599c2fd3..00000000 --- a/api/src/main/java/io/opencensus/internal/CheckerFrameworkUtils.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.internal; - -import io.opencensus.common.Function; - -/*>>> -import org.checkerframework.checker.nullness.qual.KeyForBottom; -*/ - -/** Utility methods for working around Checker Framework issues. */ -public final class CheckerFrameworkUtils { - private CheckerFrameworkUtils() {} - - /** - * Works around https://github.com/typetools/checker-framework/issues/1712 by removing {@code ? - * super} from a {@code Function}'s argument type. - */ - // TODO(sebright): Remove this method once the issue is fixed. - public static Function removeSuperFromFunctionParameterType( - Function function) { - @SuppressWarnings("unchecked") - Function castFunction = (Function) function; - return castFunction; - } -} diff --git a/api/src/main/java/io/opencensus/stats/Aggregation.java b/api/src/main/java/io/opencensus/stats/Aggregation.java index 1983b908..f097f5ad 100644 --- a/api/src/main/java/io/opencensus/stats/Aggregation.java +++ b/api/src/main/java/io/opencensus/stats/Aggregation.java @@ -20,7 +20,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; import io.opencensus.common.Function; -import io.opencensus.internal.CheckerFrameworkUtils; import javax.annotation.concurrent.Immutable; /** @@ -91,7 +90,7 @@ public abstract class Aggregation { Function p2, Function p3, Function defaultFunction) { - return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p0).apply(this); + return p0.apply(this); } } @@ -128,7 +127,7 @@ public abstract class Aggregation { Function p2, Function p3, Function defaultFunction) { - return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p1).apply(this); + return p1.apply(this); } } @@ -165,7 +164,7 @@ public abstract class Aggregation { Function p2, Function p3, Function defaultFunction) { - return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p2).apply(this); + return p2.apply(this); } } @@ -210,8 +209,7 @@ public abstract class Aggregation { Function p2, Function p3, Function defaultFunction) { - return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p3) - .apply(this); + return p3.apply(this); } } } diff --git a/api/src/main/java/io/opencensus/stats/AggregationData.java b/api/src/main/java/io/opencensus/stats/AggregationData.java index be0df5e0..0244f4e1 100644 --- a/api/src/main/java/io/opencensus/stats/AggregationData.java +++ b/api/src/main/java/io/opencensus/stats/AggregationData.java @@ -22,7 +22,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; import com.google.common.collect.Lists; import io.opencensus.common.Function; -import io.opencensus.internal.CheckerFrameworkUtils; import java.util.Collections; import java.util.List; import javax.annotation.concurrent.Immutable; @@ -105,8 +104,7 @@ public abstract class AggregationData { Function p3, Function p4, Function defaultFunction) { - return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p0) - .apply(this); + return p0.apply(this); } } @@ -151,8 +149,7 @@ public abstract class AggregationData { Function p3, Function p4, Function defaultFunction) { - return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p1) - .apply(this); + return p1.apply(this); } } @@ -197,8 +194,7 @@ public abstract class AggregationData { Function p3, Function p4, Function defaultFunction) { - return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p2) - .apply(this); + return p2.apply(this); } } @@ -252,8 +248,7 @@ public abstract class AggregationData { Function p3, Function p4, Function defaultFunction) { - return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p3) - .apply(this); + return p3.apply(this); } } @@ -362,8 +357,7 @@ public abstract class AggregationData { Function p3, Function p4, Function defaultFunction) { - return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p4) - .apply(this); + return p4.apply(this); } } } diff --git a/api/src/main/java/io/opencensus/stats/Measure.java b/api/src/main/java/io/opencensus/stats/Measure.java index 3cbbedef..9dede342 100644 --- a/api/src/main/java/io/opencensus/stats/Measure.java +++ b/api/src/main/java/io/opencensus/stats/Measure.java @@ -21,7 +21,6 @@ import static com.google.common.base.Preconditions.checkArgument; import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; import io.opencensus.common.Function; -import io.opencensus.internal.CheckerFrameworkUtils; import io.opencensus.internal.StringUtil; import javax.annotation.concurrent.Immutable; @@ -121,8 +120,7 @@ public abstract class Measure { Function p0, Function p1, Function defaultFunction) { - return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p0) - .apply(this); + return p0.apply(this); } @Override @@ -172,8 +170,7 @@ public abstract class Measure { Function p0, Function p1, Function defaultFunction) { - return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p1) - .apply(this); + return p1.apply(this); } @Override diff --git a/api/src/main/java/io/opencensus/stats/Measurement.java b/api/src/main/java/io/opencensus/stats/Measurement.java index 2f2421cd..c6c639ea 100644 --- a/api/src/main/java/io/opencensus/stats/Measurement.java +++ b/api/src/main/java/io/opencensus/stats/Measurement.java @@ -18,7 +18,6 @@ package io.opencensus.stats; import com.google.auto.value.AutoValue; import io.opencensus.common.Function; -import io.opencensus.internal.CheckerFrameworkUtils; import io.opencensus.stats.Measure.MeasureDouble; import io.opencensus.stats.Measure.MeasureLong; import javax.annotation.concurrent.Immutable; @@ -89,8 +88,7 @@ public abstract class Measurement { Function p0, Function p1, Function defaultFunction) { - return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p0) - .apply(this); + return p0.apply(this); } } @@ -132,8 +130,7 @@ public abstract class Measurement { Function p0, Function p1, Function defaultFunction) { - return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p1) - .apply(this); + return p1.apply(this); } } } diff --git a/api/src/main/java/io/opencensus/stats/View.java b/api/src/main/java/io/opencensus/stats/View.java index 78eff4ef..a26c777b 100644 --- a/api/src/main/java/io/opencensus/stats/View.java +++ b/api/src/main/java/io/opencensus/stats/View.java @@ -22,7 +22,6 @@ import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; import io.opencensus.common.Duration; import io.opencensus.common.Function; -import io.opencensus.internal.CheckerFrameworkUtils; import io.opencensus.internal.StringUtil; import io.opencensus.tags.TagKey; import java.util.ArrayList; @@ -220,8 +219,7 @@ public abstract class View { Function p0, Function p1, Function defaultFunction) { - return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p0) - .apply(this); + return p0.apply(this); } } @@ -269,8 +267,7 @@ public abstract class View { Function p0, Function p1, Function defaultFunction) { - return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p1) - .apply(this); + return p1.apply(this); } } } diff --git a/api/src/main/java/io/opencensus/stats/ViewData.java b/api/src/main/java/io/opencensus/stats/ViewData.java index 2e5e4a42..be06d28f 100644 --- a/api/src/main/java/io/opencensus/stats/ViewData.java +++ b/api/src/main/java/io/opencensus/stats/ViewData.java @@ -23,7 +23,6 @@ import com.google.common.collect.Maps; import io.opencensus.common.Function; import io.opencensus.common.Functions; import io.opencensus.common.Timestamp; -import io.opencensus.internal.CheckerFrameworkUtils; import io.opencensus.stats.Aggregation.Count; import io.opencensus.stats.Aggregation.Distribution; import io.opencensus.stats.Aggregation.Mean; @@ -268,8 +267,7 @@ public abstract class ViewData { Function p0, Function p1, Function defaultFunction) { - return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p0) - .apply(this); + return p0.apply(this); } /** @@ -312,8 +310,7 @@ public abstract class ViewData { Function p0, Function p1, Function defaultFunction) { - return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(p1) - .apply(this); + return p1.apply(this); } /** diff --git a/api/src/main/java/io/opencensus/trace/AttributeValue.java b/api/src/main/java/io/opencensus/trace/AttributeValue.java index 619d94ad..6c938bd6 100644 --- a/api/src/main/java/io/opencensus/trace/AttributeValue.java +++ b/api/src/main/java/io/opencensus/trace/AttributeValue.java @@ -20,7 +20,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; import io.opencensus.common.Function; -import io.opencensus.internal.CheckerFrameworkUtils; import javax.annotation.concurrent.Immutable; /** @@ -101,8 +100,7 @@ public abstract class AttributeValue { Function booleanFunction, Function longFunction, Function defaultFunction) { - return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(stringFunction) - .apply(getStringValue()); + return stringFunction.apply(getStringValue()); } abstract String getStringValue(); @@ -128,8 +126,7 @@ public abstract class AttributeValue { Function booleanFunction, Function longFunction, Function defaultFunction) { - return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(booleanFunction) - .apply(getBooleanValue()); + return booleanFunction.apply(getBooleanValue()); } abstract Boolean getBooleanValue(); @@ -155,8 +152,7 @@ public abstract class AttributeValue { Function booleanFunction, Function longFunction, Function defaultFunction) { - return CheckerFrameworkUtils.removeSuperFromFunctionParameterType(longFunction) - .apply(getLongValue()); + return longFunction.apply(getLongValue()); } abstract Long getLongValue(); -- cgit v1.2.3 From d853e3a2da22cbc8c5a6d5d18cee82a8bc344a4d Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Mon, 5 Feb 2018 17:32:33 -0800 Subject: Add '@since' Javadoc tag to all common APIs (issue #864). This commit also adds missing Javadocs. --- api/src/main/java/io/opencensus/common/Clock.java | 8 +++++++- api/src/main/java/io/opencensus/common/Duration.java | 6 ++++++ api/src/main/java/io/opencensus/common/ExperimentalApi.java | 8 +++++++- api/src/main/java/io/opencensus/common/Function.java | 10 ++++++++++ api/src/main/java/io/opencensus/common/Functions.java | 10 +++++++++- api/src/main/java/io/opencensus/common/Internal.java | 2 ++ .../main/java/io/opencensus/common/NonThrowingCloseable.java | 1 + .../io/opencensus/common/OpenCensusLibraryInformation.java | 12 ++++++++++-- api/src/main/java/io/opencensus/common/Scope.java | 2 ++ api/src/main/java/io/opencensus/common/Timestamp.java | 9 +++++++++ 10 files changed, 63 insertions(+), 5 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Clock.java b/api/src/main/java/io/opencensus/common/Clock.java index f359f49a..cd311935 100644 --- a/api/src/main/java/io/opencensus/common/Clock.java +++ b/api/src/main/java/io/opencensus/common/Clock.java @@ -16,13 +16,18 @@ package io.opencensus.common; -/** Interface for getting the current time. */ +/** + * Interface for getting the current time. + * + * @since 0.5 + */ public abstract class Clock { /** * Obtains the current instant from this clock. * * @return the current instant. + * @since 0.5 */ public abstract Timestamp now(); @@ -32,6 +37,7 @@ public abstract class Clock { * * @return a time measurement with nanosecond precision that can only be used to calculate elapsed * time. + * @since 0.5 */ public abstract long nowNanos(); } diff --git a/api/src/main/java/io/opencensus/common/Duration.java b/api/src/main/java/io/opencensus/common/Duration.java index 178e9cf3..1dd8d502 100644 --- a/api/src/main/java/io/opencensus/common/Duration.java +++ b/api/src/main/java/io/opencensus/common/Duration.java @@ -29,6 +29,8 @@ import javax.annotation.concurrent.Immutable; * Represents a signed, fixed-length span of time represented as a count of seconds and fractions of * seconds at nanosecond resolution. It is independent of any calendar and concepts like "day" or * "month". Range is approximately +-10,000 years. + * + * @since 0.5 */ @Immutable @AutoValue @@ -50,6 +52,7 @@ public abstract class Duration implements Comparable { * +999,999,999 inclusive. * @return new {@code Duration} with specified fields. For invalid inputs, a {@code Duration} of * zero is returned. + * @since 0.5 */ public static Duration create(long seconds, int nanos) { if (seconds < -MAX_SECONDS || seconds > MAX_SECONDS) { @@ -70,6 +73,7 @@ public abstract class Duration implements Comparable { * @param millis the duration in milliseconds. * @return a new {@code Duration} from given milliseconds. For invalid inputs, a {@code Duration} * of zero is returned. + * @since 0.5 */ public static Duration fromMillis(long millis) { long seconds = millis / MILLIS_PER_SECOND; @@ -81,6 +85,7 @@ public abstract class Duration implements Comparable { * Returns the number of seconds in the {@code Duration}. * * @return the number of seconds in the {@code Duration}. + * @since 0.5 */ public abstract long getSeconds(); @@ -88,6 +93,7 @@ public abstract class Duration implements Comparable { * Returns the number of nanoseconds in the {@code Duration}. * * @return the number of nanoseconds in the {@code Duration}. + * @since 0.5 */ public abstract int getNanos(); diff --git a/api/src/main/java/io/opencensus/common/ExperimentalApi.java b/api/src/main/java/io/opencensus/common/ExperimentalApi.java index 9906cbff..7a4da7c7 100644 --- a/api/src/main/java/io/opencensus/common/ExperimentalApi.java +++ b/api/src/main/java/io/opencensus/common/ExperimentalApi.java @@ -34,6 +34,8 @@ import java.lang.annotation.Target; * Adding it to an existing API is considered API-breaking. *

  • Removing this annotation from an API gives it stable status. * + * + * @since 0.8 */ @Internal @Retention(RetentionPolicy.SOURCE) @@ -47,6 +49,10 @@ import java.lang.annotation.Target; }) @Documented public @interface ExperimentalApi { - /** Context information such as links to discussion thread, tracking issue etc. */ + /** + * Context information such as links to discussion thread, tracking issue etc. + * + * @since 0.8 + */ String value() default ""; } diff --git a/api/src/main/java/io/opencensus/common/Function.java b/api/src/main/java/io/opencensus/common/Function.java index f790485c..a9ed5a9e 100644 --- a/api/src/main/java/io/opencensus/common/Function.java +++ b/api/src/main/java/io/opencensus/common/Function.java @@ -22,7 +22,17 @@ package io.opencensus.common; * *

    Note: This class is based on the java.util.Function class added in Java 1.8. We cannot use the * Function from Java 1.8 because this library is Java 1.6 compatible. + * + * @since 0.5 */ public interface Function { + + /** + * Applies the function to the given argument. + * + * @param arg the argument to the function. + * @return the result of the function. + * @since 0.5 + */ B apply(A arg); } diff --git a/api/src/main/java/io/opencensus/common/Functions.java b/api/src/main/java/io/opencensus/common/Functions.java index b952a697..5fce0707 100644 --- a/api/src/main/java/io/opencensus/common/Functions.java +++ b/api/src/main/java/io/opencensus/common/Functions.java @@ -16,7 +16,11 @@ package io.opencensus.common; -/** Commonly used {@link Function} instances. */ +/** + * Commonly used {@link Function} instances. + * + * @since 0.5 + */ public final class Functions { private Functions() {} @@ -48,6 +52,7 @@ public final class Functions { * A {@code Function} that always ignores its argument and returns {@code null}. * * @return a {@code Function} that always ignores its argument and returns {@code null}. + * @since 0.5 */ public static Function returnNull() { // It is safe to cast a producer of Void to anything, because Void is always null. @@ -60,6 +65,7 @@ public final class Functions { * A {@code Function} that always ignores its argument and returns a constant value. * * @return a {@code Function} that always ignores its argument and returns a constant value. + * @since 0.5 */ public static Function returnConstant(final T constant) { return new Function() { @@ -76,6 +82,7 @@ public final class Functions { * * @return a {@code Function} that always ignores its argument and throws an {@link * IllegalArgumentException}. + * @since 0.5 */ public static Function throwIllegalArgumentException() { // It is safe to cast this function to have any return type, since it never returns a result. @@ -89,6 +96,7 @@ public final class Functions { * * @return a {@code Function} that always ignores its argument and throws an {@code * AssertionError}. + * @since 0.6 */ public static Function throwAssertionError() { // It is safe to cast this function to have any return type, since it never returns a result. diff --git a/api/src/main/java/io/opencensus/common/Internal.java b/api/src/main/java/io/opencensus/common/Internal.java index c0952353..d84fba20 100644 --- a/api/src/main/java/io/opencensus/common/Internal.java +++ b/api/src/main/java/io/opencensus/common/Internal.java @@ -25,6 +25,8 @@ import java.lang.annotation.Target; /** * Annotates a program element (class, method, package etc) which is internal to OpenCensus, not * part of the public API, and should not be used by users of the OpenCensus library. + * + * @since 0.5 */ @Internal @Retention(RetentionPolicy.SOURCE) diff --git a/api/src/main/java/io/opencensus/common/NonThrowingCloseable.java b/api/src/main/java/io/opencensus/common/NonThrowingCloseable.java index de47f4dc..30d07ac7 100644 --- a/api/src/main/java/io/opencensus/common/NonThrowingCloseable.java +++ b/api/src/main/java/io/opencensus/common/NonThrowingCloseable.java @@ -33,6 +33,7 @@ import java.io.Closeable; * * * @deprecated {@link Scope} is a better match for operations involving the current context. + * @since 0.5 */ @Deprecated public interface NonThrowingCloseable extends Closeable { diff --git a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java index 38ec8d32..fe908c1e 100644 --- a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java +++ b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java @@ -16,11 +16,19 @@ package io.opencensus.common; -/** Class holder for all common constants (such as the version) for the OpenCensus Java library. */ +/** + * Class holder for all common constants (such as the version) for the OpenCensus Java library. + * + * @since 0.8 + */ @ExperimentalApi public final class OpenCensusLibraryInformation { - /** The current version of the OpenCensus Java library. */ + /** + * The current version of the OpenCensus Java library. + * + * @since 0.8 + */ public static final String VERSION = "0.12.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION private OpenCensusLibraryInformation() {} diff --git a/api/src/main/java/io/opencensus/common/Scope.java b/api/src/main/java/io/opencensus/common/Scope.java index 3893fad4..de954f50 100644 --- a/api/src/main/java/io/opencensus/common/Scope.java +++ b/api/src/main/java/io/opencensus/common/Scope.java @@ -27,6 +27,8 @@ package io.opencensus.common; * ... * } * + * + * @since 0.6 */ @SuppressWarnings("deprecation") public interface Scope extends NonThrowingCloseable { diff --git a/api/src/main/java/io/opencensus/common/Timestamp.java b/api/src/main/java/io/opencensus/common/Timestamp.java index 04fed453..9671f245 100644 --- a/api/src/main/java/io/opencensus/common/Timestamp.java +++ b/api/src/main/java/io/opencensus/common/Timestamp.java @@ -34,6 +34,8 @@ import javax.annotation.concurrent.Immutable; * *

    Use {@code Tracing.getClock().now()} to get the current timestamp since epoch * (1970-01-01T00:00:00Z). + * + * @since 0.5 */ @Immutable @AutoValue @@ -55,6 +57,7 @@ public abstract class Timestamp implements Comparable { * Must be from 0 to 999,999,999 inclusive. * @return new {@code Timestamp} with specified fields. For invalid inputs, a {@code Timestamp} of * zero is returned. + * @since 0.5 */ public static Timestamp create(long seconds, int nanos) { if (seconds < -MAX_SECONDS || seconds > MAX_SECONDS) { @@ -72,6 +75,7 @@ public abstract class Timestamp implements Comparable { * @param epochMilli the timestamp represented in milliseconds since epoch. * @return new {@code Timestamp} with specified fields. For invalid inputs, a {@code Timestamp} of * zero is returned. + * @since 0.5 */ public static Timestamp fromMillis(long epochMilli) { long secs = floorDiv(epochMilli, MILLIS_PER_SECOND); @@ -83,6 +87,7 @@ public abstract class Timestamp implements Comparable { * Returns the number of seconds since the Unix Epoch represented by this timestamp. * * @return the number of seconds since the Unix Epoch. + * @since 0.5 */ public abstract long getSeconds(); @@ -91,6 +96,7 @@ public abstract class Timestamp implements Comparable { * by this timestamp. * * @return the number of nanoseconds after the number of seconds since the Unix Epoch. + * @since 0.5 */ public abstract int getNanos(); @@ -102,6 +108,7 @@ public abstract class Timestamp implements Comparable { * @return the calculated {@code Timestamp}. For invalid inputs, a {@code Timestamp} of zero is * returned. * @throws ArithmeticException if numeric overflow occurs. + * @since 0.5 */ public Timestamp addNanos(long nanosToAdd) { return plus(0, nanosToAdd); @@ -112,6 +119,7 @@ public abstract class Timestamp implements Comparable { * * @param duration the {@code Duration} to add. * @return a {@code Timestamp} with the specified {@code Duration} added. + * @since 0.5 */ public Timestamp addDuration(Duration duration) { return plus(duration.getSeconds(), duration.getNanos()); @@ -123,6 +131,7 @@ public abstract class Timestamp implements Comparable { * @param timestamp the {@code Timestamp} to subtract. * @return the calculated {@code Duration}. For invalid inputs, a {@code Duration} of zero is * returned. + * @since 0.5 */ public Duration subtractTimestamp(Timestamp timestamp) { long durationSeconds = getSeconds() - timestamp.getSeconds(); -- cgit v1.2.3 From 420201505eb0ae4e79e9dba65807ff7c1cf32714 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Mon, 5 Feb 2018 17:33:54 -0800 Subject: Add '@since' Javadoc tag to all tracing APIs (issue #864). This commit also adds missing Javadocs. --- .../main/java/io/opencensus/trace/Annotation.java | 10 +- .../java/io/opencensus/trace/AttributeValue.java | 6 + .../main/java/io/opencensus/trace/BlankSpan.java | 8 +- .../java/io/opencensus/trace/EndSpanOptions.java | 20 ++- api/src/main/java/io/opencensus/trace/Link.java | 26 +++- .../java/io/opencensus/trace/NetworkEvent.java | 38 ++++- api/src/main/java/io/opencensus/trace/Sampler.java | 8 +- api/src/main/java/io/opencensus/trace/Span.java | 21 +++ .../main/java/io/opencensus/trace/SpanBuilder.java | 7 + .../main/java/io/opencensus/trace/SpanContext.java | 13 +- api/src/main/java/io/opencensus/trace/SpanId.java | 22 ++- api/src/main/java/io/opencensus/trace/Status.java | 170 ++++++++++++++++++--- .../java/io/opencensus/trace/TraceComponent.java | 7 + api/src/main/java/io/opencensus/trace/TraceId.java | 22 ++- .../java/io/opencensus/trace/TraceOptions.java | 30 +++- api/src/main/java/io/opencensus/trace/Tracer.java | 7 + api/src/main/java/io/opencensus/trace/Tracing.java | 11 +- .../io/opencensus/trace/config/TraceConfig.java | 5 + .../io/opencensus/trace/config/TraceParams.java | 29 +++- .../opencensus/trace/export/ExportComponent.java | 6 + .../opencensus/trace/export/RunningSpanStore.java | 25 ++- .../opencensus/trace/export/SampledSpanStore.java | 104 +++++++++++-- .../java/io/opencensus/trace/export/SpanData.java | 45 +++++- .../io/opencensus/trace/export/SpanExporter.java | 8 + .../opencensus/trace/propagation/BinaryFormat.java | 6 + .../trace/propagation/PropagationComponent.java | 4 + .../propagation/SpanContextParseException.java | 8 +- .../opencensus/trace/propagation/TextFormat.java | 10 ++ .../io/opencensus/trace/samplers/Samplers.java | 9 +- .../io/opencensus/trace/unsafe/ContextUtils.java | 8 +- 30 files changed, 632 insertions(+), 61 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/Annotation.java b/api/src/main/java/io/opencensus/trace/Annotation.java index 3a893647..233968d3 100644 --- a/api/src/main/java/io/opencensus/trace/Annotation.java +++ b/api/src/main/java/io/opencensus/trace/Annotation.java @@ -24,7 +24,11 @@ import java.util.HashMap; import java.util.Map; import javax.annotation.concurrent.Immutable; -/** A text annotation with a set of attributes. */ +/** + * A text annotation with a set of attributes. + * + * @since 0.5 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -40,6 +44,7 @@ public abstract class Annotation { * @param description the text description of the {@code Annotation}. * @return a new {@code Annotation} with the given description. * @throws NullPointerException if {@code description} is {@code null}. + * @since 0.5 */ public static Annotation fromDescription(String description) { return new AutoValue_Annotation(description, EMPTY_ATTRIBUTES); @@ -52,6 +57,7 @@ public abstract class Annotation { * @param attributes the attributes of the {@code Annotation}. * @return a new {@code Annotation} with the given description and set of attributes. * @throws NullPointerException if {@code description} or {@code attributes} are {@code null}. + * @since 0.5 */ public static Annotation fromDescriptionAndAttributes( String description, Map attributes) { @@ -65,6 +71,7 @@ public abstract class Annotation { * Return the description of the {@code Annotation}. * * @return the description of the {@code Annotation}. + * @since 0.5 */ public abstract String getDescription(); @@ -72,6 +79,7 @@ public abstract class Annotation { * Return the attributes of the {@code Annotation}. * * @return the attributes of the {@code Annotation}. + * @since 0.5 */ public abstract Map getAttributes(); diff --git a/api/src/main/java/io/opencensus/trace/AttributeValue.java b/api/src/main/java/io/opencensus/trace/AttributeValue.java index 6c938bd6..ed59830e 100644 --- a/api/src/main/java/io/opencensus/trace/AttributeValue.java +++ b/api/src/main/java/io/opencensus/trace/AttributeValue.java @@ -25,6 +25,8 @@ import javax.annotation.concurrent.Immutable; /** * A class that represents all the possible values for an attribute. An attribute can have 3 types * of values: {@code String}, {@code Boolean} or {@code Long}. + * + * @since 0.5 */ @Immutable public abstract class AttributeValue { @@ -34,6 +36,7 @@ public abstract class AttributeValue { * @param stringValue The new value. * @return an {@code AttributeValue} with a string value. * @throws NullPointerException if {@code stringValue} is {@code null}. + * @since 0.5 */ public static AttributeValue stringAttributeValue(String stringValue) { return AttributeValueString.create(stringValue); @@ -44,6 +47,7 @@ public abstract class AttributeValue { * * @param booleanValue The new value. * @return an {@code AttributeValue} with a boolean value. + * @since 0.5 */ public static AttributeValue booleanAttributeValue(boolean booleanValue) { return AttributeValueBoolean.create(booleanValue); @@ -54,6 +58,7 @@ public abstract class AttributeValue { * * @param longValue The new value. * @return an {@code AttributeValue} with a long value. + * @since 0.5 */ public static AttributeValue longAttributeValue(long longValue) { return AttributeValueLong.create(longValue); @@ -73,6 +78,7 @@ public abstract class AttributeValue { * added after this {@code match} method was added to the API. See {@link * io.opencensus.common.Functions} for some common functions for handling unknown types. * @return the result of the function applied to the underlying value. + * @since 0.5 */ public abstract T match( Function stringFunction, diff --git a/api/src/main/java/io/opencensus/trace/BlankSpan.java b/api/src/main/java/io/opencensus/trace/BlankSpan.java index 0c35a885..0f11a034 100644 --- a/api/src/main/java/io/opencensus/trace/BlankSpan.java +++ b/api/src/main/java/io/opencensus/trace/BlankSpan.java @@ -24,10 +24,16 @@ import javax.annotation.concurrent.Immutable; * no {@code Span} implementation is available. All operations are no-op. * *

    Used also to stop tracing, see {@link Tracer#withSpan}. + * + * @since 0.5 */ @Immutable public final class BlankSpan extends Span { - /** Singleton instance of this class. */ + /** + * Singleton instance of this class. + * + * @since 0.5 + */ public static final BlankSpan INSTANCE = new BlankSpan(); private BlankSpan() { diff --git a/api/src/main/java/io/opencensus/trace/EndSpanOptions.java b/api/src/main/java/io/opencensus/trace/EndSpanOptions.java index 5c46e06f..d9e31e63 100644 --- a/api/src/main/java/io/opencensus/trace/EndSpanOptions.java +++ b/api/src/main/java/io/opencensus/trace/EndSpanOptions.java @@ -25,6 +25,8 @@ import javax.annotation.concurrent.Immutable; /** * A class that enables overriding the default values used when ending a {@link Span}. Allows * overriding the {@link Status status}. + * + * @since 0.5 */ @Immutable @AutoValue @@ -32,13 +34,18 @@ import javax.annotation.concurrent.Immutable; @AutoValue.CopyAnnotations @SuppressWarnings("nullness") public abstract class EndSpanOptions { - /** The default {@code EndSpanOptions}. */ + /** + * The default {@code EndSpanOptions}. + * + * @since 0.5 + */ public static final EndSpanOptions DEFAULT = builder().build(); /** * Returns a new {@link Builder} with default options. * * @return a new {@code Builder} with default options. + * @since 0.5 */ public static Builder builder() { return new AutoValue_EndSpanOptions.Builder().setSampleToLocalSpanStore(false); @@ -55,6 +62,7 @@ public abstract class EndSpanOptions { * * @return {@code true} if the name of the {@code Span} should be registered to the {@code * io.opencensus.trace.export.SampledSpanStore}. + * @since 0.8 */ @ExperimentalApi public abstract boolean getSampleToLocalSpanStore(); @@ -66,11 +74,16 @@ public abstract class EndSpanOptions { * Span#setStatus(Status)} or the default {@link Status#OK} if no status was set. * * @return the status. + * @since 0.5 */ @Nullable public abstract Status getStatus(); - /** Builder class for {@link EndSpanOptions}. */ + /** + * Builder class for {@link EndSpanOptions}. + * + * @since 0.5 + */ @AutoValue.Builder public abstract static class Builder { /** @@ -80,6 +93,7 @@ public abstract class EndSpanOptions { * * @param status the status. * @return this. + * @since 0.5 */ public abstract Builder setStatus(Status status); @@ -96,6 +110,7 @@ public abstract class EndSpanOptions { * instead. * * @return this. + * @since 0.8 */ @ExperimentalApi public abstract Builder setSampleToLocalSpanStore(boolean sampleToLocalSpanStore); @@ -104,6 +119,7 @@ public abstract class EndSpanOptions { * Builds and returns a {@code EndSpanOptions} with the desired settings. * * @return a {@code EndSpanOptions} with the desired settings. + * @since 0.5 */ public abstract EndSpanOptions build(); diff --git a/api/src/main/java/io/opencensus/trace/Link.java b/api/src/main/java/io/opencensus/trace/Link.java index 77b17206..e877a010 100644 --- a/api/src/main/java/io/opencensus/trace/Link.java +++ b/api/src/main/java/io/opencensus/trace/Link.java @@ -30,6 +30,8 @@ import javax.annotation.concurrent.Immutable; * *

    Used (for example) in batching operations, where a single batch handler processes multiple * requests from different traces. + * + * @since 0.5 */ @Immutable @AutoValue @@ -39,11 +41,23 @@ import javax.annotation.concurrent.Immutable; public abstract class Link { private static final Map EMPTY_ATTRIBUTES = Collections.emptyMap(); - /** The relationship with the linked {@code Span} relative to the current {@code Span}. */ + /** + * The relationship with the linked {@code Span} relative to the current {@code Span}. + * + * @since 0.5 + */ public enum Type { - /** When the linked {@code Span} is a child of the current {@code Span}. */ + /** + * When the linked {@code Span} is a child of the current {@code Span}. + * + * @since 0.5 + */ CHILD_LINKED_SPAN, - /** When the linked {@code Span} is a parent of the current {@code Span}. */ + /** + * When the linked {@code Span} is a parent of the current {@code Span}. + * + * @since 0.5 + */ PARENT_LINKED_SPAN } @@ -53,6 +67,7 @@ public abstract class Link { * @param context the context of the linked {@code Span}. * @param type the type of the relationship with the linked {@code Span}. * @return a new {@code Link}. + * @since 0.5 */ public static Link fromSpanContext(SpanContext context, Type type) { return new AutoValue_Link(context.getTraceId(), context.getSpanId(), type, EMPTY_ATTRIBUTES); @@ -65,6 +80,7 @@ public abstract class Link { * @param type the type of the relationship with the linked {@code Span}. * @param attributes the attributes of the {@code Link}. * @return a new {@code Link}. + * @since 0.5 */ public static Link fromSpanContext( SpanContext context, Type type, Map attributes) { @@ -79,6 +95,7 @@ public abstract class Link { * Returns the {@code TraceId}. * * @return the {@code TraceId}. + * @since 0.5 */ public abstract TraceId getTraceId(); @@ -86,6 +103,7 @@ public abstract class Link { * Returns the {@code SpanId}. * * @return the {@code SpanId} + * @since 0.5 */ public abstract SpanId getSpanId(); @@ -93,6 +111,7 @@ public abstract class Link { * Returns the {@code Type}. * * @return the {@code Type}. + * @since 0.5 */ public abstract Type getType(); @@ -100,6 +119,7 @@ public abstract class Link { * Returns the set of attributes. * * @return the set of attributes. + * @since 0.5 */ public abstract Map getAttributes(); diff --git a/api/src/main/java/io/opencensus/trace/NetworkEvent.java b/api/src/main/java/io/opencensus/trace/NetworkEvent.java index a38bbdb8..a8dfdb70 100644 --- a/api/src/main/java/io/opencensus/trace/NetworkEvent.java +++ b/api/src/main/java/io/opencensus/trace/NetworkEvent.java @@ -27,6 +27,8 @@ import javax.annotation.concurrent.Immutable; * A class that represents a network event. It requires a {@link Type type} and a message id that * serves to uniquely identify each network message. It can optionally can have information about * the kernel time and message size. + * + * @since 0.5 */ @Immutable @AutoValue @@ -34,11 +36,23 @@ import javax.annotation.concurrent.Immutable; @AutoValue.CopyAnnotations @SuppressWarnings("nullness") public abstract class NetworkEvent { - /** Available types for a {@code NetworkEvent}. */ + /** + * Available types for a {@code NetworkEvent}. + * + * @since 0.5 + */ public enum Type { - /** When the message was sent. */ + /** + * When the message was sent. + * + * @since 0.5 + */ SENT, - /** When the message was received. */ + /** + * When the message was received. + * + * @since 0.5 + */ RECV, } @@ -49,6 +63,7 @@ public abstract class NetworkEvent { * @param messageId serves to uniquely identify each network message. * @return a new {@code Builder} with default values. * @throws NullPointerException if {@code type} is {@code null}. + * @since 0.5 */ public static Builder builder(Type type, long messageId) { return new AutoValue_NetworkEvent.Builder() @@ -66,6 +81,7 @@ public abstract class NetworkEvent { * * @return the kernel timestamp associated with the {@code NetworkEvent} or {@code null} if not * set. + * @since 0.5 */ @Nullable public abstract Timestamp getKernelTimestamp(); @@ -74,6 +90,7 @@ public abstract class NetworkEvent { * Returns the type of the {@code NetworkEvent}. * * @return the type of the {@code NetworkEvent}. + * @since 0.5 */ public abstract Type getType(); @@ -81,6 +98,7 @@ public abstract class NetworkEvent { * Returns the message id argument that serves to uniquely identify each network message. * * @return the message id of the {@code NetworkEvent}. + * @since 0.5 */ public abstract long getMessageId(); @@ -88,6 +106,7 @@ public abstract class NetworkEvent { * Returns the uncompressed size in bytes of the {@code NetworkEvent}. * * @return the uncompressed size in bytes of the {@code NetworkEvent}. + * @since 0.6 */ public abstract long getUncompressedMessageSize(); @@ -95,19 +114,25 @@ public abstract class NetworkEvent { * Returns the compressed size in bytes of the {@code NetworkEvent}. * * @return the compressed size in bytes of the {@code NetworkEvent}. + * @since 0.6 */ public abstract long getCompressedMessageSize(); /** * @deprecated Use {@link #getUncompressedMessageSize}. * @return the uncompressed size in bytes of the {@code NetworkEvent}. + * @since 0.5 */ @Deprecated public long getMessageSize() { return getUncompressedMessageSize(); } - /** Builder class for {@link NetworkEvent}. */ + /** + * Builder class for {@link NetworkEvent}. + * + * @since 0.5 + */ @AutoValue.Builder public abstract static class Builder { // Package protected methods because these values are mandatory and set only in the @@ -121,6 +146,7 @@ public abstract class NetworkEvent { * * @param kernelTimestamp The kernel timestamp of the event. * @return this. + * @since 0.5 */ public abstract Builder setKernelTimestamp(@Nullable Timestamp kernelTimestamp); @@ -128,6 +154,7 @@ public abstract class NetworkEvent { * @deprecated Use {@link #setUncompressedMessageSize}. * @param messageSize represents the uncompressed size in bytes of this message. * @return this. + * @since 0.5 */ @Deprecated public Builder setMessageSize(long messageSize) { @@ -139,6 +166,7 @@ public abstract class NetworkEvent { * * @param uncompressedMessageSize represents the uncompressed size in bytes of this message. * @return this. + * @since 0.6 */ public abstract Builder setUncompressedMessageSize(long uncompressedMessageSize); @@ -147,6 +175,7 @@ public abstract class NetworkEvent { * * @param compressedMessageSize represents the compressed size in bytes of this message. * @return this. + * @since 0.6 */ public abstract Builder setCompressedMessageSize(long compressedMessageSize); @@ -154,6 +183,7 @@ public abstract class NetworkEvent { * Builds and returns a {@code NetworkEvent} with the desired values. * * @return a {@code NetworkEvent} with the desired values. + * @since 0.5 */ public abstract NetworkEvent build(); diff --git a/api/src/main/java/io/opencensus/trace/Sampler.java b/api/src/main/java/io/opencensus/trace/Sampler.java index e30b5fdd..e89af89b 100644 --- a/api/src/main/java/io/opencensus/trace/Sampler.java +++ b/api/src/main/java/io/opencensus/trace/Sampler.java @@ -19,7 +19,11 @@ package io.opencensus.trace; import java.util.List; import javax.annotation.Nullable; -/** Sampler is used to make decisions on {@link Span} sampling. */ +/** + * Sampler is used to make decisions on {@link Span} sampling. + * + * @since 0.5 + */ public abstract class Sampler { /** * Called during {@link Span} creation to make a sampling decision. @@ -34,6 +38,7 @@ public abstract class Sampler { * @param name the name of the new {@code Span}. * @param parentLinks the parentLinks associated with the new {@code Span}. * @return {@code true} if the {@code Span} is sampled. + * @since 0.5 */ public abstract boolean shouldSample( @Nullable SpanContext parentContext, @@ -50,6 +55,7 @@ public abstract class Sampler { *

    Example: "ProbabilitySampler{0.000100}" * * @return the description of this {@code Sampler}. + * @since 0.6 */ public abstract String getDescription(); } diff --git a/api/src/main/java/io/opencensus/trace/Span.java b/api/src/main/java/io/opencensus/trace/Span.java index 16aac33f..29673930 100644 --- a/api/src/main/java/io/opencensus/trace/Span.java +++ b/api/src/main/java/io/opencensus/trace/Span.java @@ -32,6 +32,8 @@ import javax.annotation.Nullable; *

    Spans are created by the {@link SpanBuilder#startSpan} method. * *

    {@code Span} must be ended by calling {@link #end()} or {@link #end(EndSpanOptions)} + * + * @since 0.5 */ public abstract class Span { private static final Map EMPTY_ATTRIBUTES = Collections.emptyMap(); @@ -45,11 +47,15 @@ public abstract class Span { /** * {@code Span} options. These options are NOT propagated to child spans. These options determine * features such as whether a {@code Span} should record any annotations or events. + * + * @since 0.5 */ public enum Options { /** * This option is set if the Span is part of a sampled distributed trace OR {@link * SpanBuilder#setRecordEvents(boolean)} was called with true. + * + * @since 0.5 */ RECORD_EVENTS; } @@ -66,6 +72,7 @@ public abstract class Span { * @throws NullPointerException if context is {@code null}. * @throws IllegalArgumentException if the {@code SpanContext} is sampled but no RECORD_EVENTS * options. + * @since 0.5 */ protected Span(SpanContext context, @Nullable EnumSet options) { this.context = checkNotNull(context, "context"); @@ -84,6 +91,7 @@ public abstract class Span { * * @param key the key for this attribute. * @param value the value for this attribute. + * @since 0.6 */ public void putAttribute(String key, AttributeValue value) { // Not final because for performance reasons we want to override this in the implementation. @@ -98,6 +106,7 @@ public abstract class Span { * map. * * @param attributes the attributes that will be added and associated with the {@code Span}. + * @since 0.6 */ public void putAttributes(Map attributes) { // Not final because we want to start overriding this method from the beginning, this will @@ -108,6 +117,7 @@ public abstract class Span { /** * @deprecated Use {@link #putAttributes(Map)} * @param attributes the attributes that will be added and associated with the {@code Span}. + * @since 0.5 */ @Deprecated public void addAttributes(Map attributes) { @@ -118,6 +128,7 @@ public abstract class Span { * Adds an annotation to the {@code Span}. * * @param description the description of the annotation time event. + * @since 0.5 */ public final void addAnnotation(String description) { addAnnotation(description, EMPTY_ATTRIBUTES); @@ -129,6 +140,7 @@ public abstract class Span { * @param description the description of the annotation time event. * @param attributes the attributes that will be added; these are associated with this annotation, * not the {@code Span} as for {@link #putAttributes(Map)}. + * @since 0.5 */ public abstract void addAnnotation(String description, Map attributes); @@ -136,6 +148,7 @@ public abstract class Span { * Adds an annotation to the {@code Span}. * * @param annotation the annotations to add. + * @since 0.5 */ public abstract void addAnnotation(Annotation annotation); @@ -146,6 +159,7 @@ public abstract class Span { * higher level applications. * * @param networkEvent the network event to add. + * @since 0.5 */ public abstract void addNetworkEvent(NetworkEvent networkEvent); @@ -156,6 +170,7 @@ public abstract class Span { * requests from different traces. * * @param link the link to add. + * @since 0.5 */ public abstract void addLink(Link link); @@ -169,6 +184,7 @@ public abstract class Span { * will always be the last call. * * @param status the {@link Status} to set. + * @since 0.9 */ public void setStatus(Status status) { // Implemented as no-op for backwards compatibility (for example gRPC extends Span in tests). @@ -182,6 +198,7 @@ public abstract class Span { * implementations are free to ignore all further calls. * * @param options the options to be used for the end of the {@code Span}. + * @since 0.5 */ public abstract void end(EndSpanOptions options); @@ -190,6 +207,8 @@ public abstract class Span { * *

    Only the timing of the first end call for a given {@code Span} will be recorded, and * implementations are free to ignore all further calls. + * + * @since 0.5 */ public final void end() { end(EndSpanOptions.DEFAULT); @@ -199,6 +218,7 @@ public abstract class Span { * Returns the {@code SpanContext} associated with this {@code Span}. * * @return the {@code SpanContext} associated with this {@code Span}. + * @since 0.5 */ public final SpanContext getContext() { return context; @@ -208,6 +228,7 @@ public abstract class Span { * Returns the options associated with this {@code Span}. * * @return the options associated with this {@code Span}. + * @since 0.5 */ public final Set getOptions() { return options; diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java index 04c339ff..ee68d109 100644 --- a/api/src/main/java/io/opencensus/trace/SpanBuilder.java +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -104,6 +104,8 @@ import javax.annotation.Nullable; * *

    If your Java version is less than Java SE 7, see {@link SpanBuilder#startSpan} and {@link * SpanBuilder#startScopedSpan} for usage examples. + * + * @since 0.5 */ public abstract class SpanBuilder { @@ -112,6 +114,7 @@ public abstract class SpanBuilder { * * @param sampler The {@code Sampler} to use when determining sampling for a {@code Span}. * @return this. + * @since 0.5 */ public abstract SpanBuilder setSampler(Sampler sampler); @@ -123,6 +126,7 @@ public abstract class SpanBuilder { * @param parentLinks New links to be added. * @return this. * @throws NullPointerException if {@code parentLinks} is {@code null}. + * @since 0.5 */ public abstract SpanBuilder setParentLinks(List parentLinks); @@ -132,6 +136,7 @@ public abstract class SpanBuilder { * * @param recordEvents New value determining if this {@code Span} should have events recorded. * @return this. + * @since 0.5 */ public abstract SpanBuilder setRecordEvents(boolean recordEvents); @@ -162,6 +167,7 @@ public abstract class SpanBuilder { * } * * @return the newly created {@code Span}. + * @since 0.5 */ public abstract Span startSpan(); @@ -218,6 +224,7 @@ public abstract class SpanBuilder { * * @return an object that defines a scope where the newly created {@code Span} will be set to the * current Context. + * @since 0.5 */ @MustBeClosed public final Scope startScopedSpan() { diff --git a/api/src/main/java/io/opencensus/trace/SpanContext.java b/api/src/main/java/io/opencensus/trace/SpanContext.java index 6084c674..cdc74886 100644 --- a/api/src/main/java/io/opencensus/trace/SpanContext.java +++ b/api/src/main/java/io/opencensus/trace/SpanContext.java @@ -26,6 +26,8 @@ import javax.annotation.concurrent.Immutable; * child {@link Span}s and across process boundaries. It contains the identifiers (a {@link TraceId * trace_id} and {@link SpanId span_id}) associated with the {@link Span} and a set of {@link * TraceOptions options}. + * + * @since 0.5 */ @Immutable public final class SpanContext { @@ -33,7 +35,11 @@ public final class SpanContext { private final SpanId spanId; private final TraceOptions traceOptions; - /** The invalid {@code SpanContext}. */ + /** + * The invalid {@code SpanContext}. + * + * @since 0.5 + */ public static final SpanContext INVALID = new SpanContext(TraceId.INVALID, SpanId.INVALID, TraceOptions.DEFAULT); @@ -44,6 +50,7 @@ public final class SpanContext { * @param spanId the span identifier of the span context. * @param traceOptions the trace options for the span context. * @return a new {@code SpanContext} with the given identifiers and options. + * @since 0.5 */ public static SpanContext create(TraceId traceId, SpanId spanId, TraceOptions traceOptions) { return new SpanContext(traceId, spanId, traceOptions); @@ -53,6 +60,7 @@ public final class SpanContext { * Returns the trace identifier associated with this {@code SpanContext}. * * @return the trace identifier associated with this {@code SpanContext}. + * @since 0.5 */ public TraceId getTraceId() { return traceId; @@ -62,6 +70,7 @@ public final class SpanContext { * Returns the span identifier associated with this {@code SpanContext}. * * @return the span identifier associated with this {@code SpanContext}. + * @since 0.5 */ public SpanId getSpanId() { return spanId; @@ -71,6 +80,7 @@ public final class SpanContext { * Returns the trace options associated with this {@code SpanContext}. * * @return the trace options associated with this {@code SpanContext}. + * @since 0.5 */ public TraceOptions getTraceOptions() { return traceOptions; @@ -80,6 +90,7 @@ public final class SpanContext { * Returns true if this {@code SpanContext} is valid. * * @return true if this {@code SpanContext} is valid. + * @since 0.5 */ public boolean isValid() { return traceId.isValid() && spanId.isValid(); diff --git a/api/src/main/java/io/opencensus/trace/SpanId.java b/api/src/main/java/io/opencensus/trace/SpanId.java index 76747acf..eee5f497 100644 --- a/api/src/main/java/io/opencensus/trace/SpanId.java +++ b/api/src/main/java/io/opencensus/trace/SpanId.java @@ -29,13 +29,23 @@ import javax.annotation.concurrent.Immutable; /** * A class that represents a span identifier. A valid span identifier is an 8-byte array with at * least one non-zero byte. + * + * @since 0.5 */ @Immutable public final class SpanId implements Comparable { - /** The size in bytes of the {@code SpanId}. */ + /** + * The size in bytes of the {@code SpanId}. + * + * @since 0.5 + */ public static final int SIZE = 8; - /** The invalid {@code SpanId}. All bytes are 0. */ + /** + * The invalid {@code SpanId}. All bytes are 0. + * + * @since 0.5 + */ public static final SpanId INVALID = new SpanId(new byte[SIZE]); // The internal representation of the SpanId. @@ -58,6 +68,7 @@ public final class SpanId implements Comparable { * @return a {@code SpanId} whose representation is given by the {@code buffer} parameter. * @throws NullPointerException if {@code buffer} is null. * @throws IllegalArgumentException if {@code buffer.length} is not {@link SpanId#SIZE}. + * @since 0.5 */ public static SpanId fromBytes(byte[] buffer) { checkNotNull(buffer, "buffer"); @@ -77,6 +88,7 @@ public final class SpanId implements Comparable { * @throws NullPointerException if {@code src} is null. * @throws IndexOutOfBoundsException if {@code srcOffset+SpanId.SIZE} is greater than {@code * src.length}. + * @since 0.5 */ public static SpanId fromBytes(byte[] src, int srcOffset) { byte[] bytes = new byte[SIZE]; @@ -92,6 +104,7 @@ public final class SpanId implements Comparable { * @throws NullPointerException if {@code src} is null. * @throws IllegalArgumentException if {@code src.length} is not {@code 2 * SpanId.SIZE} OR if the * {@code str} has invalid characters. + * @since 0.11 */ public static SpanId fromLowerBase16(CharSequence src) { checkArgument( @@ -105,6 +118,7 @@ public final class SpanId implements Comparable { * * @param random The random number generator. * @return a valid new {@code SpanId}. + * @since 0.5 */ public static SpanId generateRandomId(Random random) { byte[] bytes = new byte[SIZE]; @@ -118,6 +132,7 @@ public final class SpanId implements Comparable { * Returns the byte representation of the {@code SpanId}. * * @return the byte representation of the {@code SpanId}. + * @since 0.5 */ public byte[] getBytes() { return Arrays.copyOf(bytes, SIZE); @@ -138,6 +153,7 @@ public final class SpanId implements Comparable { * @throws NullPointerException if {@code dest} is null. * @throws IndexOutOfBoundsException if {@code destOffset+SpanId.SIZE} is greater than {@code * dest.length}. + * @since 0.5 */ public void copyBytesTo(byte[] dest, int destOffset) { System.arraycopy(bytes, 0, dest, destOffset, SIZE); @@ -148,6 +164,7 @@ public final class SpanId implements Comparable { * at least one non-zero byte. * * @return {@code true} if the span identifier is valid. + * @since 0.5 */ public boolean isValid() { return !Arrays.equals(bytes, INVALID.bytes); @@ -157,6 +174,7 @@ public final class SpanId implements Comparable { * Returns the lowercase base16 encoding of this {@code SpanId}. * * @return the lowercase base16 encoding of this {@code SpanId}. + * @since 0.11 */ public String toLowerBase16() { return BaseEncoding.base16().lowerCase().encode(bytes); diff --git a/api/src/main/java/io/opencensus/trace/Status.java b/api/src/main/java/io/opencensus/trace/Status.java index f5a275bf..b8c6b7a1 100644 --- a/api/src/main/java/io/opencensus/trace/Status.java +++ b/api/src/main/java/io/opencensus/trace/Status.java @@ -38,18 +38,30 @@ import org.checkerframework.dataflow.qual.Deterministic; * the template for the appropriate {@link Status.CanonicalCode} and supplementing it with * additional information: {@code Status.NOT_FOUND.withDescription("Could not find * 'important_file.txt'");} + * + * @since 0.5 */ @Immutable public final class Status { /** * The set of canonical status codes. If new codes are added over time they must choose a * numerical value that does not collide with any previously used value. + * + * @since 0.5 */ public enum CanonicalCode { - /** The operation completed successfully. */ + /** + * The operation completed successfully. + * + * @since 0.5 + */ OK(0), - /** The operation was cancelled (typically by the caller). */ + /** + * The operation was cancelled (typically by the caller). + * + * @since 0.5 + */ CANCELLED(1), /** @@ -57,6 +69,8 @@ public final class Status { * from another address space belongs to an error-space that is not known in this address space. * Also errors raised by APIs that do not return enough error information may be converted to * this error. + * + * @since 0.5 */ UNKNOWN(2), @@ -64,6 +78,8 @@ public final class Status { * Client specified an invalid argument. Note that this differs from FAILED_PRECONDITION. * INVALID_ARGUMENT indicates arguments that are problematic regardless of the state of the * system (e.g., a malformed file name). + * + * @since 0.5 */ INVALID_ARGUMENT(3), @@ -72,13 +88,23 @@ public final class Status { * system, this error may be returned even if the operation has completed successfully. For * example, a successful response from a server could have been delayed long enough for the * deadline to expire. + * + * @since 0.5 */ DEADLINE_EXCEEDED(4), - /** Some requested entity (e.g., file or directory) was not found. */ + /** + * Some requested entity (e.g., file or directory) was not found. + * + * @since 0.5 + */ NOT_FOUND(5), - /** Some entity that we attempted to create (e.g., file or directory) already exists. */ + /** + * Some entity that we attempted to create (e.g., file or directory) already exists. + * + * @since 0.5 + */ ALREADY_EXISTS(6), /** @@ -86,12 +112,16 @@ public final class Status { * must not be used for rejections caused by exhausting some resource (use RESOURCE_EXHAUSTED * instead for those errors). PERMISSION_DENIED must not be used if the caller cannot be * identified (use UNAUTHENTICATED instead for those errors). + * + * @since 0.5 */ PERMISSION_DENIED(7), /** * Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system * is out of space. + * + * @since 0.5 */ RESOURCE_EXHAUSTED(8), @@ -107,6 +137,8 @@ public final class Status { * the system state has been explicitly fixed. E.g., if an "rmdir" fails because the directory * is non-empty, FAILED_PRECONDITION should be returned since the client should not retry unless * they have first fixed up the directory by deleting files from it. + * + * @since 0.5 */ FAILED_PRECONDITION(9), @@ -115,6 +147,8 @@ public final class Status { * failures, transaction aborts, etc. * *

    See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE. + * + * @since 0.5 */ ABORTED(10), @@ -130,15 +164,23 @@ public final class Status { * using OUT_OF_RANGE (the more specific error) when it applies so that callers who are * iterating through a space can easily look for an OUT_OF_RANGE error to detect when they are * done. + * + * @since 0.5 */ OUT_OF_RANGE(11), - /** Operation is not implemented or not supported/enabled in this service. */ + /** + * Operation is not implemented or not supported/enabled in this service. + * + * @since 0.5 + */ UNIMPLEMENTED(12), /** * Internal errors. Means some invariants expected by underlying system has been broken. If you * see one of these errors, something is very broken. + * + * @since 0.5 */ INTERNAL(13), @@ -147,13 +189,23 @@ public final class Status { * corrected by retrying with a backoff. * *

    See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE. + * + * @since 0.5 */ UNAVAILABLE(14), - /** Unrecoverable data loss or corruption. */ + /** + * Unrecoverable data loss or corruption. + * + * @since 0.5 + */ DATA_LOSS(15), - /** The request does not have valid authentication credentials for the operation. */ + /** + * The request does not have valid authentication credentials for the operation. + * + * @since 0.5 + */ UNAUTHENTICATED(16); private final int value; @@ -166,6 +218,7 @@ public final class Status { * Returns the numerical value of the code. * * @return the numerical value of the code. + * @since 0.5 */ public int value() { return value; @@ -175,6 +228,7 @@ public final class Status { * Returns the status that has the current {@code CanonicalCode}.. * * @return the status that has the current {@code CanonicalCode}. + * @since 0.5 */ @VisibleForTesting public Status toStatus() { @@ -202,53 +256,127 @@ public final class Status { // A pseudo-enum of Status instances mapped 1:1 with values in CanonicalCode. This simplifies // construction patterns for derived instances of Status. - /** The operation completed successfully. */ + /** + * The operation completed successfully. + * + * @since 0.5 + */ public static final Status OK = CanonicalCode.OK.toStatus(); - /** The operation was cancelled (typically by the caller). */ + + /** + * The operation was cancelled (typically by the caller). + * + * @since 0.5 + */ public static final Status CANCELLED = CanonicalCode.CANCELLED.toStatus(); - /** Unknown error. See {@link CanonicalCode#UNKNOWN}. */ + + /** + * Unknown error. See {@link CanonicalCode#UNKNOWN}. + * + * @since 0.5 + */ public static final Status UNKNOWN = CanonicalCode.UNKNOWN.toStatus(); - /** Client specified an invalid argument. See {@link CanonicalCode#INVALID_ARGUMENT}. */ + + /** + * Client specified an invalid argument. See {@link CanonicalCode#INVALID_ARGUMENT}. + * + * @since 0.5 + */ public static final Status INVALID_ARGUMENT = CanonicalCode.INVALID_ARGUMENT.toStatus(); + /** * Deadline expired before operation could complete. See {@link CanonicalCode#DEADLINE_EXCEEDED}. + * + * @since 0.5 */ public static final Status DEADLINE_EXCEEDED = CanonicalCode.DEADLINE_EXCEEDED.toStatus(); - /** Some requested entity (e.g., file or directory) was not found. */ + + /** + * Some requested entity (e.g., file or directory) was not found. + * + * @since 0.5 + */ public static final Status NOT_FOUND = CanonicalCode.NOT_FOUND.toStatus(); - /** Some entity that we attempted to create (e.g., file or directory) already exists. */ + + /** + * Some entity that we attempted to create (e.g., file or directory) already exists. + * + * @since 0.5 + */ public static final Status ALREADY_EXISTS = CanonicalCode.ALREADY_EXISTS.toStatus(); + /** * The caller does not have permission to execute the specified operation. See {@link * CanonicalCode#PERMISSION_DENIED}. + * + * @since 0.5 */ public static final Status PERMISSION_DENIED = CanonicalCode.PERMISSION_DENIED.toStatus(); - /** The request does not have valid authentication credentials for the operation. */ + + /** + * The request does not have valid authentication credentials for the operation. + * + * @since 0.5 + */ public static final Status UNAUTHENTICATED = CanonicalCode.UNAUTHENTICATED.toStatus(); + /** * Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system * is out of space. + * + * @since 0.5 */ public static final Status RESOURCE_EXHAUSTED = CanonicalCode.RESOURCE_EXHAUSTED.toStatus(); + /** * Operation was rejected because the system is not in a state required for the operation's * execution. See {@link CanonicalCode#FAILED_PRECONDITION}. + * + * @since 0.5 */ public static final Status FAILED_PRECONDITION = CanonicalCode.FAILED_PRECONDITION.toStatus(); + /** * The operation was aborted, typically due to a concurrency issue like sequencer check failures, * transaction aborts, etc. See {@link CanonicalCode#ABORTED}. + * + * @since 0.5 */ public static final Status ABORTED = CanonicalCode.ABORTED.toStatus(); - /** Operation was attempted past the valid range. See {@link CanonicalCode#OUT_OF_RANGE}. */ + + /** + * Operation was attempted past the valid range. See {@link CanonicalCode#OUT_OF_RANGE}. + * + * @since 0.5 + */ public static final Status OUT_OF_RANGE = CanonicalCode.OUT_OF_RANGE.toStatus(); - /** Operation is not implemented or not supported/enabled in this service. */ + + /** + * Operation is not implemented or not supported/enabled in this service. + * + * @since 0.5 + */ public static final Status UNIMPLEMENTED = CanonicalCode.UNIMPLEMENTED.toStatus(); - /** Internal errors. See {@link CanonicalCode#INTERNAL}. */ + + /** + * Internal errors. See {@link CanonicalCode#INTERNAL}. + * + * @since 0.5 + */ public static final Status INTERNAL = CanonicalCode.INTERNAL.toStatus(); - /** The service is currently unavailable. See {@link CanonicalCode#UNAVAILABLE}. */ + + /** + * The service is currently unavailable. See {@link CanonicalCode#UNAVAILABLE}. + * + * @since 0.5 + */ public static final Status UNAVAILABLE = CanonicalCode.UNAVAILABLE.toStatus(); - /** Unrecoverable data loss or corruption. */ + + /** + * Unrecoverable data loss or corruption. + * + * @since 0.5 + */ public static final Status DATA_LOSS = CanonicalCode.DATA_LOSS.toStatus(); // The canonical code of this message. @@ -267,6 +395,7 @@ public final class Status { * * @param description the new description of the {@code Status}. * @return The newly created {@code Status} with the given description. + * @since 0.5 */ public Status withDescription(String description) { if (Objects.equal(this.description, description)) { @@ -279,6 +408,7 @@ public final class Status { * Returns the canonical status code. * * @return the canonical status code. + * @since 0.5 */ public CanonicalCode getCanonicalCode() { return canonicalCode; @@ -288,6 +418,7 @@ public final class Status { * Returns the description of this {@code Status} for human consumption. * * @return the description of this {@code Status}. + * @since 0.5 */ @Nullable /*@Deterministic*/ @@ -299,6 +430,7 @@ public final class Status { * Returns {@code true} if this {@code Status} is OK, i.e., not an error. * * @return {@code true} if this {@code Status} is OK. + * @since 0.5 */ public boolean isOk() { return CanonicalCode.OK == canonicalCode; diff --git a/api/src/main/java/io/opencensus/trace/TraceComponent.java b/api/src/main/java/io/opencensus/trace/TraceComponent.java index a781f045..d98d0f9e 100644 --- a/api/src/main/java/io/opencensus/trace/TraceComponent.java +++ b/api/src/main/java/io/opencensus/trace/TraceComponent.java @@ -27,6 +27,8 @@ import io.opencensus.trace.propagation.PropagationComponent; * {@link Clock}, {@link ExportComponent} and {@link TraceConfig}. * *

    Unless otherwise noted all methods (on component) results are cacheable. + * + * @since 0.5 */ public abstract class TraceComponent { @@ -35,6 +37,7 @@ public abstract class TraceComponent { * then no-op implementations will be used. * * @return the {@code Tracer} implementation. + * @since 0.5 */ public abstract Tracer getTracer(); @@ -43,6 +46,7 @@ public abstract class TraceComponent { * is provided then no-op implementation will be used. * * @return the {@code PropagationComponent} implementation. + * @since 0.5 */ public abstract PropagationComponent getPropagationComponent(); @@ -50,6 +54,7 @@ public abstract class TraceComponent { * Returns the {@link Clock} with the provided implementation. * * @return the {@code Clock} implementation. + * @since 0.5 */ public abstract Clock getClock(); @@ -58,6 +63,7 @@ public abstract class TraceComponent { * provided then no-op implementations will be used. * * @return the {@link ExportComponent} implementation. + * @since 0.5 */ public abstract ExportComponent getExportComponent(); @@ -66,6 +72,7 @@ public abstract class TraceComponent { * provided then no-op implementations will be used. * * @return the {@link TraceConfig} implementation. + * @since 0.5 */ public abstract TraceConfig getTraceConfig(); diff --git a/api/src/main/java/io/opencensus/trace/TraceId.java b/api/src/main/java/io/opencensus/trace/TraceId.java index 2fad8949..6378bf58 100644 --- a/api/src/main/java/io/opencensus/trace/TraceId.java +++ b/api/src/main/java/io/opencensus/trace/TraceId.java @@ -30,13 +30,23 @@ import javax.annotation.concurrent.Immutable; /** * A class that represents a trace identifier. A valid trace identifier is a 16-byte array with at * least one non-zero byte. + * + * @since 0.5 */ @Immutable public final class TraceId implements Comparable { - /** The size in bytes of the {@code TraceId}. */ + /** + * The size in bytes of the {@code TraceId}. + * + * @since 0.5 + */ public static final int SIZE = 16; - /** The invalid {@code TraceId}. All bytes are '\0'. */ + /** + * The invalid {@code TraceId}. All bytes are '\0'. + * + * @since 0.5 + */ public static final TraceId INVALID = new TraceId(new byte[SIZE]); // The internal representation of the TraceId. @@ -59,6 +69,7 @@ public final class TraceId implements Comparable { * @return a {@code TraceId} whose representation is given by the {@code buffer} parameter. * @throws NullPointerException if {@code buffer} is null. * @throws IllegalArgumentException if {@code buffer.length} is not {@link TraceId#SIZE}. + * @since 0.5 */ public static TraceId fromBytes(byte[] buffer) { checkNotNull(buffer, "buffer"); @@ -78,6 +89,7 @@ public final class TraceId implements Comparable { * @throws NullPointerException if {@code src} is null. * @throws IndexOutOfBoundsException if {@code srcOffset+TraceId.SIZE} is greater than {@code * src.length}. + * @since 0.5 */ public static TraceId fromBytes(byte[] src, int srcOffset) { byte[] bytes = new byte[SIZE]; @@ -93,6 +105,7 @@ public final class TraceId implements Comparable { * @throws NullPointerException if {@code src} is null. * @throws IllegalArgumentException if {@code src.length} is not {@code 2 * TraceId.SIZE} OR if * the {@code str} has invalid characters. + * @since 0.11 */ public static TraceId fromLowerBase16(CharSequence src) { checkArgument( @@ -106,6 +119,7 @@ public final class TraceId implements Comparable { * * @param random the random number generator. * @return a new valid {@code TraceId}. + * @since 0.5 */ public static TraceId generateRandomId(Random random) { byte[] bytes = new byte[SIZE]; @@ -119,6 +133,7 @@ public final class TraceId implements Comparable { * Returns the 16-bytes array representation of the {@code TraceId}. * * @return the 16-bytes array representation of the {@code TraceId}. + * @since 0.5 */ public byte[] getBytes() { return Arrays.copyOf(bytes, SIZE); @@ -139,6 +154,7 @@ public final class TraceId implements Comparable { * @throws NullPointerException if {@code dest} is null. * @throws IndexOutOfBoundsException if {@code destOffset+TraceId.SIZE} is greater than {@code * dest.length}. + * @since 0.5 */ public void copyBytesTo(byte[] dest, int destOffset) { System.arraycopy(bytes, 0, dest, destOffset, SIZE); @@ -149,6 +165,7 @@ public final class TraceId implements Comparable { * at least one non-zero byte. * * @return {@code true} if the {@code TraceId} is valid. + * @since 0.5 */ public boolean isValid() { return !Arrays.equals(bytes, INVALID.bytes); @@ -158,6 +175,7 @@ public final class TraceId implements Comparable { * Returns the lowercase base16 encoding of this {@code TraceId}. * * @return the lowercase base16 encoding of this {@code TraceId}. + * @since 0.11 */ public String toLowerBase16() { return BaseEncoding.base16().lowerCase().encode(bytes); diff --git a/api/src/main/java/io/opencensus/trace/TraceOptions.java b/api/src/main/java/io/opencensus/trace/TraceOptions.java index 2f57f3a7..bd6fe6bd 100644 --- a/api/src/main/java/io/opencensus/trace/TraceOptions.java +++ b/api/src/main/java/io/opencensus/trace/TraceOptions.java @@ -30,6 +30,8 @@ import javax.annotation.concurrent.Immutable; * A class that represents global trace options. These options are propagated to all child {@link * io.opencensus.trace.Span spans}. These determine features such as whether a {@code Span} should * be traced. It is implemented as a bitmask. + * + * @since 0.5 */ @Immutable public final class TraceOptions { @@ -38,10 +40,18 @@ public final class TraceOptions { // Bit to represent whether trace is sampled or not. private static final byte IS_SAMPLED = 0x1; - /** The size in bytes of the {@code TraceOptions}. */ + /** + * The size in bytes of the {@code TraceOptions}. + * + * @since 0.5 + */ public static final int SIZE = 1; - /** The default {@code TraceOptions}. */ + /** + * The default {@code TraceOptions}. + * + * @since 0.5 + */ public static final TraceOptions DEFAULT = new TraceOptions(DEFAULT_OPTIONS); // The set of enabled features is determined by all the enabled bits. @@ -65,6 +75,7 @@ public final class TraceOptions { * @return a {@code TraceOptions} whose representation is given by the {@code buffer} parameter. * @throws NullPointerException if {@code buffer} is null. * @throws IllegalArgumentException if {@code buffer.length} is not {@link TraceOptions#SIZE}. + * @since 0.5 */ public static TraceOptions fromBytes(byte[] buffer) { checkNotNull(buffer, "buffer"); @@ -83,6 +94,7 @@ public final class TraceOptions { * @throws NullPointerException if {@code src} is null. * @throws IndexOutOfBoundsException if {@code srcOffset+TraceOptions.SIZE} is greater than {@code * src.length}. + * @since 0.5 */ public static TraceOptions fromBytes(byte[] src, int srcOffset) { checkElementIndex(srcOffset, src.length); @@ -93,6 +105,7 @@ public final class TraceOptions { * Returns the 1-byte array representation of the {@code TraceOptions}. * * @return the 1-byte array representation of the {@code TraceOptions}. + * @since 0.5 */ public byte[] getBytes() { byte[] bytes = new byte[SIZE]; @@ -115,6 +128,7 @@ public final class TraceOptions { * @throws NullPointerException if {@code dest} is null. * @throws IndexOutOfBoundsException if {@code destOffset+TraceOptions.SIZE} is greater than * {@code dest.length}. + * @since 0.5 */ public void copyBytesTo(byte[] dest, int destOffset) { checkElementIndex(destOffset, dest.length); @@ -125,6 +139,7 @@ public final class TraceOptions { * Returns a new {@link Builder} with default options. * * @return a new {@code Builder} with default options. + * @since 0.5 */ public static Builder builder() { return new Builder(DEFAULT_OPTIONS); @@ -135,6 +150,7 @@ public final class TraceOptions { * * @param traceOptions the given options set. * @return a new {@code Builder} with all given options set. + * @since 0.5 */ public static Builder builder(TraceOptions traceOptions) { return new Builder(traceOptions.options); @@ -145,6 +161,7 @@ public final class TraceOptions { * should be exported to a persistent store. * * @return a boolean indicating whether the trace is sampled. + * @since 0.5 */ public boolean isSampled() { return hasOption(IS_SAMPLED); @@ -174,7 +191,11 @@ public final class TraceOptions { return MoreObjects.toStringHelper(this).add("sampled", isSampled()).toString(); } - /** Builder class for {@link TraceOptions}. */ + /** + * Builder class for {@link TraceOptions}. + * + * @since 0.5 + */ public static final class Builder { private byte options; @@ -185,6 +206,7 @@ public final class TraceOptions { /** * @deprecated Use {@code Builder.setIsSampled(true)}. * @return this. + * @since 0.5 */ @Deprecated public Builder setIsSampled() { @@ -196,6 +218,7 @@ public final class TraceOptions { * * @param isSampled the sampling bit. * @return this. + * @since 0.7 */ public Builder setIsSampled(boolean isSampled) { if (isSampled) { @@ -211,6 +234,7 @@ public final class TraceOptions { * Builds and returns a {@code TraceOptions} with the desired options. * * @return a {@code TraceOptions} with the desired options. + * @since 0.5 */ public TraceOptions build() { return new TraceOptions(options); diff --git a/api/src/main/java/io/opencensus/trace/Tracer.java b/api/src/main/java/io/opencensus/trace/Tracer.java index 22b98da5..f4ac8c65 100644 --- a/api/src/main/java/io/opencensus/trace/Tracer.java +++ b/api/src/main/java/io/opencensus/trace/Tracer.java @@ -67,6 +67,8 @@ import javax.annotation.Nullable; * } * } * } + * + * @since 0.5 */ public abstract class Tracer { private static final NoopTracer noopTracer = new NoopTracer(); @@ -91,6 +93,7 @@ public abstract class Tracer { * @return a default {@code Span} that does nothing and has an invalid {@link SpanContext} if no * {@code Span} is associated with the current Context, otherwise the current {@code Span} * from the Context. + * @since 0.5 */ public final Span getCurrentSpan() { Span currentSpan = CurrentSpanUtils.getCurrentSpan(); @@ -145,6 +148,7 @@ public abstract class Tracer { * @return an object that defines a scope where the given {@link Span} will be set to the current * Context. * @throws NullPointerException if {@code span} is {@code null}. + * @since 0.5 */ @MustBeClosed public final Scope withSpan(Span span) { @@ -299,6 +303,7 @@ public abstract class Tracer { * @param spanName The name of the returned Span. * @return a {@code SpanBuilder} to create and start a new {@code Span}. * @throws NullPointerException if {@code spanName} is {@code null}. + * @since 0.5 */ public final SpanBuilder spanBuilder(String spanName) { return spanBuilderWithExplicitParent(spanName, CurrentSpanUtils.getCurrentSpan()); @@ -319,6 +324,7 @@ public abstract class Tracer { * build a root {@code Span}. * @return a {@code SpanBuilder} to create and start a new {@code Span}. * @throws NullPointerException if {@code spanName} is {@code null}. + * @since 0.5 */ public abstract SpanBuilder spanBuilderWithExplicitParent(String spanName, @Nullable Span parent); @@ -339,6 +345,7 @@ public abstract class Tracer { * @param remoteParentSpanContext The remote parent of the returned Span. * @return a {@code SpanBuilder} to create and start a new {@code Span}. * @throws NullPointerException if {@code spanName} is {@code null}. + * @since 0.5 */ public abstract SpanBuilder spanBuilderWithRemoteParent( String spanName, @Nullable SpanContext remoteParentSpanContext); diff --git a/api/src/main/java/io/opencensus/trace/Tracing.java b/api/src/main/java/io/opencensus/trace/Tracing.java index 31d8cdc2..f3673020 100644 --- a/api/src/main/java/io/opencensus/trace/Tracing.java +++ b/api/src/main/java/io/opencensus/trace/Tracing.java @@ -26,7 +26,11 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; -/** Class that manages a global instance of the {@link TraceComponent}. */ +/** + * Class that manages a global instance of the {@link TraceComponent}. + * + * @since 0.5 + */ public final class Tracing { private static final Logger logger = Logger.getLogger(Tracing.class.getName()); private static final TraceComponent traceComponent = @@ -36,6 +40,7 @@ public final class Tracing { * Returns the global {@link Tracer}. * * @return the global {@code Tracer}. + * @since 0.5 */ public static Tracer getTracer() { return traceComponent.getTracer(); @@ -45,6 +50,7 @@ public final class Tracing { * Returns the global {@link PropagationComponent}. * * @return the global {@code PropagationComponent}. + * @since 0.5 */ public static PropagationComponent getPropagationComponent() { return traceComponent.getPropagationComponent(); @@ -54,6 +60,7 @@ public final class Tracing { * Returns the global {@link Clock}. * * @return the global {@code Clock}. + * @since 0.5 */ public static Clock getClock() { return traceComponent.getClock(); @@ -63,6 +70,7 @@ public final class Tracing { * Returns the global {@link ExportComponent}. * * @return the global {@code ExportComponent}. + * @since 0.5 */ public static ExportComponent getExportComponent() { return traceComponent.getExportComponent(); @@ -72,6 +80,7 @@ public final class Tracing { * Returns the global {@link TraceConfig}. * * @return the global {@code TraceConfig}. + * @since 0.5 */ public static TraceConfig getTraceConfig() { return traceComponent.getTraceConfig(); diff --git a/api/src/main/java/io/opencensus/trace/config/TraceConfig.java b/api/src/main/java/io/opencensus/trace/config/TraceConfig.java index bebf4a7f..ff701e20 100644 --- a/api/src/main/java/io/opencensus/trace/config/TraceConfig.java +++ b/api/src/main/java/io/opencensus/trace/config/TraceConfig.java @@ -19,6 +19,8 @@ package io.opencensus.trace.config; /** * Global configuration of the trace service. This allows users to change configs for the default * sampler, maximum events to be kept, etc. (see {@link TraceParams} for details). + * + * @since 0.5 */ public abstract class TraceConfig { private static final NoopTraceConfig NOOP_TRACE_CONFIG = new NoopTraceConfig(); @@ -27,6 +29,7 @@ public abstract class TraceConfig { * Returns the active {@code TraceParams}. * * @return the active {@code TraceParams}. + * @since 0.5 */ public abstract TraceParams getActiveTraceParams(); @@ -34,6 +37,7 @@ public abstract class TraceConfig { * Updates the active {@link TraceParams}. * * @param traceParams the new active {@code TraceParams}. + * @since 0.5 */ public abstract void updateActiveTraceParams(TraceParams traceParams); @@ -41,6 +45,7 @@ public abstract class TraceConfig { * Returns the no-op implementation of the {@code TraceConfig}. * * @return the no-op implementation of the {@code TraceConfig}. + * @since 0.5 */ public static TraceConfig getNoopTraceConfig() { return NOOP_TRACE_CONFIG; diff --git a/api/src/main/java/io/opencensus/trace/config/TraceParams.java b/api/src/main/java/io/opencensus/trace/config/TraceParams.java index c56cc9f7..17dbbb9d 100644 --- a/api/src/main/java/io/opencensus/trace/config/TraceParams.java +++ b/api/src/main/java/io/opencensus/trace/config/TraceParams.java @@ -27,7 +27,11 @@ import io.opencensus.trace.Span; import io.opencensus.trace.samplers.Samplers; import javax.annotation.concurrent.Immutable; -/** Class that holds global trace parameters. */ +/** + * Class that holds global trace parameters. + * + * @since 0.5 + */ @AutoValue @Immutable // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -42,6 +46,11 @@ public abstract class TraceParams { private static final int DEFAULT_SPAN_MAX_NUM_NETWORK_EVENTS = 128; private static final int DEFAULT_SPAN_MAX_NUM_LINKS = 128; + /** + * Default {@code TraceParams}. + * + * @since 0.5 + */ public static final TraceParams DEFAULT = TraceParams.builder() .setSampler(DEFAULT_SAMPLER) @@ -56,6 +65,7 @@ public abstract class TraceParams { * io.opencensus.trace.SpanBuilder#setSampler(Sampler)}. * * @return the global default {@code Sampler}. + * @since 0.5 */ public abstract Sampler getSampler(); @@ -63,6 +73,7 @@ public abstract class TraceParams { * Returns the global default max number of attributes per {@link Span}. * * @return the global default max number of attributes per {@link Span}. + * @since 0.5 */ public abstract int getMaxNumberOfAttributes(); @@ -70,6 +81,7 @@ public abstract class TraceParams { * Returns the global default max number of {@link Annotation} events per {@link Span}. * * @return the global default max number of {@code Annotation} events per {@code Span}. + * @since 0.5 */ public abstract int getMaxNumberOfAnnotations(); @@ -77,6 +89,7 @@ public abstract class TraceParams { * Returns the global default max number of {@link NetworkEvent} events per {@link Span}. * * @return the global default max number of {@code NetworkEvent} events per {@code Span}. + * @since 0.5 */ public abstract int getMaxNumberOfNetworkEvents(); @@ -84,6 +97,7 @@ public abstract class TraceParams { * Returns the global default max number of {@link Link} entries per {@link Span}. * * @return the global default max number of {@code Link} entries per {@code Span}. + * @since 0.5 */ public abstract int getMaxNumberOfLinks(); @@ -95,10 +109,15 @@ public abstract class TraceParams { * Returns a {@link Builder} initialized to the same property values as the current instance. * * @return a {@link Builder} initialized to the same property values as the current instance. + * @since 0.5 */ public abstract Builder toBuilder(); - /** A {@code Builder} class for {@link TraceParams}. */ + /** + * A {@code Builder} class for {@link TraceParams}. + * + * @since 0.5 + */ @AutoValue.Builder public abstract static class Builder { @@ -108,6 +127,7 @@ public abstract class TraceParams { * * @param sampler the global default {@code Sampler}. * @return this. + * @since 0.5 */ public abstract Builder setSampler(Sampler sampler); @@ -117,6 +137,7 @@ public abstract class TraceParams { * @param maxNumberOfAttributes the global default max number of attributes per {@link Span}. It * must be positive otherwise {@link #build()} will throw an exception. * @return this. + * @since 0.5 */ public abstract Builder setMaxNumberOfAttributes(int maxNumberOfAttributes); @@ -126,6 +147,7 @@ public abstract class TraceParams { * @param maxNumberOfAnnotations the global default max number of {@link Annotation} events per * {@link Span}. It must be positive otherwise {@link #build()} will throw an exception. * @return this. + * @since 0.5 */ public abstract Builder setMaxNumberOfAnnotations(int maxNumberOfAnnotations); @@ -135,6 +157,7 @@ public abstract class TraceParams { * @param maxNumberOfNetworkEvents the global default max number of {@link NetworkEvent} events * per {@link Span}. It must be positive otherwise {@link #build()} will throw an exception. * @return this. + * @since 0.5 */ public abstract Builder setMaxNumberOfNetworkEvents(int maxNumberOfNetworkEvents); @@ -144,6 +167,7 @@ public abstract class TraceParams { * @param maxNumberOfLinks the global default max number of {@link Link} entries per {@link * Span}. It must be positive otherwise {@link #build()} will throw an exception. * @return this. + * @since 0.5 */ public abstract Builder setMaxNumberOfLinks(int maxNumberOfLinks); @@ -155,6 +179,7 @@ public abstract class TraceParams { * @return a {@code TraceParams} with the desired values. * @throws NullPointerException if the sampler is {@code null}. * @throws IllegalArgumentException if any of the max numbers are not positive. + * @since 0.5 */ public TraceParams build() { TraceParams traceParams = autoBuild(); diff --git a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java index 7e2eb88e..63447a76 100644 --- a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java +++ b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java @@ -23,6 +23,8 @@ import io.opencensus.trace.TraceOptions; * and {@link SampledSpanStore}. * *

    Unless otherwise noted all methods (on component) results are cacheable. + * + * @since 0.5 */ public abstract class ExportComponent { @@ -30,6 +32,7 @@ public abstract class ExportComponent { * Returns the no-op implementation of the {@code ExportComponent}. * * @return the no-op implementation of the {@code ExportComponent}. + * @since 0.5 */ public static ExportComponent newNoopExportComponent() { return new NoopExportComponent(); @@ -41,6 +44,7 @@ public abstract class ExportComponent { * * @return the implementation of the {@code SpanExporter} or no-op if no implementation linked in * the binary. + * @since 0.5 */ public abstract SpanExporter getSpanExporter(); @@ -49,6 +53,7 @@ public abstract class ExportComponent { * all the current active spans. * * @return the {@code RunningSpanStore}. + * @since 0.5 */ public abstract RunningSpanStore getRunningSpanStore(); @@ -57,6 +62,7 @@ public abstract class ExportComponent { * as latency based sampled spans, error based sampled spans. * * @return the {@code SampledSpanStore}. + * @since 0.5 */ public abstract SampledSpanStore getSampledSpanStore(); diff --git a/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java b/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java index 209afe05..fbfc5ff1 100644 --- a/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java @@ -33,6 +33,8 @@ import javax.annotation.concurrent.ThreadSafe; *

    The running spans tracking is available for all the spans with the option {@link * io.opencensus.trace.Span.Options#RECORD_EVENTS}. This functionality allows users to debug stuck * operations or long living operations. + * + * @since 0.5 */ @ThreadSafe public abstract class RunningSpanStore { @@ -54,6 +56,7 @@ public abstract class RunningSpanStore { * Returns the summary of all available data such, as number of running spans. * * @return the summary of all available data. + * @since 0.5 */ public abstract Summary getSummary(); @@ -62,10 +65,15 @@ public abstract class RunningSpanStore { * * @param filter used to filter the returned spans. * @return a list of running spans that match the {@code Filter}. + * @since 0.5 */ public abstract Collection getRunningSpans(Filter filter); - /** The summary of all available data. */ + /** + * The summary of all available data. + * + * @since 0.5 + */ @AutoValue @Immutable // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -81,6 +89,7 @@ public abstract class RunningSpanStore { * @param perSpanNameSummary a map with summary for each span name. * @return a new instance of {@code Summary}. * @throws NullPointerException if {@code perSpanNameSummary} is {@code null}. + * @since 0.5 */ public static Summary create(Map perSpanNameSummary) { return new AutoValue_RunningSpanStore_Summary( @@ -93,11 +102,16 @@ public abstract class RunningSpanStore { * Returns a map with summary of available data for each span name. * * @return a map with all the span names and the summary. + * @since 0.5 */ public abstract Map getPerSpanNameSummary(); } - /** Summary of all available data for a span name. */ + /** + * Summary of all available data for a span name. + * + * @since 0.5 + */ @AutoValue @Immutable // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -113,6 +127,7 @@ public abstract class RunningSpanStore { * @param numRunningSpans the number of running spans. * @return a new instance of {@code PerSpanNameSummary}. * @throws IllegalArgumentException if {@code numRunningSpans} is negative. + * @since 0.5 */ public static PerSpanNameSummary create(int numRunningSpans) { checkArgument(numRunningSpans >= 0, "Negative numRunningSpans."); @@ -123,6 +138,7 @@ public abstract class RunningSpanStore { * Returns the number of running spans. * * @return the number of running spans. + * @since 0.5 */ public abstract int getNumRunningSpans(); } @@ -130,6 +146,8 @@ public abstract class RunningSpanStore { /** * Filter for running spans. Used to filter results returned by the {@link * #getRunningSpans(Filter)} request. + * + * @since 0.5 */ @AutoValue @Immutable @@ -151,6 +169,7 @@ public abstract class RunningSpanStore { * @return a new instance of {@code Filter}. * @throws NullPointerException if {@code spanName} is {@code null}. * @throws IllegalArgumentException if {@code maxSpansToReturn} is negative. + * @since 0.5 */ public static Filter create(String spanName, int maxSpansToReturn) { checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); @@ -161,6 +180,7 @@ public abstract class RunningSpanStore { * Returns the span name. * * @return the span name. + * @since 0.5 */ public abstract String getSpanName(); @@ -168,6 +188,7 @@ public abstract class RunningSpanStore { * Returns the maximum number of spans to be returned. {@code 0} means all. * * @return the maximum number of spans to be returned. + * @since 0.5 */ public abstract int getMaxSpansToReturn(); } diff --git a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java index c04b19f6..67a40567 100644 --- a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java @@ -45,6 +45,8 @@ import javax.annotation.concurrent.ThreadSafe; * store samples based on latency for succeeded operations or based on error code for failed * operations. To activate this, users MUST manually configure all the span names for which samples * will be collected (see {@link #registerSpanNamesForCollection(Collection)}). + * + * @since 0.5 */ @ThreadSafe public abstract class SampledSpanStore { @@ -70,6 +72,7 @@ public abstract class SampledSpanStore { * #registerSpanNamesForCollection(Collection)}. * * @return the summary of all available data. + * @since 0.5 */ public abstract Summary getSummary(); @@ -82,6 +85,7 @@ public abstract class SampledSpanStore { * * @param filter used to filter the returned sampled spans. * @return a list of succeeded spans that match the {@code filter}. + * @since 0.5 */ public abstract Collection getLatencySampledSpans(LatencyFilter filter); @@ -94,6 +98,7 @@ public abstract class SampledSpanStore { * * @param filter used to filter the returned sampled spans. * @return a list of failed spans that match the {@code filter}. + * @since 0.5 */ public abstract Collection getErrorSampledSpans(ErrorFilter filter); @@ -104,6 +109,7 @@ public abstract class SampledSpanStore { *

    If called multiple times the library keeps the list of unique span names from all the calls. * * @param spanNames list of span names for which the library will collect samples. + * @since 0.5 */ public abstract void registerSpanNamesForCollection(Collection spanNames); @@ -115,6 +121,7 @@ public abstract class SampledSpanStore { * This method allows users to remove span names from that list. * * @param spanNames list of span names for which the library will no longer collect samples. + * @since 0.5 */ public abstract void unregisterSpanNamesForCollection(Collection spanNames); @@ -123,11 +130,16 @@ public abstract class SampledSpanStore { * library will collect latency based sampled spans and error based sampled spans. * * @return the set of unique span names registered to the library. + * @since 0.7 */ @VisibleForTesting public abstract Set getRegisteredSpanNamesForCollection(); - /** The summary of all available data. */ + /** + * The summary of all available data. + * + * @since 0.5 + */ @AutoValue @Immutable // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -143,6 +155,7 @@ public abstract class SampledSpanStore { * @param perSpanNameSummary a map with summary for each span name. * @return a new instance of {@code Summary}. * @throws NullPointerException if {@code perSpanNameSummary} is {@code null}. + * @since 0.5 */ public static Summary create(Map perSpanNameSummary) { return new AutoValue_SampledSpanStore_Summary( @@ -155,11 +168,16 @@ public abstract class SampledSpanStore { * Returns a map with summary of available data for each span name. * * @return a map with all the span names and the summary. + * @since 0.5 */ public abstract Map getPerSpanNameSummary(); } - /** Summary of all available data for a span name. */ + /** + * Summary of all available data for a span name. + * + * @since 0.5 + */ @AutoValue @Immutable // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -177,6 +195,7 @@ public abstract class SampledSpanStore { * @return a new instance of {@code PerSpanNameSummary}. * @throws NullPointerException if {@code numbersOfLatencySampledSpans} or {@code * numbersOfErrorSampledSpans} are {@code null}. + * @since 0.5 */ public static PerSpanNameSummary create( Map numbersOfLatencySampledSpans, @@ -197,6 +216,7 @@ public abstract class SampledSpanStore { * #registerSpanNamesForCollection(Collection)}. * * @return the number of sampled spans in all the latency buckets. + * @since 0.5 */ public abstract Map getNumbersOfLatencySampledSpans(); @@ -207,6 +227,7 @@ public abstract class SampledSpanStore { * #registerSpanNamesForCollection(Collection)}. * * @return the number of sampled spans in all the error buckets. + * @since 0.5 */ public abstract Map getNumbersOfErrorSampledSpans(); } @@ -215,25 +236,71 @@ public abstract class SampledSpanStore { * The latency buckets boundaries. Samples based on latency for successful spans (the status of * the span has a canonical code equal to {@link CanonicalCode#OK}) are collected in one of these * latency buckets. + * + * @since 0.5 */ public enum LatencyBucketBoundaries { - // Stores finished successful requests of duration within the interval [0, 10us) + /** + * Stores finished successful requests of duration within the interval [0, 10us) + * + * @since 0.5 + */ ZERO_MICROSx10(0, TimeUnit.MICROSECONDS.toNanos(10)), - // Stores finished successful requests of duration within the interval [10us, 100us) + + /** + * Stores finished successful requests of duration within the interval [10us, 100us) + * + * @since 0.5 + */ MICROSx10_MICROSx100(TimeUnit.MICROSECONDS.toNanos(10), TimeUnit.MICROSECONDS.toNanos(100)), - // Stores finished successful requests of duration within the interval [100us, 1ms) + + /** + * Stores finished successful requests of duration within the interval [100us, 1ms) + * + * @since 0.5 + */ MICROSx100_MILLIx1(TimeUnit.MICROSECONDS.toNanos(100), TimeUnit.MILLISECONDS.toNanos(1)), - // Stores finished successful requests of duration within the interval [1ms, 10ms) + + /** + * Stores finished successful requests of duration within the interval [1ms, 10ms) + * + * @since 0.5 + */ MILLIx1_MILLIx10(TimeUnit.MILLISECONDS.toNanos(1), TimeUnit.MILLISECONDS.toNanos(10)), - // Stores finished successful requests of duration within the interval [10ms, 100ms) + + /** + * Stores finished successful requests of duration within the interval [10ms, 100ms) + * + * @since 0.5 + */ MILLIx10_MILLIx100(TimeUnit.MILLISECONDS.toNanos(10), TimeUnit.MILLISECONDS.toNanos(100)), - // Stores finished successful requests of duration within the interval [100ms, 1sec) + + /** + * Stores finished successful requests of duration within the interval [100ms, 1sec) + * + * @since 0.5 + */ MILLIx100_SECONDx1(TimeUnit.MILLISECONDS.toNanos(100), TimeUnit.SECONDS.toNanos(1)), - // Stores finished successful requests of duration within the interval [1sec, 10sec) + + /** + * Stores finished successful requests of duration within the interval [1sec, 10sec) + * + * @since 0.5 + */ SECONDx1_SECONDx10(TimeUnit.SECONDS.toNanos(1), TimeUnit.SECONDS.toNanos(10)), - // Stores finished successful requests of duration within the interval [10sec, 100sec) + + /** + * Stores finished successful requests of duration within the interval [10sec, 100sec) + * + * @since 0.5 + */ SECONDx10_SECONDx100(TimeUnit.SECONDS.toNanos(10), TimeUnit.SECONDS.toNanos(100)), - // Stores finished successful requests of duration >= 100sec + + /** + * Stores finished successful requests of duration >= 100sec + * + * @since 0.5 + */ SECONDx100_MAX(TimeUnit.SECONDS.toNanos(100), Long.MAX_VALUE); /** @@ -251,6 +318,7 @@ public abstract class SampledSpanStore { * Returns the latency lower bound of the bucket. * * @return the latency lower bound of the bucket. + * @since 0.5 */ public long getLatencyLowerNs() { return latencyLowerNs; @@ -260,6 +328,7 @@ public abstract class SampledSpanStore { * Returns the latency upper bound of the bucket. * * @return the latency upper bound of the bucket. + * @since 0.5 */ public long getLatencyUpperNs() { return latencyUpperNs; @@ -272,6 +341,8 @@ public abstract class SampledSpanStore { /** * Filter for latency based sampled spans. Used to filter results returned by the {@link * #getLatencySampledSpans(LatencyFilter)} request. + * + * @since 0.5 */ @AutoValue @Immutable @@ -296,6 +367,7 @@ public abstract class SampledSpanStore { * @throws NullPointerException if {@code spanName} is {@code null}. * @throws IllegalArgumentException if {@code maxSpansToReturn} or {@code latencyLowerNs} or * {@code latencyUpperNs} are negative. + * @since 0.5 */ public static LatencyFilter create( String spanName, long latencyLowerNs, long latencyUpperNs, int maxSpansToReturn) { @@ -310,6 +382,7 @@ public abstract class SampledSpanStore { * Returns the span name used by this filter. * * @return the span name used by this filter. + * @since 0.5 */ public abstract String getSpanName(); @@ -317,6 +390,7 @@ public abstract class SampledSpanStore { * Returns the latency lower bound of this bucket (inclusive). * * @return the latency lower bound of this bucket. + * @since 0.5 */ public abstract long getLatencyLowerNs(); @@ -324,6 +398,7 @@ public abstract class SampledSpanStore { * Returns the latency upper bound of this bucket (exclusive). * * @return the latency upper bound of this bucket. + * @since 0.5 */ public abstract long getLatencyUpperNs(); @@ -331,6 +406,7 @@ public abstract class SampledSpanStore { * Returns the maximum number of spans to be returned. {@code 0} means all. * * @return the maximum number of spans to be returned. + * @since 0.5 */ public abstract int getMaxSpansToReturn(); } @@ -338,6 +414,8 @@ public abstract class SampledSpanStore { /** * Filter for error based sampled spans. Used to filter results returned by the {@link * #getErrorSampledSpans(ErrorFilter)} request. + * + * @since 0.5 */ @AutoValue @Immutable @@ -362,6 +440,7 @@ public abstract class SampledSpanStore { * @throws NullPointerException if {@code spanName} is {@code null}. * @throws IllegalArgumentException if {@code canonicalCode} is {@link CanonicalCode#OK} or * {@code maxSpansToReturn} is negative. + * @since 0.5 */ public static ErrorFilter create( String spanName, @Nullable CanonicalCode canonicalCode, int maxSpansToReturn) { @@ -376,6 +455,7 @@ public abstract class SampledSpanStore { * Returns the span name used by this filter. * * @return the span name used by this filter. + * @since 0.5 */ public abstract String getSpanName(); @@ -384,6 +464,7 @@ public abstract class SampledSpanStore { * CanonicalCode#OK}. If {@code null} then all errors match. * * @return the canonical code used by this filter. + * @since 0.5 */ @Nullable public abstract CanonicalCode getCanonicalCode(); @@ -393,6 +474,7 @@ public abstract class SampledSpanStore { * {@code SpanData}. {@code 0} means all. * * @return the maximum number of spans to be returned. + * @since 0.5 */ public abstract int getMaxSpansToReturn(); } diff --git a/api/src/main/java/io/opencensus/trace/export/SpanData.java b/api/src/main/java/io/opencensus/trace/export/SpanData.java index 498c142e..546b65b6 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanData.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanData.java @@ -40,7 +40,11 @@ import javax.annotation.concurrent.Immutable; import org.checkerframework.dataflow.qual.Deterministic; */ -/** Immutable representation of all data collected by the {@link Span} class. */ +/** + * Immutable representation of all data collected by the {@link Span} class. + * + * @since 0.5 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -68,6 +72,7 @@ public abstract class SpanData { * @param endTimestamp the end {@code Timestamp} of the {@code Span}. {@code null} if the {@code * Span} is still active. * @return a new immutable {@code SpanData}. + * @since 0.5 */ public static SpanData create( SpanContext context, @@ -101,6 +106,7 @@ public abstract class SpanData { * Returns the {@code SpanContext} associated with this {@code Span}. * * @return the {@code SpanContext} associated with this {@code Span}. + * @since 0.5 */ public abstract SpanContext getContext(); @@ -108,6 +114,7 @@ public abstract class SpanData { * Returns the parent {@code SpanId} or {@code null} if the {@code Span} is a root {@code Span}. * * @return the parent {@code SpanId} or {@code null} if the {@code Span} is a root {@code Span}. + * @since 0.5 */ @Nullable /*@Deterministic*/ @@ -119,6 +126,7 @@ public abstract class SpanData { * * @return {@code true} if the parent is on a different process. {@code null} if this is a root * span. + * @since 0.5 */ @Nullable public abstract Boolean getHasRemoteParent(); @@ -127,6 +135,7 @@ public abstract class SpanData { * Returns the name of this {@code Span}. * * @return the name of this {@code Span}. + * @since 0.5 */ public abstract String getName(); @@ -134,6 +143,7 @@ public abstract class SpanData { * Returns the start {@code Timestamp} of this {@code Span}. * * @return the start {@code Timestamp} of this {@code Span}. + * @since 0.5 */ public abstract Timestamp getStartTimestamp(); @@ -141,6 +151,7 @@ public abstract class SpanData { * Returns the attributes recorded for this {@code Span}. * * @return the attributes recorded for this {@code Span}. + * @since 0.5 */ public abstract Attributes getAttributes(); @@ -148,6 +159,7 @@ public abstract class SpanData { * Returns the annotations recorded for this {@code Span}. * * @return the annotations recorded for this {@code Span}. + * @since 0.5 */ public abstract TimedEvents getAnnotations(); @@ -155,6 +167,7 @@ public abstract class SpanData { * Returns network events recorded for this {@code Span}. * * @return network events recorded for this {@code Span}. + * @since 0.5 */ public abstract TimedEvents getNetworkEvents(); @@ -162,6 +175,7 @@ public abstract class SpanData { * Returns links recorded for this {@code Span}. * * @return links recorded for this {@code Span}. + * @since 0.5 */ public abstract Links getLinks(); @@ -172,6 +186,7 @@ public abstract class SpanData { *

    This information is not always available. * * @return the number of child spans that were generated while the {@code Span} was running. + * @since 0.5 */ @Nullable public abstract Integer getChildSpanCount(); @@ -180,6 +195,7 @@ public abstract class SpanData { * Returns the {@code Status} or {@code null} if {@code Span} is still active. * * @return the {@code Status} or {@code null} if {@code Span} is still active. + * @since 0.5 */ @Nullable /*@Deterministic*/ @@ -189,6 +205,7 @@ public abstract class SpanData { * Returns the end {@code Timestamp} or {@code null} if the {@code Span} is still active. * * @return the end {@code Timestamp} or {@code null} if the {@code Span} is still active. + * @since 0.5 */ @Nullable /*@Deterministic*/ @@ -200,6 +217,7 @@ public abstract class SpanData { * A timed event representation. * * @param the type of value that is timed. + * @since 0.5 */ @Immutable @AutoValue @@ -214,6 +232,7 @@ public abstract class SpanData { * @param event the event. * @param the type of value that is timed. * @return a new immutable {@code TimedEvent} + * @since 0.5 */ public static TimedEvent create(Timestamp timestamp, T event) { return new AutoValue_SpanData_TimedEvent(timestamp, event); @@ -223,6 +242,7 @@ public abstract class SpanData { * Returns the {@code Timestamp} of this event. * * @return the {@code Timestamp} of this event. + * @since 0.5 */ public abstract Timestamp getTimestamp(); @@ -230,6 +250,7 @@ public abstract class SpanData { * Returns the event. * * @return the event. + * @since 0.5 */ /*@Deterministic*/ public abstract T getEvent(); @@ -241,6 +262,7 @@ public abstract class SpanData { * A list of timed events and the number of dropped events representation. * * @param the type of value that is timed. + * @since 0.5 */ @Immutable @AutoValue @@ -255,6 +277,7 @@ public abstract class SpanData { * @param droppedEventsCount the number of dropped events. * @param the type of value that is timed. * @return a new immutable {@code TimedEvents} + * @since 0.5 */ public static TimedEvents create(List> events, int droppedEventsCount) { return new AutoValue_SpanData_TimedEvents( @@ -267,6 +290,7 @@ public abstract class SpanData { * Returns the list of events. * * @return the list of events. + * @since 0.5 */ public abstract List> getEvents(); @@ -274,13 +298,18 @@ public abstract class SpanData { * Returns the number of dropped events. * * @return the number of dropped events. + * @since 0.5 */ public abstract int getDroppedEventsCount(); TimedEvents() {} } - /** A set of attributes and the number of dropped attributes representation. */ + /** + * A set of attributes and the number of dropped attributes representation. + * + * @since 0.5 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -293,6 +322,7 @@ public abstract class SpanData { * @param attributeMap the set of attributes. * @param droppedAttributesCount the number of dropped attributes. * @return a new immutable {@code Attributes}. + * @since 0.5 */ public static Attributes create( Map attributeMap, int droppedAttributesCount) { @@ -308,6 +338,7 @@ public abstract class SpanData { * Returns the set of attributes. * * @return the set of attributes. + * @since 0.5 */ public abstract Map getAttributeMap(); @@ -315,13 +346,18 @@ public abstract class SpanData { * Returns the number of dropped attributes. * * @return the number of dropped attributes. + * @since 0.5 */ public abstract int getDroppedAttributesCount(); Attributes() {} } - /** A list of links and the number of dropped links representation. */ + /** + * A list of links and the number of dropped links representation. + * + * @since 0.5 + */ @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -334,6 +370,7 @@ public abstract class SpanData { * @param links the list of links. * @param droppedLinksCount the number of dropped links. * @return a new immutable {@code Links}. + * @since 0.5 */ public static Links create(List links, int droppedLinksCount) { return new AutoValue_SpanData_Links( @@ -345,6 +382,7 @@ public abstract class SpanData { * Returns the list of links. * * @return the list of links. + * @since 0.5 */ public abstract List getLinks(); @@ -352,6 +390,7 @@ public abstract class SpanData { * Returns the number of dropped links. * * @return the number of dropped links. + * @since 0.5 */ public abstract int getDroppedLinksCount(); diff --git a/api/src/main/java/io/opencensus/trace/export/SpanExporter.java b/api/src/main/java/io/opencensus/trace/export/SpanExporter.java index e872904f..73ac5265 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanExporter.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanExporter.java @@ -24,6 +24,8 @@ import javax.annotation.concurrent.ThreadSafe; /** * A service that is used by the library to export {@code SpanData} for all the spans that are part * of a distributed sampled trace (see {@link TraceOptions#isSampled()}). + * + * @since 0.5 */ @ThreadSafe public abstract class SpanExporter { @@ -33,6 +35,7 @@ public abstract class SpanExporter { * Returns the no-op implementation of the {@code ExportComponent}. * * @return the no-op implementation of the {@code ExportComponent}. + * @since 0.5 */ public static SpanExporter getNoopSpanExporter() { return NOOP_SPAN_EXPORTER; @@ -44,6 +47,7 @@ public abstract class SpanExporter { * * @param name the name of the service handler. Must be unique for each service. * @param handler the service handler that is called for each ended sampled span. + * @since 0.5 */ public abstract void registerHandler(String name, Handler handler); @@ -51,6 +55,7 @@ public abstract class SpanExporter { * Unregisters the service handler with the provided name. * * @param name the name of the service handler that will be unregistered. + * @since 0.5 */ public abstract void unregisterHandler(String name); @@ -60,6 +65,8 @@ public abstract class SpanExporter { * *

    To export data this MUST be register to to the ExportComponent using {@link * #registerHandler(String, Handler)}. + * + * @since 0.5 */ public abstract static class Handler { @@ -73,6 +80,7 @@ public abstract class SpanExporter { * different thread if possible. * * @param spanDataList a list of {@code SpanData} objects to be exported. + * @since 0.5 */ public abstract void export(Collection spanDataList); } diff --git a/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java b/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java index f9c59142..e07afd12 100644 --- a/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java +++ b/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java @@ -60,6 +60,8 @@ import java.text.ParseException; * } * } * } + * + * @since 0.5 */ public abstract class BinaryFormat { static final NoopBinaryFormat NOOP_BINARY_FORMAT = new NoopBinaryFormat(); @@ -69,6 +71,7 @@ public abstract class BinaryFormat { * @param spanContext the {@code SpanContext} to serialize. * @return the serialized binary value. * @throws NullPointerException if the {@code spanContext} is {@code null}. + * @since 0.5 */ @Deprecated public byte[] toBinaryValue(SpanContext spanContext) { @@ -81,6 +84,7 @@ public abstract class BinaryFormat { * @param spanContext the {@code SpanContext} to serialize. * @return the serialized binary value. * @throws NullPointerException if the {@code spanContext} is {@code null}. + * @since 0.7 */ public byte[] toByteArray(SpanContext spanContext) { // Implementation must override this method. @@ -93,6 +97,7 @@ public abstract class BinaryFormat { * @return the parsed {@code SpanContext}. * @throws NullPointerException if the {@code input} is {@code null}. * @throws ParseException if the version is not supported or the input is invalid + * @since 0.5 */ @Deprecated public SpanContext fromBinaryValue(byte[] bytes) throws ParseException { @@ -110,6 +115,7 @@ public abstract class BinaryFormat { * @return the parsed {@code SpanContext}. * @throws NullPointerException if the {@code input} is {@code null}. * @throws SpanContextParseException if the version is not supported or the input is invalid + * @since 0.7 */ public SpanContext fromByteArray(byte[] bytes) throws SpanContextParseException { // Implementation must override this method. diff --git a/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java b/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java index a56c6d13..a90f0419 100644 --- a/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java +++ b/api/src/main/java/io/opencensus/trace/propagation/PropagationComponent.java @@ -22,6 +22,8 @@ import io.opencensus.common.ExperimentalApi; * Container class for all the supported propagation formats. Currently supports only Binary format * (see {@link BinaryFormat}) and B3 Text format (see {@link TextFormat}) but more formats will be * added. + * + * @since 0.5 */ public abstract class PropagationComponent { private static final PropagationComponent NOOP_PROPAGATION_COMPONENT = @@ -32,6 +34,7 @@ public abstract class PropagationComponent { * provided then no-op implementation will be used. * * @return the {@code BinaryFormat} implementation. + * @since 0.5 */ public abstract BinaryFormat getBinaryFormat(); @@ -50,6 +53,7 @@ public abstract class PropagationComponent { * Returns an instance that contains no-op implementations for all the instances. * * @return an instance that contains no-op implementations for all the instances. + * @since 0.5 */ public static PropagationComponent getNoopPropagationComponent() { return NOOP_PROPAGATION_COMPONENT; diff --git a/api/src/main/java/io/opencensus/trace/propagation/SpanContextParseException.java b/api/src/main/java/io/opencensus/trace/propagation/SpanContextParseException.java index fa7f2d4e..80d42af5 100644 --- a/api/src/main/java/io/opencensus/trace/propagation/SpanContextParseException.java +++ b/api/src/main/java/io/opencensus/trace/propagation/SpanContextParseException.java @@ -16,7 +16,11 @@ package io.opencensus.trace.propagation; -/** Exception thrown when a {@link io.opencensus.trace.SpanContext} cannot be parsed. */ +/** + * Exception thrown when a {@link io.opencensus.trace.SpanContext} cannot be parsed. + * + * @since 0.7 + */ public final class SpanContextParseException extends Exception { private static final long serialVersionUID = 0L; @@ -24,6 +28,7 @@ public final class SpanContextParseException extends Exception { * Constructs a new {@code SpanContextParseException} with the given message. * * @param message a message describing the parse error. + * @since 0.7 */ public SpanContextParseException(String message) { super(message); @@ -34,6 +39,7 @@ public final class SpanContextParseException extends Exception { * * @param message a message describing the parse error. * @param cause the cause of the parse error. + * @since 0.7 */ public SpanContextParseException(String message, Throwable cause) { super(message, cause); diff --git a/api/src/main/java/io/opencensus/trace/propagation/TextFormat.java b/api/src/main/java/io/opencensus/trace/propagation/TextFormat.java index 25880917..eaa7bf00 100644 --- a/api/src/main/java/io/opencensus/trace/propagation/TextFormat.java +++ b/api/src/main/java/io/opencensus/trace/propagation/TextFormat.java @@ -73,6 +73,8 @@ import javax.annotation.Nullable; * span.end() * } * } + * + * @since 0.11 */ @ExperimentalApi public abstract class TextFormat { @@ -85,6 +87,8 @@ public abstract class TextFormat { *

    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. + * + * @since 0.11 */ // The use cases of this are: // * allow pre-allocation of fields, especially in systems like gRPC Metadata @@ -97,6 +101,7 @@ public abstract class TextFormat { * @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. + * @since 0.11 */ public abstract void inject(SpanContext spanContext, C carrier, Setter setter); @@ -107,6 +112,7 @@ public abstract class TextFormat { * allocations. * * @param carrier of propagation fields, such as an http request + * @since 0.11 */ public abstract static class Setter { @@ -119,6 +125,7 @@ public abstract class TextFormat { * @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. + * @since 0.11 */ public abstract void put(C carrier, String key, String value); } @@ -129,6 +136,7 @@ public abstract class TextFormat { * @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 + * @since 0.11 */ public abstract SpanContext extract(C carrier, Getter getter) throws SpanContextParseException; @@ -140,6 +148,7 @@ public abstract class TextFormat { * allocations. * * @param carrier of propagation fields, such as an http request + * @since 0.11 */ public abstract static class Getter { @@ -149,6 +158,7 @@ public abstract class TextFormat { * @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}. + * @since 0.11 */ @Nullable public abstract String get(C carrier, String key); diff --git a/api/src/main/java/io/opencensus/trace/samplers/Samplers.java b/api/src/main/java/io/opencensus/trace/samplers/Samplers.java index 3d33a7f1..c10610a0 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/Samplers.java +++ b/api/src/main/java/io/opencensus/trace/samplers/Samplers.java @@ -19,7 +19,11 @@ package io.opencensus.trace.samplers; import io.opencensus.trace.Sampler; import io.opencensus.trace.Span; -/** Static class to access a set of pre-defined {@link Sampler Samplers}. */ +/** + * Static class to access a set of pre-defined {@link Sampler Samplers}. + * + * @since 0.5 + */ public final class Samplers { private static final Sampler ALWAYS_SAMPLE = new AlwaysSampleSampler(); private static final Sampler NEVER_SAMPLE = new NeverSampleSampler(); @@ -31,6 +35,7 @@ public final class Samplers { * Returns a {@link Sampler} that always makes a "yes" decision on {@link Span} sampling. * * @return a {@code Sampler} that always makes a "yes" decision on {@code Span} sampling. + * @since 0.5 */ public static Sampler alwaysSample() { return ALWAYS_SAMPLE; @@ -40,6 +45,7 @@ public final class Samplers { * Returns a {@link Sampler} that always makes a "no" decision on {@link Span} sampling. * * @return a {@code Sampler} that always makes a "no" decision on {@code Span} sampling. + * @since 0.5 */ public static Sampler neverSample() { return NEVER_SAMPLE; @@ -51,6 +57,7 @@ public final class Samplers { * @param probability The desired probability of sampling. Must be within [0.0, 1.0]. * @return a {@code Sampler} that makes a "yes" decision with a given probability. * @throws IllegalArgumentException if {@code probability} is out of range + * @since 0.5 */ public static Sampler probabilitySampler(double probability) { return ProbabilitySampler.create(probability); diff --git a/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java b/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java index cf0d2a65..f7905c25 100644 --- a/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java +++ b/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java @@ -24,11 +24,17 @@ import io.opencensus.trace.Span; * *

    Users must interact with the current Context via the public APIs in {@link * io.opencensus.trace.Tracer} and avoid usages of the {@link #CONTEXT_SPAN_KEY} directly. + * + * @since 0.5 */ public final class ContextUtils { // No instance of this class. private ContextUtils() {} - /** The {@link io.grpc.Context.Key} used to interact with {@link io.grpc.Context}. */ + /** + * The {@link io.grpc.Context.Key} used to interact with {@link io.grpc.Context}. + * + * @since 0.5 + */ public static final Context.Key CONTEXT_SPAN_KEY = Context.key("opencensus-trace-span-key"); } -- cgit v1.2.3 From 2ac619dc282613ced7635c15b18b3fbbb89312a5 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Thu, 15 Feb 2018 09:16:57 -0800 Subject: Add Nullable annotation to tag values. (#998) --- api/src/main/java/io/opencensus/stats/ViewData.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/ViewData.java b/api/src/main/java/io/opencensus/stats/ViewData.java index be06d28f..951afb2e 100644 --- a/api/src/main/java/io/opencensus/stats/ViewData.java +++ b/api/src/main/java/io/opencensus/stats/ViewData.java @@ -75,7 +75,7 @@ public abstract class ViewData { * * @since 0.8 */ - public abstract Map, AggregationData> getAggregationMap(); + public abstract Map, AggregationData> getAggregationMap(); /** * Returns the {@link AggregationWindowData} associated with this {@link ViewData}. @@ -99,14 +99,15 @@ public abstract class ViewData { */ public static ViewData create( View view, - Map, ? extends AggregationData> map, + Map, ? extends AggregationData> map, final AggregationWindowData windowData) { checkWindow(view.getWindow(), windowData); Map, AggregationData> deepCopy = Maps.newHashMap(); for (Entry, ? extends AggregationData> entry : map.entrySet()) { checkAggregation(view.getAggregation(), entry.getValue(), view.getMeasure()); deepCopy.put( - Collections.unmodifiableList(new ArrayList(entry.getKey())), entry.getValue()); + Collections.unmodifiableList(new ArrayList(entry.getKey())), + entry.getValue()); } return new AutoValue_ViewData(view, Collections.unmodifiableMap(deepCopy), windowData); } -- cgit v1.2.3 From 131b6f062a68d91b4d7a06d1edc25d8e856b6a21 Mon Sep 17 00:00:00 2001 From: Hailong Wen Date: Fri, 16 Feb 2018 15:09:17 +0800 Subject: Add MessageEvent and deprecate NetworkEvent. (closes #858) (#894) --- .../opencensus/internal/BaseMessageEventUtil.java | 80 +++++++++++ .../java/io/opencensus/trace/BaseMessageEvent.java | 37 +++++ .../main/java/io/opencensus/trace/BlankSpan.java | 5 + .../java/io/opencensus/trace/MessageEvent.java | 154 +++++++++++++++++++++ .../java/io/opencensus/trace/NetworkEvent.java | 7 +- api/src/main/java/io/opencensus/trace/Span.java | 24 +++- .../io/opencensus/trace/config/TraceParams.java | 47 +++++-- .../java/io/opencensus/trace/export/SpanData.java | 56 +++++++- .../internal/BaseMessageEventUtilTest.java | 71 ++++++++++ .../java/io/opencensus/trace/BlankSpanTest.java | 1 + .../java/io/opencensus/trace/MessageEventTest.java | 84 +++++++++++ .../test/java/io/opencensus/trace/NoopSpan.java | 3 + .../test/java/io/opencensus/trace/SpanTest.java | 18 +++ .../opencensus/trace/config/TraceConfigTest.java | 1 + .../opencensus/trace/config/TraceParamsTest.java | 19 ++- .../io/opencensus/trace/export/SpanDataTest.java | 59 +++++++- 16 files changed, 642 insertions(+), 24 deletions(-) create mode 100644 api/src/main/java/io/opencensus/internal/BaseMessageEventUtil.java create mode 100644 api/src/main/java/io/opencensus/trace/BaseMessageEvent.java create mode 100644 api/src/main/java/io/opencensus/trace/MessageEvent.java create mode 100644 api/src/test/java/io/opencensus/internal/BaseMessageEventUtilTest.java create mode 100644 api/src/test/java/io/opencensus/trace/MessageEventTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/BaseMessageEventUtil.java b/api/src/main/java/io/opencensus/internal/BaseMessageEventUtil.java new file mode 100644 index 00000000..56ec3301 --- /dev/null +++ b/api/src/main/java/io/opencensus/internal/BaseMessageEventUtil.java @@ -0,0 +1,80 @@ +/* + * Copyright 2018, 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.internal; + +import static com.google.common.base.Preconditions.checkNotNull; + +import io.opencensus.trace.MessageEvent; + +/** + * Helper class to convert/cast between for {@link MessageEvent} and {@link NetworkEvent}. + * + * @since 0.12 + */ +@SuppressWarnings("deprecation") +public final class BaseMessageEventUtil { + /** + * Cast or convert a {@link io.opencensus.trace.BaseMessageEvent} to {@link MessageEvent}. + * + *

    Warning: if the input is a {@code io.opencensus.trace.NetworkEvent} and contains {@code + * kernelTimestamp} information, this information will be dropped. + * + * @param event the {@code BaseMessageEvent} that is being cast or converted. + * @return a {@code MessageEvent} representation of the input. + */ + public static MessageEvent asMessageEvent(io.opencensus.trace.BaseMessageEvent event) { + checkNotNull(event); + if (event instanceof MessageEvent) { + return (MessageEvent) event; + } + io.opencensus.trace.NetworkEvent networkEvent = (io.opencensus.trace.NetworkEvent) event; + MessageEvent.Type type = + (networkEvent.getType() == io.opencensus.trace.NetworkEvent.Type.RECV) + ? MessageEvent.Type.RECEIVED + : MessageEvent.Type.SENT; + return MessageEvent.builder(type, networkEvent.getMessageId()) + .setUncompressedMessageSize(networkEvent.getUncompressedMessageSize()) + .setCompressedMessageSize(networkEvent.getCompressedMessageSize()) + .build(); + } + + /** + * Cast or convert a {@link io.opencensus.trace.BaseMessageEvent} to {@link + * io.opencensus.trace.NetworkEvent}. + * + * @param event the {@code BaseMessageEvent} that is being cast or converted. + * @return a {@code io.opencensus.trace.NetworkEvent} representation of the input. + */ + public static io.opencensus.trace.NetworkEvent asNetworkEvent( + io.opencensus.trace.BaseMessageEvent event) { + checkNotNull(event); + if (event instanceof io.opencensus.trace.NetworkEvent) { + return (io.opencensus.trace.NetworkEvent) event; + } + MessageEvent messageEvent = (MessageEvent) event; + io.opencensus.trace.NetworkEvent.Type type = + (messageEvent.getType() == MessageEvent.Type.RECEIVED) + ? io.opencensus.trace.NetworkEvent.Type.RECV + : io.opencensus.trace.NetworkEvent.Type.SENT; + return io.opencensus.trace.NetworkEvent.builder(type, messageEvent.getMessageId()) + .setUncompressedMessageSize(messageEvent.getUncompressedMessageSize()) + .setCompressedMessageSize(messageEvent.getCompressedMessageSize()) + .build(); + } + + private BaseMessageEventUtil() {} +} diff --git a/api/src/main/java/io/opencensus/trace/BaseMessageEvent.java b/api/src/main/java/io/opencensus/trace/BaseMessageEvent.java new file mode 100644 index 00000000..5ad961f6 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/BaseMessageEvent.java @@ -0,0 +1,37 @@ +/* + * Copyright 2018, 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; + +/** + * Superclass for {@link MessageEvent} and {@link NetworkEvent} to resolve API backward + * compatibility issue. + * + *

    {@code SpanData.create} can't be overloaded with parameter types that differ only in the type + * of the TimedEvent, because the signatures are the same after generic type erasure. {@code + * BaseMessageEvent} allows the same method to accept both {@code TimedEvents} and + * {@code TimedEvents}. + * + *

    This class should only be extended by {@code NetworkEvent} and {@code MessageEvent}. + * + * @deprecated This class is for internal use only. + * @since 0.12 + */ +@Deprecated +public abstract class BaseMessageEvent { + // package protected to avoid users to extend it. + BaseMessageEvent() {} +} diff --git a/api/src/main/java/io/opencensus/trace/BlankSpan.java b/api/src/main/java/io/opencensus/trace/BlankSpan.java index 0f11a034..641bad7e 100644 --- a/api/src/main/java/io/opencensus/trace/BlankSpan.java +++ b/api/src/main/java/io/opencensus/trace/BlankSpan.java @@ -58,8 +58,13 @@ public final class BlankSpan extends Span { /** No-op implementation of the {@link Span#addNetworkEvent(NetworkEvent)} method. */ @Override + @Deprecated public void addNetworkEvent(NetworkEvent networkEvent) {} + /** No-op implementation of the {@link Span#addMessageEvent(MessageEvent)} method. */ + @Override + public void addMessageEvent(MessageEvent messageEvent) {} + /** No-op implementation of the {@link Span#addLink(Link)} method. */ @Override public void addLink(Link link) {} diff --git a/api/src/main/java/io/opencensus/trace/MessageEvent.java b/api/src/main/java/io/opencensus/trace/MessageEvent.java new file mode 100644 index 00000000..49a4673c --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/MessageEvent.java @@ -0,0 +1,154 @@ +/* + * Copyright 2018, 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; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.auto.value.AutoValue; +import javax.annotation.concurrent.Immutable; + +/** + * A class that represents a generic messaging event. This class can represent messaging happened in + * any layer, especially higher application layer. Thus, it can be used when recording events in + * pipeline works, in-process bidirectional streams and batch processing. + * + *

    It requires a {@link Type type} and a message id that serves to uniquely identify each + * message. It can optionally have information about the message size. + * + * @since 0.12 + */ +@Immutable +@AutoValue +// Suppress Checker Framework warning about missing @Nullable in generated equals method. +@AutoValue.CopyAnnotations +@SuppressWarnings({"nullness", "deprecation"}) +public abstract class MessageEvent extends BaseMessageEvent { + /** + * Available types for a {@code MessageEvent}. + * + * @since 0.12 + */ + public enum Type { + /** + * When the message was sent. + * + * @since 0.12 + */ + SENT, + /** + * When the message was received. + * + * @since 0.12 + */ + RECEIVED, + } + + /** + * Returns a new {@link Builder} with default values. + * + * @param type designates whether this is a send or receive message. + * @param messageId serves to uniquely identify each message. + * @return a new {@code Builder} with default values. + * @throws NullPointerException if {@code type} is {@code null}. + * @since 0.12 + */ + public static Builder builder(Type type, long messageId) { + return new AutoValue_MessageEvent.Builder() + .setType(checkNotNull(type, "type")) + .setMessageId(messageId) + // We need to set a value for the message size because the autovalue requires all + // primitives to be initialized. + .setUncompressedMessageSize(0) + .setCompressedMessageSize(0); + } + + /** + * Returns the type of the {@code MessageEvent}. + * + * @return the type of the {@code MessageEvent}. + * @since 0.12 + */ + public abstract Type getType(); + + /** + * Returns the message id argument that serves to uniquely identify each message. + * + * @return the message id of the {@code MessageEvent}. + * @since 0.12 + */ + public abstract long getMessageId(); + + /** + * Returns the uncompressed size in bytes of the {@code MessageEvent}. + * + * @return the uncompressed size in bytes of the {@code MessageEvent}. + * @since 0.12 + */ + public abstract long getUncompressedMessageSize(); + + /** + * Returns the compressed size in bytes of the {@code MessageEvent}. + * + * @return the compressed size in bytes of the {@code MessageEvent}. + * @since 0.12 + */ + public abstract long getCompressedMessageSize(); + + /** + * Builder class for {@link MessageEvent}. + * + * @since 0.12 + */ + @AutoValue.Builder + public abstract static class Builder { + // Package protected methods because these values are mandatory and set only in the + // MessageEvent#builder() function. + abstract Builder setType(Type type); + + abstract Builder setMessageId(long messageId); + + /** + * Sets the uncompressed message size. + * + * @param uncompressedMessageSize represents the uncompressed size in bytes of this message. + * @return this. + * @since 0.12 + */ + public abstract Builder setUncompressedMessageSize(long uncompressedMessageSize); + + /** + * Sets the compressed message size. + * + * @param compressedMessageSize represents the compressed size in bytes of this message. + * @return this. + * @since 0.12 + */ + public abstract Builder setCompressedMessageSize(long compressedMessageSize); + + /** + * Builds and returns a {@code MessageEvent} with the desired values. + * + * @return a {@code MessageEvent} with the desired values. + * @since 0.12 + */ + public abstract MessageEvent build(); + + Builder() {} + } + + MessageEvent() {} +} diff --git a/api/src/main/java/io/opencensus/trace/NetworkEvent.java b/api/src/main/java/io/opencensus/trace/NetworkEvent.java index a8dfdb70..1c8fe393 100644 --- a/api/src/main/java/io/opencensus/trace/NetworkEvent.java +++ b/api/src/main/java/io/opencensus/trace/NetworkEvent.java @@ -28,6 +28,7 @@ import javax.annotation.concurrent.Immutable; * serves to uniquely identify each network message. It can optionally can have information about * the kernel time and message size. * + * @deprecated Use {@link MessageEvent}. * @since 0.5 */ @Immutable @@ -35,7 +36,8 @@ import javax.annotation.concurrent.Immutable; // Suppress Checker Framework warning about missing @Nullable in generated equals method. @AutoValue.CopyAnnotations @SuppressWarnings("nullness") -public abstract class NetworkEvent { +@Deprecated +public abstract class NetworkEvent extends io.opencensus.trace.BaseMessageEvent { /** * Available types for a {@code NetworkEvent}. * @@ -131,9 +133,12 @@ public abstract class NetworkEvent { /** * Builder class for {@link NetworkEvent}. * + * @deprecated {@link NetworkEvent} is deprecated. Please use {@link MessageEvent} and its builder + * {@link MessageEvent.Builder}. * @since 0.5 */ @AutoValue.Builder + @Deprecated public abstract static class Builder { // Package protected methods because these values are mandatory and set only in the // NetworkEvent#builder() function. diff --git a/api/src/main/java/io/opencensus/trace/Span.java b/api/src/main/java/io/opencensus/trace/Span.java index 29673930..ae0e9b4b 100644 --- a/api/src/main/java/io/opencensus/trace/Span.java +++ b/api/src/main/java/io/opencensus/trace/Span.java @@ -19,6 +19,7 @@ package io.opencensus.trace; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import io.opencensus.internal.BaseMessageEventUtil; import java.util.Collections; import java.util.EnumSet; import java.util.Map; @@ -159,9 +160,30 @@ public abstract class Span { * higher level applications. * * @param networkEvent the network event to add. + * @deprecated Use {@link #addMessageEvent}. * @since 0.5 */ - public abstract void addNetworkEvent(NetworkEvent networkEvent); + @Deprecated + public void addNetworkEvent(NetworkEvent networkEvent) { + addMessageEvent(BaseMessageEventUtil.asMessageEvent(networkEvent)); + } + + /** + * Adds a MessageEvent to the {@code Span}. + * + *

    This function can be used by higher level applications to record messaging event. + * + *

    This method should always be overridden by users whose API versions are larger or equal to + * {@code 0.12}. + * + * @param messageEvent the message to add. + * @since 0.12 + */ + public void addMessageEvent(MessageEvent messageEvent) { + // Default implementation by invoking addNetworkEvent() so that any existing derived classes, + // including implementation and the mocked ones, do not need to override this method explicitly. + addNetworkEvent(BaseMessageEventUtil.asNetworkEvent(messageEvent)); + } /** * Adds a {@link Link} to the {@code Span}. diff --git a/api/src/main/java/io/opencensus/trace/config/TraceParams.java b/api/src/main/java/io/opencensus/trace/config/TraceParams.java index 17dbbb9d..6c2ee7ff 100644 --- a/api/src/main/java/io/opencensus/trace/config/TraceParams.java +++ b/api/src/main/java/io/opencensus/trace/config/TraceParams.java @@ -21,7 +21,7 @@ import static com.google.common.base.Preconditions.checkArgument; import com.google.auto.value.AutoValue; import io.opencensus.trace.Annotation; import io.opencensus.trace.Link; -import io.opencensus.trace.NetworkEvent; +import io.opencensus.trace.MessageEvent; import io.opencensus.trace.Sampler; import io.opencensus.trace.Span; import io.opencensus.trace.samplers.Samplers; @@ -43,7 +43,7 @@ public abstract class TraceParams { private static final Sampler DEFAULT_SAMPLER = Samplers.probabilitySampler(DEFAULT_PROBABILITY); private static final int DEFAULT_SPAN_MAX_NUM_ATTRIBUTES = 32; private static final int DEFAULT_SPAN_MAX_NUM_ANNOTATIONS = 32; - private static final int DEFAULT_SPAN_MAX_NUM_NETWORK_EVENTS = 128; + private static final int DEFAULT_SPAN_MAX_NUM_MESSAGE_EVENTS = 128; private static final int DEFAULT_SPAN_MAX_NUM_LINKS = 128; /** @@ -56,7 +56,7 @@ public abstract class TraceParams { .setSampler(DEFAULT_SAMPLER) .setMaxNumberOfAttributes(DEFAULT_SPAN_MAX_NUM_ATTRIBUTES) .setMaxNumberOfAnnotations(DEFAULT_SPAN_MAX_NUM_ANNOTATIONS) - .setMaxNumberOfNetworkEvents(DEFAULT_SPAN_MAX_NUM_NETWORK_EVENTS) + .setMaxNumberOfMessageEvents(DEFAULT_SPAN_MAX_NUM_MESSAGE_EVENTS) .setMaxNumberOfLinks(DEFAULT_SPAN_MAX_NUM_LINKS) .build(); @@ -86,12 +86,25 @@ public abstract class TraceParams { public abstract int getMaxNumberOfAnnotations(); /** - * Returns the global default max number of {@link NetworkEvent} events per {@link Span}. + * Returns the global default max number of {@link MessageEvent} events per {@link Span}. + * + * @return the global default max number of {@code MessageEvent} events per {@code Span}. + * @since 0.12 + */ + public abstract int getMaxNumberOfMessageEvents(); + + /** + * Returns the global default max number of {@link io.opencensus.trace.NetworkEvent} events per + * {@link Span}. * * @return the global default max number of {@code NetworkEvent} events per {@code Span}. + * @deprecated Use {@link getMaxNumberOfMessageEvents}. * @since 0.5 */ - public abstract int getMaxNumberOfNetworkEvents(); + @Deprecated + public int getMaxNumberOfNetworkEvents() { + return getMaxNumberOfMessageEvents(); + } /** * Returns the global default max number of {@link Link} entries per {@link Span}. @@ -152,14 +165,30 @@ public abstract class TraceParams { public abstract Builder setMaxNumberOfAnnotations(int maxNumberOfAnnotations); /** - * Sets the global default max number of {@link NetworkEvent} events per {@link Span}. + * Sets the global default max number of {@link MessageEvent} events per {@link Span}. * - * @param maxNumberOfNetworkEvents the global default max number of {@link NetworkEvent} events + * @param maxNumberOfMessageEvents the global default max number of {@link MessageEvent} events * per {@link Span}. It must be positive otherwise {@link #build()} will throw an exception. + * @since 0.12 * @return this. + */ + public abstract Builder setMaxNumberOfMessageEvents(int maxNumberOfMessageEvents); + + /** + * Sets the global default max number of {@link io.opencensus.trace.NetworkEvent} events per + * {@link Span}. + * + * @param maxNumberOfNetworkEvents the global default max number of {@link + * io.opencensus.trace.NetworkEvent} events per {@link Span}. It must be positive otherwise + * {@link #build()} will throw an exception. + * @return this. + * @deprecated Use {@link setMaxNumberOfMessageEvents}. * @since 0.5 */ - public abstract Builder setMaxNumberOfNetworkEvents(int maxNumberOfNetworkEvents); + @Deprecated + public Builder setMaxNumberOfNetworkEvents(int maxNumberOfNetworkEvents) { + return setMaxNumberOfMessageEvents(maxNumberOfNetworkEvents); + } /** * Sets the global default max number of {@link Link} entries per {@link Span}. @@ -185,7 +214,7 @@ public abstract class TraceParams { TraceParams traceParams = autoBuild(); checkArgument(traceParams.getMaxNumberOfAttributes() > 0, "maxNumberOfAttributes"); checkArgument(traceParams.getMaxNumberOfAnnotations() > 0, "maxNumberOfAnnotations"); - checkArgument(traceParams.getMaxNumberOfNetworkEvents() > 0, "maxNumberOfNetworkEvents"); + checkArgument(traceParams.getMaxNumberOfMessageEvents() > 0, "maxNumberOfMessageEvents"); checkArgument(traceParams.getMaxNumberOfLinks() > 0, "maxNumberOfLinks"); return traceParams; } diff --git a/api/src/main/java/io/opencensus/trace/export/SpanData.java b/api/src/main/java/io/opencensus/trace/export/SpanData.java index 546b65b6..120c231a 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanData.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanData.java @@ -19,11 +19,13 @@ package io.opencensus.trace.export; import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; +import com.google.common.collect.Lists; import io.opencensus.common.Timestamp; +import io.opencensus.internal.BaseMessageEventUtil; import io.opencensus.trace.Annotation; import io.opencensus.trace.AttributeValue; import io.opencensus.trace.Link; -import io.opencensus.trace.NetworkEvent; +import io.opencensus.trace.MessageEvent; import io.opencensus.trace.Span; import io.opencensus.trace.SpanContext; import io.opencensus.trace.SpanId; @@ -64,7 +66,8 @@ public abstract class SpanData { * @param startTimestamp the start {@code Timestamp} of the {@code Span}. * @param attributes the attributes associated with the {@code Span}. * @param annotations the annotations associated with the {@code Span}. - * @param networkEvents the network events associated with the {@code Span}. + * @param messageOrNetworkEvents the message events (or network events for backward compatibility) + * associated with the {@code Span}. * @param links the links associated with the {@code Span}. * @param childSpanCount the number of child spans that were generated while the span was active. * @param status the {@code Status} of the {@code Span}. {@code null} if the {@code Span} is still @@ -74,6 +77,7 @@ public abstract class SpanData { * @return a new immutable {@code SpanData}. * @since 0.5 */ + @SuppressWarnings("deprecation") public static SpanData create( SpanContext context, @Nullable SpanId parentSpanId, @@ -82,11 +86,31 @@ public abstract class SpanData { Timestamp startTimestamp, Attributes attributes, TimedEvents annotations, - TimedEvents networkEvents, + TimedEvents messageOrNetworkEvents, Links links, @Nullable Integer childSpanCount, @Nullable Status status, @Nullable Timestamp endTimestamp) { + if (messageOrNetworkEvents == null) { + throw new NullPointerException("Null messageOrNetworkEvents"); + } + List> messageEventsList = Lists.newArrayList(); + for (TimedEvent timedEvent : + messageOrNetworkEvents.getEvents()) { + io.opencensus.trace.BaseMessageEvent event = timedEvent.getEvent(); + if (event instanceof MessageEvent) { + @SuppressWarnings("unchecked") + TimedEvent timedMessageEvent = (TimedEvent) timedEvent; + messageEventsList.add(timedMessageEvent); + } else { + messageEventsList.add( + TimedEvent.create( + timedEvent.getTimestamp(), BaseMessageEventUtil.asMessageEvent(event))); + } + } + TimedEvents messageEvents = + TimedEvents.create( + messageEventsList, messageOrNetworkEvents.getDroppedEventsCount()); return new AutoValue_SpanData( context, parentSpanId, @@ -95,7 +119,7 @@ public abstract class SpanData { startTimestamp, attributes, annotations, - networkEvents, + messageEvents, links, childSpanCount, status, @@ -167,9 +191,31 @@ public abstract class SpanData { * Returns network events recorded for this {@code Span}. * * @return network events recorded for this {@code Span}. + * @deprecated Use {@link #getMessageEvents}. * @since 0.5 */ - public abstract TimedEvents getNetworkEvents(); + @Deprecated + @SuppressWarnings({"deprecation"}) + public TimedEvents getNetworkEvents() { + TimedEvents timedEvents = getMessageEvents(); + List> networkEventsList = Lists.newArrayList(); + for (TimedEvent timedEvent : timedEvents.getEvents()) { + networkEventsList.add( + TimedEvent.create( + timedEvent.getTimestamp(), + BaseMessageEventUtil.asNetworkEvent(timedEvent.getEvent()))); + } + return TimedEvents.create( + networkEventsList, timedEvents.getDroppedEventsCount()); + } + + /** + * Returns message events recorded for this {@code Span}. + * + * @return message events recorded for this {@code Span}. + * @since 0.12 + */ + public abstract TimedEvents getMessageEvents(); /** * Returns links recorded for this {@code Span}. diff --git a/api/src/test/java/io/opencensus/internal/BaseMessageEventUtilTest.java b/api/src/test/java/io/opencensus/internal/BaseMessageEventUtilTest.java new file mode 100644 index 00000000..8de1b1c9 --- /dev/null +++ b/api/src/test/java/io/opencensus/internal/BaseMessageEventUtilTest.java @@ -0,0 +1,71 @@ +/* + * Copyright 2018, 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.internal; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.trace.MessageEvent; +import io.opencensus.trace.NetworkEvent; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link BaseMessageEventUtil}. */ +@RunWith(JUnit4.class) +public class BaseMessageEventUtilTest { + private static final long SENT_EVENT_ID = 12345L; + private static final long RECV_EVENT_ID = 67890L; + private static final long UNCOMPRESSED_SIZE = 100; + private static final long COMPRESSED_SIZE = 99; + + private static final MessageEvent SENT_MESSAGE_EVENT = + MessageEvent.builder(MessageEvent.Type.SENT, SENT_EVENT_ID) + .setUncompressedMessageSize(UNCOMPRESSED_SIZE) + .setCompressedMessageSize(COMPRESSED_SIZE) + .build(); + private static final MessageEvent RECV_MESSAGE_EVENT = + MessageEvent.builder(MessageEvent.Type.RECEIVED, RECV_EVENT_ID) + .setUncompressedMessageSize(UNCOMPRESSED_SIZE) + .setCompressedMessageSize(COMPRESSED_SIZE) + .build(); + private static final NetworkEvent SENT_NETWORK_EVENT = + NetworkEvent.builder(NetworkEvent.Type.SENT, SENT_EVENT_ID) + .setUncompressedMessageSize(UNCOMPRESSED_SIZE) + .setCompressedMessageSize(COMPRESSED_SIZE) + .build(); + private static final NetworkEvent RECV_NETWORK_EVENT = + NetworkEvent.builder(NetworkEvent.Type.RECV, RECV_EVENT_ID) + .setUncompressedMessageSize(UNCOMPRESSED_SIZE) + .setCompressedMessageSize(COMPRESSED_SIZE) + .build(); + + @Test + public void networkEventToMessageEvent() { + assertThat(BaseMessageEventUtil.asMessageEvent(SENT_NETWORK_EVENT)) + .isEqualTo(SENT_MESSAGE_EVENT); + assertThat(BaseMessageEventUtil.asMessageEvent(RECV_NETWORK_EVENT)) + .isEqualTo(RECV_MESSAGE_EVENT); + } + + @Test + public void messageEventToNetworkEvent() { + assertThat(BaseMessageEventUtil.asNetworkEvent(SENT_MESSAGE_EVENT)) + .isEqualTo(SENT_NETWORK_EVENT); + assertThat(BaseMessageEventUtil.asNetworkEvent(RECV_MESSAGE_EVENT)) + .isEqualTo(RECV_NETWORK_EVENT); + } +} diff --git a/api/src/test/java/io/opencensus/trace/BlankSpanTest.java b/api/src/test/java/io/opencensus/trace/BlankSpanTest.java index b9760c2f..185a5acd 100644 --- a/api/src/test/java/io/opencensus/trace/BlankSpanTest.java +++ b/api/src/test/java/io/opencensus/trace/BlankSpanTest.java @@ -53,6 +53,7 @@ public class BlankSpanTest { BlankSpan.INSTANCE.addAnnotation("MyAnnotation", multipleAttributes); BlankSpan.INSTANCE.addAnnotation(Annotation.fromDescription("MyAnnotation")); BlankSpan.INSTANCE.addNetworkEvent(NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).build()); + BlankSpan.INSTANCE.addMessageEvent(MessageEvent.builder(MessageEvent.Type.SENT, 1L).build()); BlankSpan.INSTANCE.addLink( Link.fromSpanContext(SpanContext.INVALID, Link.Type.CHILD_LINKED_SPAN)); BlankSpan.INSTANCE.setStatus(Status.OK); diff --git a/api/src/test/java/io/opencensus/trace/MessageEventTest.java b/api/src/test/java/io/opencensus/trace/MessageEventTest.java new file mode 100644 index 00000000..fde32fe6 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/MessageEventTest.java @@ -0,0 +1,84 @@ +/* + * Copyright 2018, 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; + +import static com.google.common.truth.Truth.assertThat; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link MessageEvent}. */ +@RunWith(JUnit4.class) +public class MessageEventTest { + @Test(expected = NullPointerException.class) + public void buildMessageEvent_NullType() { + MessageEvent.builder(null, 1L).build(); + } + + @Test + public void buildMessageEvent_WithRequiredFields() { + MessageEvent messageEvent = MessageEvent.builder(MessageEvent.Type.SENT, 1L).build(); + assertThat(messageEvent.getType()).isEqualTo(MessageEvent.Type.SENT); + assertThat(messageEvent.getMessageId()).isEqualTo(1L); + assertThat(messageEvent.getUncompressedMessageSize()).isEqualTo(0L); + } + + @Test + public void buildMessageEvent_WithUncompressedMessageSize() { + MessageEvent messageEvent = + MessageEvent.builder(MessageEvent.Type.SENT, 1L).setUncompressedMessageSize(123L).build(); + assertThat(messageEvent.getType()).isEqualTo(MessageEvent.Type.SENT); + assertThat(messageEvent.getMessageId()).isEqualTo(1L); + assertThat(messageEvent.getUncompressedMessageSize()).isEqualTo(123L); + } + + @Test + public void buildMessageEvent_WithCompressedMessageSize() { + MessageEvent messageEvent = + MessageEvent.builder(MessageEvent.Type.SENT, 1L).setCompressedMessageSize(123L).build(); + assertThat(messageEvent.getType()).isEqualTo(MessageEvent.Type.SENT); + assertThat(messageEvent.getMessageId()).isEqualTo(1L); + assertThat(messageEvent.getCompressedMessageSize()).isEqualTo(123L); + } + + @Test + public void buildMessageEvent_WithAllValues() { + MessageEvent messageEvent = + MessageEvent.builder(MessageEvent.Type.RECEIVED, 1L) + .setUncompressedMessageSize(123L) + .setCompressedMessageSize(63L) + .build(); + assertThat(messageEvent.getType()).isEqualTo(MessageEvent.Type.RECEIVED); + assertThat(messageEvent.getMessageId()).isEqualTo(1L); + assertThat(messageEvent.getUncompressedMessageSize()).isEqualTo(123L); + assertThat(messageEvent.getCompressedMessageSize()).isEqualTo(63L); + } + + @Test + public void messageEvent_ToString() { + MessageEvent messageEvent = + MessageEvent.builder(MessageEvent.Type.SENT, 1L) + .setUncompressedMessageSize(123L) + .setCompressedMessageSize(63L) + .build(); + assertThat(messageEvent.toString()).contains("type=SENT"); + assertThat(messageEvent.toString()).contains("messageId=1"); + assertThat(messageEvent.toString()).contains("compressedMessageSize=63"); + assertThat(messageEvent.toString()).contains("uncompressedMessageSize=123"); + } +} diff --git a/api/src/test/java/io/opencensus/trace/NoopSpan.java b/api/src/test/java/io/opencensus/trace/NoopSpan.java index 0217529d..7c8d9b7a 100644 --- a/api/src/test/java/io/opencensus/trace/NoopSpan.java +++ b/api/src/test/java/io/opencensus/trace/NoopSpan.java @@ -44,6 +44,9 @@ public class NoopSpan extends Span { @Override public void addNetworkEvent(NetworkEvent networkEvent) {} + @Override + public void addMessageEvent(MessageEvent messageEvent) {} + @Override public void addLink(Link link) {} diff --git a/api/src/test/java/io/opencensus/trace/SpanTest.java b/api/src/test/java/io/opencensus/trace/SpanTest.java index 327b9abe..f7546ca4 100644 --- a/api/src/test/java/io/opencensus/trace/SpanTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanTest.java @@ -98,4 +98,22 @@ public class SpanTest { span.end(); verify(span).end(same(EndSpanOptions.DEFAULT)); } + + @Test + public void addMessageEventDefaultImplementation() { + Span mockSpan = Mockito.mock(Span.class); + MessageEvent messageEvent = + MessageEvent.builder(MessageEvent.Type.SENT, 123) + .setUncompressedMessageSize(456) + .setCompressedMessageSize(789) + .build(); + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.SENT, 123) + .setUncompressedMessageSize(456) + .setCompressedMessageSize(789) + .build(); + Mockito.doCallRealMethod().when(mockSpan).addMessageEvent(messageEvent); + mockSpan.addMessageEvent(messageEvent); + verify(mockSpan).addNetworkEvent(eq(networkEvent)); + } } diff --git a/api/src/test/java/io/opencensus/trace/config/TraceConfigTest.java b/api/src/test/java/io/opencensus/trace/config/TraceConfigTest.java index ee80cab4..d48e0894 100644 --- a/api/src/test/java/io/opencensus/trace/config/TraceConfigTest.java +++ b/api/src/test/java/io/opencensus/trace/config/TraceConfigTest.java @@ -42,6 +42,7 @@ public class TraceConfigTest { .setMaxNumberOfAttributes(8) .setMaxNumberOfAnnotations(9) .setMaxNumberOfNetworkEvents(10) + .setMaxNumberOfMessageEvents(10) .setMaxNumberOfLinks(11) .build(); traceConfig.updateActiveTraceParams(traceParams); diff --git a/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java b/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java index 7ede0a29..6c216174 100644 --- a/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java +++ b/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java @@ -32,6 +32,7 @@ public class TraceParamsTest { assertThat(TraceParams.DEFAULT.getMaxNumberOfAttributes()).isEqualTo(32); assertThat(TraceParams.DEFAULT.getMaxNumberOfAnnotations()).isEqualTo(32); assertThat(TraceParams.DEFAULT.getMaxNumberOfNetworkEvents()).isEqualTo(128); + assertThat(TraceParams.DEFAULT.getMaxNumberOfMessageEvents()).isEqualTo(128); assertThat(TraceParams.DEFAULT.getMaxNumberOfLinks()).isEqualTo(128); } @@ -55,6 +56,11 @@ public class TraceParamsTest { TraceParams.DEFAULT.toBuilder().setMaxNumberOfNetworkEvents(0).build(); } + @Test(expected = IllegalArgumentException.class) + public void updateTraceParams_NonPositiveMaxNumberOfMessageEvents() { + TraceParams.DEFAULT.toBuilder().setMaxNumberOfMessageEvents(0).build(); + } + @Test(expected = IllegalArgumentException.class) public void updateTraceParams_NonPositiveMaxNumberOfLinks() { TraceParams.DEFAULT.toBuilder().setMaxNumberOfLinks(0).build(); @@ -68,13 +74,24 @@ public class TraceParamsTest { .setSampler(Samplers.alwaysSample()) .setMaxNumberOfAttributes(8) .setMaxNumberOfAnnotations(9) - .setMaxNumberOfNetworkEvents(10) + .setMaxNumberOfMessageEvents(10) .setMaxNumberOfLinks(11) .build(); assertThat(traceParams.getSampler()).isEqualTo(Samplers.alwaysSample()); assertThat(traceParams.getMaxNumberOfAttributes()).isEqualTo(8); assertThat(traceParams.getMaxNumberOfAnnotations()).isEqualTo(9); + // test maxNumberOfNetworkEvent can be set via maxNumberOfMessageEvent assertThat(traceParams.getMaxNumberOfNetworkEvents()).isEqualTo(10); + assertThat(traceParams.getMaxNumberOfMessageEvents()).isEqualTo(10); assertThat(traceParams.getMaxNumberOfLinks()).isEqualTo(11); } + + @Test + public void updateTraceParams_maxNumberOfNetworkEvents() { + TraceParams traceParams = + TraceParams.DEFAULT.toBuilder().setMaxNumberOfNetworkEvents(10).build(); + assertThat(traceParams.getMaxNumberOfNetworkEvents()).isEqualTo(10); + // test maxNumberOfMessageEvent can be set via maxNumberOfNetworkEvent + assertThat(traceParams.getMaxNumberOfMessageEvents()).isEqualTo(10); + } } diff --git a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java index 5c8097fa..399b35e0 100644 --- a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java +++ b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java @@ -24,6 +24,7 @@ import io.opencensus.trace.Annotation; import io.opencensus.trace.AttributeValue; import io.opencensus.trace.Link; import io.opencensus.trace.Link.Type; +import io.opencensus.trace.MessageEvent; import io.opencensus.trace.NetworkEvent; import io.opencensus.trace.SpanContext; import io.opencensus.trace.SpanId; @@ -60,6 +61,10 @@ public class SpanDataTest { NetworkEvent.builder(NetworkEvent.Type.RECV, 1).build(); private static final NetworkEvent sentNetworkEvent = NetworkEvent.builder(NetworkEvent.Type.SENT, 1).build(); + private static final MessageEvent recvMessageEvent = + MessageEvent.builder(MessageEvent.Type.RECEIVED, 1).build(); + private static final MessageEvent sentMessageEvent = + MessageEvent.builder(MessageEvent.Type.SENT, 1).build(); private static final Status status = Status.DEADLINE_EXCEEDED.withDescription("TooSlow"); private static final int CHILD_SPAN_COUNT = 13; private final Random random = new Random(1234); @@ -72,11 +77,14 @@ public class SpanDataTest { new ArrayList>(); private final List> networkEventsList = new ArrayList>(); + private final List> messageEventsList = + new ArrayList>(); private final List linksList = new ArrayList(); private Attributes attributes; private TimedEvents annotations; private TimedEvents networkEvents; + private TimedEvents messageEvents; private Links links; @Before @@ -90,12 +98,46 @@ public class SpanDataTest { networkEventsList.add(SpanData.TimedEvent.create(eventTimestamp1, recvNetworkEvent)); networkEventsList.add(SpanData.TimedEvent.create(eventTimestamp2, sentNetworkEvent)); networkEvents = TimedEvents.create(networkEventsList, 3); + messageEventsList.add(SpanData.TimedEvent.create(eventTimestamp1, recvMessageEvent)); + messageEventsList.add(SpanData.TimedEvent.create(eventTimestamp2, sentMessageEvent)); + messageEvents = TimedEvents.create(messageEventsList, 3); linksList.add(Link.fromSpanContext(spanContext, Type.CHILD_LINKED_SPAN)); links = Links.create(linksList, 0); } @Test public void spanData_AllValues() { + SpanData spanData = + SpanData.create( + spanContext, + parentSpanId, + true, + SPAN_NAME, + startTimestamp, + attributes, + annotations, + messageEvents, + links, + CHILD_SPAN_COUNT, + status, + endTimestamp); + assertThat(spanData.getContext()).isEqualTo(spanContext); + assertThat(spanData.getParentSpanId()).isEqualTo(parentSpanId); + assertThat(spanData.getHasRemoteParent()).isTrue(); + assertThat(spanData.getName()).isEqualTo(SPAN_NAME); + assertThat(spanData.getStartTimestamp()).isEqualTo(startTimestamp); + assertThat(spanData.getAttributes()).isEqualTo(attributes); + assertThat(spanData.getAnnotations()).isEqualTo(annotations); + assertThat(spanData.getNetworkEvents()).isEqualTo(networkEvents); + assertThat(spanData.getMessageEvents()).isEqualTo(messageEvents); + assertThat(spanData.getLinks()).isEqualTo(links); + assertThat(spanData.getChildSpanCount()).isEqualTo(CHILD_SPAN_COUNT); + assertThat(spanData.getStatus()).isEqualTo(status); + assertThat(spanData.getEndTimestamp()).isEqualTo(endTimestamp); + } + + @Test + public void spanData_Create_Compatibility() { SpanData spanData = SpanData.create( spanContext, @@ -118,6 +160,7 @@ public class SpanDataTest { assertThat(spanData.getAttributes()).isEqualTo(attributes); assertThat(spanData.getAnnotations()).isEqualTo(annotations); assertThat(spanData.getNetworkEvents()).isEqualTo(networkEvents); + assertThat(spanData.getMessageEvents()).isEqualTo(messageEvents); assertThat(spanData.getLinks()).isEqualTo(links); assertThat(spanData.getChildSpanCount()).isEqualTo(CHILD_SPAN_COUNT); assertThat(spanData.getStatus()).isEqualTo(status); @@ -135,7 +178,7 @@ public class SpanDataTest { startTimestamp, attributes, annotations, - networkEvents, + messageEvents, links, null, null, @@ -148,6 +191,7 @@ public class SpanDataTest { assertThat(spanData.getAttributes()).isEqualTo(attributes); assertThat(spanData.getAnnotations()).isEqualTo(annotations); assertThat(spanData.getNetworkEvents()).isEqualTo(networkEvents); + assertThat(spanData.getMessageEvents()).isEqualTo(messageEvents); assertThat(spanData.getLinks()).isEqualTo(links); assertThat(spanData.getChildSpanCount()).isNull(); assertThat(spanData.getStatus()).isNull(); @@ -165,7 +209,7 @@ public class SpanDataTest { startTimestamp, Attributes.create(Collections.emptyMap(), 0), TimedEvents.create(Collections.>emptyList(), 0), - TimedEvents.create(Collections.>emptyList(), 0), + TimedEvents.create(Collections.>emptyList(), 0), Links.create(Collections.emptyList(), 0), 0, status, @@ -178,6 +222,7 @@ public class SpanDataTest { assertThat(spanData.getAttributes().getAttributeMap().isEmpty()).isTrue(); assertThat(spanData.getAnnotations().getEvents().isEmpty()).isTrue(); assertThat(spanData.getNetworkEvents().getEvents().isEmpty()).isTrue(); + assertThat(spanData.getMessageEvents().getEvents().isEmpty()).isTrue(); assertThat(spanData.getLinks().getLinks().isEmpty()).isTrue(); assertThat(spanData.getChildSpanCount()).isEqualTo(0); assertThat(spanData.getStatus()).isEqualTo(status); @@ -195,7 +240,7 @@ public class SpanDataTest { startTimestamp, attributes, annotations, - networkEvents, + messageEvents, links, CHILD_SPAN_COUNT, status, @@ -209,7 +254,7 @@ public class SpanDataTest { startTimestamp, attributes, annotations, - networkEvents, + messageEvents, links, CHILD_SPAN_COUNT, status, @@ -223,7 +268,7 @@ public class SpanDataTest { startTimestamp, Attributes.create(Collections.emptyMap(), 0), TimedEvents.create(Collections.>emptyList(), 0), - TimedEvents.create(Collections.>emptyList(), 0), + TimedEvents.create(Collections.>emptyList(), 0), Links.create(Collections.emptyList(), 0), 0, status, @@ -245,7 +290,7 @@ public class SpanDataTest { startTimestamp, attributes, annotations, - networkEvents, + messageEvents, links, CHILD_SPAN_COUNT, status, @@ -257,7 +302,7 @@ public class SpanDataTest { assertThat(spanDataString).contains(startTimestamp.toString()); assertThat(spanDataString).contains(attributes.toString()); assertThat(spanDataString).contains(annotations.toString()); - assertThat(spanDataString).contains(networkEvents.toString()); + assertThat(spanDataString).contains(messageEvents.toString()); assertThat(spanDataString).contains(links.toString()); assertThat(spanDataString).contains(status.toString()); assertThat(spanDataString).contains(endTimestamp.toString()); -- cgit v1.2.3 From 0caef939f8fa6320da7297017416340f433830e4 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Fri, 16 Feb 2018 18:30:59 -0800 Subject: Start 0.13.0 development cycle (#1004) --- .../main/java/io/opencensus/common/OpenCensusLibraryInformation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java index fe908c1e..61a33bb4 100644 --- a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java +++ b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java @@ -29,7 +29,7 @@ public final class OpenCensusLibraryInformation { * * @since 0.8 */ - public static final String VERSION = "0.12.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION + public static final String VERSION = "0.13.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION private OpenCensusLibraryInformation() {} } -- cgit v1.2.3 From f0e9b541d93cc3df67310aa47d12729824c31d5f Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Wed, 21 Feb 2018 21:58:46 -0800 Subject: Add comments to boolean arguments to fix Error Prone warning (BooleanParameter). --- api/src/main/java/io/opencensus/stats/Stats.java | 8 ++++++-- api/src/main/java/io/opencensus/tags/Tags.java | 8 ++++++-- api/src/main/java/io/opencensus/trace/Tracing.java | 8 ++++++-- 3 files changed, 18 insertions(+), 6 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/Stats.java b/api/src/main/java/io/opencensus/stats/Stats.java index 4b7852ce..d7f77e34 100644 --- a/api/src/main/java/io/opencensus/stats/Stats.java +++ b/api/src/main/java/io/opencensus/stats/Stats.java @@ -94,7 +94,8 @@ public final class Stats { try { // Call Class.forName with literal string name of the class to help shading tools. return Provider.createInstance( - Class.forName("io.opencensus.impl.stats.StatsComponentImpl", true, classLoader), + Class.forName( + "io.opencensus.impl.stats.StatsComponentImpl", /*initialize=*/ true, classLoader), StatsComponent.class); } catch (ClassNotFoundException e) { logger.log( @@ -106,7 +107,10 @@ public final class Stats { try { // Call Class.forName with literal string name of the class to help shading tools. return Provider.createInstance( - Class.forName("io.opencensus.impllite.stats.StatsComponentImplLite", true, classLoader), + Class.forName( + "io.opencensus.impllite.stats.StatsComponentImplLite", + /*initialize=*/ true, + classLoader), StatsComponent.class); } catch (ClassNotFoundException e) { logger.log( diff --git a/api/src/main/java/io/opencensus/tags/Tags.java b/api/src/main/java/io/opencensus/tags/Tags.java index b784b5f5..e4c6a579 100644 --- a/api/src/main/java/io/opencensus/tags/Tags.java +++ b/api/src/main/java/io/opencensus/tags/Tags.java @@ -96,7 +96,8 @@ public final class Tags { try { // Call Class.forName with literal string name of the class to help shading tools. return Provider.createInstance( - Class.forName("io.opencensus.impl.tags.TagsComponentImpl", true, classLoader), + Class.forName( + "io.opencensus.impl.tags.TagsComponentImpl", /*initialize=*/ true, classLoader), TagsComponent.class); } catch (ClassNotFoundException e) { logger.log( @@ -108,7 +109,10 @@ public final class Tags { try { // Call Class.forName with literal string name of the class to help shading tools. return Provider.createInstance( - Class.forName("io.opencensus.impllite.tags.TagsComponentImplLite", true, classLoader), + Class.forName( + "io.opencensus.impllite.tags.TagsComponentImplLite", + /*initialize=*/ true, + classLoader), TagsComponent.class); } catch (ClassNotFoundException e) { logger.log( diff --git a/api/src/main/java/io/opencensus/trace/Tracing.java b/api/src/main/java/io/opencensus/trace/Tracing.java index f3673020..e67eb008 100644 --- a/api/src/main/java/io/opencensus/trace/Tracing.java +++ b/api/src/main/java/io/opencensus/trace/Tracing.java @@ -92,7 +92,8 @@ public final class Tracing { try { // Call Class.forName with literal string name of the class to help shading tools. return Provider.createInstance( - Class.forName("io.opencensus.impl.trace.TraceComponentImpl", true, classLoader), + Class.forName( + "io.opencensus.impl.trace.TraceComponentImpl", /*initialize=*/ true, classLoader), TraceComponent.class); } catch (ClassNotFoundException e) { logger.log( @@ -104,7 +105,10 @@ public final class Tracing { try { // Call Class.forName with literal string name of the class to help shading tools. return Provider.createInstance( - Class.forName("io.opencensus.impllite.trace.TraceComponentImplLite", true, classLoader), + Class.forName( + "io.opencensus.impllite.trace.TraceComponentImplLite", + /*initialize=*/ true, + classLoader), TraceComponent.class); } catch (ClassNotFoundException e) { logger.log( -- cgit v1.2.3 From e9ae88670c7f9b695452ca1a5a3a31fad9791a80 Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Fri, 2 Mar 2018 02:37:19 +0100 Subject: Fix probabilitySampler_getDescription for all locales. (#1040) PropabilitySampler#getDescription returns a string that contains the probability formatted according to the current locale, while the test expects a certain format. --- api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java b/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java index 6cb41975..7a46e97a 100644 --- a/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java +++ b/api/src/test/java/io/opencensus/trace/samplers/SamplersTest.java @@ -271,7 +271,7 @@ public class SamplersTest { @Test public void probabilitySampler_getDescription() { assertThat((Samplers.probabilitySampler(0.5)).getDescription()) - .isEqualTo("ProbabilitySampler{0.500000}"); + .isEqualTo(String.format("ProbabilitySampler{%.6f}", 0.5)); } @Test -- cgit v1.2.3 From b28e6efbf8d36304cae8977e83faf1f47b4d5c69 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Wed, 7 Mar 2018 14:51:17 -0800 Subject: Deprecate Window and WindowData. (#1018) * Deprecate Window and WindowType in Stats APIs * Window and WindowData will continue to be NonNull * Suppress warnings for impl, exporter and zpages. * NoopStats should continue to use old method. --- .../main/java/io/opencensus/stats/NoopStats.java | 22 ++--- api/src/main/java/io/opencensus/stats/View.java | 41 ++++++++- .../main/java/io/opencensus/stats/ViewData.java | 96 ++++++++++++++++++++-- .../io/opencensus/stats/NoopViewManagerTest.java | 16 +--- 4 files changed, 144 insertions(+), 31 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/NoopStats.java b/api/src/main/java/io/opencensus/stats/NoopStats.java index 74f8f660..97d2976a 100644 --- a/api/src/main/java/io/opencensus/stats/NoopStats.java +++ b/api/src/main/java/io/opencensus/stats/NoopStats.java @@ -27,10 +27,6 @@ import io.opencensus.common.Functions; import io.opencensus.common.Timestamp; import io.opencensus.stats.Measure.MeasureDouble; import io.opencensus.stats.Measure.MeasureLong; -import io.opencensus.stats.View.AggregationWindow; -import io.opencensus.stats.ViewData.AggregationWindowData; -import io.opencensus.stats.ViewData.AggregationWindowData.CumulativeData; -import io.opencensus.stats.ViewData.AggregationWindowData.IntervalData; import io.opencensus.tags.TagContext; import io.opencensus.tags.TagValue; import java.util.Collection; @@ -176,6 +172,7 @@ final class NoopStats { @Override @Nullable + @SuppressWarnings("deprecation") public ViewData getView(View.Name name) { checkNotNull(name, "name"); synchronized (registeredViews) { @@ -188,11 +185,12 @@ final class NoopStats { Collections., AggregationData>emptyMap(), view.getWindow() .match( - Functions.returnConstant( - CumulativeData.create(ZERO_TIMESTAMP, ZERO_TIMESTAMP)), - Functions.returnConstant( - IntervalData.create(ZERO_TIMESTAMP)), - Functions.throwAssertionError())); + Functions.returnConstant( + ViewData.AggregationWindowData.CumulativeData.create( + ZERO_TIMESTAMP, ZERO_TIMESTAMP)), + Functions.returnConstant( + ViewData.AggregationWindowData.IntervalData.create(ZERO_TIMESTAMP)), + Functions.throwAssertionError())); } } } @@ -209,12 +207,14 @@ final class NoopStats { } // Returns the subset of the given views that should be exported + @SuppressWarnings("deprecation") private static Set filterExportedViews(Collection allViews) { Set views = Sets.newHashSet(); for (View view : allViews) { - if (view.getWindow() instanceof AggregationWindow.Cumulative) { - views.add(view); + if (view.getWindow() instanceof View.AggregationWindow.Interval) { + continue; } + views.add(view); } return Collections.unmodifiableSet(views); } diff --git a/api/src/main/java/io/opencensus/stats/View.java b/api/src/main/java/io/opencensus/stats/View.java index a26c777b..32915919 100644 --- a/api/src/main/java/io/opencensus/stats/View.java +++ b/api/src/main/java/io/opencensus/stats/View.java @@ -40,7 +40,7 @@ import javax.annotation.concurrent.Immutable; @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @AutoValue.CopyAnnotations -@SuppressWarnings("nullness") +@SuppressWarnings({"nullness", "deprecation"}) public abstract class View { @VisibleForTesting static final int NAME_MAX_LENGTH = 255; @@ -90,7 +90,9 @@ public abstract class View { * * @return the time {@link AggregationWindow}. * @since 0.8 + * @deprecated since 0.13. In the future all {@link View}s will be cumulative. */ + @Deprecated public abstract AggregationWindow getWindow(); /** @@ -105,7 +107,9 @@ public abstract class View { * @param window the {@link AggregationWindow} of view. * @return a new {@link View}. * @since 0.8 + * @deprecated in favor of {@link #create(Name, String, Measure, Aggregation, List)}. */ + @Deprecated public static View create( Name name, String description, @@ -124,6 +128,35 @@ public abstract class View { window); } + /** + * Constructs a new {@link View}. + * + * @param name the {@link Name} of view. Must be unique. + * @param description the description of view. + * @param measure the {@link Measure} to be aggregated by this view. + * @param aggregation the basic {@link Aggregation} that this view will support. + * @param columns the {@link TagKey}s that this view will aggregate on. Columns should not contain + * duplicates. + * @return a new {@link View}. + * @since 0.13 + */ + public static View create( + Name name, + String description, + Measure measure, + Aggregation aggregation, + List columns) { + checkArgument(new HashSet(columns).size() == columns.size(), "Columns have duplicate."); + + return new AutoValue_View( + name, + description, + measure, + aggregation, + Collections.unmodifiableList(new ArrayList(columns)), + AggregationWindow.Cumulative.create()); + } + /** * The name of a {@code View}. * @@ -169,7 +202,9 @@ public abstract class View { * The time window for a {@code View}. * * @since 0.8 + * @deprecated since 0.13. In the future all {@link View}s will be cumulative. */ + @Deprecated @Immutable public abstract static class AggregationWindow { @@ -189,7 +224,9 @@ public abstract class View { * Cumulative (infinite interval) time {@code AggregationWindow}. * * @since 0.8 + * @deprecated since 0.13. In the future all {@link View}s will be cumulative. */ + @Deprecated @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -227,7 +264,9 @@ public abstract class View { * Interval (finite interval) time {@code AggregationWindow}. * * @since 0.8 + * @deprecated since 0.13. In the future all {@link View}s will be cumulative. */ + @Deprecated @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. diff --git a/api/src/main/java/io/opencensus/stats/ViewData.java b/api/src/main/java/io/opencensus/stats/ViewData.java index 951afb2e..3ee67ca9 100644 --- a/api/src/main/java/io/opencensus/stats/ViewData.java +++ b/api/src/main/java/io/opencensus/stats/ViewData.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkArgument; import com.google.auto.value.AutoValue; import com.google.common.collect.Maps; +import io.opencensus.common.Duration; import io.opencensus.common.Function; import io.opencensus.common.Functions; import io.opencensus.common.Timestamp; @@ -34,7 +35,6 @@ import io.opencensus.stats.AggregationData.SumDataDouble; import io.opencensus.stats.AggregationData.SumDataLong; import io.opencensus.stats.Measure.MeasureDouble; import io.opencensus.stats.Measure.MeasureLong; -import io.opencensus.stats.View.AggregationWindow; import io.opencensus.tags.TagValue; import java.util.ArrayList; import java.util.Collections; @@ -56,7 +56,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @AutoValue.CopyAnnotations -@SuppressWarnings("nullness") +@SuppressWarnings({"nullness", "deprecation"}) public abstract class ViewData { // Prevents this class from being subclassed anywhere else. @@ -80,11 +80,32 @@ public abstract class ViewData { /** * Returns the {@link AggregationWindowData} associated with this {@link ViewData}. * + *

    {@link AggregationWindowData} is deprecated since 0.13, please avoid using this method. Use + * {@link #getStart()} and {@link #getEnd()} instead. + * * @return the {@code AggregationWindowData}. * @since 0.8 + * @deprecated in favor of {@link #getStart()} and {@link #getEnd()}. */ + @Deprecated public abstract AggregationWindowData getWindowData(); + /** + * Returns the start {@code Timestamp} for a {@link ViewData}. + * + * @return the start {@code Timestamp}. + * @since 0.13 + */ + public abstract Timestamp getStart(); + + /** + * Returns the end {@code Timestamp} for a {@link ViewData}. + * + * @return the end {@code Timestamp}. + * @since 0.13 + */ + public abstract Timestamp getEnd(); + /** * Constructs a new {@link ViewData}. * @@ -96,12 +117,62 @@ public abstract class ViewData { * AggregationData} don't match, or the types of {@code Window} and {@code WindowData} don't * match. * @since 0.8 + * @deprecated in favor of {@link #create(View, Map, Timestamp, Timestamp)}. */ + @Deprecated public static ViewData create( - View view, + final View view, Map, ? extends AggregationData> map, final AggregationWindowData windowData) { checkWindow(view.getWindow(), windowData); + final Map, AggregationData> deepCopy = Maps.newHashMap(); + for (Entry, ? extends AggregationData> entry : map.entrySet()) { + checkAggregation(view.getAggregation(), entry.getValue(), view.getMeasure()); + deepCopy.put( + Collections.unmodifiableList(new ArrayList(entry.getKey())), + entry.getValue()); + } + return windowData.match( + new Function() { + @Override + public ViewData apply(ViewData.AggregationWindowData.CumulativeData arg) { + return new AutoValue_ViewData( + view, Collections.unmodifiableMap(deepCopy), arg, arg.getStart(), arg.getEnd()); + } + }, + new Function() { + @Override + public ViewData apply(ViewData.AggregationWindowData.IntervalData arg) { + Duration duration = ((View.AggregationWindow.Interval) view.getWindow()).getDuration(); + return new AutoValue_ViewData( + view, + Collections.unmodifiableMap(deepCopy), + arg, + arg.getEnd() + .addDuration(Duration.create(-duration.getSeconds(), -duration.getNanos())), + arg.getEnd()); + } + }, + Functions.throwAssertionError()); + } + + /** + * Constructs a new {@link ViewData}. + * + * @param view the {@link View} associated with this {@link ViewData}. + * @param map the mapping from {@link TagValue} list to {@link AggregationData}. + * @param start the start {@link Timestamp} for this {@link ViewData}. + * @param end the end {@link Timestamp} for this {@link ViewData}. + * @return a {@code ViewData}. + * @throws IllegalArgumentException if the types of {@code Aggregation} and {@code + * AggregationData} don't match. + * @since 0.13 + */ + public static ViewData create( + View view, + Map, ? extends AggregationData> map, + Timestamp start, + Timestamp end) { Map, AggregationData> deepCopy = Maps.newHashMap(); for (Entry, ? extends AggregationData> entry : map.entrySet()) { checkAggregation(view.getAggregation(), entry.getValue(), view.getMeasure()); @@ -109,11 +180,16 @@ public abstract class ViewData { Collections.unmodifiableList(new ArrayList(entry.getKey())), entry.getValue()); } - return new AutoValue_ViewData(view, Collections.unmodifiableMap(deepCopy), windowData); + return new AutoValue_ViewData( + view, + Collections.unmodifiableMap(deepCopy), + AggregationWindowData.CumulativeData.create(start, end), + start, + end); } private static void checkWindow( - AggregationWindow window, final AggregationWindowData windowData) { + View.AggregationWindow window, final AggregationWindowData windowData) { window.match( new Function() { @Override @@ -133,11 +209,11 @@ public abstract class ViewData { return null; } }, - Functions.throwIllegalArgumentException()); + Functions.throwAssertionError()); } private static String createErrorMessageForWindow( - AggregationWindow window, AggregationWindowData windowData) { + View.AggregationWindow window, AggregationWindowData windowData) { return "AggregationWindow and AggregationWindowData types mismatch. " + "AggregationWindow: " + window @@ -217,7 +293,9 @@ public abstract class ViewData { * The {@code AggregationWindowData} for a {@link ViewData}. * * @since 0.8 + * @deprecated since 0.13, please use start and end {@link Timestamp} instead. */ + @Deprecated @Immutable public abstract static class AggregationWindowData { @@ -237,7 +315,9 @@ public abstract class ViewData { * Cumulative {@code AggregationWindowData}. * * @since 0.8 + * @deprecated since 0.13, please use start and end {@link Timestamp} instead. */ + @Deprecated @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. @@ -288,7 +368,9 @@ public abstract class ViewData { * Interval {@code AggregationWindowData}. * * @since 0.8 + * @deprecated since 0.13, please use start and end {@link Timestamp} instead. */ + @Deprecated @Immutable @AutoValue // Suppress Checker Framework warning about missing @Nullable in generated equals method. diff --git a/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java b/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java index 4aaa60dc..44c7626f 100644 --- a/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java +++ b/api/src/test/java/io/opencensus/stats/NoopViewManagerTest.java @@ -105,6 +105,8 @@ public final class NoopViewManagerTest { ViewData viewData = viewManager.getView(VIEW_NAME); assertThat(viewData.getView()).isEqualTo(view); assertThat(viewData.getAggregationMap()).isEmpty(); + assertThat(viewData.getStart()).isEqualTo(Timestamp.create(0, 0)); + assertThat(viewData.getEnd()).isEqualTo(Timestamp.create(0, 0)); assertThat(viewData.getWindowData()) .isEqualTo(CumulativeData.create(Timestamp.create(0, 0), Timestamp.create(0, 0))); } @@ -171,23 +173,13 @@ public final class NoopViewManagerTest { ViewManager viewManager = NoopStats.newNoopViewManager(); View view1 = View.create( - View.Name.create("View 1"), - VIEW_DESCRIPTION, - MEASURE, - AGGREGATION, - Arrays.asList(KEY), - CUMULATIVE); + View.Name.create("View 1"), VIEW_DESCRIPTION, MEASURE, AGGREGATION, Arrays.asList(KEY)); viewManager.registerView(view1); Set exported = viewManager.getAllExportedViews(); View view2 = View.create( - View.Name.create("View 2"), - VIEW_DESCRIPTION, - MEASURE, - AGGREGATION, - Arrays.asList(KEY), - CUMULATIVE); + View.Name.create("View 2"), VIEW_DESCRIPTION, MEASURE, AGGREGATION, Arrays.asList(KEY)); thrown.expect(UnsupportedOperationException.class); exported.add(view2); } -- cgit v1.2.3 From 1e524dca48c9a9de6bd4e4058138391ff23bea2e Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Mon, 19 Mar 2018 11:10:59 -0700 Subject: Remove usages of guava collections in api/ (#1069) This allows proguard to strip out the com.google.common.collect.* classes on Android --- .../java/io/opencensus/stats/AggregationData.java | 4 +-- .../main/java/io/opencensus/stats/NoopStats.java | 8 ++--- .../main/java/io/opencensus/stats/ViewData.java | 7 +++-- .../main/java/io/opencensus/tags/TagContext.java | 36 ++++++++++++++-------- .../opencensus/trace/export/SampledSpanStore.java | 9 +++--- .../java/io/opencensus/trace/export/SpanData.java | 6 ++-- 6 files changed, 40 insertions(+), 30 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/AggregationData.java b/api/src/main/java/io/opencensus/stats/AggregationData.java index 0244f4e1..e58e5143 100644 --- a/api/src/main/java/io/opencensus/stats/AggregationData.java +++ b/api/src/main/java/io/opencensus/stats/AggregationData.java @@ -20,8 +20,8 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; -import com.google.common.collect.Lists; import io.opencensus.common.Function; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.annotation.concurrent.Immutable; @@ -291,7 +291,7 @@ public abstract class AggregationData { } checkNotNull(bucketCounts, "bucket counts should not be null."); - List bucketCountsCopy = Collections.unmodifiableList(Lists.newArrayList(bucketCounts)); + List bucketCountsCopy = Collections.unmodifiableList(new ArrayList(bucketCounts)); for (Long bucket : bucketCountsCopy) { checkNotNull(bucket, "bucket should not be null."); } diff --git a/api/src/main/java/io/opencensus/stats/NoopStats.java b/api/src/main/java/io/opencensus/stats/NoopStats.java index 97d2976a..45fb6a17 100644 --- a/api/src/main/java/io/opencensus/stats/NoopStats.java +++ b/api/src/main/java/io/opencensus/stats/NoopStats.java @@ -21,8 +21,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import com.google.common.base.Preconditions; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; import io.opencensus.common.Functions; import io.opencensus.common.Timestamp; import io.opencensus.stats.Measure.MeasureDouble; @@ -31,6 +29,8 @@ import io.opencensus.tags.TagContext; import io.opencensus.tags.TagValue; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -149,7 +149,7 @@ final class NoopStats { private static final Timestamp ZERO_TIMESTAMP = Timestamp.create(0, 0); @GuardedBy("registeredViews") - private final Map registeredViews = Maps.newHashMap(); + private final Map registeredViews = new HashMap(); // Cached set of exported views. It must be set to null whenever a view is registered or // unregistered. @@ -209,7 +209,7 @@ final class NoopStats { // Returns the subset of the given views that should be exported @SuppressWarnings("deprecation") private static Set filterExportedViews(Collection allViews) { - Set views = Sets.newHashSet(); + Set views = new HashSet(); for (View view : allViews) { if (view.getWindow() instanceof View.AggregationWindow.Interval) { continue; diff --git a/api/src/main/java/io/opencensus/stats/ViewData.java b/api/src/main/java/io/opencensus/stats/ViewData.java index 3ee67ca9..491a84e5 100644 --- a/api/src/main/java/io/opencensus/stats/ViewData.java +++ b/api/src/main/java/io/opencensus/stats/ViewData.java @@ -19,7 +19,6 @@ package io.opencensus.stats; import static com.google.common.base.Preconditions.checkArgument; import com.google.auto.value.AutoValue; -import com.google.common.collect.Maps; import io.opencensus.common.Duration; import io.opencensus.common.Function; import io.opencensus.common.Functions; @@ -38,6 +37,7 @@ import io.opencensus.stats.Measure.MeasureLong; import io.opencensus.tags.TagValue; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -125,7 +125,8 @@ public abstract class ViewData { Map, ? extends AggregationData> map, final AggregationWindowData windowData) { checkWindow(view.getWindow(), windowData); - final Map, AggregationData> deepCopy = Maps.newHashMap(); + final Map, AggregationData> deepCopy = + new HashMap, AggregationData>(); for (Entry, ? extends AggregationData> entry : map.entrySet()) { checkAggregation(view.getAggregation(), entry.getValue(), view.getMeasure()); deepCopy.put( @@ -173,7 +174,7 @@ public abstract class ViewData { Map, ? extends AggregationData> map, Timestamp start, Timestamp end) { - Map, AggregationData> deepCopy = Maps.newHashMap(); + Map, AggregationData> deepCopy = new HashMap, AggregationData>(); for (Entry, ? extends AggregationData> entry : map.entrySet()) { checkAggregation(view.getAggregation(), entry.getValue(), view.getMeasure()); deepCopy.put( diff --git a/api/src/main/java/io/opencensus/tags/TagContext.java b/api/src/main/java/io/opencensus/tags/TagContext.java index 841c8ab5..e36acdff 100644 --- a/api/src/main/java/io/opencensus/tags/TagContext.java +++ b/api/src/main/java/io/opencensus/tags/TagContext.java @@ -16,10 +16,7 @@ package io.opencensus.tags; -import com.google.common.collect.HashMultiset; -import com.google.common.collect.ImmutableMultiset; -import com.google.common.collect.Lists; -import com.google.common.collect.Multiset; +import java.util.HashMap; import java.util.Iterator; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; @@ -70,15 +67,28 @@ public abstract class TagContext { TagContext otherTags = (TagContext) other; Iterator iter1 = getIterator(); Iterator iter2 = otherTags.getIterator(); - Multiset tags1 = - iter1 == null - ? ImmutableMultiset.of() - : HashMultiset.create(Lists.newArrayList(iter1)); - Multiset tags2 = - iter2 == null - ? ImmutableMultiset.of() - : HashMultiset.create(Lists.newArrayList(iter2)); - return tags1.equals(tags2); + HashMap tags = new HashMap(); + while (iter1 != null && iter1.hasNext()) { + Tag tag = iter1.next(); + if (tags.containsKey(tag)) { + tags.put(tag, tags.get(tag) + 1); + } else { + tags.put(tag, 1); + } + } + while (iter2 != null && iter2.hasNext()) { + Tag tag = iter2.next(); + if (!tags.containsKey(tag)) { + return false; + } + int count = tags.get(tag); + if (count > 1) { + tags.put(tag, count - 1); + } else { + tags.remove(tag); + } + } + return tags.isEmpty(); } @Override diff --git a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java index 67a40567..14b5dcf9 100644 --- a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java @@ -21,14 +21,13 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; import io.opencensus.trace.Span; import io.opencensus.trace.Status; import io.opencensus.trace.Status.CanonicalCode; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -487,11 +486,11 @@ public abstract class SampledSpanStore { Collections.emptyMap()); @GuardedBy("registeredSpanNames") - private final Set registeredSpanNames = Sets.newHashSet(); + private final Set registeredSpanNames = new HashSet(); @Override public Summary getSummary() { - Map result = Maps.newHashMap(); + Map result = new HashMap(); synchronized (registeredSpanNames) { for (String registeredSpanName : registeredSpanNames) { result.put(registeredSpanName, EMPTY_PER_SPAN_NAME_SUMMARY); @@ -531,7 +530,7 @@ public abstract class SampledSpanStore { @Override public Set getRegisteredSpanNamesForCollection() { synchronized (registeredSpanNames) { - return Collections.unmodifiableSet(Sets.newHashSet(registeredSpanNames)); + return Collections.unmodifiableSet(new HashSet(registeredSpanNames)); } } } diff --git a/api/src/main/java/io/opencensus/trace/export/SpanData.java b/api/src/main/java/io/opencensus/trace/export/SpanData.java index 120c231a..16ff4331 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanData.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanData.java @@ -19,7 +19,6 @@ package io.opencensus.trace.export; import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; -import com.google.common.collect.Lists; import io.opencensus.common.Timestamp; import io.opencensus.internal.BaseMessageEventUtil; import io.opencensus.trace.Annotation; @@ -94,7 +93,7 @@ public abstract class SpanData { if (messageOrNetworkEvents == null) { throw new NullPointerException("Null messageOrNetworkEvents"); } - List> messageEventsList = Lists.newArrayList(); + List> messageEventsList = new ArrayList>(); for (TimedEvent timedEvent : messageOrNetworkEvents.getEvents()) { io.opencensus.trace.BaseMessageEvent event = timedEvent.getEvent(); @@ -198,7 +197,8 @@ public abstract class SpanData { @SuppressWarnings({"deprecation"}) public TimedEvents getNetworkEvents() { TimedEvents timedEvents = getMessageEvents(); - List> networkEventsList = Lists.newArrayList(); + List> networkEventsList = + new ArrayList>(); for (TimedEvent timedEvent : timedEvents.getEvents()) { networkEventsList.add( TimedEvent.create( -- cgit v1.2.3 From eb826581a9d3e2e99cd93bd07ee2b336978e8fb2 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Wed, 21 Mar 2018 17:25:35 -0700 Subject: Move BaseMessageEventUtil to trace package. (#1076) * Move BaseMessageEventUtil to trace package. * Move BaseMessageEventUtil to trace.internal. Work around findbugs. * Update findbugs-exclude and remove since tag. --- .../opencensus/internal/BaseMessageEventUtil.java | 80 --------------------- api/src/main/java/io/opencensus/trace/Span.java | 2 +- .../java/io/opencensus/trace/export/SpanData.java | 2 +- .../trace/internal/BaseMessageEventUtil.java | 82 ++++++++++++++++++++++ .../internal/BaseMessageEventUtilTest.java | 71 ------------------- .../trace/internal/BaseMessageEventUtilTest.java | 71 +++++++++++++++++++ 6 files changed, 155 insertions(+), 153 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/internal/BaseMessageEventUtil.java create mode 100644 api/src/main/java/io/opencensus/trace/internal/BaseMessageEventUtil.java delete mode 100644 api/src/test/java/io/opencensus/internal/BaseMessageEventUtilTest.java create mode 100644 api/src/test/java/io/opencensus/trace/internal/BaseMessageEventUtilTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/BaseMessageEventUtil.java b/api/src/main/java/io/opencensus/internal/BaseMessageEventUtil.java deleted file mode 100644 index 56ec3301..00000000 --- a/api/src/main/java/io/opencensus/internal/BaseMessageEventUtil.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2018, 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.internal; - -import static com.google.common.base.Preconditions.checkNotNull; - -import io.opencensus.trace.MessageEvent; - -/** - * Helper class to convert/cast between for {@link MessageEvent} and {@link NetworkEvent}. - * - * @since 0.12 - */ -@SuppressWarnings("deprecation") -public final class BaseMessageEventUtil { - /** - * Cast or convert a {@link io.opencensus.trace.BaseMessageEvent} to {@link MessageEvent}. - * - *

    Warning: if the input is a {@code io.opencensus.trace.NetworkEvent} and contains {@code - * kernelTimestamp} information, this information will be dropped. - * - * @param event the {@code BaseMessageEvent} that is being cast or converted. - * @return a {@code MessageEvent} representation of the input. - */ - public static MessageEvent asMessageEvent(io.opencensus.trace.BaseMessageEvent event) { - checkNotNull(event); - if (event instanceof MessageEvent) { - return (MessageEvent) event; - } - io.opencensus.trace.NetworkEvent networkEvent = (io.opencensus.trace.NetworkEvent) event; - MessageEvent.Type type = - (networkEvent.getType() == io.opencensus.trace.NetworkEvent.Type.RECV) - ? MessageEvent.Type.RECEIVED - : MessageEvent.Type.SENT; - return MessageEvent.builder(type, networkEvent.getMessageId()) - .setUncompressedMessageSize(networkEvent.getUncompressedMessageSize()) - .setCompressedMessageSize(networkEvent.getCompressedMessageSize()) - .build(); - } - - /** - * Cast or convert a {@link io.opencensus.trace.BaseMessageEvent} to {@link - * io.opencensus.trace.NetworkEvent}. - * - * @param event the {@code BaseMessageEvent} that is being cast or converted. - * @return a {@code io.opencensus.trace.NetworkEvent} representation of the input. - */ - public static io.opencensus.trace.NetworkEvent asNetworkEvent( - io.opencensus.trace.BaseMessageEvent event) { - checkNotNull(event); - if (event instanceof io.opencensus.trace.NetworkEvent) { - return (io.opencensus.trace.NetworkEvent) event; - } - MessageEvent messageEvent = (MessageEvent) event; - io.opencensus.trace.NetworkEvent.Type type = - (messageEvent.getType() == MessageEvent.Type.RECEIVED) - ? io.opencensus.trace.NetworkEvent.Type.RECV - : io.opencensus.trace.NetworkEvent.Type.SENT; - return io.opencensus.trace.NetworkEvent.builder(type, messageEvent.getMessageId()) - .setUncompressedMessageSize(messageEvent.getUncompressedMessageSize()) - .setCompressedMessageSize(messageEvent.getCompressedMessageSize()) - .build(); - } - - private BaseMessageEventUtil() {} -} diff --git a/api/src/main/java/io/opencensus/trace/Span.java b/api/src/main/java/io/opencensus/trace/Span.java index ae0e9b4b..c24a495b 100644 --- a/api/src/main/java/io/opencensus/trace/Span.java +++ b/api/src/main/java/io/opencensus/trace/Span.java @@ -19,7 +19,7 @@ package io.opencensus.trace; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -import io.opencensus.internal.BaseMessageEventUtil; +import io.opencensus.trace.internal.BaseMessageEventUtil; import java.util.Collections; import java.util.EnumSet; import java.util.Map; diff --git a/api/src/main/java/io/opencensus/trace/export/SpanData.java b/api/src/main/java/io/opencensus/trace/export/SpanData.java index 16ff4331..47de1abe 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanData.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanData.java @@ -20,7 +20,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auto.value.AutoValue; import io.opencensus.common.Timestamp; -import io.opencensus.internal.BaseMessageEventUtil; import io.opencensus.trace.Annotation; import io.opencensus.trace.AttributeValue; import io.opencensus.trace.Link; @@ -29,6 +28,7 @@ import io.opencensus.trace.Span; import io.opencensus.trace.SpanContext; import io.opencensus.trace.SpanId; import io.opencensus.trace.Status; +import io.opencensus.trace.internal.BaseMessageEventUtil; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; diff --git a/api/src/main/java/io/opencensus/trace/internal/BaseMessageEventUtil.java b/api/src/main/java/io/opencensus/trace/internal/BaseMessageEventUtil.java new file mode 100644 index 00000000..955c8859 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/internal/BaseMessageEventUtil.java @@ -0,0 +1,82 @@ +/* + * Copyright 2018, 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.internal; + +import static com.google.common.base.Preconditions.checkNotNull; + +import io.opencensus.common.Internal; + +/** + * Helper class to convert/cast between for {@link io.opencensus.trace.MessageEvent} and {@link + * io.opencensus.trace.NetworkEvent}. + */ +@Internal +@SuppressWarnings("deprecation") +public final class BaseMessageEventUtil { + /** + * Cast or convert a {@link io.opencensus.trace.BaseMessageEvent} to {@link + * io.opencensus.trace.MessageEvent}. + * + *

    Warning: if the input is a {@code io.opencensus.trace.NetworkEvent} and contains {@code + * kernelTimestamp} information, this information will be dropped. + * + * @param event the {@code BaseMessageEvent} that is being cast or converted. + * @return a {@code MessageEvent} representation of the input. + */ + public static io.opencensus.trace.MessageEvent asMessageEvent( + io.opencensus.trace.BaseMessageEvent event) { + checkNotNull(event); + if (event instanceof io.opencensus.trace.MessageEvent) { + return (io.opencensus.trace.MessageEvent) event; + } + io.opencensus.trace.NetworkEvent networkEvent = (io.opencensus.trace.NetworkEvent) event; + io.opencensus.trace.MessageEvent.Type type = + (networkEvent.getType() == io.opencensus.trace.NetworkEvent.Type.RECV) + ? io.opencensus.trace.MessageEvent.Type.RECEIVED + : io.opencensus.trace.MessageEvent.Type.SENT; + return io.opencensus.trace.MessageEvent.builder(type, networkEvent.getMessageId()) + .setUncompressedMessageSize(networkEvent.getUncompressedMessageSize()) + .setCompressedMessageSize(networkEvent.getCompressedMessageSize()) + .build(); + } + + /** + * Cast or convert a {@link io.opencensus.trace.BaseMessageEvent} to {@link + * io.opencensus.trace.NetworkEvent}. + * + * @param event the {@code BaseMessageEvent} that is being cast or converted. + * @return a {@code io.opencensus.trace.NetworkEvent} representation of the input. + */ + public static io.opencensus.trace.NetworkEvent asNetworkEvent( + io.opencensus.trace.BaseMessageEvent event) { + checkNotNull(event); + if (event instanceof io.opencensus.trace.NetworkEvent) { + return (io.opencensus.trace.NetworkEvent) event; + } + io.opencensus.trace.MessageEvent messageEvent = (io.opencensus.trace.MessageEvent) event; + io.opencensus.trace.NetworkEvent.Type type = + (messageEvent.getType() == io.opencensus.trace.MessageEvent.Type.RECEIVED) + ? io.opencensus.trace.NetworkEvent.Type.RECV + : io.opencensus.trace.NetworkEvent.Type.SENT; + return io.opencensus.trace.NetworkEvent.builder(type, messageEvent.getMessageId()) + .setUncompressedMessageSize(messageEvent.getUncompressedMessageSize()) + .setCompressedMessageSize(messageEvent.getCompressedMessageSize()) + .build(); + } + + private BaseMessageEventUtil() {} +} diff --git a/api/src/test/java/io/opencensus/internal/BaseMessageEventUtilTest.java b/api/src/test/java/io/opencensus/internal/BaseMessageEventUtilTest.java deleted file mode 100644 index 8de1b1c9..00000000 --- a/api/src/test/java/io/opencensus/internal/BaseMessageEventUtilTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2018, 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.internal; - -import static com.google.common.truth.Truth.assertThat; - -import io.opencensus.trace.MessageEvent; -import io.opencensus.trace.NetworkEvent; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link BaseMessageEventUtil}. */ -@RunWith(JUnit4.class) -public class BaseMessageEventUtilTest { - private static final long SENT_EVENT_ID = 12345L; - private static final long RECV_EVENT_ID = 67890L; - private static final long UNCOMPRESSED_SIZE = 100; - private static final long COMPRESSED_SIZE = 99; - - private static final MessageEvent SENT_MESSAGE_EVENT = - MessageEvent.builder(MessageEvent.Type.SENT, SENT_EVENT_ID) - .setUncompressedMessageSize(UNCOMPRESSED_SIZE) - .setCompressedMessageSize(COMPRESSED_SIZE) - .build(); - private static final MessageEvent RECV_MESSAGE_EVENT = - MessageEvent.builder(MessageEvent.Type.RECEIVED, RECV_EVENT_ID) - .setUncompressedMessageSize(UNCOMPRESSED_SIZE) - .setCompressedMessageSize(COMPRESSED_SIZE) - .build(); - private static final NetworkEvent SENT_NETWORK_EVENT = - NetworkEvent.builder(NetworkEvent.Type.SENT, SENT_EVENT_ID) - .setUncompressedMessageSize(UNCOMPRESSED_SIZE) - .setCompressedMessageSize(COMPRESSED_SIZE) - .build(); - private static final NetworkEvent RECV_NETWORK_EVENT = - NetworkEvent.builder(NetworkEvent.Type.RECV, RECV_EVENT_ID) - .setUncompressedMessageSize(UNCOMPRESSED_SIZE) - .setCompressedMessageSize(COMPRESSED_SIZE) - .build(); - - @Test - public void networkEventToMessageEvent() { - assertThat(BaseMessageEventUtil.asMessageEvent(SENT_NETWORK_EVENT)) - .isEqualTo(SENT_MESSAGE_EVENT); - assertThat(BaseMessageEventUtil.asMessageEvent(RECV_NETWORK_EVENT)) - .isEqualTo(RECV_MESSAGE_EVENT); - } - - @Test - public void messageEventToNetworkEvent() { - assertThat(BaseMessageEventUtil.asNetworkEvent(SENT_MESSAGE_EVENT)) - .isEqualTo(SENT_NETWORK_EVENT); - assertThat(BaseMessageEventUtil.asNetworkEvent(RECV_MESSAGE_EVENT)) - .isEqualTo(RECV_NETWORK_EVENT); - } -} diff --git a/api/src/test/java/io/opencensus/trace/internal/BaseMessageEventUtilTest.java b/api/src/test/java/io/opencensus/trace/internal/BaseMessageEventUtilTest.java new file mode 100644 index 00000000..2d02d403 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/internal/BaseMessageEventUtilTest.java @@ -0,0 +1,71 @@ +/* + * Copyright 2018, 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.internal; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.trace.MessageEvent; +import io.opencensus.trace.NetworkEvent; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link BaseMessageEventUtil}. */ +@RunWith(JUnit4.class) +public class BaseMessageEventUtilTest { + private static final long SENT_EVENT_ID = 12345L; + private static final long RECV_EVENT_ID = 67890L; + private static final long UNCOMPRESSED_SIZE = 100; + private static final long COMPRESSED_SIZE = 99; + + private static final MessageEvent SENT_MESSAGE_EVENT = + MessageEvent.builder(MessageEvent.Type.SENT, SENT_EVENT_ID) + .setUncompressedMessageSize(UNCOMPRESSED_SIZE) + .setCompressedMessageSize(COMPRESSED_SIZE) + .build(); + private static final MessageEvent RECV_MESSAGE_EVENT = + MessageEvent.builder(MessageEvent.Type.RECEIVED, RECV_EVENT_ID) + .setUncompressedMessageSize(UNCOMPRESSED_SIZE) + .setCompressedMessageSize(COMPRESSED_SIZE) + .build(); + private static final NetworkEvent SENT_NETWORK_EVENT = + NetworkEvent.builder(NetworkEvent.Type.SENT, SENT_EVENT_ID) + .setUncompressedMessageSize(UNCOMPRESSED_SIZE) + .setCompressedMessageSize(COMPRESSED_SIZE) + .build(); + private static final NetworkEvent RECV_NETWORK_EVENT = + NetworkEvent.builder(NetworkEvent.Type.RECV, RECV_EVENT_ID) + .setUncompressedMessageSize(UNCOMPRESSED_SIZE) + .setCompressedMessageSize(COMPRESSED_SIZE) + .build(); + + @Test + public void networkEventToMessageEvent() { + assertThat(BaseMessageEventUtil.asMessageEvent(SENT_NETWORK_EVENT)) + .isEqualTo(SENT_MESSAGE_EVENT); + assertThat(BaseMessageEventUtil.asMessageEvent(RECV_NETWORK_EVENT)) + .isEqualTo(RECV_MESSAGE_EVENT); + } + + @Test + public void messageEventToNetworkEvent() { + assertThat(BaseMessageEventUtil.asNetworkEvent(SENT_MESSAGE_EVENT)) + .isEqualTo(SENT_NETWORK_EVENT); + assertThat(BaseMessageEventUtil.asNetworkEvent(RECV_MESSAGE_EVENT)) + .isEqualTo(RECV_NETWORK_EVENT); + } +} -- cgit v1.2.3 From cc7c7e1dbc516b57122e61284aebbc385cbecca1 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Fri, 23 Mar 2018 15:14:29 -0700 Subject: Enable FindBugs in tests. This would have caught the unused variable that was fixed by #1082. Changes in this commit: - Enable FindBugs in tests in build.gradle. - Fix some existing minor FindBugs issues in tests. - Suppress some warnings in all test classes that are less important in test code, such as requiring nested classes to be static whenever possible. - Enable nullness-related FindBugs warnings in tests, since we don't run the Checker Framework on test code. --- .../test/java/io/opencensus/trace/export/NoopSampledSpanStoreTest.java | 3 --- 1 file changed, 3 deletions(-) (limited to 'api') diff --git a/api/src/test/java/io/opencensus/trace/export/NoopSampledSpanStoreTest.java b/api/src/test/java/io/opencensus/trace/export/NoopSampledSpanStoreTest.java index e18621ac..6e9c7b0f 100644 --- a/api/src/test/java/io/opencensus/trace/export/NoopSampledSpanStoreTest.java +++ b/api/src/test/java/io/opencensus/trace/export/NoopSampledSpanStoreTest.java @@ -23,9 +23,7 @@ import io.opencensus.trace.Status.CanonicalCode; import java.util.Collection; import java.util.Collections; import java.util.Set; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -33,7 +31,6 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public final class NoopSampledSpanStoreTest { - @Rule public final ExpectedException thrown = ExpectedException.none(); private static final SampledSpanStore.PerSpanNameSummary EMPTY_PER_SPAN_NAME_SUMMARY = SampledSpanStore.PerSpanNameSummary.create( Collections.emptyMap(), -- cgit v1.2.3 From 422d78f044a3941f6910d1b66452ded45a386b0c Mon Sep 17 00:00:00 2001 From: Yang Song Date: Mon, 26 Mar 2018 12:07:30 -0700 Subject: Update Guava and Jmh versions (#1095) --- api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java index 539339bc..7ff7dd0a 100644 --- a/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java +++ b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java @@ -121,7 +121,7 @@ final class CurrentSpanUtils { runnable.run(); } catch (Throwable t) { setErrorStatus(span, t); - Throwables.propagateIfPossible(t); + Throwables.throwIfUnchecked(t); throw new RuntimeException("unexpected", t); } finally { Context.current().detach(origContext); @@ -154,7 +154,7 @@ final class CurrentSpanUtils { throw e; } catch (Throwable t) { setErrorStatus(span, t); - Throwables.propagateIfPossible(t); + Throwables.throwIfUnchecked(t); throw new RuntimeException("unexpected", t); } finally { Context.current().detach(origContext); -- cgit v1.2.3 From 20da2d47707d89c1927b272817ff554cdafb3a90 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 27 Mar 2018 12:28:55 -0700 Subject: Remove @SuppressWarnings("nullness") from all AutoValue classes. This change allows the Checker Framework to check the classes annotated with @AutoValue, even though their generated subclasses are skipped. This commit also fixes some previously suppressed warnings in the ViewData class. --- .../main/java/io/opencensus/common/Duration.java | 3 -- .../main/java/io/opencensus/common/Timestamp.java | 3 -- .../main/java/io/opencensus/stats/Aggregation.java | 12 ------ .../java/io/opencensus/stats/AggregationData.java | 15 -------- .../java/io/opencensus/stats/BucketBoundaries.java | 3 -- api/src/main/java/io/opencensus/stats/Measure.java | 6 --- .../main/java/io/opencensus/stats/Measurement.java | 6 --- api/src/main/java/io/opencensus/stats/View.java | 10 +---- .../main/java/io/opencensus/stats/ViewData.java | 43 ++++++++++++++-------- api/src/main/java/io/opencensus/tags/Tag.java | 3 -- api/src/main/java/io/opencensus/tags/TagKey.java | 3 -- api/src/main/java/io/opencensus/tags/TagValue.java | 3 -- .../main/java/io/opencensus/trace/Annotation.java | 3 -- .../java/io/opencensus/trace/AttributeValue.java | 9 ----- .../java/io/opencensus/trace/EndSpanOptions.java | 3 -- api/src/main/java/io/opencensus/trace/Link.java | 3 -- .../java/io/opencensus/trace/MessageEvent.java | 4 +- .../java/io/opencensus/trace/NetworkEvent.java | 2 - .../io/opencensus/trace/config/TraceParams.java | 3 -- .../opencensus/trace/export/RunningSpanStore.java | 9 ----- .../opencensus/trace/export/SampledSpanStore.java | 12 ------ .../java/io/opencensus/trace/export/SpanData.java | 15 -------- .../trace/samplers/ProbabilitySampler.java | 3 -- 23 files changed, 29 insertions(+), 147 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Duration.java b/api/src/main/java/io/opencensus/common/Duration.java index 1dd8d502..c03fecad 100644 --- a/api/src/main/java/io/opencensus/common/Duration.java +++ b/api/src/main/java/io/opencensus/common/Duration.java @@ -34,9 +34,6 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue -// Suppress Checker Framework warning about missing @Nullable in generated equals method. -@AutoValue.CopyAnnotations -@SuppressWarnings("nullness") public abstract class Duration implements Comparable { private static final Duration ZERO = create(0, 0); diff --git a/api/src/main/java/io/opencensus/common/Timestamp.java b/api/src/main/java/io/opencensus/common/Timestamp.java index 9671f245..b6ba1316 100644 --- a/api/src/main/java/io/opencensus/common/Timestamp.java +++ b/api/src/main/java/io/opencensus/common/Timestamp.java @@ -39,9 +39,6 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue -// Suppress Checker Framework warning about missing @Nullable in generated equals method. -@AutoValue.CopyAnnotations -@SuppressWarnings("nullness") public abstract class Timestamp implements Comparable { private static final Timestamp EPOCH = new AutoValue_Timestamp(0, 0); diff --git a/api/src/main/java/io/opencensus/stats/Aggregation.java b/api/src/main/java/io/opencensus/stats/Aggregation.java index f097f5ad..4362b4a8 100644 --- a/api/src/main/java/io/opencensus/stats/Aggregation.java +++ b/api/src/main/java/io/opencensus/stats/Aggregation.java @@ -64,9 +64,6 @@ public abstract class Aggregation { */ @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class Sum extends Aggregation { Sum() {} @@ -101,9 +98,6 @@ public abstract class Aggregation { */ @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class Count extends Aggregation { Count() {} @@ -138,9 +132,6 @@ public abstract class Aggregation { */ @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class Mean extends Aggregation { Mean() {} @@ -176,9 +167,6 @@ public abstract class Aggregation { */ @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class Distribution extends Aggregation { Distribution() {} diff --git a/api/src/main/java/io/opencensus/stats/AggregationData.java b/api/src/main/java/io/opencensus/stats/AggregationData.java index e58e5143..50feb034 100644 --- a/api/src/main/java/io/opencensus/stats/AggregationData.java +++ b/api/src/main/java/io/opencensus/stats/AggregationData.java @@ -70,9 +70,6 @@ public abstract class AggregationData { */ @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class SumDataDouble extends AggregationData { SumDataDouble() {} @@ -115,9 +112,6 @@ public abstract class AggregationData { */ @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class SumDataLong extends AggregationData { SumDataLong() {} @@ -160,9 +154,6 @@ public abstract class AggregationData { */ @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class CountData extends AggregationData { CountData() {} @@ -205,9 +196,6 @@ public abstract class AggregationData { */ @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class MeanData extends AggregationData { MeanData() {} @@ -260,9 +248,6 @@ public abstract class AggregationData { */ @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class DistributionData extends AggregationData { DistributionData() {} diff --git a/api/src/main/java/io/opencensus/stats/BucketBoundaries.java b/api/src/main/java/io/opencensus/stats/BucketBoundaries.java index 01ec6db7..0dcb1710 100644 --- a/api/src/main/java/io/opencensus/stats/BucketBoundaries.java +++ b/api/src/main/java/io/opencensus/stats/BucketBoundaries.java @@ -32,9 +32,6 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue -// Suppress Checker Framework warning about missing @Nullable in generated equals method. -@AutoValue.CopyAnnotations -@SuppressWarnings("nullness") public abstract class BucketBoundaries { /** diff --git a/api/src/main/java/io/opencensus/stats/Measure.java b/api/src/main/java/io/opencensus/stats/Measure.java index 9dede342..c0e3033e 100644 --- a/api/src/main/java/io/opencensus/stats/Measure.java +++ b/api/src/main/java/io/opencensus/stats/Measure.java @@ -90,9 +90,6 @@ public abstract class Measure { */ @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class MeasureDouble extends Measure { MeasureDouble() {} @@ -140,9 +137,6 @@ public abstract class Measure { */ @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class MeasureLong extends Measure { MeasureLong() {} diff --git a/api/src/main/java/io/opencensus/stats/Measurement.java b/api/src/main/java/io/opencensus/stats/Measurement.java index c6c639ea..647a667d 100644 --- a/api/src/main/java/io/opencensus/stats/Measurement.java +++ b/api/src/main/java/io/opencensus/stats/Measurement.java @@ -57,9 +57,6 @@ public abstract class Measurement { */ @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class MeasurementDouble extends Measurement { MeasurementDouble() {} @@ -99,9 +96,6 @@ public abstract class Measurement { */ @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class MeasurementLong extends Measurement { MeasurementLong() {} diff --git a/api/src/main/java/io/opencensus/stats/View.java b/api/src/main/java/io/opencensus/stats/View.java index 32915919..14534339 100644 --- a/api/src/main/java/io/opencensus/stats/View.java +++ b/api/src/main/java/io/opencensus/stats/View.java @@ -38,9 +38,8 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue -// Suppress Checker Framework warning about missing @Nullable in generated equals method. @AutoValue.CopyAnnotations -@SuppressWarnings({"nullness", "deprecation"}) +@SuppressWarnings("deprecation") public abstract class View { @VisibleForTesting static final int NAME_MAX_LENGTH = 255; @@ -165,9 +164,6 @@ public abstract class View { // This type should be used as the key when associating data with Views. @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class Name { Name() {} @@ -229,9 +225,7 @@ public abstract class View { @Deprecated @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class Cumulative extends AggregationWindow { private static final Cumulative CUMULATIVE = @@ -269,9 +263,7 @@ public abstract class View { @Deprecated @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class Interval extends AggregationWindow { private static final Duration ZERO = Duration.create(0, 0); diff --git a/api/src/main/java/io/opencensus/stats/ViewData.java b/api/src/main/java/io/opencensus/stats/ViewData.java index 491a84e5..ef9a6795 100644 --- a/api/src/main/java/io/opencensus/stats/ViewData.java +++ b/api/src/main/java/io/opencensus/stats/ViewData.java @@ -54,9 +54,8 @@ import org.checkerframework.checker.nullness.qual.Nullable; */ @Immutable @AutoValue -// Suppress Checker Framework warning about missing @Nullable in generated equals method. @AutoValue.CopyAnnotations -@SuppressWarnings({"nullness", "deprecation"}) +@SuppressWarnings("deprecation") public abstract class ViewData { // Prevents this class from being subclassed anywhere else. @@ -125,9 +124,10 @@ public abstract class ViewData { Map, ? extends AggregationData> map, final AggregationWindowData windowData) { checkWindow(view.getWindow(), windowData); - final Map, AggregationData> deepCopy = - new HashMap, AggregationData>(); - for (Entry, ? extends AggregationData> entry : map.entrySet()) { + final Map, AggregationData> deepCopy = + new HashMap, AggregationData>(); + for (Entry, ? extends AggregationData> entry : + map.entrySet()) { checkAggregation(view.getAggregation(), entry.getValue(), view.getMeasure()); deepCopy.put( Collections.unmodifiableList(new ArrayList(entry.getKey())), @@ -137,7 +137,7 @@ public abstract class ViewData { new Function() { @Override public ViewData apply(ViewData.AggregationWindowData.CumulativeData arg) { - return new AutoValue_ViewData( + return createInternal( view, Collections.unmodifiableMap(deepCopy), arg, arg.getStart(), arg.getEnd()); } }, @@ -145,7 +145,7 @@ public abstract class ViewData { @Override public ViewData apply(ViewData.AggregationWindowData.IntervalData arg) { Duration duration = ((View.AggregationWindow.Interval) view.getWindow()).getDuration(); - return new AutoValue_ViewData( + return createInternal( view, Collections.unmodifiableMap(deepCopy), arg, @@ -174,14 +174,16 @@ public abstract class ViewData { Map, ? extends AggregationData> map, Timestamp start, Timestamp end) { - Map, AggregationData> deepCopy = new HashMap, AggregationData>(); - for (Entry, ? extends AggregationData> entry : map.entrySet()) { + Map, AggregationData> deepCopy = + new HashMap, AggregationData>(); + for (Entry, ? extends AggregationData> entry : + map.entrySet()) { checkAggregation(view.getAggregation(), entry.getValue(), view.getMeasure()); deepCopy.put( Collections.unmodifiableList(new ArrayList(entry.getKey())), entry.getValue()); } - return new AutoValue_ViewData( + return createInternal( view, Collections.unmodifiableMap(deepCopy), AggregationWindowData.CumulativeData.create(start, end), @@ -189,6 +191,19 @@ public abstract class ViewData { end); } + // Suppresses a nullness warning about calls to the AutoValue_ViewData constructor. The generated + // constructor does not have the @Nullable annotation on TagValue. + private static ViewData createInternal( + View view, + Map, AggregationData> aggregationMap, + AggregationWindowData window, + Timestamp start, + Timestamp end) { + @SuppressWarnings("nullness") + Map, AggregationData> map = aggregationMap; + return new AutoValue_ViewData(view, map, window, start, end); + } + private static void checkWindow( View.AggregationWindow window, final AggregationWindowData windowData) { window.match( @@ -247,7 +262,7 @@ public abstract class ViewData { return null; } }, - Functions.throwAssertionError()); + Functions.throwAssertionError()); return null; } }, @@ -278,7 +293,7 @@ public abstract class ViewData { return null; } }, - Functions.throwAssertionError()); + Functions.throwAssertionError()); } private static String createErrorMessageForAggregation( @@ -321,9 +336,7 @@ public abstract class ViewData { @Deprecated @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class CumulativeData extends AggregationWindowData { CumulativeData() {} @@ -374,9 +387,7 @@ public abstract class ViewData { @Deprecated @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class IntervalData extends AggregationWindowData { IntervalData() {} diff --git a/api/src/main/java/io/opencensus/tags/Tag.java b/api/src/main/java/io/opencensus/tags/Tag.java index d5415e02..9e0a7a82 100644 --- a/api/src/main/java/io/opencensus/tags/Tag.java +++ b/api/src/main/java/io/opencensus/tags/Tag.java @@ -26,9 +26,6 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue -// Suppress Checker Framework warning about missing @Nullable in generated equals method. -@AutoValue.CopyAnnotations -@SuppressWarnings("nullness") public abstract class Tag { Tag() {} diff --git a/api/src/main/java/io/opencensus/tags/TagKey.java b/api/src/main/java/io/opencensus/tags/TagKey.java index bad2fec3..ceaa1b80 100644 --- a/api/src/main/java/io/opencensus/tags/TagKey.java +++ b/api/src/main/java/io/opencensus/tags/TagKey.java @@ -35,9 +35,6 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue -// Suppress Checker Framework warning about missing @Nullable in generated equals method. -@AutoValue.CopyAnnotations -@SuppressWarnings("nullness") public abstract class TagKey { /** * The maximum length for a tag key name. The value is {@value #MAX_LENGTH}. diff --git a/api/src/main/java/io/opencensus/tags/TagValue.java b/api/src/main/java/io/opencensus/tags/TagValue.java index 07ccc2cc..5ba71959 100644 --- a/api/src/main/java/io/opencensus/tags/TagValue.java +++ b/api/src/main/java/io/opencensus/tags/TagValue.java @@ -31,9 +31,6 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue -// Suppress Checker Framework warning about missing @Nullable in generated equals method. -@AutoValue.CopyAnnotations -@SuppressWarnings("nullness") public abstract class TagValue { /** * The maximum length for a tag value. The value is {@value #MAX_LENGTH}. diff --git a/api/src/main/java/io/opencensus/trace/Annotation.java b/api/src/main/java/io/opencensus/trace/Annotation.java index 233968d3..5eb3a505 100644 --- a/api/src/main/java/io/opencensus/trace/Annotation.java +++ b/api/src/main/java/io/opencensus/trace/Annotation.java @@ -31,9 +31,6 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue -// Suppress Checker Framework warning about missing @Nullable in generated equals method. -@AutoValue.CopyAnnotations -@SuppressWarnings("nullness") public abstract class Annotation { private static final Map EMPTY_ATTRIBUTES = Collections.unmodifiableMap(Collections.emptyMap()); diff --git a/api/src/main/java/io/opencensus/trace/AttributeValue.java b/api/src/main/java/io/opencensus/trace/AttributeValue.java index ed59830e..b4759fd2 100644 --- a/api/src/main/java/io/opencensus/trace/AttributeValue.java +++ b/api/src/main/java/io/opencensus/trace/AttributeValue.java @@ -88,9 +88,6 @@ public abstract class AttributeValue { @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") abstract static class AttributeValueString extends AttributeValue { AttributeValueString() {} @@ -114,9 +111,6 @@ public abstract class AttributeValue { @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") abstract static class AttributeValueBoolean extends AttributeValue { AttributeValueBoolean() {} @@ -140,9 +134,6 @@ public abstract class AttributeValue { @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") abstract static class AttributeValueLong extends AttributeValue { AttributeValueLong() {} diff --git a/api/src/main/java/io/opencensus/trace/EndSpanOptions.java b/api/src/main/java/io/opencensus/trace/EndSpanOptions.java index d9e31e63..b0d9a470 100644 --- a/api/src/main/java/io/opencensus/trace/EndSpanOptions.java +++ b/api/src/main/java/io/opencensus/trace/EndSpanOptions.java @@ -30,9 +30,6 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue -// Suppress Checker Framework warning about missing @Nullable in generated equals method. -@AutoValue.CopyAnnotations -@SuppressWarnings("nullness") public abstract class EndSpanOptions { /** * The default {@code EndSpanOptions}. diff --git a/api/src/main/java/io/opencensus/trace/Link.java b/api/src/main/java/io/opencensus/trace/Link.java index e877a010..1de79710 100644 --- a/api/src/main/java/io/opencensus/trace/Link.java +++ b/api/src/main/java/io/opencensus/trace/Link.java @@ -35,9 +35,6 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue -// Suppress Checker Framework warning about missing @Nullable in generated equals method. -@AutoValue.CopyAnnotations -@SuppressWarnings("nullness") public abstract class Link { private static final Map EMPTY_ATTRIBUTES = Collections.emptyMap(); diff --git a/api/src/main/java/io/opencensus/trace/MessageEvent.java b/api/src/main/java/io/opencensus/trace/MessageEvent.java index 49a4673c..3be65f52 100644 --- a/api/src/main/java/io/opencensus/trace/MessageEvent.java +++ b/api/src/main/java/io/opencensus/trace/MessageEvent.java @@ -33,9 +33,7 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue -// Suppress Checker Framework warning about missing @Nullable in generated equals method. -@AutoValue.CopyAnnotations -@SuppressWarnings({"nullness", "deprecation"}) +@SuppressWarnings("deprecation") public abstract class MessageEvent extends BaseMessageEvent { /** * Available types for a {@code MessageEvent}. diff --git a/api/src/main/java/io/opencensus/trace/NetworkEvent.java b/api/src/main/java/io/opencensus/trace/NetworkEvent.java index 1c8fe393..f12597f9 100644 --- a/api/src/main/java/io/opencensus/trace/NetworkEvent.java +++ b/api/src/main/java/io/opencensus/trace/NetworkEvent.java @@ -33,9 +33,7 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue -// Suppress Checker Framework warning about missing @Nullable in generated equals method. @AutoValue.CopyAnnotations -@SuppressWarnings("nullness") @Deprecated public abstract class NetworkEvent extends io.opencensus.trace.BaseMessageEvent { /** diff --git a/api/src/main/java/io/opencensus/trace/config/TraceParams.java b/api/src/main/java/io/opencensus/trace/config/TraceParams.java index 6c2ee7ff..7594e696 100644 --- a/api/src/main/java/io/opencensus/trace/config/TraceParams.java +++ b/api/src/main/java/io/opencensus/trace/config/TraceParams.java @@ -34,9 +34,6 @@ import javax.annotation.concurrent.Immutable; */ @AutoValue @Immutable -// Suppress Checker Framework warning about missing @Nullable in generated equals method. -@AutoValue.CopyAnnotations -@SuppressWarnings("nullness") public abstract class TraceParams { // These values are the default values for all the global parameters. private static final double DEFAULT_PROBABILITY = 1e-4; diff --git a/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java b/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java index fbfc5ff1..aa05e4fe 100644 --- a/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java @@ -76,9 +76,6 @@ public abstract class RunningSpanStore { */ @AutoValue @Immutable - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class Summary { Summary() {} @@ -114,9 +111,6 @@ public abstract class RunningSpanStore { */ @AutoValue @Immutable - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class PerSpanNameSummary { PerSpanNameSummary() {} @@ -151,9 +145,6 @@ public abstract class RunningSpanStore { */ @AutoValue @Immutable - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class Filter { Filter() {} diff --git a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java index 14b5dcf9..5e7f4dd6 100644 --- a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java @@ -141,9 +141,6 @@ public abstract class SampledSpanStore { */ @AutoValue @Immutable - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class Summary { Summary() {} @@ -179,9 +176,6 @@ public abstract class SampledSpanStore { */ @AutoValue @Immutable - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class PerSpanNameSummary { PerSpanNameSummary() {} @@ -345,9 +339,6 @@ public abstract class SampledSpanStore { */ @AutoValue @Immutable - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class LatencyFilter { LatencyFilter() {} @@ -418,9 +409,6 @@ public abstract class SampledSpanStore { */ @AutoValue @Immutable - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class ErrorFilter { ErrorFilter() {} diff --git a/api/src/main/java/io/opencensus/trace/export/SpanData.java b/api/src/main/java/io/opencensus/trace/export/SpanData.java index 47de1abe..f93193b5 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanData.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanData.java @@ -48,9 +48,6 @@ import org.checkerframework.dataflow.qual.Deterministic; */ @Immutable @AutoValue -// Suppress Checker Framework warning about missing @Nullable in generated equals method. -@AutoValue.CopyAnnotations -@SuppressWarnings("nullness") public abstract class SpanData { /** @@ -267,9 +264,6 @@ public abstract class SpanData { */ @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class TimedEvent { /** * Returns a new immutable {@code TimedEvent}. @@ -312,9 +306,6 @@ public abstract class SpanData { */ @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class TimedEvents { /** * Returns a new immutable {@code TimedEvents}. @@ -358,9 +349,6 @@ public abstract class SpanData { */ @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class Attributes { /** * Returns a new immutable {@code Attributes}. @@ -406,9 +394,6 @@ public abstract class SpanData { */ @Immutable @AutoValue - // Suppress Checker Framework warning about missing @Nullable in generated equals method. - @AutoValue.CopyAnnotations - @SuppressWarnings("nullness") public abstract static class Links { /** * Returns a new immutable {@code Links}. diff --git a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java index 8d8be354..21d4d6ca 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java +++ b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java @@ -37,9 +37,6 @@ import javax.annotation.concurrent.Immutable; */ @AutoValue @Immutable -// Suppress Checker Framework warning about missing @Nullable in generated equals method. -@AutoValue.CopyAnnotations -@SuppressWarnings("nullness") abstract class ProbabilitySampler extends Sampler { ProbabilitySampler() {} -- cgit v1.2.3 From 95e8f18cf1020419755a1fc207e500fbdb23081d Mon Sep 17 00:00:00 2001 From: Yang Song Date: Wed, 28 Mar 2018 09:53:07 -0700 Subject: Deprecate Mean and MeanData (#1101) * Deprecate Mean and MeanData * Suppress deprecation warnings. * Suppress warning InconsistentOverloads * CopyAnnotations for AutoValue Mean and MeanData --- .../main/java/io/opencensus/stats/Aggregation.java | 56 ++++++++++++++++- .../java/io/opencensus/stats/AggregationData.java | 71 +++++++++++++++++++++- .../main/java/io/opencensus/stats/ViewData.java | 8 +-- 3 files changed, 126 insertions(+), 9 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/Aggregation.java b/api/src/main/java/io/opencensus/stats/Aggregation.java index 4362b4a8..55ce9d96 100644 --- a/api/src/main/java/io/opencensus/stats/Aggregation.java +++ b/api/src/main/java/io/opencensus/stats/Aggregation.java @@ -26,12 +26,11 @@ import javax.annotation.concurrent.Immutable; * {@link Aggregation} is the process of combining a certain set of {@code MeasureValue}s for a * given {@code Measure} into an {@link AggregationData}. * - *

    {@link Aggregation} currently supports 4 types of basic aggregation: + *

    {@link Aggregation} currently supports 3 types of basic aggregation: * *

      *
    • Sum *
    • Count - *
    • Mean *
    • Distribution *
    * @@ -49,7 +48,9 @@ public abstract class Aggregation { * Applies the given match function to the underlying data type. * * @since 0.8 + * @deprecated in favor of {@link #match(Function, Function, Function, Function)}. */ + @Deprecated public abstract T match( Function p0, Function p1, @@ -57,6 +58,18 @@ public abstract class Aggregation { Function p3, Function defaultFunction); + /** + * Applies the given match function to the underlying data type. + * + * @since 0.13 + */ + @SuppressWarnings("InconsistentOverloads") + public abstract T match( + Function p0, + Function p1, + Function p2, + Function defaultFunction); + /** * Calculate sum on aggregated {@code MeasureValue}s. * @@ -89,6 +102,15 @@ public abstract class Aggregation { Function defaultFunction) { return p0.apply(this); } + + @Override + public final T match( + Function p0, + Function p1, + Function p2, + Function defaultFunction) { + return p0.apply(this); + } } /** @@ -123,15 +145,27 @@ public abstract class Aggregation { Function defaultFunction) { return p1.apply(this); } + + @Override + public final T match( + Function p0, + Function p1, + Function p2, + Function defaultFunction) { + return p1.apply(this); + } } /** * Calculate mean on aggregated {@code MeasureValue}s. * * @since 0.8 + * @deprecated since 0.13, use {@link Distribution} instead. */ @Immutable @AutoValue + @Deprecated + @AutoValue.CopyAnnotations public abstract static class Mean extends Aggregation { Mean() {} @@ -157,6 +191,15 @@ public abstract class Aggregation { Function defaultFunction) { return p2.apply(this); } + + @Override + public final T match( + Function p0, + Function p1, + Function p2, + Function defaultFunction) { + return defaultFunction.apply(this); + } } /** @@ -199,5 +242,14 @@ public abstract class Aggregation { Function defaultFunction) { return p3.apply(this); } + + @Override + public final T match( + Function p0, + Function p1, + Function p2, + Function defaultFunction) { + return p2.apply(this); + } } } diff --git a/api/src/main/java/io/opencensus/stats/AggregationData.java b/api/src/main/java/io/opencensus/stats/AggregationData.java index 50feb034..637621e9 100644 --- a/api/src/main/java/io/opencensus/stats/AggregationData.java +++ b/api/src/main/java/io/opencensus/stats/AggregationData.java @@ -30,13 +30,12 @@ import javax.annotation.concurrent.Immutable; * {@link AggregationData} is the result of applying a given {@link Aggregation} to a set of {@code * MeasureValue}s. * - *

    {@link AggregationData} currently supports 5 types of basic aggregation values: + *

    {@link AggregationData} currently supports 4 types of basic aggregation values: * *

      *
    • SumDataDouble *
    • SumDataLong *
    • CountData - *
    • MeanData *
    • DistributionData *
    * @@ -54,7 +53,9 @@ public abstract class AggregationData { * Applies the given match function to the underlying data type. * * @since 0.8 + * @deprecated in favor of {@link #match(Function, Function, Function, Function, Function)}. */ + @Deprecated public abstract T match( Function p0, Function p1, @@ -63,6 +64,19 @@ public abstract class AggregationData { Function p4, Function defaultFunction); + /** + * Applies the given match function to the underlying data type. + * + * @since 0.13 + */ + @SuppressWarnings("InconsistentOverloads") + public abstract T match( + Function p0, + Function p1, + Function p2, + Function p3, + Function defaultFunction); + /** * The sum value of aggregated {@code MeasureValueDouble}s. * @@ -103,6 +117,16 @@ public abstract class AggregationData { Function defaultFunction) { return p0.apply(this); } + + @Override + public final T match( + Function p0, + Function p1, + Function p2, + Function p3, + Function defaultFunction) { + return p0.apply(this); + } } /** @@ -145,6 +169,16 @@ public abstract class AggregationData { Function defaultFunction) { return p1.apply(this); } + + @Override + public final T match( + Function p0, + Function p1, + Function p2, + Function p3, + Function defaultFunction) { + return p1.apply(this); + } } /** @@ -187,15 +221,28 @@ public abstract class AggregationData { Function defaultFunction) { return p2.apply(this); } + + @Override + public final T match( + Function p0, + Function p1, + Function p2, + Function p3, + Function defaultFunction) { + return p2.apply(this); + } } /** * The mean value of aggregated {@code MeasureValue}s. * * @since 0.8 + * @deprecated since 0.13, use {@link DistributionData} instead. */ @Immutable @AutoValue + @Deprecated + @AutoValue.CopyAnnotations public abstract static class MeanData extends AggregationData { MeanData() {} @@ -238,6 +285,16 @@ public abstract class AggregationData { Function defaultFunction) { return p3.apply(this); } + + @Override + public final T match( + Function p0, + Function p1, + Function p2, + Function p3, + Function defaultFunction) { + return defaultFunction.apply(this); + } } /** @@ -344,5 +401,15 @@ public abstract class AggregationData { Function defaultFunction) { return p4.apply(this); } + + @Override + public final T match( + Function p0, + Function p1, + Function p2, + Function p3, + Function defaultFunction) { + return p3.apply(this); + } } } diff --git a/api/src/main/java/io/opencensus/stats/ViewData.java b/api/src/main/java/io/opencensus/stats/ViewData.java index ef9a6795..788bea76 100644 --- a/api/src/main/java/io/opencensus/stats/ViewData.java +++ b/api/src/main/java/io/opencensus/stats/ViewData.java @@ -25,11 +25,9 @@ import io.opencensus.common.Functions; import io.opencensus.common.Timestamp; import io.opencensus.stats.Aggregation.Count; import io.opencensus.stats.Aggregation.Distribution; -import io.opencensus.stats.Aggregation.Mean; import io.opencensus.stats.Aggregation.Sum; import io.opencensus.stats.AggregationData.CountData; import io.opencensus.stats.AggregationData.DistributionData; -import io.opencensus.stats.AggregationData.MeanData; import io.opencensus.stats.AggregationData.SumDataDouble; import io.opencensus.stats.AggregationData.SumDataLong; import io.opencensus.stats.Measure.MeasureDouble; @@ -275,11 +273,11 @@ public abstract class ViewData { return null; } }, - new Function() { + new Function() { @Override - public Void apply(Mean arg) { + public Void apply(Aggregation.Mean arg) { checkArgument( - aggregationData instanceof MeanData, + aggregationData instanceof AggregationData.MeanData, createErrorMessageForAggregation(aggregation, aggregationData)); return null; } -- cgit v1.2.3 From 4f2d5a7c910388fa87c7c1738c27df693372e0e6 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Fri, 30 Mar 2018 15:15:18 -0700 Subject: Clean up ViewTest.java. --- .../test/java/io/opencensus/stats/ViewTest.java | 38 ++++++++++------------ 1 file changed, 17 insertions(+), 21 deletions(-) (limited to 'api') diff --git a/api/src/test/java/io/opencensus/stats/ViewTest.java b/api/src/test/java/io/opencensus/stats/ViewTest.java index 4781854c..580d48ed 100644 --- a/api/src/test/java/io/opencensus/stats/ViewTest.java +++ b/api/src/test/java/io/opencensus/stats/ViewTest.java @@ -18,7 +18,6 @@ package io.opencensus.stats; import static com.google.common.truth.Truth.assertThat; -import com.google.common.collect.ImmutableList; import com.google.common.testing.EqualsTester; import io.opencensus.common.Duration; import io.opencensus.stats.Aggregation.Mean; @@ -26,6 +25,7 @@ import io.opencensus.stats.View.AggregationWindow.Cumulative; import io.opencensus.stats.View.AggregationWindow.Interval; import io.opencensus.tags.TagKey; import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.junit.Rule; import org.junit.Test; @@ -46,24 +46,22 @@ public final class ViewTest { @Test public void testDistributionView() { - final View view = View.create(NAME, DESCRIPTION, MEASURE, MEAN, keys, Cumulative.create()); + final View view = View.create(NAME, DESCRIPTION, MEASURE, MEAN, KEYS, Cumulative.create()); assertThat(view.getName()).isEqualTo(NAME); assertThat(view.getDescription()).isEqualTo(DESCRIPTION); assertThat(view.getMeasure().getName()).isEqualTo(MEASURE.getName()); assertThat(view.getAggregation()).isEqualTo(MEAN); - assertThat(view.getColumns()).hasSize(2); assertThat(view.getColumns()).containsExactly(FOO, BAR).inOrder(); assertThat(view.getWindow()).isEqualTo(Cumulative.create()); } @Test public void testIntervalView() { - final View view = View.create(NAME, DESCRIPTION, MEASURE, MEAN, keys, Interval.create(MINUTE)); + final View view = View.create(NAME, DESCRIPTION, MEASURE, MEAN, KEYS, Interval.create(MINUTE)); assertThat(view.getName()).isEqualTo(NAME); assertThat(view.getDescription()).isEqualTo(DESCRIPTION); assertThat(view.getMeasure().getName()).isEqualTo(MEASURE.getName()); assertThat(view.getAggregation()).isEqualTo(MEAN); - assertThat(view.getColumns()).hasSize(2); assertThat(view.getColumns()).containsExactly(FOO, BAR).inOrder(); assertThat(view.getWindow()).isEqualTo(Interval.create(MINUTE)); } @@ -72,32 +70,30 @@ public final class ViewTest { public void testViewEquals() { new EqualsTester() .addEqualityGroup( - View.create(NAME, DESCRIPTION, MEASURE, MEAN, keys, Cumulative.create()), - View.create(NAME, DESCRIPTION, MEASURE, MEAN, keys, Cumulative.create())) + View.create(NAME, DESCRIPTION, MEASURE, MEAN, KEYS, Cumulative.create()), + View.create(NAME, DESCRIPTION, MEASURE, MEAN, KEYS, Cumulative.create())) .addEqualityGroup( - View.create(NAME, DESCRIPTION + 2, MEASURE, MEAN, keys, Cumulative.create())) + View.create(NAME, DESCRIPTION + 2, MEASURE, MEAN, KEYS, Cumulative.create())) .addEqualityGroup( - View.create(NAME, DESCRIPTION, MEASURE, MEAN, keys, Interval.create(MINUTE)), - View.create(NAME, DESCRIPTION, MEASURE, MEAN, keys, Interval.create(MINUTE))) + View.create(NAME, DESCRIPTION, MEASURE, MEAN, KEYS, Interval.create(MINUTE)), + View.create(NAME, DESCRIPTION, MEASURE, MEAN, KEYS, Interval.create(MINUTE))) .addEqualityGroup( - View.create(NAME, DESCRIPTION, MEASURE, MEAN, keys, Interval.create(TWO_MINUTES))) + View.create(NAME, DESCRIPTION, MEASURE, MEAN, KEYS, Interval.create(TWO_MINUTES))) .testEquals(); } - @Test(expected = IllegalArgumentException.class) + @Test public void preventDuplicateColumns() { - View.create( - NAME, - DESCRIPTION, - MEASURE, - MEAN, - Arrays.asList(TagKey.create("duplicate"), TagKey.create("duplicate")), - Cumulative.create()); + TagKey key1 = TagKey.create("duplicate"); + TagKey key2 = TagKey.create("duplicate"); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Columns have duplicate."); + View.create(NAME, DESCRIPTION, MEASURE, MEAN, Arrays.asList(key1, key2)); } @Test(expected = NullPointerException.class) public void preventNullViewName() { - View.create(null, DESCRIPTION, MEASURE, MEAN, keys, Interval.create(MINUTE)); + View.create(null, DESCRIPTION, MEASURE, MEAN, KEYS, Interval.create(MINUTE)); } @Test @@ -144,7 +140,7 @@ public final class ViewTest { Measure.MeasureDouble.create("measure", "measure description", "1"); private static final TagKey FOO = TagKey.create("foo"); private static final TagKey BAR = TagKey.create("bar"); - private static final List keys = ImmutableList.of(FOO, BAR); + private static final List KEYS = Collections.unmodifiableList(Arrays.asList(FOO, BAR)); private static final Mean MEAN = Mean.create(); private static final Duration MINUTE = Duration.create(60, 0); private static final Duration TWO_MINUTES = Duration.create(120, 0); -- cgit v1.2.3 From 0444fb47f3c05e7e64664e6f56ddaf79c049d964 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Fri, 30 Mar 2018 15:16:54 -0700 Subject: Remove some uses of deprecated AggregationWindow in ViewTest.java. --- api/src/test/java/io/opencensus/stats/ViewTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'api') diff --git a/api/src/test/java/io/opencensus/stats/ViewTest.java b/api/src/test/java/io/opencensus/stats/ViewTest.java index 580d48ed..259ad221 100644 --- a/api/src/test/java/io/opencensus/stats/ViewTest.java +++ b/api/src/test/java/io/opencensus/stats/ViewTest.java @@ -46,7 +46,7 @@ public final class ViewTest { @Test public void testDistributionView() { - final View view = View.create(NAME, DESCRIPTION, MEASURE, MEAN, KEYS, Cumulative.create()); + final View view = View.create(NAME, DESCRIPTION, MEASURE, MEAN, KEYS); assertThat(view.getName()).isEqualTo(NAME); assertThat(view.getDescription()).isEqualTo(DESCRIPTION); assertThat(view.getMeasure().getName()).isEqualTo(MEASURE.getName()); @@ -70,7 +70,7 @@ public final class ViewTest { public void testViewEquals() { new EqualsTester() .addEqualityGroup( - View.create(NAME, DESCRIPTION, MEASURE, MEAN, KEYS, Cumulative.create()), + View.create(NAME, DESCRIPTION, MEASURE, MEAN, KEYS), View.create(NAME, DESCRIPTION, MEASURE, MEAN, KEYS, Cumulative.create())) .addEqualityGroup( View.create(NAME, DESCRIPTION + 2, MEASURE, MEAN, KEYS, Cumulative.create())) @@ -93,7 +93,7 @@ public final class ViewTest { @Test(expected = NullPointerException.class) public void preventNullViewName() { - View.create(null, DESCRIPTION, MEASURE, MEAN, KEYS, Interval.create(MINUTE)); + View.create(null, DESCRIPTION, MEASURE, MEAN, KEYS); } @Test -- cgit v1.2.3 From e8d8a33a05b802b9f42b0dcce3246ee335482abd Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Fri, 30 Mar 2018 15:20:04 -0700 Subject: Sort TagKeys in View.create(...) (fixes #1080). --- api/src/main/java/io/opencensus/stats/View.java | 28 +++++++++++----------- .../test/java/io/opencensus/stats/ViewTest.java | 20 ++++++++++++++-- 2 files changed, 32 insertions(+), 16 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/View.java b/api/src/main/java/io/opencensus/stats/View.java index 14534339..fc0579e9 100644 --- a/api/src/main/java/io/opencensus/stats/View.java +++ b/api/src/main/java/io/opencensus/stats/View.java @@ -26,6 +26,7 @@ import io.opencensus.internal.StringUtil; import io.opencensus.tags.TagKey; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.HashSet; import java.util.List; import javax.annotation.concurrent.Immutable; @@ -44,6 +45,14 @@ public abstract class View { @VisibleForTesting static final int NAME_MAX_LENGTH = 255; + private static final Comparator TAG_KEY_COMPARATOR = + new Comparator() { + @Override + public int compare(TagKey key1, TagKey key2) { + return key1.getName().compareTo(key2.getName()); + } + }; + View() {} /** @@ -118,13 +127,10 @@ public abstract class View { AggregationWindow window) { checkArgument(new HashSet(columns).size() == columns.size(), "Columns have duplicate."); + List tagKeys = new ArrayList(columns); + Collections.sort(tagKeys, TAG_KEY_COMPARATOR); return new AutoValue_View( - name, - description, - measure, - aggregation, - Collections.unmodifiableList(new ArrayList(columns)), - window); + name, description, measure, aggregation, Collections.unmodifiableList(tagKeys), window); } /** @@ -146,14 +152,8 @@ public abstract class View { Aggregation aggregation, List columns) { checkArgument(new HashSet(columns).size() == columns.size(), "Columns have duplicate."); - - return new AutoValue_View( - name, - description, - measure, - aggregation, - Collections.unmodifiableList(new ArrayList(columns)), - AggregationWindow.Cumulative.create()); + return create( + name, description, measure, aggregation, columns, AggregationWindow.Cumulative.create()); } /** diff --git a/api/src/test/java/io/opencensus/stats/ViewTest.java b/api/src/test/java/io/opencensus/stats/ViewTest.java index 259ad221..afba1bc0 100644 --- a/api/src/test/java/io/opencensus/stats/ViewTest.java +++ b/api/src/test/java/io/opencensus/stats/ViewTest.java @@ -44,6 +44,22 @@ public final class ViewTest { assertThat(View.NAME_MAX_LENGTH).isEqualTo(255); } + @Test + public void sortTagKeys() { + final View view = + View.create( + NAME, + DESCRIPTION, + MEASURE, + MEAN, + Arrays.asList( + TagKey.create("ab"), TagKey.create("a"), TagKey.create("A"), TagKey.create("b"))); + assertThat(view.getColumns()) + .containsExactly( + TagKey.create("A"), TagKey.create("a"), TagKey.create("ab"), TagKey.create("b")) + .inOrder(); + } + @Test public void testDistributionView() { final View view = View.create(NAME, DESCRIPTION, MEASURE, MEAN, KEYS); @@ -51,7 +67,7 @@ public final class ViewTest { assertThat(view.getDescription()).isEqualTo(DESCRIPTION); assertThat(view.getMeasure().getName()).isEqualTo(MEASURE.getName()); assertThat(view.getAggregation()).isEqualTo(MEAN); - assertThat(view.getColumns()).containsExactly(FOO, BAR).inOrder(); + assertThat(view.getColumns()).containsExactly(BAR, FOO).inOrder(); assertThat(view.getWindow()).isEqualTo(Cumulative.create()); } @@ -62,7 +78,7 @@ public final class ViewTest { assertThat(view.getDescription()).isEqualTo(DESCRIPTION); assertThat(view.getMeasure().getName()).isEqualTo(MEASURE.getName()); assertThat(view.getAggregation()).isEqualTo(MEAN); - assertThat(view.getColumns()).containsExactly(FOO, BAR).inOrder(); + assertThat(view.getColumns()).containsExactly(BAR, FOO).inOrder(); assertThat(view.getWindow()).isEqualTo(Interval.create(MINUTE)); } -- cgit v1.2.3 From 26110b6cbf41dcf889502022a495576511025335 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 3 Apr 2018 16:37:22 -0700 Subject: Rename "Util" classes to "Utils", for consistency with public "Utils" classes. This commit adds an "s" to TimeUtil, StringUtil, and BaseMessageEventUtil, for consistency with utility classes that have been made public, such as ContextUtils. --- .../main/java/io/opencensus/common/Duration.java | 8 +-- .../main/java/io/opencensus/common/TimeUtil.java | 28 -------- .../main/java/io/opencensus/common/TimeUtils.java | 28 ++++++++ .../main/java/io/opencensus/common/Timestamp.java | 10 +-- .../java/io/opencensus/internal/StringUtil.java | 42 ----------- .../java/io/opencensus/internal/StringUtils.java | 42 +++++++++++ api/src/main/java/io/opencensus/stats/Measure.java | 6 +- api/src/main/java/io/opencensus/stats/View.java | 4 +- api/src/main/java/io/opencensus/tags/TagKey.java | 4 +- api/src/main/java/io/opencensus/tags/TagValue.java | 4 +- api/src/main/java/io/opencensus/trace/Span.java | 6 +- .../java/io/opencensus/trace/export/SpanData.java | 6 +- .../trace/internal/BaseMessageEventUtil.java | 82 ---------------------- .../trace/internal/BaseMessageEventUtils.java | 82 ++++++++++++++++++++++ .../io/opencensus/internal/StringUtilTest.java | 35 --------- .../io/opencensus/internal/StringUtilsTest.java | 35 +++++++++ .../trace/internal/BaseMessageEventUtilTest.java | 71 ------------------- .../trace/internal/BaseMessageEventUtilsTest.java | 71 +++++++++++++++++++ 18 files changed, 282 insertions(+), 282 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/common/TimeUtil.java create mode 100644 api/src/main/java/io/opencensus/common/TimeUtils.java delete mode 100644 api/src/main/java/io/opencensus/internal/StringUtil.java create mode 100644 api/src/main/java/io/opencensus/internal/StringUtils.java delete mode 100644 api/src/main/java/io/opencensus/trace/internal/BaseMessageEventUtil.java create mode 100644 api/src/main/java/io/opencensus/trace/internal/BaseMessageEventUtils.java delete mode 100644 api/src/test/java/io/opencensus/internal/StringUtilTest.java create mode 100644 api/src/test/java/io/opencensus/internal/StringUtilsTest.java delete mode 100644 api/src/test/java/io/opencensus/trace/internal/BaseMessageEventUtilTest.java create mode 100644 api/src/test/java/io/opencensus/trace/internal/BaseMessageEventUtilsTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Duration.java b/api/src/main/java/io/opencensus/common/Duration.java index c03fecad..c20bbda7 100644 --- a/api/src/main/java/io/opencensus/common/Duration.java +++ b/api/src/main/java/io/opencensus/common/Duration.java @@ -16,10 +16,10 @@ package io.opencensus.common; -import static io.opencensus.common.TimeUtil.MAX_NANOS; -import static io.opencensus.common.TimeUtil.MAX_SECONDS; -import static io.opencensus.common.TimeUtil.MILLIS_PER_SECOND; -import static io.opencensus.common.TimeUtil.NANOS_PER_MILLI; +import static io.opencensus.common.TimeUtils.MAX_NANOS; +import static io.opencensus.common.TimeUtils.MAX_SECONDS; +import static io.opencensus.common.TimeUtils.MILLIS_PER_SECOND; +import static io.opencensus.common.TimeUtils.NANOS_PER_MILLI; import com.google.auto.value.AutoValue; import com.google.common.primitives.Longs; diff --git a/api/src/main/java/io/opencensus/common/TimeUtil.java b/api/src/main/java/io/opencensus/common/TimeUtil.java deleted file mode 100644 index 09b3ddf9..00000000 --- a/api/src/main/java/io/opencensus/common/TimeUtil.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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.common; - -/** Util class for {@link Timestamp} and {@link Duration}. */ -final class TimeUtil { - static final long MAX_SECONDS = 315576000000L; - static final int MAX_NANOS = 999999999; - static final long MILLIS_PER_SECOND = 1000L; - static final long NANOS_PER_MILLI = 1000 * 1000; - static final long NANOS_PER_SECOND = NANOS_PER_MILLI * MILLIS_PER_SECOND; - - private TimeUtil() {} -} diff --git a/api/src/main/java/io/opencensus/common/TimeUtils.java b/api/src/main/java/io/opencensus/common/TimeUtils.java new file mode 100644 index 00000000..2429cc90 --- /dev/null +++ b/api/src/main/java/io/opencensus/common/TimeUtils.java @@ -0,0 +1,28 @@ +/* + * 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.common; + +/** Util class for {@link Timestamp} and {@link Duration}. */ +final class TimeUtils { + static final long MAX_SECONDS = 315576000000L; + static final int MAX_NANOS = 999999999; + static final long MILLIS_PER_SECOND = 1000L; + static final long NANOS_PER_MILLI = 1000 * 1000; + static final long NANOS_PER_SECOND = NANOS_PER_MILLI * MILLIS_PER_SECOND; + + private TimeUtils() {} +} diff --git a/api/src/main/java/io/opencensus/common/Timestamp.java b/api/src/main/java/io/opencensus/common/Timestamp.java index b6ba1316..970a0031 100644 --- a/api/src/main/java/io/opencensus/common/Timestamp.java +++ b/api/src/main/java/io/opencensus/common/Timestamp.java @@ -16,11 +16,11 @@ package io.opencensus.common; -import static io.opencensus.common.TimeUtil.MAX_NANOS; -import static io.opencensus.common.TimeUtil.MAX_SECONDS; -import static io.opencensus.common.TimeUtil.MILLIS_PER_SECOND; -import static io.opencensus.common.TimeUtil.NANOS_PER_MILLI; -import static io.opencensus.common.TimeUtil.NANOS_PER_SECOND; +import static io.opencensus.common.TimeUtils.MAX_NANOS; +import static io.opencensus.common.TimeUtils.MAX_SECONDS; +import static io.opencensus.common.TimeUtils.MILLIS_PER_SECOND; +import static io.opencensus.common.TimeUtils.NANOS_PER_MILLI; +import static io.opencensus.common.TimeUtils.NANOS_PER_SECOND; import com.google.auto.value.AutoValue; import com.google.common.math.LongMath; diff --git a/api/src/main/java/io/opencensus/internal/StringUtil.java b/api/src/main/java/io/opencensus/internal/StringUtil.java deleted file mode 100644 index 70f5299e..00000000 --- a/api/src/main/java/io/opencensus/internal/StringUtil.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2016-17, 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.internal; - -/** Internal utility methods for working with tag keys, tag values, and metric names. */ -public final class StringUtil { - - /** - * Determines whether the {@code String} contains only printable characters. - * - * @param str the {@code String} to be validated. - * @return whether the {@code String} contains only printable characters. - */ - public static boolean isPrintableString(String str) { - for (int i = 0; i < str.length(); i++) { - if (!isPrintableChar(str.charAt(i))) { - return false; - } - } - return true; - } - - private static boolean isPrintableChar(char ch) { - return ch >= ' ' && ch <= '~'; - } - - private StringUtil() {} -} diff --git a/api/src/main/java/io/opencensus/internal/StringUtils.java b/api/src/main/java/io/opencensus/internal/StringUtils.java new file mode 100644 index 00000000..717e333c --- /dev/null +++ b/api/src/main/java/io/opencensus/internal/StringUtils.java @@ -0,0 +1,42 @@ +/* + * Copyright 2016-17, 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.internal; + +/** Internal utility methods for working with tag keys, tag values, and metric names. */ +public final class StringUtils { + + /** + * Determines whether the {@code String} contains only printable characters. + * + * @param str the {@code String} to be validated. + * @return whether the {@code String} contains only printable characters. + */ + public static boolean isPrintableString(String str) { + for (int i = 0; i < str.length(); i++) { + if (!isPrintableChar(str.charAt(i))) { + return false; + } + } + return true; + } + + private static boolean isPrintableChar(char ch) { + return ch >= ' ' && ch <= '~'; + } + + private StringUtils() {} +} diff --git a/api/src/main/java/io/opencensus/stats/Measure.java b/api/src/main/java/io/opencensus/stats/Measure.java index c0e3033e..7b9b833e 100644 --- a/api/src/main/java/io/opencensus/stats/Measure.java +++ b/api/src/main/java/io/opencensus/stats/Measure.java @@ -21,7 +21,7 @@ import static com.google.common.base.Preconditions.checkArgument; import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; import io.opencensus.common.Function; -import io.opencensus.internal.StringUtil; +import io.opencensus.internal.StringUtils; import javax.annotation.concurrent.Immutable; /** @@ -105,7 +105,7 @@ public abstract class Measure { */ public static MeasureDouble create(String name, String description, String unit) { checkArgument( - StringUtil.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, + StringUtils.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, "Name should be a ASCII string with a length no greater than " + NAME_MAX_LENGTH + " characters."); @@ -152,7 +152,7 @@ public abstract class Measure { */ public static MeasureLong create(String name, String description, String unit) { checkArgument( - StringUtil.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, + StringUtils.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, "Name should be a ASCII string with a length no greater than " + NAME_MAX_LENGTH + " characters."); diff --git a/api/src/main/java/io/opencensus/stats/View.java b/api/src/main/java/io/opencensus/stats/View.java index fc0579e9..e3d4540d 100644 --- a/api/src/main/java/io/opencensus/stats/View.java +++ b/api/src/main/java/io/opencensus/stats/View.java @@ -22,7 +22,7 @@ import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; import io.opencensus.common.Duration; import io.opencensus.common.Function; -import io.opencensus.internal.StringUtil; +import io.opencensus.internal.StringUtils; import io.opencensus.tags.TagKey; import java.util.ArrayList; import java.util.Collections; @@ -188,7 +188,7 @@ public abstract class View { */ public static Name create(String name) { checkArgument( - StringUtil.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, + StringUtils.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, "Name should be a ASCII string with a length no greater than 255 characters."); return new AutoValue_View_Name(name); } diff --git a/api/src/main/java/io/opencensus/tags/TagKey.java b/api/src/main/java/io/opencensus/tags/TagKey.java index ceaa1b80..ba0b91ed 100644 --- a/api/src/main/java/io/opencensus/tags/TagKey.java +++ b/api/src/main/java/io/opencensus/tags/TagKey.java @@ -19,7 +19,7 @@ package io.opencensus.tags; import static com.google.common.base.Preconditions.checkArgument; import com.google.auto.value.AutoValue; -import io.opencensus.internal.StringUtil; +import io.opencensus.internal.StringUtils; import javax.annotation.concurrent.Immutable; /** @@ -80,6 +80,6 @@ public abstract class TagKey { * @return whether the name is valid. */ private static boolean isValid(String name) { - return !name.isEmpty() && name.length() <= MAX_LENGTH && StringUtil.isPrintableString(name); + return !name.isEmpty() && name.length() <= MAX_LENGTH && StringUtils.isPrintableString(name); } } diff --git a/api/src/main/java/io/opencensus/tags/TagValue.java b/api/src/main/java/io/opencensus/tags/TagValue.java index 5ba71959..95e13002 100644 --- a/api/src/main/java/io/opencensus/tags/TagValue.java +++ b/api/src/main/java/io/opencensus/tags/TagValue.java @@ -18,7 +18,7 @@ package io.opencensus.tags; import com.google.auto.value.AutoValue; import com.google.common.base.Preconditions; -import io.opencensus.internal.StringUtil; +import io.opencensus.internal.StringUtils; import javax.annotation.concurrent.Immutable; /** @@ -74,6 +74,6 @@ public abstract class TagValue { * @return whether the value is valid. */ private static boolean isValid(String value) { - return value.length() <= MAX_LENGTH && StringUtil.isPrintableString(value); + return value.length() <= MAX_LENGTH && StringUtils.isPrintableString(value); } } diff --git a/api/src/main/java/io/opencensus/trace/Span.java b/api/src/main/java/io/opencensus/trace/Span.java index c24a495b..523b9517 100644 --- a/api/src/main/java/io/opencensus/trace/Span.java +++ b/api/src/main/java/io/opencensus/trace/Span.java @@ -19,7 +19,7 @@ package io.opencensus.trace; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -import io.opencensus.trace.internal.BaseMessageEventUtil; +import io.opencensus.trace.internal.BaseMessageEventUtils; import java.util.Collections; import java.util.EnumSet; import java.util.Map; @@ -165,7 +165,7 @@ public abstract class Span { */ @Deprecated public void addNetworkEvent(NetworkEvent networkEvent) { - addMessageEvent(BaseMessageEventUtil.asMessageEvent(networkEvent)); + addMessageEvent(BaseMessageEventUtils.asMessageEvent(networkEvent)); } /** @@ -182,7 +182,7 @@ public abstract class Span { public void addMessageEvent(MessageEvent messageEvent) { // Default implementation by invoking addNetworkEvent() so that any existing derived classes, // including implementation and the mocked ones, do not need to override this method explicitly. - addNetworkEvent(BaseMessageEventUtil.asNetworkEvent(messageEvent)); + addNetworkEvent(BaseMessageEventUtils.asNetworkEvent(messageEvent)); } /** diff --git a/api/src/main/java/io/opencensus/trace/export/SpanData.java b/api/src/main/java/io/opencensus/trace/export/SpanData.java index f93193b5..34a0920d 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanData.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanData.java @@ -28,7 +28,7 @@ import io.opencensus.trace.Span; import io.opencensus.trace.SpanContext; import io.opencensus.trace.SpanId; import io.opencensus.trace.Status; -import io.opencensus.trace.internal.BaseMessageEventUtil; +import io.opencensus.trace.internal.BaseMessageEventUtils; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -101,7 +101,7 @@ public abstract class SpanData { } else { messageEventsList.add( TimedEvent.create( - timedEvent.getTimestamp(), BaseMessageEventUtil.asMessageEvent(event))); + timedEvent.getTimestamp(), BaseMessageEventUtils.asMessageEvent(event))); } } TimedEvents messageEvents = @@ -200,7 +200,7 @@ public abstract class SpanData { networkEventsList.add( TimedEvent.create( timedEvent.getTimestamp(), - BaseMessageEventUtil.asNetworkEvent(timedEvent.getEvent()))); + BaseMessageEventUtils.asNetworkEvent(timedEvent.getEvent()))); } return TimedEvents.create( networkEventsList, timedEvents.getDroppedEventsCount()); diff --git a/api/src/main/java/io/opencensus/trace/internal/BaseMessageEventUtil.java b/api/src/main/java/io/opencensus/trace/internal/BaseMessageEventUtil.java deleted file mode 100644 index 955c8859..00000000 --- a/api/src/main/java/io/opencensus/trace/internal/BaseMessageEventUtil.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2018, 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.internal; - -import static com.google.common.base.Preconditions.checkNotNull; - -import io.opencensus.common.Internal; - -/** - * Helper class to convert/cast between for {@link io.opencensus.trace.MessageEvent} and {@link - * io.opencensus.trace.NetworkEvent}. - */ -@Internal -@SuppressWarnings("deprecation") -public final class BaseMessageEventUtil { - /** - * Cast or convert a {@link io.opencensus.trace.BaseMessageEvent} to {@link - * io.opencensus.trace.MessageEvent}. - * - *

    Warning: if the input is a {@code io.opencensus.trace.NetworkEvent} and contains {@code - * kernelTimestamp} information, this information will be dropped. - * - * @param event the {@code BaseMessageEvent} that is being cast or converted. - * @return a {@code MessageEvent} representation of the input. - */ - public static io.opencensus.trace.MessageEvent asMessageEvent( - io.opencensus.trace.BaseMessageEvent event) { - checkNotNull(event); - if (event instanceof io.opencensus.trace.MessageEvent) { - return (io.opencensus.trace.MessageEvent) event; - } - io.opencensus.trace.NetworkEvent networkEvent = (io.opencensus.trace.NetworkEvent) event; - io.opencensus.trace.MessageEvent.Type type = - (networkEvent.getType() == io.opencensus.trace.NetworkEvent.Type.RECV) - ? io.opencensus.trace.MessageEvent.Type.RECEIVED - : io.opencensus.trace.MessageEvent.Type.SENT; - return io.opencensus.trace.MessageEvent.builder(type, networkEvent.getMessageId()) - .setUncompressedMessageSize(networkEvent.getUncompressedMessageSize()) - .setCompressedMessageSize(networkEvent.getCompressedMessageSize()) - .build(); - } - - /** - * Cast or convert a {@link io.opencensus.trace.BaseMessageEvent} to {@link - * io.opencensus.trace.NetworkEvent}. - * - * @param event the {@code BaseMessageEvent} that is being cast or converted. - * @return a {@code io.opencensus.trace.NetworkEvent} representation of the input. - */ - public static io.opencensus.trace.NetworkEvent asNetworkEvent( - io.opencensus.trace.BaseMessageEvent event) { - checkNotNull(event); - if (event instanceof io.opencensus.trace.NetworkEvent) { - return (io.opencensus.trace.NetworkEvent) event; - } - io.opencensus.trace.MessageEvent messageEvent = (io.opencensus.trace.MessageEvent) event; - io.opencensus.trace.NetworkEvent.Type type = - (messageEvent.getType() == io.opencensus.trace.MessageEvent.Type.RECEIVED) - ? io.opencensus.trace.NetworkEvent.Type.RECV - : io.opencensus.trace.NetworkEvent.Type.SENT; - return io.opencensus.trace.NetworkEvent.builder(type, messageEvent.getMessageId()) - .setUncompressedMessageSize(messageEvent.getUncompressedMessageSize()) - .setCompressedMessageSize(messageEvent.getCompressedMessageSize()) - .build(); - } - - private BaseMessageEventUtil() {} -} diff --git a/api/src/main/java/io/opencensus/trace/internal/BaseMessageEventUtils.java b/api/src/main/java/io/opencensus/trace/internal/BaseMessageEventUtils.java new file mode 100644 index 00000000..812ec30a --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/internal/BaseMessageEventUtils.java @@ -0,0 +1,82 @@ +/* + * Copyright 2018, 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.internal; + +import static com.google.common.base.Preconditions.checkNotNull; + +import io.opencensus.common.Internal; + +/** + * Helper class to convert/cast between for {@link io.opencensus.trace.MessageEvent} and {@link + * io.opencensus.trace.NetworkEvent}. + */ +@Internal +@SuppressWarnings("deprecation") +public final class BaseMessageEventUtils { + /** + * Cast or convert a {@link io.opencensus.trace.BaseMessageEvent} to {@link + * io.opencensus.trace.MessageEvent}. + * + *

    Warning: if the input is a {@code io.opencensus.trace.NetworkEvent} and contains {@code + * kernelTimestamp} information, this information will be dropped. + * + * @param event the {@code BaseMessageEvent} that is being cast or converted. + * @return a {@code MessageEvent} representation of the input. + */ + public static io.opencensus.trace.MessageEvent asMessageEvent( + io.opencensus.trace.BaseMessageEvent event) { + checkNotNull(event); + if (event instanceof io.opencensus.trace.MessageEvent) { + return (io.opencensus.trace.MessageEvent) event; + } + io.opencensus.trace.NetworkEvent networkEvent = (io.opencensus.trace.NetworkEvent) event; + io.opencensus.trace.MessageEvent.Type type = + (networkEvent.getType() == io.opencensus.trace.NetworkEvent.Type.RECV) + ? io.opencensus.trace.MessageEvent.Type.RECEIVED + : io.opencensus.trace.MessageEvent.Type.SENT; + return io.opencensus.trace.MessageEvent.builder(type, networkEvent.getMessageId()) + .setUncompressedMessageSize(networkEvent.getUncompressedMessageSize()) + .setCompressedMessageSize(networkEvent.getCompressedMessageSize()) + .build(); + } + + /** + * Cast or convert a {@link io.opencensus.trace.BaseMessageEvent} to {@link + * io.opencensus.trace.NetworkEvent}. + * + * @param event the {@code BaseMessageEvent} that is being cast or converted. + * @return a {@code io.opencensus.trace.NetworkEvent} representation of the input. + */ + public static io.opencensus.trace.NetworkEvent asNetworkEvent( + io.opencensus.trace.BaseMessageEvent event) { + checkNotNull(event); + if (event instanceof io.opencensus.trace.NetworkEvent) { + return (io.opencensus.trace.NetworkEvent) event; + } + io.opencensus.trace.MessageEvent messageEvent = (io.opencensus.trace.MessageEvent) event; + io.opencensus.trace.NetworkEvent.Type type = + (messageEvent.getType() == io.opencensus.trace.MessageEvent.Type.RECEIVED) + ? io.opencensus.trace.NetworkEvent.Type.RECV + : io.opencensus.trace.NetworkEvent.Type.SENT; + return io.opencensus.trace.NetworkEvent.builder(type, messageEvent.getMessageId()) + .setUncompressedMessageSize(messageEvent.getUncompressedMessageSize()) + .setCompressedMessageSize(messageEvent.getCompressedMessageSize()) + .build(); + } + + private BaseMessageEventUtils() {} +} diff --git a/api/src/test/java/io/opencensus/internal/StringUtilTest.java b/api/src/test/java/io/opencensus/internal/StringUtilTest.java deleted file mode 100644 index b5c74be0..00000000 --- a/api/src/test/java/io/opencensus/internal/StringUtilTest.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2016-17, 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.internal; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Tests for {@link StringUtil}. */ -@RunWith(JUnit4.class) -public final class StringUtilTest { - - @Test - public void isPrintableString() { - assertTrue(StringUtil.isPrintableString("abcd")); - assertFalse(StringUtil.isPrintableString("\2ab\3cd")); - } -} diff --git a/api/src/test/java/io/opencensus/internal/StringUtilsTest.java b/api/src/test/java/io/opencensus/internal/StringUtilsTest.java new file mode 100644 index 00000000..5e866940 --- /dev/null +++ b/api/src/test/java/io/opencensus/internal/StringUtilsTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 2016-17, 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.internal; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link StringUtils}. */ +@RunWith(JUnit4.class) +public final class StringUtilsTest { + + @Test + public void isPrintableString() { + assertTrue(StringUtils.isPrintableString("abcd")); + assertFalse(StringUtils.isPrintableString("\2ab\3cd")); + } +} diff --git a/api/src/test/java/io/opencensus/trace/internal/BaseMessageEventUtilTest.java b/api/src/test/java/io/opencensus/trace/internal/BaseMessageEventUtilTest.java deleted file mode 100644 index 2d02d403..00000000 --- a/api/src/test/java/io/opencensus/trace/internal/BaseMessageEventUtilTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2018, 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.internal; - -import static com.google.common.truth.Truth.assertThat; - -import io.opencensus.trace.MessageEvent; -import io.opencensus.trace.NetworkEvent; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link BaseMessageEventUtil}. */ -@RunWith(JUnit4.class) -public class BaseMessageEventUtilTest { - private static final long SENT_EVENT_ID = 12345L; - private static final long RECV_EVENT_ID = 67890L; - private static final long UNCOMPRESSED_SIZE = 100; - private static final long COMPRESSED_SIZE = 99; - - private static final MessageEvent SENT_MESSAGE_EVENT = - MessageEvent.builder(MessageEvent.Type.SENT, SENT_EVENT_ID) - .setUncompressedMessageSize(UNCOMPRESSED_SIZE) - .setCompressedMessageSize(COMPRESSED_SIZE) - .build(); - private static final MessageEvent RECV_MESSAGE_EVENT = - MessageEvent.builder(MessageEvent.Type.RECEIVED, RECV_EVENT_ID) - .setUncompressedMessageSize(UNCOMPRESSED_SIZE) - .setCompressedMessageSize(COMPRESSED_SIZE) - .build(); - private static final NetworkEvent SENT_NETWORK_EVENT = - NetworkEvent.builder(NetworkEvent.Type.SENT, SENT_EVENT_ID) - .setUncompressedMessageSize(UNCOMPRESSED_SIZE) - .setCompressedMessageSize(COMPRESSED_SIZE) - .build(); - private static final NetworkEvent RECV_NETWORK_EVENT = - NetworkEvent.builder(NetworkEvent.Type.RECV, RECV_EVENT_ID) - .setUncompressedMessageSize(UNCOMPRESSED_SIZE) - .setCompressedMessageSize(COMPRESSED_SIZE) - .build(); - - @Test - public void networkEventToMessageEvent() { - assertThat(BaseMessageEventUtil.asMessageEvent(SENT_NETWORK_EVENT)) - .isEqualTo(SENT_MESSAGE_EVENT); - assertThat(BaseMessageEventUtil.asMessageEvent(RECV_NETWORK_EVENT)) - .isEqualTo(RECV_MESSAGE_EVENT); - } - - @Test - public void messageEventToNetworkEvent() { - assertThat(BaseMessageEventUtil.asNetworkEvent(SENT_MESSAGE_EVENT)) - .isEqualTo(SENT_NETWORK_EVENT); - assertThat(BaseMessageEventUtil.asNetworkEvent(RECV_MESSAGE_EVENT)) - .isEqualTo(RECV_NETWORK_EVENT); - } -} diff --git a/api/src/test/java/io/opencensus/trace/internal/BaseMessageEventUtilsTest.java b/api/src/test/java/io/opencensus/trace/internal/BaseMessageEventUtilsTest.java new file mode 100644 index 00000000..4f8c8508 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/internal/BaseMessageEventUtilsTest.java @@ -0,0 +1,71 @@ +/* + * Copyright 2018, 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.internal; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.trace.MessageEvent; +import io.opencensus.trace.NetworkEvent; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link BaseMessageEventUtils}. */ +@RunWith(JUnit4.class) +public class BaseMessageEventUtilsTest { + private static final long SENT_EVENT_ID = 12345L; + private static final long RECV_EVENT_ID = 67890L; + private static final long UNCOMPRESSED_SIZE = 100; + private static final long COMPRESSED_SIZE = 99; + + private static final MessageEvent SENT_MESSAGE_EVENT = + MessageEvent.builder(MessageEvent.Type.SENT, SENT_EVENT_ID) + .setUncompressedMessageSize(UNCOMPRESSED_SIZE) + .setCompressedMessageSize(COMPRESSED_SIZE) + .build(); + private static final MessageEvent RECV_MESSAGE_EVENT = + MessageEvent.builder(MessageEvent.Type.RECEIVED, RECV_EVENT_ID) + .setUncompressedMessageSize(UNCOMPRESSED_SIZE) + .setCompressedMessageSize(COMPRESSED_SIZE) + .build(); + private static final NetworkEvent SENT_NETWORK_EVENT = + NetworkEvent.builder(NetworkEvent.Type.SENT, SENT_EVENT_ID) + .setUncompressedMessageSize(UNCOMPRESSED_SIZE) + .setCompressedMessageSize(COMPRESSED_SIZE) + .build(); + private static final NetworkEvent RECV_NETWORK_EVENT = + NetworkEvent.builder(NetworkEvent.Type.RECV, RECV_EVENT_ID) + .setUncompressedMessageSize(UNCOMPRESSED_SIZE) + .setCompressedMessageSize(COMPRESSED_SIZE) + .build(); + + @Test + public void networkEventToMessageEvent() { + assertThat(BaseMessageEventUtils.asMessageEvent(SENT_NETWORK_EVENT)) + .isEqualTo(SENT_MESSAGE_EVENT); + assertThat(BaseMessageEventUtils.asMessageEvent(RECV_NETWORK_EVENT)) + .isEqualTo(RECV_MESSAGE_EVENT); + } + + @Test + public void messageEventToNetworkEvent() { + assertThat(BaseMessageEventUtils.asNetworkEvent(SENT_MESSAGE_EVENT)) + .isEqualTo(SENT_NETWORK_EVENT); + assertThat(BaseMessageEventUtils.asNetworkEvent(RECV_MESSAGE_EVENT)) + .isEqualTo(RECV_NETWORK_EVENT); + } +} -- cgit v1.2.3 From 1e09da2b34cce91cab3bd40290a0e16d60042afe Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 3 Apr 2018 16:37:22 -0700 Subject: Add nullness annotations to Preconditions.checkNotNull. This commit also adds annotations to TextFormat that were required after the change in checkNotNull. --- .../java/io/opencensus/trace/propagation/TextFormat.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/propagation/TextFormat.java b/api/src/main/java/io/opencensus/trace/propagation/TextFormat.java index eaa7bf00..66d018ce 100644 --- a/api/src/main/java/io/opencensus/trace/propagation/TextFormat.java +++ b/api/src/main/java/io/opencensus/trace/propagation/TextFormat.java @@ -24,6 +24,10 @@ import java.util.Collections; import java.util.List; import javax.annotation.Nullable; +/*>>> +import org.checkerframework.checker.nullness.qual.NonNull; +*/ + /** * 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 @@ -103,7 +107,8 @@ public abstract class TextFormat { * @param setter invoked for each propagation key to add or remove. * @since 0.11 */ - public abstract void inject(SpanContext spanContext, C carrier, Setter setter); + public abstract >> extends @NonNull Object*/> void inject( + SpanContext spanContext, C carrier, Setter setter); /** * Class that allows a {@code TextFormat} to set propagated fields into a carrier. @@ -138,8 +143,8 @@ public abstract class TextFormat { * @throws SpanContextParseException if the input is invalid * @since 0.11 */ - public abstract SpanContext extract(C carrier, Getter getter) - throws SpanContextParseException; + public abstract >> extends @NonNull Object*/> SpanContext extract( + C carrier, Getter getter) throws SpanContextParseException; /** * Class that allows a {@code TextFormat} to read propagated fields from a carrier. @@ -183,14 +188,15 @@ public abstract class TextFormat { } @Override - public void inject(SpanContext spanContext, C carrier, Setter setter) { + public >> extends @NonNull Object*/> void inject( + SpanContext spanContext, C carrier, Setter setter) { checkNotNull(spanContext, "spanContext"); checkNotNull(carrier, "carrier"); checkNotNull(setter, "setter"); } @Override - public SpanContext extract(C carrier, Getter getter) { + public >> extends @NonNull Object*/> SpanContext extract(C carrier, Getter getter) { checkNotNull(carrier, "carrier"); checkNotNull(getter, "getter"); return SpanContext.INVALID; -- cgit v1.2.3 From ba8aea851d53764ec2cd45ccb76ff224c8846358 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 3 Apr 2018 16:37:22 -0700 Subject: Remove usages of Guava Precondtions from opencensus-api (issue #1081). This commit replaces the most commonly used precondtion checks with methods in a new utility class, io.opencensus.internal.Utils. --- .../main/java/io/opencensus/internal/Utils.java | 86 +++++++++++++++++++++ .../main/java/io/opencensus/stats/Aggregation.java | 5 +- .../java/io/opencensus/stats/AggregationData.java | 10 +-- .../java/io/opencensus/stats/BucketBoundaries.java | 8 +- api/src/main/java/io/opencensus/stats/Measure.java | 7 +- .../main/java/io/opencensus/stats/NoopStats.java | 18 ++--- api/src/main/java/io/opencensus/stats/View.java | 13 ++-- .../main/java/io/opencensus/stats/ViewData.java | 17 ++--- api/src/main/java/io/opencensus/tags/NoopTags.java | 22 +++--- api/src/main/java/io/opencensus/tags/TagKey.java | 5 +- api/src/main/java/io/opencensus/tags/TagValue.java | 4 +- .../main/java/io/opencensus/trace/Annotation.java | 5 +- .../java/io/opencensus/trace/AttributeValue.java | 9 +-- .../java/io/opencensus/trace/MessageEvent.java | 5 +- .../java/io/opencensus/trace/NetworkEvent.java | 5 +- api/src/main/java/io/opencensus/trace/Span.java | 8 +- .../main/java/io/opencensus/trace/SpanBuilder.java | 5 +- api/src/main/java/io/opencensus/trace/SpanId.java | 15 ++-- api/src/main/java/io/opencensus/trace/Status.java | 5 +- api/src/main/java/io/opencensus/trace/TraceId.java | 15 ++-- .../java/io/opencensus/trace/TraceOptions.java | 15 ++-- api/src/main/java/io/opencensus/trace/Tracer.java | 5 +- .../io/opencensus/trace/config/TraceParams.java | 12 +-- .../opencensus/trace/export/RunningSpanStore.java | 12 ++- .../opencensus/trace/export/SampledSpanStore.java | 29 ++++--- .../java/io/opencensus/trace/export/SpanData.java | 10 +-- .../trace/internal/BaseMessageEventUtils.java | 7 +- .../opencensus/trace/propagation/BinaryFormat.java | 7 +- .../opencensus/trace/propagation/TextFormat.java | 13 ++-- .../trace/samplers/ProbabilitySampler.java | 5 +- .../java/io/opencensus/internal/UtilsTest.java | 88 ++++++++++++++++++++++ 31 files changed, 308 insertions(+), 162 deletions(-) create mode 100644 api/src/main/java/io/opencensus/internal/Utils.java create mode 100644 api/src/test/java/io/opencensus/internal/UtilsTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/Utils.java b/api/src/main/java/io/opencensus/internal/Utils.java new file mode 100644 index 00000000..85bf3785 --- /dev/null +++ b/api/src/main/java/io/opencensus/internal/Utils.java @@ -0,0 +1,86 @@ +/* + * Copyright 2018, 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.internal; + +/*>>> +import org.checkerframework.checker.nullness.qual.NonNull; +*/ + +/** General internal utility methods. */ +public final class Utils { + + private Utils() {} + + /** + * Throws an {@link IllegalArgumentException} if the argument is false. This method is similar to + * {@code Preconditions.checkArgument(boolean, Object)} from Guava. + * + * @param isValid whether the argument check passed. + * @param message the message to use for the exception. + */ + public static void checkArgument(boolean isValid, String message) { + if (!isValid) { + throw new IllegalArgumentException(message); + } + } + + /** + * Throws an {@link IllegalStateException} if the argument is false. This method is similar to + * {@code Preconditions.checkState(boolean, Object)} from Guava. + * + * @param isValid whether the state check passed. + * @param message the message to use for the exception. + */ + public static void checkState(boolean isValid, String message) { + if (!isValid) { + throw new IllegalStateException(message); + } + } + + /** + * Validates an index in an array or other container. This method throws an {@link + * IllegalArgumentException} if the size is negative and throws an {@link + * IndexOutOfBoundsException} if the index is negative or greater than or equal to the size. This + * method is similar to {@code Preconditions.checkElementIndex(int, int)} from Guava. + * + * @param index the index to validate. + * @param size the size of the array or container. + */ + public static void checkIndex(int index, int size) { + if (size < 0) { + throw new IllegalArgumentException("Negative size: " + size); + } + if (index < 0 || index >= size) { + throw new IndexOutOfBoundsException("Index out of bounds: size=" + size + ", index=" + index); + } + } + + /** + * Throws a {@link NullPointerException} if the argument is null. This method is similar to {@code + * Preconditions.checkNotNull(Object, Object)} from Guava. + * + * @param arg the argument to check for null. + * @param message the message to use for the exception. + * @return the argument, if it passes the null check. + */ + public static >> extends @NonNull Object*/> T checkNotNull(T arg, String message) { + if (arg == null) { + throw new NullPointerException(message); + } + return arg; + } +} diff --git a/api/src/main/java/io/opencensus/stats/Aggregation.java b/api/src/main/java/io/opencensus/stats/Aggregation.java index 55ce9d96..e8579c33 100644 --- a/api/src/main/java/io/opencensus/stats/Aggregation.java +++ b/api/src/main/java/io/opencensus/stats/Aggregation.java @@ -16,10 +16,9 @@ package io.opencensus.stats; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.auto.value.AutoValue; import io.opencensus.common.Function; +import io.opencensus.internal.Utils; import javax.annotation.concurrent.Immutable; /** @@ -221,7 +220,7 @@ public abstract class Aggregation { * @since 0.8 */ public static Distribution create(BucketBoundaries bucketBoundaries) { - checkNotNull(bucketBoundaries, "bucketBoundaries should not be null."); + Utils.checkNotNull(bucketBoundaries, "bucketBoundaries should not be null."); return new AutoValue_Aggregation_Distribution(bucketBoundaries); } diff --git a/api/src/main/java/io/opencensus/stats/AggregationData.java b/api/src/main/java/io/opencensus/stats/AggregationData.java index 637621e9..716e97d8 100644 --- a/api/src/main/java/io/opencensus/stats/AggregationData.java +++ b/api/src/main/java/io/opencensus/stats/AggregationData.java @@ -16,11 +16,9 @@ package io.opencensus.stats; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.auto.value.AutoValue; import io.opencensus.common.Function; +import io.opencensus.internal.Utils; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -329,13 +327,13 @@ public abstract class AggregationData { double sumOfSquaredDeviations, List bucketCounts) { if (min != Double.POSITIVE_INFINITY || max != Double.NEGATIVE_INFINITY) { - checkArgument(min <= max, "max should be greater or equal to min."); + Utils.checkArgument(min <= max, "max should be greater or equal to min."); } - checkNotNull(bucketCounts, "bucket counts should not be null."); + Utils.checkNotNull(bucketCounts, "bucket counts should not be null."); List bucketCountsCopy = Collections.unmodifiableList(new ArrayList(bucketCounts)); for (Long bucket : bucketCountsCopy) { - checkNotNull(bucket, "bucket should not be null."); + Utils.checkNotNull(bucket, "bucket should not be null."); } return new AutoValue_AggregationData_DistributionData( diff --git a/api/src/main/java/io/opencensus/stats/BucketBoundaries.java b/api/src/main/java/io/opencensus/stats/BucketBoundaries.java index 0dcb1710..20588d59 100644 --- a/api/src/main/java/io/opencensus/stats/BucketBoundaries.java +++ b/api/src/main/java/io/opencensus/stats/BucketBoundaries.java @@ -16,10 +16,8 @@ package io.opencensus.stats; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.auto.value.AutoValue; +import io.opencensus.internal.Utils; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -42,14 +40,14 @@ public abstract class BucketBoundaries { * @since 0.8 */ public static final BucketBoundaries create(List bucketBoundaries) { - checkNotNull(bucketBoundaries, "bucketBoundaries list should not be null."); + Utils.checkNotNull(bucketBoundaries, "bucketBoundaries list should not be null."); List bucketBoundariesCopy = new ArrayList(bucketBoundaries); // Deep copy. // Check if sorted. if (bucketBoundariesCopy.size() > 1) { double lower = bucketBoundariesCopy.get(0); for (int i = 1; i < bucketBoundariesCopy.size(); i++) { double next = bucketBoundariesCopy.get(i); - checkArgument(lower < next, "Bucket boundaries not sorted."); + Utils.checkArgument(lower < next, "Bucket boundaries not sorted."); lower = next; } } diff --git a/api/src/main/java/io/opencensus/stats/Measure.java b/api/src/main/java/io/opencensus/stats/Measure.java index 7b9b833e..ddd25763 100644 --- a/api/src/main/java/io/opencensus/stats/Measure.java +++ b/api/src/main/java/io/opencensus/stats/Measure.java @@ -16,12 +16,11 @@ package io.opencensus.stats; -import static com.google.common.base.Preconditions.checkArgument; - import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; import io.opencensus.common.Function; import io.opencensus.internal.StringUtils; +import io.opencensus.internal.Utils; import javax.annotation.concurrent.Immutable; /** @@ -104,7 +103,7 @@ public abstract class Measure { * @since 0.8 */ public static MeasureDouble create(String name, String description, String unit) { - checkArgument( + Utils.checkArgument( StringUtils.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, "Name should be a ASCII string with a length no greater than " + NAME_MAX_LENGTH @@ -151,7 +150,7 @@ public abstract class Measure { * @since 0.8 */ public static MeasureLong create(String name, String description, String unit) { - checkArgument( + Utils.checkArgument( StringUtils.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, "Name should be a ASCII string with a length no greater than " + NAME_MAX_LENGTH diff --git a/api/src/main/java/io/opencensus/stats/NoopStats.java b/api/src/main/java/io/opencensus/stats/NoopStats.java index 45fb6a17..02f7c521 100644 --- a/api/src/main/java/io/opencensus/stats/NoopStats.java +++ b/api/src/main/java/io/opencensus/stats/NoopStats.java @@ -16,13 +16,9 @@ package io.opencensus.stats; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; - -import com.google.common.base.Preconditions; import io.opencensus.common.Functions; import io.opencensus.common.Timestamp; +import io.opencensus.internal.Utils; import io.opencensus.stats.Measure.MeasureDouble; import io.opencensus.stats.Measure.MeasureLong; import io.opencensus.tags.TagContext; @@ -106,8 +102,8 @@ final class NoopStats { @Override @Deprecated public void setState(StatsCollectionState state) { - Preconditions.checkNotNull(state, "state"); - checkState(!isRead, "State was already read, cannot set state."); + Utils.checkNotNull(state, "state"); + Utils.checkState(!isRead, "State was already read, cannot set state."); } } @@ -140,7 +136,7 @@ final class NoopStats { @Override public void record(TagContext tags) { - checkNotNull(tags, "tags"); + Utils.checkNotNull(tags, "tags"); } } @@ -157,11 +153,11 @@ final class NoopStats { @Override public void registerView(View newView) { - checkNotNull(newView, "newView"); + Utils.checkNotNull(newView, "newView"); synchronized (registeredViews) { exportedViews = null; View existing = registeredViews.get(newView.getName()); - checkArgument( + Utils.checkArgument( existing == null || newView.equals(existing), "A different view with the same name already exists."); if (existing == null) { @@ -174,7 +170,7 @@ final class NoopStats { @Nullable @SuppressWarnings("deprecation") public ViewData getView(View.Name name) { - checkNotNull(name, "name"); + Utils.checkNotNull(name, "name"); synchronized (registeredViews) { View view = registeredViews.get(name); if (view == null) { diff --git a/api/src/main/java/io/opencensus/stats/View.java b/api/src/main/java/io/opencensus/stats/View.java index e3d4540d..42179d58 100644 --- a/api/src/main/java/io/opencensus/stats/View.java +++ b/api/src/main/java/io/opencensus/stats/View.java @@ -16,13 +16,12 @@ package io.opencensus.stats; -import static com.google.common.base.Preconditions.checkArgument; - import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; import io.opencensus.common.Duration; import io.opencensus.common.Function; import io.opencensus.internal.StringUtils; +import io.opencensus.internal.Utils; import io.opencensus.tags.TagKey; import java.util.ArrayList; import java.util.Collections; @@ -125,7 +124,8 @@ public abstract class View { Aggregation aggregation, List columns, AggregationWindow window) { - checkArgument(new HashSet(columns).size() == columns.size(), "Columns have duplicate."); + Utils.checkArgument( + new HashSet(columns).size() == columns.size(), "Columns have duplicate."); List tagKeys = new ArrayList(columns); Collections.sort(tagKeys, TAG_KEY_COMPARATOR); @@ -151,7 +151,8 @@ public abstract class View { Measure measure, Aggregation aggregation, List columns) { - checkArgument(new HashSet(columns).size() == columns.size(), "Columns have duplicate."); + Utils.checkArgument( + new HashSet(columns).size() == columns.size(), "Columns have duplicate."); return create( name, description, measure, aggregation, columns, AggregationWindow.Cumulative.create()); } @@ -187,7 +188,7 @@ public abstract class View { * @since 0.8 */ public static Name create(String name) { - checkArgument( + Utils.checkArgument( StringUtils.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, "Name should be a ASCII string with a length no greater than 255 characters."); return new AutoValue_View_Name(name); @@ -289,7 +290,7 @@ public abstract class View { * @since 0.8 */ public static Interval create(Duration duration) { - checkArgument(duration.compareTo(ZERO) > 0, "Duration must be positive"); + Utils.checkArgument(duration.compareTo(ZERO) > 0, "Duration must be positive"); return new AutoValue_View_AggregationWindow_Interval(duration); } diff --git a/api/src/main/java/io/opencensus/stats/ViewData.java b/api/src/main/java/io/opencensus/stats/ViewData.java index 788bea76..c511edab 100644 --- a/api/src/main/java/io/opencensus/stats/ViewData.java +++ b/api/src/main/java/io/opencensus/stats/ViewData.java @@ -16,13 +16,12 @@ package io.opencensus.stats; -import static com.google.common.base.Preconditions.checkArgument; - import com.google.auto.value.AutoValue; import io.opencensus.common.Duration; import io.opencensus.common.Function; import io.opencensus.common.Functions; import io.opencensus.common.Timestamp; +import io.opencensus.internal.Utils; import io.opencensus.stats.Aggregation.Count; import io.opencensus.stats.Aggregation.Distribution; import io.opencensus.stats.Aggregation.Sum; @@ -208,7 +207,7 @@ public abstract class ViewData { new Function() { @Override public Void apply(View.AggregationWindow.Cumulative arg) { - checkArgument( + Utils.checkArgument( windowData instanceof AggregationWindowData.CumulativeData, createErrorMessageForWindow(arg, windowData)); return null; @@ -217,7 +216,7 @@ public abstract class ViewData { new Function() { @Override public Void apply(View.AggregationWindow.Interval arg) { - checkArgument( + Utils.checkArgument( windowData instanceof AggregationWindowData.IntervalData, createErrorMessageForWindow(arg, windowData)); return null; @@ -245,7 +244,7 @@ public abstract class ViewData { new Function() { @Override public Void apply(MeasureDouble arg) { - checkArgument( + Utils.checkArgument( aggregationData instanceof SumDataDouble, createErrorMessageForAggregation(aggregation, aggregationData)); return null; @@ -254,7 +253,7 @@ public abstract class ViewData { new Function() { @Override public Void apply(MeasureLong arg) { - checkArgument( + Utils.checkArgument( aggregationData instanceof SumDataLong, createErrorMessageForAggregation(aggregation, aggregationData)); return null; @@ -267,7 +266,7 @@ public abstract class ViewData { new Function() { @Override public Void apply(Count arg) { - checkArgument( + Utils.checkArgument( aggregationData instanceof CountData, createErrorMessageForAggregation(aggregation, aggregationData)); return null; @@ -276,7 +275,7 @@ public abstract class ViewData { new Function() { @Override public Void apply(Aggregation.Mean arg) { - checkArgument( + Utils.checkArgument( aggregationData instanceof AggregationData.MeanData, createErrorMessageForAggregation(aggregation, aggregationData)); return null; @@ -285,7 +284,7 @@ public abstract class ViewData { new Function() { @Override public Void apply(Distribution arg) { - checkArgument( + Utils.checkArgument( aggregationData instanceof DistributionData, createErrorMessageForAggregation(aggregation, aggregationData)); return null; diff --git a/api/src/main/java/io/opencensus/tags/NoopTags.java b/api/src/main/java/io/opencensus/tags/NoopTags.java index 973a1b40..fb52b164 100644 --- a/api/src/main/java/io/opencensus/tags/NoopTags.java +++ b/api/src/main/java/io/opencensus/tags/NoopTags.java @@ -16,11 +16,9 @@ package io.opencensus.tags; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.base.Preconditions; import io.opencensus.common.Scope; import io.opencensus.internal.NoopScope; +import io.opencensus.internal.Utils; import io.opencensus.tags.propagation.TagContextBinarySerializer; import io.opencensus.tags.propagation.TagPropagationComponent; import java.util.Collections; @@ -105,8 +103,8 @@ final class NoopTags { @Override @Deprecated public void setState(TaggingState state) { - Preconditions.checkNotNull(state, "state"); - Preconditions.checkState(!isRead, "State was already read, cannot set state."); + Utils.checkNotNull(state, "state"); + Utils.checkState(!isRead, "State was already read, cannot set state."); } } @@ -131,7 +129,7 @@ final class NoopTags { @Override public TagContextBuilder toBuilder(TagContext tags) { - checkNotNull(tags, "tags"); + Utils.checkNotNull(tags, "tags"); return getNoopTagContextBuilder(); } @@ -142,7 +140,7 @@ final class NoopTags { @Override public Scope withTagContext(TagContext tags) { - checkNotNull(tags, "tags"); + Utils.checkNotNull(tags, "tags"); return NoopScope.getInstance(); } } @@ -153,14 +151,14 @@ final class NoopTags { @Override public TagContextBuilder put(TagKey key, TagValue value) { - checkNotNull(key, "key"); - checkNotNull(value, "value"); + Utils.checkNotNull(key, "key"); + Utils.checkNotNull(value, "value"); return this; } @Override public TagContextBuilder remove(TagKey key) { - checkNotNull(key, "key"); + Utils.checkNotNull(key, "key"); return this; } @@ -203,13 +201,13 @@ final class NoopTags { @Override public byte[] toByteArray(TagContext tags) { - checkNotNull(tags, "tags"); + Utils.checkNotNull(tags, "tags"); return EMPTY_BYTE_ARRAY; } @Override public TagContext fromByteArray(byte[] bytes) { - checkNotNull(bytes, "bytes"); + Utils.checkNotNull(bytes, "bytes"); return getNoopTagContext(); } } diff --git a/api/src/main/java/io/opencensus/tags/TagKey.java b/api/src/main/java/io/opencensus/tags/TagKey.java index ba0b91ed..615c2d46 100644 --- a/api/src/main/java/io/opencensus/tags/TagKey.java +++ b/api/src/main/java/io/opencensus/tags/TagKey.java @@ -16,10 +16,9 @@ package io.opencensus.tags; -import static com.google.common.base.Preconditions.checkArgument; - import com.google.auto.value.AutoValue; import io.opencensus.internal.StringUtils; +import io.opencensus.internal.Utils; import javax.annotation.concurrent.Immutable; /** @@ -61,7 +60,7 @@ public abstract class TagKey { * @since 0.8 */ public static TagKey create(String name) { - checkArgument(isValid(name)); + Utils.checkArgument(isValid(name), "Invalid TagKey name: " + name); return new AutoValue_TagKey(name); } diff --git a/api/src/main/java/io/opencensus/tags/TagValue.java b/api/src/main/java/io/opencensus/tags/TagValue.java index 95e13002..5c1019ff 100644 --- a/api/src/main/java/io/opencensus/tags/TagValue.java +++ b/api/src/main/java/io/opencensus/tags/TagValue.java @@ -17,8 +17,8 @@ package io.opencensus.tags; import com.google.auto.value.AutoValue; -import com.google.common.base.Preconditions; import io.opencensus.internal.StringUtils; +import io.opencensus.internal.Utils; import javax.annotation.concurrent.Immutable; /** @@ -55,7 +55,7 @@ public abstract class TagValue { * @since 0.8 */ public static TagValue create(String value) { - Preconditions.checkArgument(isValid(value)); + Utils.checkArgument(isValid(value), "Invalid TagValue: " + value); return new AutoValue_TagValue(value); } diff --git a/api/src/main/java/io/opencensus/trace/Annotation.java b/api/src/main/java/io/opencensus/trace/Annotation.java index 5eb3a505..97f2fdd2 100644 --- a/api/src/main/java/io/opencensus/trace/Annotation.java +++ b/api/src/main/java/io/opencensus/trace/Annotation.java @@ -16,9 +16,8 @@ package io.opencensus.trace; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.auto.value.AutoValue; +import io.opencensus.internal.Utils; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -61,7 +60,7 @@ public abstract class Annotation { return new AutoValue_Annotation( description, Collections.unmodifiableMap( - new HashMap(checkNotNull(attributes, "attributes")))); + new HashMap(Utils.checkNotNull(attributes, "attributes")))); } /** diff --git a/api/src/main/java/io/opencensus/trace/AttributeValue.java b/api/src/main/java/io/opencensus/trace/AttributeValue.java index b4759fd2..a8d4e1e3 100644 --- a/api/src/main/java/io/opencensus/trace/AttributeValue.java +++ b/api/src/main/java/io/opencensus/trace/AttributeValue.java @@ -16,10 +16,9 @@ package io.opencensus.trace; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.auto.value.AutoValue; import io.opencensus.common.Function; +import io.opencensus.internal.Utils; import javax.annotation.concurrent.Immutable; /** @@ -94,7 +93,7 @@ public abstract class AttributeValue { static AttributeValue create(String stringValue) { return new AutoValue_AttributeValue_AttributeValueString( - checkNotNull(stringValue, "stringValue")); + Utils.checkNotNull(stringValue, "stringValue")); } @Override @@ -117,7 +116,7 @@ public abstract class AttributeValue { static AttributeValue create(Boolean stringValue) { return new AutoValue_AttributeValue_AttributeValueBoolean( - checkNotNull(stringValue, "stringValue")); + Utils.checkNotNull(stringValue, "stringValue")); } @Override @@ -140,7 +139,7 @@ public abstract class AttributeValue { static AttributeValue create(Long stringValue) { return new AutoValue_AttributeValue_AttributeValueLong( - checkNotNull(stringValue, "stringValue")); + Utils.checkNotNull(stringValue, "stringValue")); } @Override diff --git a/api/src/main/java/io/opencensus/trace/MessageEvent.java b/api/src/main/java/io/opencensus/trace/MessageEvent.java index 3be65f52..4b693aaa 100644 --- a/api/src/main/java/io/opencensus/trace/MessageEvent.java +++ b/api/src/main/java/io/opencensus/trace/MessageEvent.java @@ -16,9 +16,8 @@ package io.opencensus.trace; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.auto.value.AutoValue; +import io.opencensus.internal.Utils; import javax.annotation.concurrent.Immutable; /** @@ -66,7 +65,7 @@ public abstract class MessageEvent extends BaseMessageEvent { */ public static Builder builder(Type type, long messageId) { return new AutoValue_MessageEvent.Builder() - .setType(checkNotNull(type, "type")) + .setType(Utils.checkNotNull(type, "type")) .setMessageId(messageId) // We need to set a value for the message size because the autovalue requires all // primitives to be initialized. diff --git a/api/src/main/java/io/opencensus/trace/NetworkEvent.java b/api/src/main/java/io/opencensus/trace/NetworkEvent.java index f12597f9..fafedf8e 100644 --- a/api/src/main/java/io/opencensus/trace/NetworkEvent.java +++ b/api/src/main/java/io/opencensus/trace/NetworkEvent.java @@ -16,10 +16,9 @@ package io.opencensus.trace; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.auto.value.AutoValue; import io.opencensus.common.Timestamp; +import io.opencensus.internal.Utils; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; @@ -67,7 +66,7 @@ public abstract class NetworkEvent extends io.opencensus.trace.BaseMessageEvent */ public static Builder builder(Type type, long messageId) { return new AutoValue_NetworkEvent.Builder() - .setType(checkNotNull(type, "type")) + .setType(Utils.checkNotNull(type, "type")) .setMessageId(messageId) // We need to set a value for the message size because the autovalue requires all // primitives to be initialized. diff --git a/api/src/main/java/io/opencensus/trace/Span.java b/api/src/main/java/io/opencensus/trace/Span.java index 523b9517..4a8c6f04 100644 --- a/api/src/main/java/io/opencensus/trace/Span.java +++ b/api/src/main/java/io/opencensus/trace/Span.java @@ -16,9 +16,7 @@ package io.opencensus.trace; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - +import io.opencensus.internal.Utils; import io.opencensus.trace.internal.BaseMessageEventUtils; import java.util.Collections; import java.util.EnumSet; @@ -76,12 +74,12 @@ public abstract class Span { * @since 0.5 */ protected Span(SpanContext context, @Nullable EnumSet options) { - this.context = checkNotNull(context, "context"); + this.context = Utils.checkNotNull(context, "context"); this.options = options == null ? DEFAULT_OPTIONS : Collections.unmodifiableSet(EnumSet.copyOf(options)); - checkArgument( + Utils.checkArgument( !context.getTraceOptions().isSampled() || (this.options.contains(Options.RECORD_EVENTS)), "Span is sampled, but does not have RECORD_EVENTS set."); } diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java index ee68d109..f10cb7c0 100644 --- a/api/src/main/java/io/opencensus/trace/SpanBuilder.java +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -16,10 +16,9 @@ package io.opencensus.trace; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.errorprone.annotations.MustBeClosed; import io.opencensus.common.Scope; +import io.opencensus.internal.Utils; import java.util.List; import java.util.concurrent.Callable; import javax.annotation.Nullable; @@ -324,7 +323,7 @@ public abstract class SpanBuilder { } private NoopSpanBuilder(String name) { - checkNotNull(name, "name"); + Utils.checkNotNull(name, "name"); } } } diff --git a/api/src/main/java/io/opencensus/trace/SpanId.java b/api/src/main/java/io/opencensus/trace/SpanId.java index eee5f497..859950c7 100644 --- a/api/src/main/java/io/opencensus/trace/SpanId.java +++ b/api/src/main/java/io/opencensus/trace/SpanId.java @@ -16,11 +16,9 @@ package io.opencensus.trace; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.common.base.MoreObjects; import com.google.common.io.BaseEncoding; +import io.opencensus.internal.Utils; import java.util.Arrays; import java.util.Random; import javax.annotation.Nullable; @@ -71,8 +69,10 @@ public final class SpanId implements Comparable { * @since 0.5 */ public static SpanId fromBytes(byte[] buffer) { - checkNotNull(buffer, "buffer"); - checkArgument(buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); + Utils.checkNotNull(buffer, "buffer"); + Utils.checkArgument( + buffer.length == SIZE, + String.format("Invalid size: expected %s, got %s", SIZE, buffer.length)); byte[] bytesCopied = Arrays.copyOf(buffer, SIZE); return new SpanId(bytesCopied); } @@ -107,8 +107,9 @@ public final class SpanId implements Comparable { * @since 0.11 */ public static SpanId fromLowerBase16(CharSequence src) { - checkArgument( - src.length() == 2 * SIZE, "Invalid size: expected %s, got %s", 2 * SIZE, src.length()); + Utils.checkArgument( + src.length() == 2 * SIZE, + String.format("Invalid size: expected %s, got %s", 2 * SIZE, src.length())); byte[] bytes = BaseEncoding.base16().lowerCase().decode(src); return new SpanId(bytes); } diff --git a/api/src/main/java/io/opencensus/trace/Status.java b/api/src/main/java/io/opencensus/trace/Status.java index b8c6b7a1..0a0e45ce 100644 --- a/api/src/main/java/io/opencensus/trace/Status.java +++ b/api/src/main/java/io/opencensus/trace/Status.java @@ -16,11 +16,10 @@ package io.opencensus.trace; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; import com.google.common.base.Objects; +import io.opencensus.internal.Utils; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -386,7 +385,7 @@ public final class Status { @Nullable private final String description; private Status(CanonicalCode canonicalCode, @Nullable String description) { - this.canonicalCode = checkNotNull(canonicalCode, "canonicalCode"); + this.canonicalCode = Utils.checkNotNull(canonicalCode, "canonicalCode"); this.description = description; } diff --git a/api/src/main/java/io/opencensus/trace/TraceId.java b/api/src/main/java/io/opencensus/trace/TraceId.java index 6378bf58..5683d750 100644 --- a/api/src/main/java/io/opencensus/trace/TraceId.java +++ b/api/src/main/java/io/opencensus/trace/TraceId.java @@ -16,12 +16,10 @@ package io.opencensus.trace; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.common.base.MoreObjects; import com.google.common.io.BaseEncoding; import io.opencensus.common.Internal; +import io.opencensus.internal.Utils; import java.util.Arrays; import java.util.Random; import javax.annotation.Nullable; @@ -72,8 +70,10 @@ public final class TraceId implements Comparable { * @since 0.5 */ public static TraceId fromBytes(byte[] buffer) { - checkNotNull(buffer, "buffer"); - checkArgument(buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); + Utils.checkNotNull(buffer, "buffer"); + Utils.checkArgument( + buffer.length == SIZE, + String.format("Invalid size: expected %s, got %s", SIZE, buffer.length)); byte[] bytesCopied = Arrays.copyOf(buffer, SIZE); return new TraceId(bytesCopied); } @@ -108,8 +108,9 @@ public final class TraceId implements Comparable { * @since 0.11 */ public static TraceId fromLowerBase16(CharSequence src) { - checkArgument( - src.length() == 2 * SIZE, "Invalid size: expected %s, got %s", 2 * SIZE, src.length()); + Utils.checkArgument( + src.length() == 2 * SIZE, + String.format("Invalid size: expected %s, got %s", 2 * SIZE, src.length())); byte[] bytes = BaseEncoding.base16().lowerCase().decode(src); return new TraceId(bytes); } diff --git a/api/src/main/java/io/opencensus/trace/TraceOptions.java b/api/src/main/java/io/opencensus/trace/TraceOptions.java index bd6fe6bd..ee09376f 100644 --- a/api/src/main/java/io/opencensus/trace/TraceOptions.java +++ b/api/src/main/java/io/opencensus/trace/TraceOptions.java @@ -16,13 +16,10 @@ package io.opencensus.trace; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkElementIndex; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; import com.google.common.base.Objects; +import io.opencensus.internal.Utils; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; @@ -78,8 +75,10 @@ public final class TraceOptions { * @since 0.5 */ public static TraceOptions fromBytes(byte[] buffer) { - checkNotNull(buffer, "buffer"); - checkArgument(buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); + Utils.checkNotNull(buffer, "buffer"); + Utils.checkArgument( + buffer.length == SIZE, + String.format("Invalid size: expected %s, got %s", SIZE, buffer.length)); return new TraceOptions(buffer[0]); } @@ -97,7 +96,7 @@ public final class TraceOptions { * @since 0.5 */ public static TraceOptions fromBytes(byte[] src, int srcOffset) { - checkElementIndex(srcOffset, src.length); + Utils.checkIndex(srcOffset, src.length); return new TraceOptions(src[srcOffset]); } @@ -131,7 +130,7 @@ public final class TraceOptions { * @since 0.5 */ public void copyBytesTo(byte[] dest, int destOffset) { - checkElementIndex(destOffset, dest.length); + Utils.checkIndex(destOffset, dest.length); dest[destOffset] = options; } diff --git a/api/src/main/java/io/opencensus/trace/Tracer.java b/api/src/main/java/io/opencensus/trace/Tracer.java index f4ac8c65..b83fbed6 100644 --- a/api/src/main/java/io/opencensus/trace/Tracer.java +++ b/api/src/main/java/io/opencensus/trace/Tracer.java @@ -16,10 +16,9 @@ package io.opencensus.trace; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.errorprone.annotations.MustBeClosed; import io.opencensus.common.Scope; +import io.opencensus.internal.Utils; import io.opencensus.trace.SpanBuilder.NoopSpanBuilder; import java.util.concurrent.Callable; import javax.annotation.Nullable; @@ -152,7 +151,7 @@ public abstract class Tracer { */ @MustBeClosed public final Scope withSpan(Span span) { - return CurrentSpanUtils.withSpan(checkNotNull(span, "span"), /* endSpan= */ false); + return CurrentSpanUtils.withSpan(Utils.checkNotNull(span, "span"), /* endSpan= */ false); } /** diff --git a/api/src/main/java/io/opencensus/trace/config/TraceParams.java b/api/src/main/java/io/opencensus/trace/config/TraceParams.java index 7594e696..d10642a8 100644 --- a/api/src/main/java/io/opencensus/trace/config/TraceParams.java +++ b/api/src/main/java/io/opencensus/trace/config/TraceParams.java @@ -16,9 +16,8 @@ package io.opencensus.trace.config; -import static com.google.common.base.Preconditions.checkArgument; - import com.google.auto.value.AutoValue; +import io.opencensus.internal.Utils; import io.opencensus.trace.Annotation; import io.opencensus.trace.Link; import io.opencensus.trace.MessageEvent; @@ -209,10 +208,11 @@ public abstract class TraceParams { */ public TraceParams build() { TraceParams traceParams = autoBuild(); - checkArgument(traceParams.getMaxNumberOfAttributes() > 0, "maxNumberOfAttributes"); - checkArgument(traceParams.getMaxNumberOfAnnotations() > 0, "maxNumberOfAnnotations"); - checkArgument(traceParams.getMaxNumberOfMessageEvents() > 0, "maxNumberOfMessageEvents"); - checkArgument(traceParams.getMaxNumberOfLinks() > 0, "maxNumberOfLinks"); + Utils.checkArgument(traceParams.getMaxNumberOfAttributes() > 0, "maxNumberOfAttributes"); + Utils.checkArgument(traceParams.getMaxNumberOfAnnotations() > 0, "maxNumberOfAnnotations"); + Utils.checkArgument( + traceParams.getMaxNumberOfMessageEvents() > 0, "maxNumberOfMessageEvents"); + Utils.checkArgument(traceParams.getMaxNumberOfLinks() > 0, "maxNumberOfLinks"); return traceParams; } } diff --git a/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java b/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java index aa05e4fe..fac3c855 100644 --- a/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/RunningSpanStore.java @@ -16,10 +16,8 @@ package io.opencensus.trace.export; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.auto.value.AutoValue; +import io.opencensus.internal.Utils; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -92,7 +90,7 @@ public abstract class RunningSpanStore { return new AutoValue_RunningSpanStore_Summary( Collections.unmodifiableMap( new HashMap( - checkNotNull(perSpanNameSummary, "perSpanNameSummary")))); + Utils.checkNotNull(perSpanNameSummary, "perSpanNameSummary")))); } /** @@ -124,7 +122,7 @@ public abstract class RunningSpanStore { * @since 0.5 */ public static PerSpanNameSummary create(int numRunningSpans) { - checkArgument(numRunningSpans >= 0, "Negative numRunningSpans."); + Utils.checkArgument(numRunningSpans >= 0, "Negative numRunningSpans."); return new AutoValue_RunningSpanStore_PerSpanNameSummary(numRunningSpans); } @@ -163,7 +161,7 @@ public abstract class RunningSpanStore { * @since 0.5 */ public static Filter create(String spanName, int maxSpansToReturn) { - checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); + Utils.checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); return new AutoValue_RunningSpanStore_Filter(spanName, maxSpansToReturn); } @@ -196,7 +194,7 @@ public abstract class RunningSpanStore { @Override public Collection getRunningSpans(Filter filter) { - checkNotNull(filter, "filter"); + Utils.checkNotNull(filter, "filter"); return Collections.emptyList(); } } diff --git a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java index 5e7f4dd6..3ee80ce2 100644 --- a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java @@ -16,11 +16,9 @@ package io.opencensus.trace.export; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; +import io.opencensus.internal.Utils; import io.opencensus.trace.Span; import io.opencensus.trace.Status; import io.opencensus.trace.Status.CanonicalCode; @@ -157,7 +155,7 @@ public abstract class SampledSpanStore { return new AutoValue_SampledSpanStore_Summary( Collections.unmodifiableMap( new HashMap( - checkNotNull(perSpanNameSummary, "perSpanNameSummary")))); + Utils.checkNotNull(perSpanNameSummary, "perSpanNameSummary")))); } /** @@ -196,10 +194,11 @@ public abstract class SampledSpanStore { return new AutoValue_SampledSpanStore_PerSpanNameSummary( Collections.unmodifiableMap( new HashMap( - checkNotNull(numbersOfLatencySampledSpans, "numbersOfLatencySampledSpans"))), + Utils.checkNotNull( + numbersOfLatencySampledSpans, "numbersOfLatencySampledSpans"))), Collections.unmodifiableMap( new HashMap( - checkNotNull(numbersOfErrorSampledSpans, "numbersOfErrorSampledSpans")))); + Utils.checkNotNull(numbersOfErrorSampledSpans, "numbersOfErrorSampledSpans")))); } /** @@ -361,9 +360,9 @@ public abstract class SampledSpanStore { */ public static LatencyFilter create( String spanName, long latencyLowerNs, long latencyUpperNs, int maxSpansToReturn) { - checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); - checkArgument(latencyLowerNs >= 0, "Negative latencyLowerNs"); - checkArgument(latencyUpperNs >= 0, "Negative latencyUpperNs"); + Utils.checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); + Utils.checkArgument(latencyLowerNs >= 0, "Negative latencyLowerNs"); + Utils.checkArgument(latencyUpperNs >= 0, "Negative latencyUpperNs"); return new AutoValue_SampledSpanStore_LatencyFilter( spanName, latencyLowerNs, latencyUpperNs, maxSpansToReturn); } @@ -432,9 +431,9 @@ public abstract class SampledSpanStore { public static ErrorFilter create( String spanName, @Nullable CanonicalCode canonicalCode, int maxSpansToReturn) { if (canonicalCode != null) { - checkArgument(canonicalCode != CanonicalCode.OK, "Invalid canonical code."); + Utils.checkArgument(canonicalCode != CanonicalCode.OK, "Invalid canonical code."); } - checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); + Utils.checkArgument(maxSpansToReturn >= 0, "Negative maxSpansToReturn."); return new AutoValue_SampledSpanStore_ErrorFilter(spanName, canonicalCode, maxSpansToReturn); } @@ -489,19 +488,19 @@ public abstract class SampledSpanStore { @Override public Collection getLatencySampledSpans(LatencyFilter filter) { - checkNotNull(filter, "latencyFilter"); + Utils.checkNotNull(filter, "latencyFilter"); return Collections.emptyList(); } @Override public Collection getErrorSampledSpans(ErrorFilter filter) { - checkNotNull(filter, "errorFilter"); + Utils.checkNotNull(filter, "errorFilter"); return Collections.emptyList(); } @Override public void registerSpanNamesForCollection(Collection spanNames) { - checkNotNull(spanNames, "spanNames"); + Utils.checkNotNull(spanNames, "spanNames"); synchronized (registeredSpanNames) { registeredSpanNames.addAll(spanNames); } @@ -509,7 +508,7 @@ public abstract class SampledSpanStore { @Override public void unregisterSpanNamesForCollection(Collection spanNames) { - checkNotNull(spanNames); + Utils.checkNotNull(spanNames, "spanNames"); synchronized (registeredSpanNames) { registeredSpanNames.removeAll(spanNames); } diff --git a/api/src/main/java/io/opencensus/trace/export/SpanData.java b/api/src/main/java/io/opencensus/trace/export/SpanData.java index 34a0920d..7b1daf42 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanData.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanData.java @@ -16,10 +16,9 @@ package io.opencensus.trace.export; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.auto.value.AutoValue; import io.opencensus.common.Timestamp; +import io.opencensus.internal.Utils; import io.opencensus.trace.Annotation; import io.opencensus.trace.AttributeValue; import io.opencensus.trace.Link; @@ -319,7 +318,7 @@ public abstract class SpanData { public static TimedEvents create(List> events, int droppedEventsCount) { return new AutoValue_SpanData_TimedEvents( Collections.unmodifiableList( - new ArrayList>(checkNotNull(events, "events"))), + new ArrayList>(Utils.checkNotNull(events, "events"))), droppedEventsCount); } @@ -364,7 +363,8 @@ public abstract class SpanData { // for others on account of determinism. return new AutoValue_SpanData_Attributes( Collections.unmodifiableMap( - new HashMap(checkNotNull(attributeMap, "attributeMap"))), + new HashMap( + Utils.checkNotNull(attributeMap, "attributeMap"))), droppedAttributesCount); } @@ -405,7 +405,7 @@ public abstract class SpanData { */ public static Links create(List links, int droppedLinksCount) { return new AutoValue_SpanData_Links( - Collections.unmodifiableList(new ArrayList(checkNotNull(links, "links"))), + Collections.unmodifiableList(new ArrayList(Utils.checkNotNull(links, "links"))), droppedLinksCount); } diff --git a/api/src/main/java/io/opencensus/trace/internal/BaseMessageEventUtils.java b/api/src/main/java/io/opencensus/trace/internal/BaseMessageEventUtils.java index 812ec30a..9d22a1c6 100644 --- a/api/src/main/java/io/opencensus/trace/internal/BaseMessageEventUtils.java +++ b/api/src/main/java/io/opencensus/trace/internal/BaseMessageEventUtils.java @@ -16,9 +16,8 @@ package io.opencensus.trace.internal; -import static com.google.common.base.Preconditions.checkNotNull; - import io.opencensus.common.Internal; +import io.opencensus.internal.Utils; /** * Helper class to convert/cast between for {@link io.opencensus.trace.MessageEvent} and {@link @@ -39,7 +38,7 @@ public final class BaseMessageEventUtils { */ public static io.opencensus.trace.MessageEvent asMessageEvent( io.opencensus.trace.BaseMessageEvent event) { - checkNotNull(event); + Utils.checkNotNull(event, "event"); if (event instanceof io.opencensus.trace.MessageEvent) { return (io.opencensus.trace.MessageEvent) event; } @@ -63,7 +62,7 @@ public final class BaseMessageEventUtils { */ public static io.opencensus.trace.NetworkEvent asNetworkEvent( io.opencensus.trace.BaseMessageEvent event) { - checkNotNull(event); + Utils.checkNotNull(event, "event"); if (event instanceof io.opencensus.trace.NetworkEvent) { return (io.opencensus.trace.NetworkEvent) event; } diff --git a/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java b/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java index e07afd12..da7ea4cc 100644 --- a/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java +++ b/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java @@ -16,8 +16,7 @@ package io.opencensus.trace.propagation; -import static com.google.common.base.Preconditions.checkNotNull; - +import io.opencensus.internal.Utils; import io.opencensus.trace.SpanContext; import java.text.ParseException; @@ -138,13 +137,13 @@ public abstract class BinaryFormat { private static final class NoopBinaryFormat extends BinaryFormat { @Override public byte[] toByteArray(SpanContext spanContext) { - checkNotNull(spanContext, "spanContext"); + Utils.checkNotNull(spanContext, "spanContext"); return new byte[0]; } @Override public SpanContext fromByteArray(byte[] bytes) { - checkNotNull(bytes, "bytes"); + Utils.checkNotNull(bytes, "bytes"); return SpanContext.INVALID; } diff --git a/api/src/main/java/io/opencensus/trace/propagation/TextFormat.java b/api/src/main/java/io/opencensus/trace/propagation/TextFormat.java index 66d018ce..d52e71f1 100644 --- a/api/src/main/java/io/opencensus/trace/propagation/TextFormat.java +++ b/api/src/main/java/io/opencensus/trace/propagation/TextFormat.java @@ -16,9 +16,8 @@ package io.opencensus.trace.propagation; -import static com.google.common.base.Preconditions.checkNotNull; - import io.opencensus.common.ExperimentalApi; +import io.opencensus.internal.Utils; import io.opencensus.trace.SpanContext; import java.util.Collections; import java.util.List; @@ -190,15 +189,15 @@ public abstract class TextFormat { @Override public >> extends @NonNull Object*/> void inject( SpanContext spanContext, C carrier, Setter setter) { - checkNotNull(spanContext, "spanContext"); - checkNotNull(carrier, "carrier"); - checkNotNull(setter, "setter"); + Utils.checkNotNull(spanContext, "spanContext"); + Utils.checkNotNull(carrier, "carrier"); + Utils.checkNotNull(setter, "setter"); } @Override public >> extends @NonNull Object*/> SpanContext extract(C carrier, Getter getter) { - checkNotNull(carrier, "carrier"); - checkNotNull(getter, "getter"); + Utils.checkNotNull(carrier, "carrier"); + Utils.checkNotNull(getter, "getter"); return SpanContext.INVALID; } } diff --git a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java index 21d4d6ca..b9c18e00 100644 --- a/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java +++ b/api/src/main/java/io/opencensus/trace/samplers/ProbabilitySampler.java @@ -16,9 +16,8 @@ package io.opencensus.trace.samplers; -import static com.google.common.base.Preconditions.checkArgument; - import com.google.auto.value.AutoValue; +import io.opencensus.internal.Utils; import io.opencensus.trace.Sampler; import io.opencensus.trace.Span; import io.opencensus.trace.SpanContext; @@ -54,7 +53,7 @@ abstract class ProbabilitySampler extends Sampler { * @throws IllegalArgumentException if {@code probability} is out of range */ static ProbabilitySampler create(double probability) { - checkArgument( + Utils.checkArgument( probability >= 0.0 && probability <= 1.0, "probability must be in range [0.0, 1.0]"); long idUpperBound; // Special case the limits, to avoid any possible issues with lack of precision across diff --git a/api/src/test/java/io/opencensus/internal/UtilsTest.java b/api/src/test/java/io/opencensus/internal/UtilsTest.java new file mode 100644 index 00000000..2416eeb8 --- /dev/null +++ b/api/src/test/java/io/opencensus/internal/UtilsTest.java @@ -0,0 +1,88 @@ +/* + * Copyright 2018, 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.internal; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link Utils}. */ +@RunWith(JUnit4.class) +public final class UtilsTest { + private static final String TEST_MESSAGE = "test message"; + + @Rule public ExpectedException thrown = ExpectedException.none(); + + @Test + public void checkArgument() { + Utils.checkArgument(true, TEST_MESSAGE); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage(TEST_MESSAGE); + Utils.checkArgument(false, TEST_MESSAGE); + } + + @Test + public void checkState() { + Utils.checkNotNull(true, TEST_MESSAGE); + thrown.expect(IllegalStateException.class); + thrown.expectMessage(TEST_MESSAGE); + Utils.checkState(false, TEST_MESSAGE); + } + + @Test + public void checkNotNull() { + Utils.checkNotNull(new Object(), TEST_MESSAGE); + thrown.expect(NullPointerException.class); + thrown.expectMessage(TEST_MESSAGE); + Utils.checkNotNull(null, TEST_MESSAGE); + } + + @Test + public void checkIndex_Valid() { + Utils.checkIndex(1, 2); + } + + @Test + public void checkIndex_NegativeSize() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Negative size: -1"); + Utils.checkIndex(0, -1); + } + + @Test + public void checkIndex_NegativeIndex() { + thrown.expect(IndexOutOfBoundsException.class); + thrown.expectMessage("Index out of bounds: size=10, index=-2"); + Utils.checkIndex(-2, 10); + } + + @Test + public void checkIndex_IndexEqualToSize() { + thrown.expect(IndexOutOfBoundsException.class); + thrown.expectMessage("Index out of bounds: size=5, index=5"); + Utils.checkIndex(5, 5); + } + + @Test + public void checkIndex_IndexGreaterThanSize() { + thrown.expect(IndexOutOfBoundsException.class); + thrown.expectMessage("Index out of bounds: size=10, index=11"); + Utils.checkIndex(11, 10); + } +} -- cgit v1.2.3 From 37730f70bdd2ee7ff214cc4ed7fb3d451a6dada7 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 3 Apr 2018 16:37:22 -0700 Subject: Remove usages of Guava LongMath from opencensus-api (issue #1081). --- .../main/java/io/opencensus/common/Duration.java | 6 ++--- .../main/java/io/opencensus/common/Timestamp.java | 16 +++++------ .../main/java/io/opencensus/internal/Utils.java | 31 ++++++++++++++++++++++ .../java/io/opencensus/internal/UtilsTest.java | 30 +++++++++++++++++++++ 4 files changed, 72 insertions(+), 11 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Duration.java b/api/src/main/java/io/opencensus/common/Duration.java index c20bbda7..1ee97191 100644 --- a/api/src/main/java/io/opencensus/common/Duration.java +++ b/api/src/main/java/io/opencensus/common/Duration.java @@ -22,7 +22,7 @@ import static io.opencensus.common.TimeUtils.MILLIS_PER_SECOND; import static io.opencensus.common.TimeUtils.NANOS_PER_MILLI; import com.google.auto.value.AutoValue; -import com.google.common.primitives.Longs; +import io.opencensus.internal.Utils; import javax.annotation.concurrent.Immutable; /** @@ -104,11 +104,11 @@ public abstract class Duration implements Comparable { */ @Override public int compareTo(Duration otherDuration) { - int cmp = Longs.compare(getSeconds(), otherDuration.getSeconds()); + int cmp = Utils.compareLongs(getSeconds(), otherDuration.getSeconds()); if (cmp != 0) { return cmp; } - return Longs.compare(getNanos(), otherDuration.getNanos()); + return Utils.compareLongs(getNanos(), otherDuration.getNanos()); } Duration() {} diff --git a/api/src/main/java/io/opencensus/common/Timestamp.java b/api/src/main/java/io/opencensus/common/Timestamp.java index 970a0031..86c14cda 100644 --- a/api/src/main/java/io/opencensus/common/Timestamp.java +++ b/api/src/main/java/io/opencensus/common/Timestamp.java @@ -23,8 +23,8 @@ import static io.opencensus.common.TimeUtils.NANOS_PER_MILLI; import static io.opencensus.common.TimeUtils.NANOS_PER_SECOND; import com.google.auto.value.AutoValue; -import com.google.common.math.LongMath; -import com.google.common.primitives.Longs; +import io.opencensus.internal.Utils; +import java.math.BigDecimal; import java.math.RoundingMode; import javax.annotation.concurrent.Immutable; @@ -153,11 +153,11 @@ public abstract class Timestamp implements Comparable { */ @Override public int compareTo(Timestamp otherTimestamp) { - int cmp = Longs.compare(getSeconds(), otherTimestamp.getSeconds()); + int cmp = Utils.compareLongs(getSeconds(), otherTimestamp.getSeconds()); if (cmp != 0) { return cmp; } - return Longs.compare(getNanos(), otherTimestamp.getNanos()); + return Utils.compareLongs(getNanos(), otherTimestamp.getNanos()); } // Returns a Timestamp with the specified duration added. @@ -165,8 +165,8 @@ public abstract class Timestamp implements Comparable { if ((secondsToAdd | nanosToAdd) == 0) { return this; } - long epochSec = LongMath.checkedAdd(getSeconds(), secondsToAdd); - epochSec = LongMath.checkedAdd(epochSec, nanosToAdd / NANOS_PER_SECOND); + long epochSec = Utils.checkedAdd(getSeconds(), secondsToAdd); + epochSec = Utils.checkedAdd(epochSec, nanosToAdd / NANOS_PER_SECOND); nanosToAdd = nanosToAdd % NANOS_PER_SECOND; long nanoAdjustment = getNanos() + nanosToAdd; // safe int + NANOS_PER_SECOND return ofEpochSecond(epochSec, nanoAdjustment); @@ -175,14 +175,14 @@ public abstract class Timestamp implements Comparable { // Returns a Timestamp calculated using seconds from the epoch and nanosecond fraction of // second (arbitrary number of nanoseconds). private static Timestamp ofEpochSecond(long epochSecond, long nanoAdjustment) { - long secs = LongMath.checkedAdd(epochSecond, floorDiv(nanoAdjustment, NANOS_PER_SECOND)); + long secs = Utils.checkedAdd(epochSecond, floorDiv(nanoAdjustment, NANOS_PER_SECOND)); int nos = (int) floorMod(nanoAdjustment, NANOS_PER_SECOND); return create(secs, nos); } // Returns the result of dividing x by y rounded using floor. private static long floorDiv(long x, long y) { - return LongMath.divide(x, y, RoundingMode.FLOOR); + return BigDecimal.valueOf(x).divide(BigDecimal.valueOf(y), 0, RoundingMode.FLOOR).longValue(); } // Returns the floor modulus "x - (floorDiv(x, y) * y)" diff --git a/api/src/main/java/io/opencensus/internal/Utils.java b/api/src/main/java/io/opencensus/internal/Utils.java index 85bf3785..044529fa 100644 --- a/api/src/main/java/io/opencensus/internal/Utils.java +++ b/api/src/main/java/io/opencensus/internal/Utils.java @@ -16,6 +16,8 @@ package io.opencensus.internal; +import java.math.BigInteger; + /*>>> import org.checkerframework.checker.nullness.qual.NonNull; */ @@ -83,4 +85,33 @@ public final class Utils { } return arg; } + + /** + * Compares two longs. This functionality is provided by {@code Long.compare(long, long)} in Java + * 7. + */ + public static int compareLongs(long x, long y) { + if (x < y) { + return -1; + } else if (x == y) { + return 0; + } else { + return 1; + } + } + + private static final BigInteger MAX_LONG_VALUE = BigInteger.valueOf(Long.MAX_VALUE); + private static final BigInteger MIN_LONG_VALUE = BigInteger.valueOf(Long.MIN_VALUE); + + /** + * Adds two longs and throws an {@link ArithmeticException} if the result overflows. This + * functionality is provided by {@code Math.addExact(long, long)} in Java 8. + */ + public static long checkedAdd(long x, long y) { + BigInteger sum = BigInteger.valueOf(x).add(BigInteger.valueOf(y)); + if (sum.compareTo(MAX_LONG_VALUE) > 0 || sum.compareTo(MIN_LONG_VALUE) < 0) { + throw new ArithmeticException("Long sum overflow: x=" + x + ", y=" + y); + } + return x + y; + } } diff --git a/api/src/test/java/io/opencensus/internal/UtilsTest.java b/api/src/test/java/io/opencensus/internal/UtilsTest.java index 2416eeb8..3313c1fd 100644 --- a/api/src/test/java/io/opencensus/internal/UtilsTest.java +++ b/api/src/test/java/io/opencensus/internal/UtilsTest.java @@ -16,6 +16,8 @@ package io.opencensus.internal; +import static com.google.common.truth.Truth.assertThat; + import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -85,4 +87,32 @@ public final class UtilsTest { thrown.expectMessage("Index out of bounds: size=10, index=11"); Utils.checkIndex(11, 10); } + + @Test + public void compareLongs() { + assertThat(Utils.compareLongs(-1L, 1L)).isLessThan(0); + assertThat(Utils.compareLongs(10L, 10L)).isEqualTo(0); + assertThat(Utils.compareLongs(1L, 0L)).isGreaterThan(0); + } + + @Test + public void checkedAdd_TooLow() { + thrown.expect(ArithmeticException.class); + thrown.expectMessage("Long sum overflow: x=-9223372036854775807, y=-2"); + Utils.checkedAdd(Long.MIN_VALUE + 1, -2); + } + + @Test + public void checkedAdd_TooHigh() { + thrown.expect(ArithmeticException.class); + thrown.expectMessage("Long sum overflow: x=9223372036854775806, y=2"); + Utils.checkedAdd(Long.MAX_VALUE - 1, 2); + } + + @Test + public void checkedAdd_Valid() { + assertThat(Utils.checkedAdd(1, 2)).isEqualTo(3); + assertThat(Utils.checkedAdd(Integer.MAX_VALUE, Integer.MAX_VALUE)) + .isEqualTo(2L * Integer.MAX_VALUE); + } } -- cgit v1.2.3 From 952d64323cf95aa2fe04ddb6188303bac8a5fb35 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 3 Apr 2018 16:37:22 -0700 Subject: Replace Guava VisibleForTesting in opencensus-api (issue #1081). This commit adds two annotations to replace the uses of Guava's VisibleForTesting annotation in opencensus-api. Each annotation has a more specific meaning than VisibleForTesting, to make the uses of the annotations more informative. DefaultVisibilityForTesting - This annotation replaces the main use of @VisibleForTesting, indicating that an element was changed from private to package-private for testing. PublicForTesting - This annotation is temporary and should be removed as part of issue #977. --- .../internal/DefaultVisibilityForTesting.java | 37 +++++++++++++++++++++ .../io/opencensus/internal/PublicForTesting.java | 38 ++++++++++++++++++++++ api/src/main/java/io/opencensus/stats/Measure.java | 4 +-- api/src/main/java/io/opencensus/stats/Stats.java | 4 +-- api/src/main/java/io/opencensus/stats/View.java | 4 +-- api/src/main/java/io/opencensus/tags/Tags.java | 4 +-- api/src/main/java/io/opencensus/trace/Status.java | 4 +-- .../java/io/opencensus/trace/TraceOptions.java | 4 +-- api/src/main/java/io/opencensus/trace/Tracing.java | 4 +-- .../opencensus/trace/export/SampledSpanStore.java | 4 +-- 10 files changed, 91 insertions(+), 16 deletions(-) create mode 100644 api/src/main/java/io/opencensus/internal/DefaultVisibilityForTesting.java create mode 100644 api/src/main/java/io/opencensus/internal/PublicForTesting.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/DefaultVisibilityForTesting.java b/api/src/main/java/io/opencensus/internal/DefaultVisibilityForTesting.java new file mode 100644 index 00000000..e90a6573 --- /dev/null +++ b/api/src/main/java/io/opencensus/internal/DefaultVisibilityForTesting.java @@ -0,0 +1,37 @@ +/* + * Copyright 2018, 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.internal; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Indicates that an element is package-private instead of private only for the purpose of testing. + * This annotation is only meant to be used as documentation in the source code. + */ +@Retention(RetentionPolicy.SOURCE) +@Target({ + ElementType.ANNOTATION_TYPE, + ElementType.CONSTRUCTOR, + ElementType.FIELD, + ElementType.METHOD, + ElementType.PACKAGE, + ElementType.TYPE +}) +public @interface DefaultVisibilityForTesting {} diff --git a/api/src/main/java/io/opencensus/internal/PublicForTesting.java b/api/src/main/java/io/opencensus/internal/PublicForTesting.java new file mode 100644 index 00000000..cfd37ff2 --- /dev/null +++ b/api/src/main/java/io/opencensus/internal/PublicForTesting.java @@ -0,0 +1,38 @@ +/* + * Copyright 2018, 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.internal; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Indicates that an element is public instead of package-private only for the purpose of testing. + * This annotation is only meant to be used as documentation in the source code. + */ +// TODO(#977): All uses of this annotation should be removed or replaced with @Internal. +@Retention(RetentionPolicy.SOURCE) +@Target({ + ElementType.ANNOTATION_TYPE, + ElementType.CONSTRUCTOR, + ElementType.FIELD, + ElementType.METHOD, + ElementType.PACKAGE, + ElementType.TYPE +}) +public @interface PublicForTesting {} diff --git a/api/src/main/java/io/opencensus/stats/Measure.java b/api/src/main/java/io/opencensus/stats/Measure.java index ddd25763..4b47cd79 100644 --- a/api/src/main/java/io/opencensus/stats/Measure.java +++ b/api/src/main/java/io/opencensus/stats/Measure.java @@ -17,8 +17,8 @@ package io.opencensus.stats; import com.google.auto.value.AutoValue; -import com.google.common.annotations.VisibleForTesting; import io.opencensus.common.Function; +import io.opencensus.internal.DefaultVisibilityForTesting; import io.opencensus.internal.StringUtils; import io.opencensus.internal.Utils; import javax.annotation.concurrent.Immutable; @@ -31,7 +31,7 @@ import javax.annotation.concurrent.Immutable; @Immutable public abstract class Measure { - @VisibleForTesting static final int NAME_MAX_LENGTH = 255; + @DefaultVisibilityForTesting static final int NAME_MAX_LENGTH = 255; /** * Applies the given match function to the underlying data type. diff --git a/api/src/main/java/io/opencensus/stats/Stats.java b/api/src/main/java/io/opencensus/stats/Stats.java index d7f77e34..8393f631 100644 --- a/api/src/main/java/io/opencensus/stats/Stats.java +++ b/api/src/main/java/io/opencensus/stats/Stats.java @@ -16,7 +16,7 @@ package io.opencensus.stats; -import com.google.common.annotations.VisibleForTesting; +import io.opencensus.internal.DefaultVisibilityForTesting; import io.opencensus.internal.Provider; import java.util.logging.Level; import java.util.logging.Logger; @@ -89,7 +89,7 @@ public final class Stats { } // Any provider that may be used for StatsComponent can be added here. - @VisibleForTesting + @DefaultVisibilityForTesting static StatsComponent loadStatsComponent(@Nullable ClassLoader classLoader) { try { // Call Class.forName with literal string name of the class to help shading tools. diff --git a/api/src/main/java/io/opencensus/stats/View.java b/api/src/main/java/io/opencensus/stats/View.java index 42179d58..f563ff9a 100644 --- a/api/src/main/java/io/opencensus/stats/View.java +++ b/api/src/main/java/io/opencensus/stats/View.java @@ -17,9 +17,9 @@ package io.opencensus.stats; import com.google.auto.value.AutoValue; -import com.google.common.annotations.VisibleForTesting; import io.opencensus.common.Duration; import io.opencensus.common.Function; +import io.opencensus.internal.DefaultVisibilityForTesting; import io.opencensus.internal.StringUtils; import io.opencensus.internal.Utils; import io.opencensus.tags.TagKey; @@ -42,7 +42,7 @@ import javax.annotation.concurrent.Immutable; @SuppressWarnings("deprecation") public abstract class View { - @VisibleForTesting static final int NAME_MAX_LENGTH = 255; + @DefaultVisibilityForTesting static final int NAME_MAX_LENGTH = 255; private static final Comparator TAG_KEY_COMPARATOR = new Comparator() { diff --git a/api/src/main/java/io/opencensus/tags/Tags.java b/api/src/main/java/io/opencensus/tags/Tags.java index e4c6a579..07123647 100644 --- a/api/src/main/java/io/opencensus/tags/Tags.java +++ b/api/src/main/java/io/opencensus/tags/Tags.java @@ -16,7 +16,7 @@ package io.opencensus.tags; -import com.google.common.annotations.VisibleForTesting; +import io.opencensus.internal.DefaultVisibilityForTesting; import io.opencensus.internal.Provider; import io.opencensus.tags.propagation.TagPropagationComponent; import java.util.logging.Level; @@ -91,7 +91,7 @@ public final class Tags { } // Any provider that may be used for TagsComponent can be added here. - @VisibleForTesting + @DefaultVisibilityForTesting static TagsComponent loadTagsComponent(@Nullable ClassLoader classLoader) { try { // Call Class.forName with literal string name of the class to help shading tools. diff --git a/api/src/main/java/io/opencensus/trace/Status.java b/api/src/main/java/io/opencensus/trace/Status.java index 0a0e45ce..5296541c 100644 --- a/api/src/main/java/io/opencensus/trace/Status.java +++ b/api/src/main/java/io/opencensus/trace/Status.java @@ -16,9 +16,9 @@ package io.opencensus.trace; -import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; import com.google.common.base.Objects; +import io.opencensus.internal.PublicForTesting; import io.opencensus.internal.Utils; import java.util.ArrayList; import java.util.Collections; @@ -229,7 +229,7 @@ public final class Status { * @return the status that has the current {@code CanonicalCode}. * @since 0.5 */ - @VisibleForTesting + @PublicForTesting public Status toStatus() { return STATUS_LIST.get(value); } diff --git a/api/src/main/java/io/opencensus/trace/TraceOptions.java b/api/src/main/java/io/opencensus/trace/TraceOptions.java index ee09376f..c5d44f45 100644 --- a/api/src/main/java/io/opencensus/trace/TraceOptions.java +++ b/api/src/main/java/io/opencensus/trace/TraceOptions.java @@ -16,9 +16,9 @@ package io.opencensus.trace; -import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; import com.google.common.base.Objects; +import io.opencensus.internal.DefaultVisibilityForTesting; import io.opencensus.internal.Utils; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; @@ -241,7 +241,7 @@ public final class TraceOptions { } // Returns the current set of options bitmask. - @VisibleForTesting + @DefaultVisibilityForTesting byte getOptions() { return options; } diff --git a/api/src/main/java/io/opencensus/trace/Tracing.java b/api/src/main/java/io/opencensus/trace/Tracing.java index e67eb008..f55cd775 100644 --- a/api/src/main/java/io/opencensus/trace/Tracing.java +++ b/api/src/main/java/io/opencensus/trace/Tracing.java @@ -16,8 +16,8 @@ package io.opencensus.trace; -import com.google.common.annotations.VisibleForTesting; import io.opencensus.common.Clock; +import io.opencensus.internal.DefaultVisibilityForTesting; import io.opencensus.internal.Provider; import io.opencensus.trace.config.TraceConfig; import io.opencensus.trace.export.ExportComponent; @@ -87,7 +87,7 @@ public final class Tracing { } // Any provider that may be used for TraceComponent can be added here. - @VisibleForTesting + @DefaultVisibilityForTesting static TraceComponent loadTraceComponent(@Nullable ClassLoader classLoader) { try { // Call Class.forName with literal string name of the class to help shading tools. diff --git a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java index 3ee80ce2..99bc5288 100644 --- a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java @@ -17,7 +17,7 @@ package io.opencensus.trace.export; import com.google.auto.value.AutoValue; -import com.google.common.annotations.VisibleForTesting; +import io.opencensus.internal.PublicForTesting; import io.opencensus.internal.Utils; import io.opencensus.trace.Span; import io.opencensus.trace.Status; @@ -129,7 +129,7 @@ public abstract class SampledSpanStore { * @return the set of unique span names registered to the library. * @since 0.7 */ - @VisibleForTesting + @PublicForTesting public abstract Set getRegisteredSpanNamesForCollection(); /** -- cgit v1.2.3 From 5d5b0f52cb724cf93af4dc7cf36258f990355c9b Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 3 Apr 2018 16:37:22 -0700 Subject: Remove usages of Guava Throwables from opencensus-api (issue #1081). --- api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java index 7ff7dd0a..a249d152 100644 --- a/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java +++ b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java @@ -16,7 +16,6 @@ package io.opencensus.trace; -import com.google.common.base.Throwables; import io.grpc.Context; import io.opencensus.common.Scope; import io.opencensus.trace.unsafe.ContextUtils; @@ -121,7 +120,11 @@ final class CurrentSpanUtils { runnable.run(); } catch (Throwable t) { setErrorStatus(span, t); - Throwables.throwIfUnchecked(t); + if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } else if (t instanceof Error) { + throw (Error) t; + } throw new RuntimeException("unexpected", t); } finally { Context.current().detach(origContext); @@ -154,7 +157,9 @@ final class CurrentSpanUtils { throw e; } catch (Throwable t) { setErrorStatus(span, t); - Throwables.throwIfUnchecked(t); + if (t instanceof Error) { + throw (Error) t; + } throw new RuntimeException("unexpected", t); } finally { Context.current().detach(origContext); -- cgit v1.2.3 From 2aad37866862900827a1a8495f2826ce61173ea8 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 3 Apr 2018 16:37:22 -0700 Subject: Remove usages of Guava Objects/MoreObjects from opencensus-api (issue #1081). --- api/src/main/java/io/opencensus/internal/Utils.java | 9 +++++++++ api/src/main/java/io/opencensus/trace/SpanContext.java | 17 +++++++++-------- api/src/main/java/io/opencensus/trace/SpanId.java | 9 +++++---- api/src/main/java/io/opencensus/trace/Status.java | 15 ++++++--------- api/src/main/java/io/opencensus/trace/TraceId.java | 9 +++++---- api/src/main/java/io/opencensus/trace/TraceOptions.java | 7 +++---- api/src/test/java/io/opencensus/internal/UtilsTest.java | 16 ++++++++++++++++ 7 files changed, 53 insertions(+), 29 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/Utils.java b/api/src/main/java/io/opencensus/internal/Utils.java index 044529fa..0b27511d 100644 --- a/api/src/main/java/io/opencensus/internal/Utils.java +++ b/api/src/main/java/io/opencensus/internal/Utils.java @@ -17,6 +17,7 @@ package io.opencensus.internal; import java.math.BigInteger; +import javax.annotation.Nullable; /*>>> import org.checkerframework.checker.nullness.qual.NonNull; @@ -86,6 +87,14 @@ public final class Utils { return arg; } + /** + * Compares two Objects for equality. This functionality is provided by {@code + * Objects.equal(Object, Object)} in Java 7. + */ + public static boolean equalsObjects(@Nullable Object x, @Nullable Object y) { + return x == null ? y == null : x.equals(y); + } + /** * Compares two longs. This functionality is provided by {@code Long.compare(long, long)} in Java * 7. diff --git a/api/src/main/java/io/opencensus/trace/SpanContext.java b/api/src/main/java/io/opencensus/trace/SpanContext.java index cdc74886..66a6bfbc 100644 --- a/api/src/main/java/io/opencensus/trace/SpanContext.java +++ b/api/src/main/java/io/opencensus/trace/SpanContext.java @@ -16,8 +16,7 @@ package io.opencensus.trace; -import com.google.common.base.MoreObjects; -import com.google.common.base.Objects; +import java.util.Arrays; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; @@ -114,16 +113,18 @@ public final class SpanContext { @Override public int hashCode() { - return Objects.hashCode(traceId, spanId, traceOptions); + return Arrays.hashCode(new Object[] {traceId, spanId, traceOptions}); } @Override public String toString() { - return MoreObjects.toStringHelper(this) - .add("traceId", traceId) - .add("spanId", spanId) - .add("traceOptions", traceOptions) - .toString(); + return "SpanContext{traceId=" + + traceId + + ", spanId=" + + spanId + + ", traceOptions=" + + traceOptions + + "}"; } private SpanContext(TraceId traceId, SpanId spanId, TraceOptions traceOptions) { diff --git a/api/src/main/java/io/opencensus/trace/SpanId.java b/api/src/main/java/io/opencensus/trace/SpanId.java index 859950c7..1556bde0 100644 --- a/api/src/main/java/io/opencensus/trace/SpanId.java +++ b/api/src/main/java/io/opencensus/trace/SpanId.java @@ -16,7 +16,6 @@ package io.opencensus.trace; -import com.google.common.base.MoreObjects; import com.google.common.io.BaseEncoding; import io.opencensus.internal.Utils; import java.util.Arrays; @@ -178,6 +177,10 @@ public final class SpanId implements Comparable { * @since 0.11 */ public String toLowerBase16() { + return toLowerBase16(bytes); + } + + private static String toLowerBase16(byte[] bytes) { return BaseEncoding.base16().lowerCase().encode(bytes); } @@ -202,9 +205,7 @@ public final class SpanId implements Comparable { @Override public String toString() { - return MoreObjects.toStringHelper(this) - .add("spanId", BaseEncoding.base16().lowerCase().encode(bytes)) - .toString(); + return "SpanId{spanId=" + toLowerBase16(bytes) + "}"; } @Override diff --git a/api/src/main/java/io/opencensus/trace/Status.java b/api/src/main/java/io/opencensus/trace/Status.java index 5296541c..61f33dc7 100644 --- a/api/src/main/java/io/opencensus/trace/Status.java +++ b/api/src/main/java/io/opencensus/trace/Status.java @@ -16,11 +16,10 @@ package io.opencensus.trace; -import com.google.common.base.MoreObjects; -import com.google.common.base.Objects; import io.opencensus.internal.PublicForTesting; import io.opencensus.internal.Utils; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.TreeMap; @@ -397,7 +396,7 @@ public final class Status { * @since 0.5 */ public Status withDescription(String description) { - if (Objects.equal(this.description, description)) { + if (Utils.equalsObjects(this.description, description)) { return this; } return new Status(this.canonicalCode, description); @@ -451,7 +450,8 @@ public final class Status { } Status that = (Status) obj; - return canonicalCode == that.canonicalCode && Objects.equal(description, that.description); + return canonicalCode == that.canonicalCode + && Utils.equalsObjects(description, that.description); } /** @@ -461,14 +461,11 @@ public final class Status { */ @Override public int hashCode() { - return Objects.hashCode(canonicalCode, description); + return Arrays.hashCode(new Object[] {canonicalCode, description}); } @Override public String toString() { - return MoreObjects.toStringHelper(this) - .add("canonicalCode", canonicalCode) - .add("description", description) - .toString(); + return "Status{canonicalCode=" + canonicalCode + ", description=" + description + "}"; } } diff --git a/api/src/main/java/io/opencensus/trace/TraceId.java b/api/src/main/java/io/opencensus/trace/TraceId.java index 5683d750..a02a4e05 100644 --- a/api/src/main/java/io/opencensus/trace/TraceId.java +++ b/api/src/main/java/io/opencensus/trace/TraceId.java @@ -16,7 +16,6 @@ package io.opencensus.trace; -import com.google.common.base.MoreObjects; import com.google.common.io.BaseEncoding; import io.opencensus.common.Internal; import io.opencensus.internal.Utils; @@ -179,6 +178,10 @@ public final class TraceId implements Comparable { * @since 0.11 */ public String toLowerBase16() { + return toLowerBase16(bytes); + } + + private static String toLowerBase16(byte[] bytes) { return BaseEncoding.base16().lowerCase().encode(bytes); } @@ -224,9 +227,7 @@ public final class TraceId implements Comparable { @Override public String toString() { - return MoreObjects.toStringHelper(this) - .add("traceId", BaseEncoding.base16().lowerCase().encode(bytes)) - .toString(); + return "TraceId{traceId=" + toLowerBase16(bytes) + "}"; } @Override diff --git a/api/src/main/java/io/opencensus/trace/TraceOptions.java b/api/src/main/java/io/opencensus/trace/TraceOptions.java index c5d44f45..cdae92b3 100644 --- a/api/src/main/java/io/opencensus/trace/TraceOptions.java +++ b/api/src/main/java/io/opencensus/trace/TraceOptions.java @@ -16,10 +16,9 @@ package io.opencensus.trace; -import com.google.common.base.MoreObjects; -import com.google.common.base.Objects; import io.opencensus.internal.DefaultVisibilityForTesting; import io.opencensus.internal.Utils; +import java.util.Arrays; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; @@ -182,12 +181,12 @@ public final class TraceOptions { @Override public int hashCode() { - return Objects.hashCode(options); + return Arrays.hashCode(new byte[] {options}); } @Override public String toString() { - return MoreObjects.toStringHelper(this).add("sampled", isSampled()).toString(); + return "TraceOptions{sampled=" + isSampled() + "}"; } /** diff --git a/api/src/test/java/io/opencensus/internal/UtilsTest.java b/api/src/test/java/io/opencensus/internal/UtilsTest.java index 3313c1fd..dea7c843 100644 --- a/api/src/test/java/io/opencensus/internal/UtilsTest.java +++ b/api/src/test/java/io/opencensus/internal/UtilsTest.java @@ -17,7 +17,10 @@ package io.opencensus.internal; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import java.util.Date; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -88,6 +91,19 @@ public final class UtilsTest { Utils.checkIndex(11, 10); } + @Test + public void equalsObjects_Equal() { + assertTrue(Utils.equalsObjects(null, null)); + assertTrue(Utils.equalsObjects(new Date(1L), new Date(1L))); + } + + @Test + public void equalsObjects_Unequal() { + assertFalse(Utils.equalsObjects(null, new Object())); + assertFalse(Utils.equalsObjects(new Object(), null)); + assertFalse(Utils.equalsObjects(new Object(), new Object())); + } + @Test public void compareLongs() { assertThat(Utils.compareLongs(-1L, 1L)).isLessThan(0); -- cgit v1.2.3 From 00fa04e5d40ed870fc1966209a64ee80fbae4cbf Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Tue, 10 Apr 2018 13:12:23 +0800 Subject: Clarifies implementation details on BinaryFormat (#1119) --- api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java b/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java index da7ea4cc..9b6c9632 100644 --- a/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java +++ b/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java @@ -117,7 +117,7 @@ public abstract class BinaryFormat { * @since 0.7 */ public SpanContext fromByteArray(byte[] bytes) throws SpanContextParseException { - // Implementation must override this method. + // Implementation must override this method. If it doesn't, the below will StackOverflowError. try { return fromBinaryValue(bytes); } catch (ParseException e) { -- cgit v1.2.3 From 3e4352b3684b4646a82eef4f2da66038531d821e Mon Sep 17 00:00:00 2001 From: Yang Song Date: Mon, 16 Apr 2018 12:13:59 -0700 Subject: Move toMillis(Duration) to Utils so that it can be reused. (#1114) * Add toMillis() method to TimeUtils. * Reuse toMillis() method in impl and exporters. * Add a note about overflow and precision loss. * Move toMillis() to Duration. --- api/src/main/java/io/opencensus/common/Duration.java | 15 +++++++++++++++ api/src/test/java/io/opencensus/common/DurationTest.java | 11 +++++++++++ 2 files changed, 26 insertions(+) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Duration.java b/api/src/main/java/io/opencensus/common/Duration.java index 1ee97191..57ca87fe 100644 --- a/api/src/main/java/io/opencensus/common/Duration.java +++ b/api/src/main/java/io/opencensus/common/Duration.java @@ -23,6 +23,7 @@ import static io.opencensus.common.TimeUtils.NANOS_PER_MILLI; import com.google.auto.value.AutoValue; import io.opencensus.internal.Utils; +import java.util.concurrent.TimeUnit; import javax.annotation.concurrent.Immutable; /** @@ -78,6 +79,20 @@ public abstract class Duration implements Comparable { return Duration.create(seconds, nanos); } + /** + * Converts a {@link Duration} to milliseconds. + * + *

    Note that there could be overflow or loss of precision by making this conversion. See {@link + * TimeUnit#convert(long, TimeUnit)} for details. + * + * @param duration a {@code Duration}. + * @return the milliseconds representation of this {@code Duration}. + */ + public static long toMillis(Duration duration) { + return TimeUnit.SECONDS.toMillis(duration.getSeconds()) + + TimeUnit.NANOSECONDS.toMillis(duration.getNanos()); + } + /** * Returns the number of seconds in the {@code Duration}. * diff --git a/api/src/test/java/io/opencensus/common/DurationTest.java b/api/src/test/java/io/opencensus/common/DurationTest.java index 40682fc4..d46f2f7a 100644 --- a/api/src/test/java/io/opencensus/common/DurationTest.java +++ b/api/src/test/java/io/opencensus/common/DurationTest.java @@ -88,4 +88,15 @@ public class DurationTest { assertThat(Duration.create(-25, -42)).isNotEqualTo(Duration.create(-24, -42)); assertThat(Duration.create(-24, -43)).isNotEqualTo(Duration.create(-24, -42)); } + + @Test + public void toMillis() { + assertThat(Duration.toMillis(Duration.create(10, 0))).isEqualTo(10000L); + assertThat(Duration.toMillis(Duration.create(10, 1000))).isEqualTo(10000L); + assertThat(Duration.toMillis(Duration.create(0, (int) 1e6))).isEqualTo(1L); + assertThat(Duration.toMillis(Duration.create(0, 0))).isEqualTo(0L); + assertThat(Duration.toMillis(Duration.create(-10, 0))).isEqualTo(-10000L); + assertThat(Duration.toMillis(Duration.create(-10, -1000))).isEqualTo(-10000L); + assertThat(Duration.toMillis(Duration.create(0, -(int) 1e6))).isEqualTo(-1L); + } } -- cgit v1.2.3 From 74d1f5dbaad7d24282edfaa95c6780bbe8191a98 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Mon, 16 Apr 2018 14:38:01 -0700 Subject: Improve Duration.toMillis() (#1132) * Improve java doc for toMillis(). * Make toMillis() non-static. --- api/src/main/java/io/opencensus/common/Duration.java | 11 +++++------ api/src/test/java/io/opencensus/common/DurationTest.java | 14 +++++++------- 2 files changed, 12 insertions(+), 13 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Duration.java b/api/src/main/java/io/opencensus/common/Duration.java index 57ca87fe..fb85a0ae 100644 --- a/api/src/main/java/io/opencensus/common/Duration.java +++ b/api/src/main/java/io/opencensus/common/Duration.java @@ -82,15 +82,14 @@ public abstract class Duration implements Comparable { /** * Converts a {@link Duration} to milliseconds. * - *

    Note that there could be overflow or loss of precision by making this conversion. See {@link - * TimeUnit#convert(long, TimeUnit)} for details. + *

    Returns {@code Long.MIN_VALUE} if conversion would negatively overflow, or {@code + * Long.MAX_VALUE} if it would positively overflow. * - * @param duration a {@code Duration}. * @return the milliseconds representation of this {@code Duration}. + * @since 0.13 */ - public static long toMillis(Duration duration) { - return TimeUnit.SECONDS.toMillis(duration.getSeconds()) - + TimeUnit.NANOSECONDS.toMillis(duration.getNanos()); + public long toMillis() { + return TimeUnit.SECONDS.toMillis(getSeconds()) + TimeUnit.NANOSECONDS.toMillis(getNanos()); } /** diff --git a/api/src/test/java/io/opencensus/common/DurationTest.java b/api/src/test/java/io/opencensus/common/DurationTest.java index d46f2f7a..fb5f314e 100644 --- a/api/src/test/java/io/opencensus/common/DurationTest.java +++ b/api/src/test/java/io/opencensus/common/DurationTest.java @@ -91,12 +91,12 @@ public class DurationTest { @Test public void toMillis() { - assertThat(Duration.toMillis(Duration.create(10, 0))).isEqualTo(10000L); - assertThat(Duration.toMillis(Duration.create(10, 1000))).isEqualTo(10000L); - assertThat(Duration.toMillis(Duration.create(0, (int) 1e6))).isEqualTo(1L); - assertThat(Duration.toMillis(Duration.create(0, 0))).isEqualTo(0L); - assertThat(Duration.toMillis(Duration.create(-10, 0))).isEqualTo(-10000L); - assertThat(Duration.toMillis(Duration.create(-10, -1000))).isEqualTo(-10000L); - assertThat(Duration.toMillis(Duration.create(0, -(int) 1e6))).isEqualTo(-1L); + assertThat(Duration.create(10, 0).toMillis()).isEqualTo(10000L); + assertThat(Duration.create(10, 1000).toMillis()).isEqualTo(10000L); + assertThat(Duration.create(0, (int) 1e6).toMillis()).isEqualTo(1L); + assertThat(Duration.create(0, 0).toMillis()).isEqualTo(0L); + assertThat(Duration.create(-10, 0).toMillis()).isEqualTo(-10000L); + assertThat(Duration.create(-10, -1000).toMillis()).isEqualTo(-10000L); + assertThat(Duration.create(0, -(int) 1e6).toMillis()).isEqualTo(-1L); } } -- cgit v1.2.3 From 9e518c6743ef46d0d1e18b5927c7dfc754b6d835 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Mon, 16 Apr 2018 15:51:26 -0700 Subject: Remove java doc about overflow cases in Duration.toMillis() (#1134) --- api/src/main/java/io/opencensus/common/Duration.java | 3 --- 1 file changed, 3 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Duration.java b/api/src/main/java/io/opencensus/common/Duration.java index fb85a0ae..2d90f506 100644 --- a/api/src/main/java/io/opencensus/common/Duration.java +++ b/api/src/main/java/io/opencensus/common/Duration.java @@ -82,9 +82,6 @@ public abstract class Duration implements Comparable { /** * Converts a {@link Duration} to milliseconds. * - *

    Returns {@code Long.MIN_VALUE} if conversion would negatively overflow, or {@code - * Long.MAX_VALUE} if it would positively overflow. - * * @return the milliseconds representation of this {@code Duration}. * @since 0.13 */ -- cgit v1.2.3 From 7dca0fedefb1187d34a8ca1ebbe5c5558f42aac4 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 17 Apr 2018 19:57:22 -0700 Subject: Move utils used by Duration and Timestamp from i.o.internal.Utils to TimeUtils. This change breaks the circular dependency between io.opencensus.internal and io.opencensus.common. --- .../main/java/io/opencensus/common/Duration.java | 5 +- .../main/java/io/opencensus/common/TimeUtils.java | 31 +++++++++++ .../main/java/io/opencensus/common/Timestamp.java | 11 ++-- .../main/java/io/opencensus/internal/Utils.java | 30 ----------- .../java/io/opencensus/common/TimeUtilsTest.java | 60 ++++++++++++++++++++++ .../java/io/opencensus/internal/UtilsTest.java | 29 ----------- 6 files changed, 98 insertions(+), 68 deletions(-) create mode 100644 api/src/test/java/io/opencensus/common/TimeUtilsTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Duration.java b/api/src/main/java/io/opencensus/common/Duration.java index 2d90f506..4b7bb367 100644 --- a/api/src/main/java/io/opencensus/common/Duration.java +++ b/api/src/main/java/io/opencensus/common/Duration.java @@ -22,7 +22,6 @@ import static io.opencensus.common.TimeUtils.MILLIS_PER_SECOND; import static io.opencensus.common.TimeUtils.NANOS_PER_MILLI; import com.google.auto.value.AutoValue; -import io.opencensus.internal.Utils; import java.util.concurrent.TimeUnit; import javax.annotation.concurrent.Immutable; @@ -115,11 +114,11 @@ public abstract class Duration implements Comparable { */ @Override public int compareTo(Duration otherDuration) { - int cmp = Utils.compareLongs(getSeconds(), otherDuration.getSeconds()); + int cmp = TimeUtils.compareLongs(getSeconds(), otherDuration.getSeconds()); if (cmp != 0) { return cmp; } - return Utils.compareLongs(getNanos(), otherDuration.getNanos()); + return TimeUtils.compareLongs(getNanos(), otherDuration.getNanos()); } Duration() {} diff --git a/api/src/main/java/io/opencensus/common/TimeUtils.java b/api/src/main/java/io/opencensus/common/TimeUtils.java index 2429cc90..db119e2e 100644 --- a/api/src/main/java/io/opencensus/common/TimeUtils.java +++ b/api/src/main/java/io/opencensus/common/TimeUtils.java @@ -16,6 +16,8 @@ package io.opencensus.common; +import java.math.BigInteger; + /** Util class for {@link Timestamp} and {@link Duration}. */ final class TimeUtils { static final long MAX_SECONDS = 315576000000L; @@ -25,4 +27,33 @@ final class TimeUtils { static final long NANOS_PER_SECOND = NANOS_PER_MILLI * MILLIS_PER_SECOND; private TimeUtils() {} + + /** + * Compares two longs. This functionality is provided by {@code Long.compare(long, long)} in Java + * 7. + */ + static int compareLongs(long x, long y) { + if (x < y) { + return -1; + } else if (x == y) { + return 0; + } else { + return 1; + } + } + + private static final BigInteger MAX_LONG_VALUE = BigInteger.valueOf(Long.MAX_VALUE); + private static final BigInteger MIN_LONG_VALUE = BigInteger.valueOf(Long.MIN_VALUE); + + /** + * Adds two longs and throws an {@link ArithmeticException} if the result overflows. This + * functionality is provided by {@code Math.addExact(long, long)} in Java 8. + */ + static long checkedAdd(long x, long y) { + BigInteger sum = BigInteger.valueOf(x).add(BigInteger.valueOf(y)); + if (sum.compareTo(MAX_LONG_VALUE) > 0 || sum.compareTo(MIN_LONG_VALUE) < 0) { + throw new ArithmeticException("Long sum overflow: x=" + x + ", y=" + y); + } + return x + y; + } } diff --git a/api/src/main/java/io/opencensus/common/Timestamp.java b/api/src/main/java/io/opencensus/common/Timestamp.java index 86c14cda..e3aae3a6 100644 --- a/api/src/main/java/io/opencensus/common/Timestamp.java +++ b/api/src/main/java/io/opencensus/common/Timestamp.java @@ -23,7 +23,6 @@ import static io.opencensus.common.TimeUtils.NANOS_PER_MILLI; import static io.opencensus.common.TimeUtils.NANOS_PER_SECOND; import com.google.auto.value.AutoValue; -import io.opencensus.internal.Utils; import java.math.BigDecimal; import java.math.RoundingMode; import javax.annotation.concurrent.Immutable; @@ -153,11 +152,11 @@ public abstract class Timestamp implements Comparable { */ @Override public int compareTo(Timestamp otherTimestamp) { - int cmp = Utils.compareLongs(getSeconds(), otherTimestamp.getSeconds()); + int cmp = TimeUtils.compareLongs(getSeconds(), otherTimestamp.getSeconds()); if (cmp != 0) { return cmp; } - return Utils.compareLongs(getNanos(), otherTimestamp.getNanos()); + return TimeUtils.compareLongs(getNanos(), otherTimestamp.getNanos()); } // Returns a Timestamp with the specified duration added. @@ -165,8 +164,8 @@ public abstract class Timestamp implements Comparable { if ((secondsToAdd | nanosToAdd) == 0) { return this; } - long epochSec = Utils.checkedAdd(getSeconds(), secondsToAdd); - epochSec = Utils.checkedAdd(epochSec, nanosToAdd / NANOS_PER_SECOND); + long epochSec = TimeUtils.checkedAdd(getSeconds(), secondsToAdd); + epochSec = TimeUtils.checkedAdd(epochSec, nanosToAdd / NANOS_PER_SECOND); nanosToAdd = nanosToAdd % NANOS_PER_SECOND; long nanoAdjustment = getNanos() + nanosToAdd; // safe int + NANOS_PER_SECOND return ofEpochSecond(epochSec, nanoAdjustment); @@ -175,7 +174,7 @@ public abstract class Timestamp implements Comparable { // Returns a Timestamp calculated using seconds from the epoch and nanosecond fraction of // second (arbitrary number of nanoseconds). private static Timestamp ofEpochSecond(long epochSecond, long nanoAdjustment) { - long secs = Utils.checkedAdd(epochSecond, floorDiv(nanoAdjustment, NANOS_PER_SECOND)); + long secs = TimeUtils.checkedAdd(epochSecond, floorDiv(nanoAdjustment, NANOS_PER_SECOND)); int nos = (int) floorMod(nanoAdjustment, NANOS_PER_SECOND); return create(secs, nos); } diff --git a/api/src/main/java/io/opencensus/internal/Utils.java b/api/src/main/java/io/opencensus/internal/Utils.java index 0b27511d..1ac2324e 100644 --- a/api/src/main/java/io/opencensus/internal/Utils.java +++ b/api/src/main/java/io/opencensus/internal/Utils.java @@ -16,7 +16,6 @@ package io.opencensus.internal; -import java.math.BigInteger; import javax.annotation.Nullable; /*>>> @@ -94,33 +93,4 @@ public final class Utils { public static boolean equalsObjects(@Nullable Object x, @Nullable Object y) { return x == null ? y == null : x.equals(y); } - - /** - * Compares two longs. This functionality is provided by {@code Long.compare(long, long)} in Java - * 7. - */ - public static int compareLongs(long x, long y) { - if (x < y) { - return -1; - } else if (x == y) { - return 0; - } else { - return 1; - } - } - - private static final BigInteger MAX_LONG_VALUE = BigInteger.valueOf(Long.MAX_VALUE); - private static final BigInteger MIN_LONG_VALUE = BigInteger.valueOf(Long.MIN_VALUE); - - /** - * Adds two longs and throws an {@link ArithmeticException} if the result overflows. This - * functionality is provided by {@code Math.addExact(long, long)} in Java 8. - */ - public static long checkedAdd(long x, long y) { - BigInteger sum = BigInteger.valueOf(x).add(BigInteger.valueOf(y)); - if (sum.compareTo(MAX_LONG_VALUE) > 0 || sum.compareTo(MIN_LONG_VALUE) < 0) { - throw new ArithmeticException("Long sum overflow: x=" + x + ", y=" + y); - } - return x + y; - } } diff --git a/api/src/test/java/io/opencensus/common/TimeUtilsTest.java b/api/src/test/java/io/opencensus/common/TimeUtilsTest.java new file mode 100644 index 00000000..d6228566 --- /dev/null +++ b/api/src/test/java/io/opencensus/common/TimeUtilsTest.java @@ -0,0 +1,60 @@ +/* + * Copyright 2018, 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.common; + +import static com.google.common.truth.Truth.assertThat; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link TimeUtils}. */ +@RunWith(JUnit4.class) +public final class TimeUtilsTest { + + @Rule public ExpectedException thrown = ExpectedException.none(); + + @Test + public void compareLongs() { + assertThat(TimeUtils.compareLongs(-1L, 1L)).isLessThan(0); + assertThat(TimeUtils.compareLongs(10L, 10L)).isEqualTo(0); + assertThat(TimeUtils.compareLongs(1L, 0L)).isGreaterThan(0); + } + + @Test + public void checkedAdd_TooLow() { + thrown.expect(ArithmeticException.class); + thrown.expectMessage("Long sum overflow: x=-9223372036854775807, y=-2"); + TimeUtils.checkedAdd(Long.MIN_VALUE + 1, -2); + } + + @Test + public void checkedAdd_TooHigh() { + thrown.expect(ArithmeticException.class); + thrown.expectMessage("Long sum overflow: x=9223372036854775806, y=2"); + TimeUtils.checkedAdd(Long.MAX_VALUE - 1, 2); + } + + @Test + public void checkedAdd_Valid() { + assertThat(TimeUtils.checkedAdd(1, 2)).isEqualTo(3); + assertThat(TimeUtils.checkedAdd(Integer.MAX_VALUE, Integer.MAX_VALUE)) + .isEqualTo(2L * Integer.MAX_VALUE); + } +} diff --git a/api/src/test/java/io/opencensus/internal/UtilsTest.java b/api/src/test/java/io/opencensus/internal/UtilsTest.java index dea7c843..983264f6 100644 --- a/api/src/test/java/io/opencensus/internal/UtilsTest.java +++ b/api/src/test/java/io/opencensus/internal/UtilsTest.java @@ -16,7 +16,6 @@ package io.opencensus.internal; -import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -103,32 +102,4 @@ public final class UtilsTest { assertFalse(Utils.equalsObjects(new Object(), null)); assertFalse(Utils.equalsObjects(new Object(), new Object())); } - - @Test - public void compareLongs() { - assertThat(Utils.compareLongs(-1L, 1L)).isLessThan(0); - assertThat(Utils.compareLongs(10L, 10L)).isEqualTo(0); - assertThat(Utils.compareLongs(1L, 0L)).isGreaterThan(0); - } - - @Test - public void checkedAdd_TooLow() { - thrown.expect(ArithmeticException.class); - thrown.expectMessage("Long sum overflow: x=-9223372036854775807, y=-2"); - Utils.checkedAdd(Long.MIN_VALUE + 1, -2); - } - - @Test - public void checkedAdd_TooHigh() { - thrown.expect(ArithmeticException.class); - thrown.expectMessage("Long sum overflow: x=9223372036854775806, y=2"); - Utils.checkedAdd(Long.MAX_VALUE - 1, 2); - } - - @Test - public void checkedAdd_Valid() { - assertThat(Utils.checkedAdd(1, 2)).isEqualTo(3); - assertThat(Utils.checkedAdd(Integer.MAX_VALUE, Integer.MAX_VALUE)) - .isEqualTo(2L * Integer.MAX_VALUE); - } } -- cgit v1.2.3 From 610ff80ebec2b831a7ea6cc73ad4614152a36ad9 Mon Sep 17 00:00:00 2001 From: dvfeinblum Date: Tue, 24 Apr 2018 21:48:51 -0400 Subject: Added null checking to Span implementations (#1150) This PR adds null checking to classes that implement Span. Specifically, - BlankSpan - NoopSpan - Span - SpanImpl For the latter, I had to use Preconditions.checkNotNull because io.opencensus.internal shouldn't be imported into ImplCore. --- .../main/java/io/opencensus/trace/BlankSpan.java | 31 +++++++++++++++++----- api/src/main/java/io/opencensus/trace/Span.java | 6 +++++ .../test/java/io/opencensus/trace/NoopSpan.java | 22 +++++++++++---- 3 files changed, 47 insertions(+), 12 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/BlankSpan.java b/api/src/main/java/io/opencensus/trace/BlankSpan.java index 641bad7e..3109f013 100644 --- a/api/src/main/java/io/opencensus/trace/BlankSpan.java +++ b/api/src/main/java/io/opencensus/trace/BlankSpan.java @@ -16,6 +16,7 @@ package io.opencensus.trace; +import io.opencensus.internal.Utils; import java.util.Map; import javax.annotation.concurrent.Immutable; @@ -42,19 +43,29 @@ public final class BlankSpan extends Span { /** No-op implementation of the {@link Span#putAttribute(String, AttributeValue)} method. */ @Override - public void putAttribute(String key, AttributeValue value) {} + public void putAttribute(String key, AttributeValue value) { + Utils.checkNotNull(key, "key"); + Utils.checkNotNull(value, "value"); + } /** No-op implementation of the {@link Span#putAttributes(Map)} method. */ @Override - public void putAttributes(Map attributes) {} + public void putAttributes(Map attributes) { + Utils.checkNotNull(attributes, "attributes"); + } /** No-op implementation of the {@link Span#addAnnotation(String, Map)} method. */ @Override - public void addAnnotation(String description, Map attributes) {} + public void addAnnotation(String description, Map attributes) { + Utils.checkNotNull(description, "description"); + Utils.checkNotNull(attributes, "attributes"); + } /** No-op implementation of the {@link Span#addAnnotation(Annotation)} method. */ @Override - public void addAnnotation(Annotation annotation) {} + public void addAnnotation(Annotation annotation) { + Utils.checkNotNull(annotation, "annotation"); + } /** No-op implementation of the {@link Span#addNetworkEvent(NetworkEvent)} method. */ @Override @@ -63,14 +74,20 @@ public final class BlankSpan extends Span { /** No-op implementation of the {@link Span#addMessageEvent(MessageEvent)} method. */ @Override - public void addMessageEvent(MessageEvent messageEvent) {} + public void addMessageEvent(MessageEvent messageEvent) { + Utils.checkNotNull(messageEvent, "messageEvent"); + } /** No-op implementation of the {@link Span#addLink(Link)} method. */ @Override - public void addLink(Link link) {} + public void addLink(Link link) { + Utils.checkNotNull(link, "link"); + } @Override - public void setStatus(Status status) {} + public void setStatus(Status status) { + Utils.checkNotNull(status, "status"); + } /** No-op implementation of the {@link Span#end(EndSpanOptions)} method. */ @Override diff --git a/api/src/main/java/io/opencensus/trace/Span.java b/api/src/main/java/io/opencensus/trace/Span.java index 4a8c6f04..cb82038d 100644 --- a/api/src/main/java/io/opencensus/trace/Span.java +++ b/api/src/main/java/io/opencensus/trace/Span.java @@ -96,6 +96,8 @@ public abstract class Span { // Not final because for performance reasons we want to override this in the implementation. // Also a default implementation is needed to not break the compatibility (users may extend this // for testing). + Utils.checkNotNull(key, "key"); + Utils.checkNotNull(value, "value"); putAttributes(Collections.singletonMap(key, value)); } @@ -110,6 +112,7 @@ public abstract class Span { public void putAttributes(Map attributes) { // Not final because we want to start overriding this method from the beginning, this will // allow us to remove the addAttributes faster. All implementations MUST override this method. + Utils.checkNotNull(attributes, "attributes"); addAttributes(attributes); } @@ -130,6 +133,7 @@ public abstract class Span { * @since 0.5 */ public final void addAnnotation(String description) { + Utils.checkNotNull(description, "description"); addAnnotation(description, EMPTY_ATTRIBUTES); } @@ -180,6 +184,7 @@ public abstract class Span { public void addMessageEvent(MessageEvent messageEvent) { // Default implementation by invoking addNetworkEvent() so that any existing derived classes, // including implementation and the mocked ones, do not need to override this method explicitly. + Utils.checkNotNull(messageEvent, "messageEvent"); addNetworkEvent(BaseMessageEventUtils.asNetworkEvent(messageEvent)); } @@ -209,6 +214,7 @@ public abstract class Span { public void setStatus(Status status) { // Implemented as no-op for backwards compatibility (for example gRPC extends Span in tests). // Implementation must override this method. + Utils.checkNotNull(status, "status"); } /** diff --git a/api/src/test/java/io/opencensus/trace/NoopSpan.java b/api/src/test/java/io/opencensus/trace/NoopSpan.java index 7c8d9b7a..e90f68cd 100644 --- a/api/src/test/java/io/opencensus/trace/NoopSpan.java +++ b/api/src/test/java/io/opencensus/trace/NoopSpan.java @@ -16,6 +16,7 @@ package io.opencensus.trace; +import io.opencensus.internal.Utils; import java.util.EnumSet; import java.util.Map; import javax.annotation.Nullable; @@ -33,22 +34,33 @@ public class NoopSpan extends Span { } @Override - public void putAttributes(Map attributes) {} + public void putAttributes(Map attributes) { + Utils.checkNotNull(attributes, "attributes"); + } @Override - public void addAnnotation(String description, Map attributes) {} + public void addAnnotation(String description, Map attributes) { + Utils.checkNotNull(description, "description"); + Utils.checkNotNull(attributes, "attributes"); + } @Override - public void addAnnotation(Annotation annotation) {} + public void addAnnotation(Annotation annotation) { + Utils.checkNotNull(annotation, "annotation"); + } @Override public void addNetworkEvent(NetworkEvent networkEvent) {} @Override - public void addMessageEvent(MessageEvent messageEvent) {} + public void addMessageEvent(MessageEvent messageEvent) { + Utils.checkNotNull(messageEvent, "messageEvent"); + } @Override - public void addLink(Link link) {} + public void addLink(Link link) { + Utils.checkNotNull(link, "link"); + } @Override public void end(EndSpanOptions options) {} -- cgit v1.2.3 From 05f5bdd7c1628a3e434542fa2af1ab2b5ccf20ce Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Fri, 27 Apr 2018 13:08:48 -0700 Subject: Check for null in more public methods in Span and its subclasses. --- api/src/main/java/io/opencensus/trace/BlankSpan.java | 4 +++- api/src/test/java/io/opencensus/trace/NoopSpan.java | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/BlankSpan.java b/api/src/main/java/io/opencensus/trace/BlankSpan.java index 3109f013..af6456d3 100644 --- a/api/src/main/java/io/opencensus/trace/BlankSpan.java +++ b/api/src/main/java/io/opencensus/trace/BlankSpan.java @@ -91,7 +91,9 @@ public final class BlankSpan extends Span { /** No-op implementation of the {@link Span#end(EndSpanOptions)} method. */ @Override - public void end(EndSpanOptions options) {} + public void end(EndSpanOptions options) { + Utils.checkNotNull(options, "options"); + } @Override public String toString() { diff --git a/api/src/test/java/io/opencensus/trace/NoopSpan.java b/api/src/test/java/io/opencensus/trace/NoopSpan.java index e90f68cd..a21a8aac 100644 --- a/api/src/test/java/io/opencensus/trace/NoopSpan.java +++ b/api/src/test/java/io/opencensus/trace/NoopSpan.java @@ -30,7 +30,7 @@ public class NoopSpan extends Span { /** Creates a new {@code NoopSpan}. */ public NoopSpan(SpanContext context, @Nullable EnumSet options) { - super(context, options); + super(Utils.checkNotNull(context, "context"), options); } @Override @@ -63,5 +63,7 @@ public class NoopSpan extends Span { } @Override - public void end(EndSpanOptions options) {} + public void end(EndSpanOptions options) { + Utils.checkNotNull(options, "options"); + } } -- cgit v1.2.3 From dec25072b4b7671a8ff35f0a121b41eddff5f66f Mon Sep 17 00:00:00 2001 From: Yang Song Date: Fri, 27 Apr 2018 14:47:12 -0700 Subject: Add Aggregation.LastValue and AggregationData.LastValueData to support Gauge (#1055) * Add LastValue and LastValueData * Support LastValue and LastValueData in impl * Use Utils instead of Precondition * Add LastValue and remove Mean from match() method. * Support LastValue and LastValueData in exporters and zpages. * Update MutableLastValue, add comments on why Mean is still supported. --- .../main/java/io/opencensus/stats/Aggregation.java | 85 +++++------ .../java/io/opencensus/stats/AggregationData.java | 157 ++++++++++++--------- .../main/java/io/opencensus/stats/ViewData.java | 52 +++++-- .../io/opencensus/stats/AggregationDataTest.java | 31 ++-- .../java/io/opencensus/stats/AggregationTest.java | 39 ++--- .../java/io/opencensus/stats/ViewDataTest.java | 19 +++ 6 files changed, 223 insertions(+), 160 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/Aggregation.java b/api/src/main/java/io/opencensus/stats/Aggregation.java index e8579c33..f5efed9b 100644 --- a/api/src/main/java/io/opencensus/stats/Aggregation.java +++ b/api/src/main/java/io/opencensus/stats/Aggregation.java @@ -25,12 +25,13 @@ import javax.annotation.concurrent.Immutable; * {@link Aggregation} is the process of combining a certain set of {@code MeasureValue}s for a * given {@code Measure} into an {@link AggregationData}. * - *

    {@link Aggregation} currently supports 3 types of basic aggregation: + *

    {@link Aggregation} currently supports 4 types of basic aggregation: * *

      *
    • Sum *
    • Count *
    • Distribution + *
    • LastValue *
    * *

    When creating a {@link View}, one {@link Aggregation} needs to be specified as how to @@ -43,30 +44,16 @@ public abstract class Aggregation { private Aggregation() {} - /** - * Applies the given match function to the underlying data type. - * - * @since 0.8 - * @deprecated in favor of {@link #match(Function, Function, Function, Function)}. - */ - @Deprecated - public abstract T match( - Function p0, - Function p1, - Function p2, - Function p3, - Function defaultFunction); - /** * Applies the given match function to the underlying data type. * * @since 0.13 */ - @SuppressWarnings("InconsistentOverloads") public abstract T match( Function p0, Function p1, Function p2, + Function p3, Function defaultFunction); /** @@ -92,21 +79,12 @@ public abstract class Aggregation { return INSTANCE; } - @Override - public final T match( - Function p0, - Function p1, - Function p2, - Function p3, - Function defaultFunction) { - return p0.apply(this); - } - @Override public final T match( Function p0, Function p1, Function p2, + Function p3, Function defaultFunction) { return p0.apply(this); } @@ -135,21 +113,12 @@ public abstract class Aggregation { return INSTANCE; } - @Override - public final T match( - Function p0, - Function p1, - Function p2, - Function p3, - Function defaultFunction) { - return p1.apply(this); - } - @Override public final T match( Function p0, Function p1, Function p2, + Function p3, Function defaultFunction) { return p1.apply(this); } @@ -181,21 +150,12 @@ public abstract class Aggregation { return INSTANCE; } - @Override - public final T match( - Function p0, - Function p1, - Function p2, - Function p3, - Function defaultFunction) { - return p2.apply(this); - } - @Override public final T match( Function p0, Function p1, Function p2, + Function p3, Function defaultFunction) { return defaultFunction.apply(this); } @@ -236,10 +196,34 @@ public abstract class Aggregation { public final T match( Function p0, Function p1, - Function p2, - Function p3, + Function p2, + Function p3, Function defaultFunction) { - return p3.apply(this); + return p2.apply(this); + } + } + + /** + * Calculate the last value of aggregated {@code MeasureValue}s. + * + * @since 0.13 + */ + @Immutable + @AutoValue + public abstract static class LastValue extends Aggregation { + + LastValue() {} + + private static final LastValue INSTANCE = new AutoValue_Aggregation_LastValue(); + + /** + * Construct a {@code LastValue}. + * + * @return a new {@code LastValue}. + * @since 0.13 + */ + public static LastValue create() { + return INSTANCE; } @Override @@ -247,8 +231,9 @@ public abstract class Aggregation { Function p0, Function p1, Function p2, + Function p3, Function defaultFunction) { - return p2.apply(this); + return p3.apply(this); } } } diff --git a/api/src/main/java/io/opencensus/stats/AggregationData.java b/api/src/main/java/io/opencensus/stats/AggregationData.java index 716e97d8..95ac3282 100644 --- a/api/src/main/java/io/opencensus/stats/AggregationData.java +++ b/api/src/main/java/io/opencensus/stats/AggregationData.java @@ -28,13 +28,15 @@ import javax.annotation.concurrent.Immutable; * {@link AggregationData} is the result of applying a given {@link Aggregation} to a set of {@code * MeasureValue}s. * - *

    {@link AggregationData} currently supports 4 types of basic aggregation values: + *

    {@link AggregationData} currently supports 6 types of basic aggregation values: * *

      *
    • SumDataDouble *
    • SumDataLong *
    • CountData *
    • DistributionData + *
    • LastValueDataDouble + *
    • LastValueDataLong *
    * *

    {@link ViewData} will contain one {@link AggregationData}, corresponding to its {@link @@ -47,32 +49,18 @@ public abstract class AggregationData { private AggregationData() {} - /** - * Applies the given match function to the underlying data type. - * - * @since 0.8 - * @deprecated in favor of {@link #match(Function, Function, Function, Function, Function)}. - */ - @Deprecated - public abstract T match( - Function p0, - Function p1, - Function p2, - Function p3, - Function p4, - Function defaultFunction); - /** * Applies the given match function to the underlying data type. * * @since 0.13 */ - @SuppressWarnings("InconsistentOverloads") public abstract T match( Function p0, Function p1, Function p2, Function p3, + Function p4, + Function p5, Function defaultFunction); /** @@ -105,23 +93,14 @@ public abstract class AggregationData { */ public abstract double getSum(); - @Override - public final T match( - Function p0, - Function p1, - Function p2, - Function p3, - Function p4, - Function defaultFunction) { - return p0.apply(this); - } - @Override public final T match( Function p0, Function p1, Function p2, Function p3, + Function p4, + Function p5, Function defaultFunction) { return p0.apply(this); } @@ -157,23 +136,14 @@ public abstract class AggregationData { */ public abstract long getSum(); - @Override - public final T match( - Function p0, - Function p1, - Function p2, - Function p3, - Function p4, - Function defaultFunction) { - return p1.apply(this); - } - @Override public final T match( Function p0, Function p1, Function p2, Function p3, + Function p4, + Function p5, Function defaultFunction) { return p1.apply(this); } @@ -209,23 +179,14 @@ public abstract class AggregationData { */ public abstract long getCount(); - @Override - public final T match( - Function p0, - Function p1, - Function p2, - Function p3, - Function p4, - Function defaultFunction) { - return p2.apply(this); - } - @Override public final T match( Function p0, Function p1, Function p2, Function p3, + Function p4, + Function p5, Function defaultFunction) { return p2.apply(this); } @@ -273,23 +234,14 @@ public abstract class AggregationData { */ public abstract long getCount(); - @Override - public final T match( - Function p0, - Function p1, - Function p2, - Function p3, - Function p4, - Function defaultFunction) { - return p3.apply(this); - } - @Override public final T match( Function p0, Function p1, Function p2, Function p3, + Function p4, + Function p5, Function defaultFunction) { return defaultFunction.apply(this); } @@ -394,11 +346,86 @@ public abstract class AggregationData { Function p0, Function p1, Function p2, - Function p3, - Function p4, + Function p3, + Function p4, + Function p5, + Function defaultFunction) { + return p3.apply(this); + } + } + + /** + * The last value of aggregated {@code MeasureValueDouble}s. + * + * @since 0.13 + */ + @Immutable + @AutoValue + public abstract static class LastValueDataDouble extends AggregationData { + + LastValueDataDouble() {} + + /** + * Creates a {@code LastValueDataDouble}. + * + * @param lastValue the last value. + * @return a {@code LastValueDataDouble}. + * @since 0.13 + */ + public static LastValueDataDouble create(double lastValue) { + return new AutoValue_AggregationData_LastValueDataDouble(lastValue); + } + + /** + * Returns the last value. + * + * @return the last value. + * @since 0.13 + */ + public abstract double getLastValue(); + + @Override + public final T match( + Function p0, + Function p1, + Function p2, + Function p3, + Function p4, + Function p5, Function defaultFunction) { return p4.apply(this); } + } + + /** + * The last value of aggregated {@code MeasureValueLong}s. + * + * @since 0.13 + */ + @Immutable + @AutoValue + public abstract static class LastValueDataLong extends AggregationData { + + LastValueDataLong() {} + + /** + * Creates a {@code LastValueDataLong}. + * + * @param lastValue the last value. + * @return a {@code LastValueDataLong}. + * @since 0.13 + */ + public static LastValueDataLong create(long lastValue) { + return new AutoValue_AggregationData_LastValueDataLong(lastValue); + } + + /** + * Returns the last value. + * + * @return the last value. + * @since 0.13 + */ + public abstract long getLastValue(); @Override public final T match( @@ -406,8 +433,10 @@ public abstract class AggregationData { Function p1, Function p2, Function p3, + Function p4, + Function p5, Function defaultFunction) { - return p3.apply(this); + return p5.apply(this); } } } diff --git a/api/src/main/java/io/opencensus/stats/ViewData.java b/api/src/main/java/io/opencensus/stats/ViewData.java index c511edab..259f1068 100644 --- a/api/src/main/java/io/opencensus/stats/ViewData.java +++ b/api/src/main/java/io/opencensus/stats/ViewData.java @@ -24,9 +24,12 @@ import io.opencensus.common.Timestamp; import io.opencensus.internal.Utils; import io.opencensus.stats.Aggregation.Count; import io.opencensus.stats.Aggregation.Distribution; +import io.opencensus.stats.Aggregation.LastValue; import io.opencensus.stats.Aggregation.Sum; import io.opencensus.stats.AggregationData.CountData; import io.opencensus.stats.AggregationData.DistributionData; +import io.opencensus.stats.AggregationData.LastValueDataDouble; +import io.opencensus.stats.AggregationData.LastValueDataLong; import io.opencensus.stats.AggregationData.SumDataDouble; import io.opencensus.stats.AggregationData.SumDataLong; import io.opencensus.stats.Measure.MeasureDouble; @@ -272,25 +275,56 @@ public abstract class ViewData { return null; } }, - new Function() { + new Function() { @Override - public Void apply(Aggregation.Mean arg) { + public Void apply(Distribution arg) { Utils.checkArgument( - aggregationData instanceof AggregationData.MeanData, + aggregationData instanceof DistributionData, createErrorMessageForAggregation(aggregation, aggregationData)); return null; } }, - new Function() { + new Function() { @Override - public Void apply(Distribution arg) { - Utils.checkArgument( - aggregationData instanceof DistributionData, - createErrorMessageForAggregation(aggregation, aggregationData)); + public Void apply(LastValue arg) { + measure.match( + new Function() { + @Override + public Void apply(MeasureDouble arg) { + Utils.checkArgument( + aggregationData instanceof LastValueDataDouble, + createErrorMessageForAggregation(aggregation, aggregationData)); + return null; + } + }, + new Function() { + @Override + public Void apply(MeasureLong arg) { + Utils.checkArgument( + aggregationData instanceof LastValueDataLong, + createErrorMessageForAggregation(aggregation, aggregationData)); + return null; + } + }, + Functions.throwAssertionError()); return null; } }, - Functions.throwAssertionError()); + new Function() { + @Override + public Void apply(Aggregation arg) { + // TODO(songya): remove this once Mean aggregation is completely removed. Before that + // we need to continue supporting Mean, since it could still be used by users and some + // deprecated RPC views. + if (arg instanceof Aggregation.Mean) { + Utils.checkArgument( + aggregationData instanceof AggregationData.MeanData, + createErrorMessageForAggregation(aggregation, aggregationData)); + return null; + } + throw new AssertionError(); + } + }); } private static String createErrorMessageForAggregation( diff --git a/api/src/test/java/io/opencensus/stats/AggregationDataTest.java b/api/src/test/java/io/opencensus/stats/AggregationDataTest.java index 3431d043..9f2aa589 100644 --- a/api/src/test/java/io/opencensus/stats/AggregationDataTest.java +++ b/api/src/test/java/io/opencensus/stats/AggregationDataTest.java @@ -23,6 +23,8 @@ import io.opencensus.common.Function; import io.opencensus.common.Functions; import io.opencensus.stats.AggregationData.CountData; import io.opencensus.stats.AggregationData.DistributionData; +import io.opencensus.stats.AggregationData.LastValueDataDouble; +import io.opencensus.stats.AggregationData.LastValueDataLong; import io.opencensus.stats.AggregationData.MeanData; import io.opencensus.stats.AggregationData.SumDataDouble; import io.opencensus.stats.AggregationData.SumDataLong; @@ -95,6 +97,8 @@ public class AggregationDataTest { .addEqualityGroup(DistributionData.create(10, 10, 1, 1, 55.5, Arrays.asList(0L, 10L, 0L))) .addEqualityGroup(MeanData.create(5.0, 1), MeanData.create(5.0, 1)) .addEqualityGroup(MeanData.create(-5.0, 1), MeanData.create(-5.0, 1)) + .addEqualityGroup(LastValueDataDouble.create(20.0), LastValueDataDouble.create(20.0)) + .addEqualityGroup(LastValueDataLong.create(20), LastValueDataLong.create(20)) .testEquals(); } @@ -105,8 +109,9 @@ public class AggregationDataTest { SumDataDouble.create(10.0), SumDataLong.create(100000000), CountData.create(40), - MeanData.create(5.0, 1), - DistributionData.create(1, 1, 1, 1, 0, Arrays.asList(0L, 10L, 0L))); + DistributionData.create(1, 1, 1, 1, 0, Arrays.asList(0L, 10L, 0L)), + LastValueDataDouble.create(20.0), + LastValueDataLong.create(200000000L)); final List actual = new ArrayList(); for (AggregationData aggregation : aggregations) { @@ -132,17 +137,24 @@ public class AggregationDataTest { return null; } }, - new Function() { + new Function() { @Override - public Void apply(MeanData arg) { - actual.add(arg.getMean()); + public Void apply(DistributionData arg) { + actual.add(arg.getBucketCounts()); return null; } }, - new Function() { + new Function() { @Override - public Void apply(DistributionData arg) { - actual.add(arg.getBucketCounts()); + public Void apply(LastValueDataDouble arg) { + actual.add(arg.getLastValue()); + return null; + } + }, + new Function() { + @Override + public Void apply(LastValueDataLong arg) { + actual.add(arg.getLastValue()); return null; } }, @@ -150,6 +162,7 @@ public class AggregationDataTest { } assertThat(actual) - .isEqualTo(Arrays.asList(10.0, 100000000L, 40L, 5.0, Arrays.asList(0L, 10L, 0L))); + .containsExactly(10.0, 100000000L, 40L, Arrays.asList(0L, 10L, 0L), 20.0, 200000000L) + .inOrder(); } } diff --git a/api/src/test/java/io/opencensus/stats/AggregationTest.java b/api/src/test/java/io/opencensus/stats/AggregationTest.java index 3ef131b8..c2e6a716 100644 --- a/api/src/test/java/io/opencensus/stats/AggregationTest.java +++ b/api/src/test/java/io/opencensus/stats/AggregationTest.java @@ -19,10 +19,10 @@ package io.opencensus.stats; import static com.google.common.truth.Truth.assertThat; import com.google.common.testing.EqualsTester; -import io.opencensus.common.Function; import io.opencensus.common.Functions; import io.opencensus.stats.Aggregation.Count; import io.opencensus.stats.Aggregation.Distribution; +import io.opencensus.stats.Aggregation.LastValue; import io.opencensus.stats.Aggregation.Mean; import io.opencensus.stats.Aggregation.Sum; import java.util.ArrayList; @@ -66,6 +66,7 @@ public class AggregationTest { Distribution.create(BucketBoundaries.create(Arrays.asList(0.0, 1.0, 5.0))), Distribution.create(BucketBoundaries.create(Arrays.asList(0.0, 1.0, 5.0)))) .addEqualityGroup(Mean.create(), Mean.create()) + .addEqualityGroup(LastValue.create(), LastValue.create()) .testEquals(); } @@ -76,39 +77,21 @@ public class AggregationTest { Sum.create(), Count.create(), Mean.create(), - Distribution.create(BucketBoundaries.create(Arrays.asList(-10.0, 1.0, 5.0)))); + Distribution.create(BucketBoundaries.create(Arrays.asList(-10.0, 1.0, 5.0))), + LastValue.create()); List actual = new ArrayList(); for (Aggregation aggregation : aggregations) { actual.add( aggregation.match( - new Function() { - @Override - public String apply(Sum arg) { - return "SUM"; - } - }, - new Function() { - @Override - public String apply(Count arg) { - return "COUNT"; - } - }, - new Function() { - @Override - public String apply(Mean arg) { - return "MEAN"; - } - }, - new Function() { - @Override - public String apply(Distribution arg) { - return "DISTRIBUTION"; - } - }, - Functions.throwIllegalArgumentException())); + Functions.returnConstant("SUM"), + Functions.returnConstant("COUNT"), + Functions.returnConstant("DISTRIBUTION"), + Functions.returnConstant("LASTVALUE"), + Functions.returnConstant("UNKNOWN"))); } - assertThat(actual).isEqualTo(Arrays.asList("SUM", "COUNT", "MEAN", "DISTRIBUTION")); + assertThat(actual) + .isEqualTo(Arrays.asList("SUM", "COUNT", "UNKNOWN", "DISTRIBUTION", "LASTVALUE")); } } diff --git a/api/src/test/java/io/opencensus/stats/ViewDataTest.java b/api/src/test/java/io/opencensus/stats/ViewDataTest.java index 0dc78e33..89009f34 100644 --- a/api/src/test/java/io/opencensus/stats/ViewDataTest.java +++ b/api/src/test/java/io/opencensus/stats/ViewDataTest.java @@ -27,10 +27,13 @@ import io.opencensus.common.Functions; import io.opencensus.common.Timestamp; import io.opencensus.stats.Aggregation.Count; import io.opencensus.stats.Aggregation.Distribution; +import io.opencensus.stats.Aggregation.LastValue; import io.opencensus.stats.Aggregation.Mean; import io.opencensus.stats.Aggregation.Sum; import io.opencensus.stats.AggregationData.CountData; import io.opencensus.stats.AggregationData.DistributionData; +import io.opencensus.stats.AggregationData.LastValueDataDouble; +import io.opencensus.stats.AggregationData.LastValueDataLong; import io.opencensus.stats.AggregationData.SumDataDouble; import io.opencensus.stats.AggregationData.SumDataLong; import io.opencensus.stats.View.AggregationWindow; @@ -218,6 +221,22 @@ public final class ViewDataTest { CountData.create(100))); } + @Test + public void preventAggregationAndAggregationDataMismatch_LastValueDouble_LastValueLong() { + aggregationAndAggregationDataMismatch( + createView(LastValue.create(), MEASURE_DOUBLE), + ImmutableMap., AggregationData>of( + Arrays.asList(V1, V2), LastValueDataLong.create(100))); + } + + @Test + public void preventAggregationAndAggregationDataMismatch_LastValueLong_LastValueDouble() { + aggregationAndAggregationDataMismatch( + createView(LastValue.create(), MEASURE_LONG), + ImmutableMap., AggregationData>of( + Arrays.asList(V1, V2), LastValueDataDouble.create(100))); + } + private static View createView(Aggregation aggregation) { return createView(aggregation, MEASURE_DOUBLE); } -- cgit v1.2.3 From 1cc5554f32b8c95625071b292e2e3bdca27acc90 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Fri, 27 Apr 2018 17:36:44 -0700 Subject: Start 0.14.0 development cycle (#1157) --- .../main/java/io/opencensus/common/OpenCensusLibraryInformation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java index 61a33bb4..f4aa8172 100644 --- a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java +++ b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java @@ -29,7 +29,7 @@ public final class OpenCensusLibraryInformation { * * @since 0.8 */ - public static final String VERSION = "0.13.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION + public static final String VERSION = "0.14.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION private OpenCensusLibraryInformation() {} } -- cgit v1.2.3 From 693ff67c13f5ec56d02ba184476845c742298092 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Wed, 2 May 2018 17:35:07 -0700 Subject: Add missing Nullable annotation to Functions.returnNull(). The Checker Framework didn't detect this error, because the method used @SuppressWarnings("unchecked") for a different reason. This commit also fixes a potential NPE in ZipkinExporterHandler. --- api/src/main/java/io/opencensus/common/Functions.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Functions.java b/api/src/main/java/io/opencensus/common/Functions.java index 5fce0707..eb5984af 100644 --- a/api/src/main/java/io/opencensus/common/Functions.java +++ b/api/src/main/java/io/opencensus/common/Functions.java @@ -16,6 +16,10 @@ package io.opencensus.common; +/*>>> +import org.checkerframework.checker.nullness.qual.Nullable; +*/ + /** * Commonly used {@link Function} instances. * @@ -24,9 +28,10 @@ package io.opencensus.common; public final class Functions { private Functions() {} - private static final Function RETURN_NULL = - new Function() { + private static final Function RETURN_NULL = + new Function() { @Override + @javax.annotation.Nullable public Void apply(Object ignored) { return null; } @@ -54,10 +59,10 @@ public final class Functions { * @return a {@code Function} that always ignores its argument and returns {@code null}. * @since 0.5 */ - public static Function returnNull() { + public static Function returnNull() { // It is safe to cast a producer of Void to anything, because Void is always null. @SuppressWarnings("unchecked") - Function function = (Function) RETURN_NULL; + Function function = (Function) RETURN_NULL; return function; } -- cgit v1.2.3 From c917cc24c7912bd3ef24da3a526f7c91bdafe33c Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Wed, 2 May 2018 18:33:52 -0700 Subject: Checker Framework: 2.5.0 -> 2.5.1 2.5.1 includes a fix for https://github.com/typetools/checker-framework/issues/1838. This commit also adds a few more @Nullable annotations that are required now. --- api/src/main/java/io/opencensus/stats/NoopStats.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/NoopStats.java b/api/src/main/java/io/opencensus/stats/NoopStats.java index 02f7c521..e7e94a38 100644 --- a/api/src/main/java/io/opencensus/stats/NoopStats.java +++ b/api/src/main/java/io/opencensus/stats/NoopStats.java @@ -30,11 +30,14 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import javax.annotation.Nullable; import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.ThreadSafe; +/*>>> +import org.checkerframework.checker.nullness.qual.Nullable; +*/ + /** No-op implementations of stats classes. */ final class NoopStats { @@ -149,7 +152,7 @@ final class NoopStats { // Cached set of exported views. It must be set to null whenever a view is registered or // unregistered. - @Nullable private volatile Set exportedViews; + @javax.annotation.Nullable private volatile Set exportedViews; @Override public void registerView(View newView) { @@ -167,7 +170,7 @@ final class NoopStats { } @Override - @Nullable + @javax.annotation.Nullable @SuppressWarnings("deprecation") public ViewData getView(View.Name name) { Utils.checkNotNull(name, "name"); @@ -178,7 +181,7 @@ final class NoopStats { } else { return ViewData.create( view, - Collections., AggregationData>emptyMap(), + Collections., AggregationData>emptyMap(), view.getWindow() .match( Functions.returnConstant( -- cgit v1.2.3 From 83fd63784edaed486e43be5570549143375fdefc Mon Sep 17 00:00:00 2001 From: Chris K Wensel Date: Fri, 11 May 2018 17:22:35 -0700 Subject: Adds Tracing.getExportComponent().flushAndShutdown() for use within application shutdown hooks. (#1141) Adds the ability to flush pending spans via a call to Tracing.getExportComponent().shutdown() This allows a developer to force a flush from within a shutdown hook or other means. Unfortunately the underlying Disruptor instance only provides a #shutdown() call, not a flush, or a public method for testing for backlog. Thus shutdown has propagated up to the above api call. --- api/src/main/java/io/opencensus/trace/export/ExportComponent.java | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java index 63447a76..bf06089c 100644 --- a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java +++ b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java @@ -66,6 +66,13 @@ public abstract class ExportComponent { */ public abstract SampledSpanStore getSampledSpanStore(); + /** + * Will shutdown this ExportComponent after flushing any pending spans. + * + * @since 0.13 + */ + public void shutdown() {} + private static final class NoopExportComponent extends ExportComponent { private final SampledSpanStore noopSampledSpanStore = SampledSpanStore.newNoopSampledSpanStore(); -- cgit v1.2.3 From cae294b95546a8928bec81b211e9765c21878ec1 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Fri, 11 May 2018 18:29:49 -0700 Subject: Update a @since tag for the next release. --- api/src/main/java/io/opencensus/trace/export/ExportComponent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java index bf06089c..c334c5a6 100644 --- a/api/src/main/java/io/opencensus/trace/export/ExportComponent.java +++ b/api/src/main/java/io/opencensus/trace/export/ExportComponent.java @@ -69,7 +69,7 @@ public abstract class ExportComponent { /** * Will shutdown this ExportComponent after flushing any pending spans. * - * @since 0.13 + * @since 0.14 */ public void shutdown() {} -- cgit v1.2.3 From cbba3c127a4f71e400a8242e7a701a8badee0041 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Mon, 14 May 2018 15:13:31 -0700 Subject: Remove PublicForTesting from Status.CanonicalCode.toStatus() (fixes #976). This method is already used by the Stackdriver stats exporter to convert status types, so it should be part of the API. --- api/src/main/java/io/opencensus/trace/Status.java | 2 -- 1 file changed, 2 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/Status.java b/api/src/main/java/io/opencensus/trace/Status.java index 61f33dc7..1fa85085 100644 --- a/api/src/main/java/io/opencensus/trace/Status.java +++ b/api/src/main/java/io/opencensus/trace/Status.java @@ -16,7 +16,6 @@ package io.opencensus.trace; -import io.opencensus.internal.PublicForTesting; import io.opencensus.internal.Utils; import java.util.ArrayList; import java.util.Arrays; @@ -228,7 +227,6 @@ public final class Status { * @return the status that has the current {@code CanonicalCode}. * @since 0.5 */ - @PublicForTesting public Status toStatus() { return STATUS_LIST.get(value); } -- cgit v1.2.3 From 9080a9ab863f4d5bcda26c22ed3651d457cc7f39 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 15 May 2018 15:04:35 -0700 Subject: Throw IllegalArgumentException when Duration.create receives invalid arguments. Fixes #1179. Throwing IllegalArgumentException for invalid arguments is more consistent with the rest of the opencensus-java API. --- .../main/java/io/opencensus/common/Duration.java | 31 +++++++---- .../java/io/opencensus/common/DurationTest.java | 64 +++++++++++++++++++--- 2 files changed, 78 insertions(+), 17 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Duration.java b/api/src/main/java/io/opencensus/common/Duration.java index 4b7bb367..f46cd187 100644 --- a/api/src/main/java/io/opencensus/common/Duration.java +++ b/api/src/main/java/io/opencensus/common/Duration.java @@ -35,7 +35,6 @@ import javax.annotation.concurrent.Immutable; @Immutable @AutoValue public abstract class Duration implements Comparable { - private static final Duration ZERO = create(0, 0); /** * Creates a new time duration from given seconds and nanoseconds. @@ -47,19 +46,30 @@ public abstract class Duration implements Comparable { * negative `nanos` field. For durations of one second or more, a non-zero value for the * `nanos` field must be of the same sign as the `seconds` field. Must be from -999,999,999 to * +999,999,999 inclusive. - * @return new {@code Duration} with specified fields. For invalid inputs, a {@code Duration} of - * zero is returned. + * @return new {@code Duration} with specified fields. + * @throws IllegalArgumentException if the arguments are out of range or have inconsistent sign. * @since 0.5 */ public static Duration create(long seconds, int nanos) { - if (seconds < -MAX_SECONDS || seconds > MAX_SECONDS) { - return ZERO; + if (seconds < -MAX_SECONDS) { + throw new IllegalArgumentException( + "'seconds' is less than minimum (" + -MAX_SECONDS + "): " + seconds); } - if (nanos < -MAX_NANOS || nanos > MAX_NANOS) { - return ZERO; + if (seconds > MAX_SECONDS) { + throw new IllegalArgumentException( + "'seconds' is greater than maximum (" + MAX_SECONDS + "): " + seconds); + } + if (nanos < -MAX_NANOS) { + throw new IllegalArgumentException( + "'nanos' is less than minimum (" + -MAX_NANOS + "): " + nanos); + } + if (nanos > MAX_NANOS) { + throw new IllegalArgumentException( + "'nanos' is greater than maximum (" + MAX_NANOS + "): " + nanos); } if ((seconds < 0 && nanos > 0) || (seconds > 0 && nanos < 0)) { - return ZERO; + throw new IllegalArgumentException( + "'seconds' and 'nanos' have inconsistent sign: seconds=" + seconds + ", nanos=" + nanos); } return new AutoValue_Duration(seconds, nanos); } @@ -68,8 +78,9 @@ public abstract class Duration implements Comparable { * Creates a new {@code Duration} from given milliseconds. * * @param millis the duration in milliseconds. - * @return a new {@code Duration} from given milliseconds. For invalid inputs, a {@code Duration} - * of zero is returned. + * @return a new {@code Duration} from given milliseconds. + * @throws IllegalArgumentException if the number of milliseconds is out of the range that can be + * represented by {@code Duration}. * @since 0.5 */ public static Duration fromMillis(long millis) { diff --git a/api/src/test/java/io/opencensus/common/DurationTest.java b/api/src/test/java/io/opencensus/common/DurationTest.java index fb5f314e..ea636ca0 100644 --- a/api/src/test/java/io/opencensus/common/DurationTest.java +++ b/api/src/test/java/io/opencensus/common/DurationTest.java @@ -18,13 +18,17 @@ package io.opencensus.common; import static com.google.common.truth.Truth.assertThat; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** Unit tests for {@link Duration}. */ @RunWith(JUnit4.class) public class DurationTest { + @Rule public ExpectedException thrown = ExpectedException.none(); + @Test public void testDurationCreate() { assertThat(Duration.create(24, 42).getSeconds()).isEqualTo(24); @@ -38,13 +42,45 @@ public class DurationTest { } @Test - public void testDurationCreateInvalidInput() { - assertThat(Duration.create(-315576000001L, 0)).isEqualTo(Duration.create(0, 0)); - assertThat(Duration.create(315576000001L, 0)).isEqualTo(Duration.create(0, 0)); - assertThat(Duration.create(0, 1000000000)).isEqualTo(Duration.create(0, 0)); - assertThat(Duration.create(0, -1000000000)).isEqualTo(Duration.create(0, 0)); - assertThat(Duration.create(-1, 1)).isEqualTo(Duration.create(0, 0)); - assertThat(Duration.create(1, -1)).isEqualTo(Duration.create(0, 0)); + public void create_SecondsTooLow() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("'seconds' is less than minimum (-315576000000): -315576000001"); + Duration.create(-315576000001L, 0); + } + + @Test + public void create_SecondsTooHigh() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("'seconds' is greater than maximum (315576000000): 315576000001"); + Duration.create(315576000001L, 0); + } + + @Test + public void create_NanosTooLow() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("'nanos' is less than minimum (-999999999): -1000000000"); + Duration.create(0, -1000000000); + } + + @Test + public void create_NanosTooHigh() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("'nanos' is greater than maximum (999999999): 1000000000"); + Duration.create(0, 1000000000); + } + + @Test + public void create_NegativeSecondsPositiveNanos() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("'seconds' and 'nanos' have inconsistent sign: seconds=-1, nanos=1"); + Duration.create(-1, 1); + } + + @Test + public void create_PositiveSecondsNegativeNanos() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("'seconds' and 'nanos' have inconsistent sign: seconds=1, nanos=-1"); + Duration.create(1, -1); } @Test @@ -62,6 +98,20 @@ public class DurationTest { assertThat(Duration.fromMillis(-3456)).isEqualTo(Duration.create(-3, -456000000)); } + @Test + public void fromMillis_TooLow() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("'seconds' is less than minimum (-315576000000): -315576000001"); + Duration.fromMillis(-315576000001000L); + } + + @Test + public void fromMillis_TooHigh() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("'seconds' is greater than maximum (315576000000): 315576000001"); + Duration.fromMillis(315576000001000L); + } + @Test public void duration_CompareLength() { assertThat(Duration.create(0, 0).compareTo(Duration.create(0, 0))).isEqualTo(0); -- cgit v1.2.3 From 6966d688ea5b14bb8c6fe8e319c5c1bcecf06e50 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 15 May 2018 15:52:30 -0700 Subject: Throw IllegalArgumentException when Timestamp.create receives invalid arguments. Throwing IllegalArgumentException for invalid arguments is more consistent with the rest of the opencensus-java API. This commit also fixes a test that created an invalid Timestamp. --- .../main/java/io/opencensus/common/Timestamp.java | 27 ++++++--- .../java/io/opencensus/common/TimestampTest.java | 64 +++++++++++++++++++--- 2 files changed, 75 insertions(+), 16 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Timestamp.java b/api/src/main/java/io/opencensus/common/Timestamp.java index e3aae3a6..d17b3fd8 100644 --- a/api/src/main/java/io/opencensus/common/Timestamp.java +++ b/api/src/main/java/io/opencensus/common/Timestamp.java @@ -39,7 +39,6 @@ import javax.annotation.concurrent.Immutable; @Immutable @AutoValue public abstract class Timestamp implements Comparable { - private static final Timestamp EPOCH = new AutoValue_Timestamp(0, 0); Timestamp() {} @@ -51,16 +50,25 @@ public abstract class Timestamp implements Comparable { * @param nanos Non-negative fractions of a second at nanosecond resolution. Negative second * values with fractions must still have non-negative nanos values that count forward in time. * Must be from 0 to 999,999,999 inclusive. - * @return new {@code Timestamp} with specified fields. For invalid inputs, a {@code Timestamp} of - * zero is returned. + * @return new {@code Timestamp} with specified fields. + * @throws IllegalArgumentException if the arguments are out of range. * @since 0.5 */ public static Timestamp create(long seconds, int nanos) { - if (seconds < -MAX_SECONDS || seconds > MAX_SECONDS) { - return EPOCH; + if (seconds < -MAX_SECONDS) { + throw new IllegalArgumentException( + "'seconds' is less than minimum (" + -MAX_SECONDS + "): " + seconds); } - if (nanos < 0 || nanos > MAX_NANOS) { - return EPOCH; + if (seconds > MAX_SECONDS) { + throw new IllegalArgumentException( + "'seconds' is greater than maximum (" + MAX_SECONDS + "): " + seconds); + } + if (nanos < 0) { + throw new IllegalArgumentException("'nanos' is less than zero: " + nanos); + } + if (nanos > MAX_NANOS) { + throw new IllegalArgumentException( + "'nanos' is greater than maximum (" + MAX_NANOS + "): " + nanos); } return new AutoValue_Timestamp(seconds, nanos); } @@ -69,8 +77,9 @@ public abstract class Timestamp implements Comparable { * Creates a new timestamp from the given milliseconds. * * @param epochMilli the timestamp represented in milliseconds since epoch. - * @return new {@code Timestamp} with specified fields. For invalid inputs, a {@code Timestamp} of - * zero is returned. + * @return new {@code Timestamp} with specified fields. + * @throws IllegalArgumentException if the number of milliseconds is out of the range that can be + * represented by {@code Timestamp}. * @since 0.5 */ public static Timestamp fromMillis(long epochMilli) { diff --git a/api/src/test/java/io/opencensus/common/TimestampTest.java b/api/src/test/java/io/opencensus/common/TimestampTest.java index 776f5f12..b193b3c8 100644 --- a/api/src/test/java/io/opencensus/common/TimestampTest.java +++ b/api/src/test/java/io/opencensus/common/TimestampTest.java @@ -18,13 +18,17 @@ package io.opencensus.common; import static com.google.common.truth.Truth.assertThat; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** Unit tests for {@link Timestamp}. */ @RunWith(JUnit4.class) public class TimestampTest { + @Rule public ExpectedException thrown = ExpectedException.none(); + @Test public void timestampCreate() { assertThat(Timestamp.create(24, 42).getSeconds()).isEqualTo(24); @@ -38,13 +42,45 @@ public class TimestampTest { } @Test - public void timestampCreate_InvalidInput() { - assertThat(Timestamp.create(-315576000001L, 0)).isEqualTo(Timestamp.create(0, 0)); - assertThat(Timestamp.create(315576000001L, 0)).isEqualTo(Timestamp.create(0, 0)); - assertThat(Timestamp.create(1, 1000000000)).isEqualTo(Timestamp.create(0, 0)); - assertThat(Timestamp.create(1, -1)).isEqualTo(Timestamp.create(0, 0)); - assertThat(Timestamp.create(-1, 1000000000)).isEqualTo(Timestamp.create(0, 0)); - assertThat(Timestamp.create(-1, -1)).isEqualTo(Timestamp.create(0, 0)); + public void create_SecondsTooLow() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("'seconds' is less than minimum (-315576000000): -315576000001"); + Timestamp.create(-315576000001L, 0); + } + + @Test + public void create_SecondsTooHigh() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("'seconds' is greater than maximum (315576000000): 315576000001"); + Timestamp.create(315576000001L, 0); + } + + @Test + public void create_NanosTooLow_PositiveTime() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("'nanos' is less than zero: -1"); + Timestamp.create(1, -1); + } + + @Test + public void create_NanosTooHigh_PositiveTime() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("'nanos' is greater than maximum (999999999): 1000000000"); + Timestamp.create(1, 1000000000); + } + + @Test + public void create_NanosTooLow_NegativeTime() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("'nanos' is less than zero: -1"); + Timestamp.create(-1, -1); + } + + @Test + public void create_NanosTooHigh_NegativeTime() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("'nanos' is greater than maximum (999999999): 1000000000"); + Timestamp.create(-1, 1000000000); } @Test @@ -61,6 +97,20 @@ public class TimestampTest { assertThat(Timestamp.fromMillis(-3456)).isEqualTo(Timestamp.create(-4, 544000000)); } + @Test + public void fromMillis_TooLow() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("'seconds' is less than minimum (-315576000000): -315576000001"); + Timestamp.fromMillis(-315576000001000L); + } + + @Test + public void fromMillis_TooHigh() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("'seconds' is greater than maximum (315576000000): 315576000001"); + Timestamp.fromMillis(315576000001000L); + } + @Test public void timestampAddNanos() { Timestamp timestamp = Timestamp.create(1234, 223); -- cgit v1.2.3 From 0334e1615b41adf455520a8b9f5960dafab25345 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Mon, 28 May 2018 17:49:53 -0700 Subject: Starts adding a metrics package. (#1211) * Start adding a metrics package. * Add ExperimentalApi annotation to the package. --- .../io/opencensus/stats/metrics/package-info.java | 31 ++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 api/src/main/java/io/opencensus/stats/metrics/package-info.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/metrics/package-info.java b/api/src/main/java/io/opencensus/stats/metrics/package-info.java new file mode 100644 index 00000000..ad7b7efb --- /dev/null +++ b/api/src/main/java/io/opencensus/stats/metrics/package-info.java @@ -0,0 +1,31 @@ +/* + * Copyright 2018, 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. + */ + +/** + * This package describes the Metrics data model. Metrics are a data model for what stats exporters + * take as input. + * + *

    Currently all the public classes under this package are marked as {@link + * io.opencensus.common.ExperimentalApi}. This data model may eventually become the wire format for + * metrics. + * + *

    Please see + * https://github.com/census-instrumentation/opencensus-specs/blob/master/stats/Metrics.md and + * https://github.com/census-instrumentation/opencensus-proto/blob/master/opencensus/proto/stats/metrics/metrics.proto + * for more details. + */ +@io.opencensus.common.ExperimentalApi +package io.opencensus.stats.metrics; -- cgit v1.2.3 From 55c12779e8a17e0d3d3e88480a01857f051cae55 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Thu, 31 May 2018 18:56:17 -0700 Subject: Add Span.Kind to the trace API. (#1223) * Add Span.Kind to the trace API. * Add @Nullable annotation where needed. * Add changes to changelog. --- api/src/main/java/io/opencensus/trace/Span.java | 19 ++++++++ .../main/java/io/opencensus/trace/SpanBuilder.java | 21 +++++++-- .../java/io/opencensus/trace/export/SpanData.java | 53 +++++++++++++++++++++- .../java/io/opencensus/trace/SpanBuilderTest.java | 13 ++++++ .../io/opencensus/trace/export/SpanDataTest.java | 11 +++++ 5 files changed, 112 insertions(+), 5 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/Span.java b/api/src/main/java/io/opencensus/trace/Span.java index cb82038d..4ec532e9 100644 --- a/api/src/main/java/io/opencensus/trace/Span.java +++ b/api/src/main/java/io/opencensus/trace/Span.java @@ -259,4 +259,23 @@ public abstract class Span { public final Set getOptions() { return options; } + + /** + * Type of span. Can be used to specify additional relationships between spans in addition to a + * parent/child relationship. + * + * @since 0.14 + */ + public enum Kind { + /** + * Indicates that the span covers server-side handling of an RPC or other remote network + * request. + */ + SERVER, + + /** + * Indicates that the span covers the client-side wrapper around an RPC or other remote request. + */ + CLIENT + } } diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java index f10cb7c0..e66adf57 100644 --- a/api/src/main/java/io/opencensus/trace/SpanBuilder.java +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -111,7 +111,7 @@ public abstract class SpanBuilder { /** * Sets the {@link Sampler} to use. If not set, the implementation will provide a default. * - * @param sampler The {@code Sampler} to use when determining sampling for a {@code Span}. + * @param sampler the {@code Sampler} to use when determining sampling for a {@code Span}. * @return this. * @since 0.5 */ @@ -122,7 +122,7 @@ public abstract class SpanBuilder { * traces. Used (for example) in batching operations, where a single batch handler processes * multiple requests from different traces. * - * @param parentLinks New links to be added. + * @param parentLinks new links to be added. * @return this. * @throws NullPointerException if {@code parentLinks} is {@code null}. * @since 0.5 @@ -133,12 +133,22 @@ public abstract class SpanBuilder { * Sets the option {@link Span.Options#RECORD_EVENTS} for the newly created {@code Span}. If not * called, the implementation will provide a default. * - * @param recordEvents New value determining if this {@code Span} should have events recorded. + * @param recordEvents new value determining if this {@code Span} should have events recorded. * @return this. * @since 0.5 */ public abstract SpanBuilder setRecordEvents(boolean recordEvents); + /** + * Sets the {@link Span.Kind} for the newly created {@code Span}. If not called, the + * implementation will provide a default. + * + * @param spanKind the kind of the newly created {@code Span}. + * @return this. + * @since 0.14 + */ + public abstract SpanBuilder setSpanKind(Span.Kind spanKind); + /** * Starts a new {@link Span}. * @@ -322,6 +332,11 @@ public abstract class SpanBuilder { return this; } + @Override + public SpanBuilder setSpanKind(Span.Kind spanKind) { + return this; + } + private NoopSpanBuilder(String name) { Utils.checkNotNull(name, "name"); } diff --git a/api/src/main/java/io/opencensus/trace/export/SpanData.java b/api/src/main/java/io/opencensus/trace/export/SpanData.java index 7b1daf42..f0a51bf3 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanData.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanData.java @@ -24,6 +24,7 @@ import io.opencensus.trace.AttributeValue; import io.opencensus.trace.Link; import io.opencensus.trace.MessageEvent; import io.opencensus.trace.Span; +import io.opencensus.trace.Span.Kind; import io.opencensus.trace.SpanContext; import io.opencensus.trace.SpanId; import io.opencensus.trace.Status; @@ -49,6 +50,42 @@ import org.checkerframework.dataflow.qual.Deterministic; @AutoValue public abstract class SpanData { + /** + * Returns a new immutable {@code SpanData}. + * + * @deprecated Use {@link #create(SpanContext, SpanId, Boolean, String, Kind, Timestamp, + * Attributes, TimedEvents, TimedEvents, Links, Integer, Status, Timestamp)}. + */ + @Deprecated + public static SpanData create( + SpanContext context, + @Nullable SpanId parentSpanId, + @Nullable Boolean hasRemoteParent, + String name, + Timestamp startTimestamp, + Attributes attributes, + TimedEvents annotations, + TimedEvents messageOrNetworkEvents, + Links links, + @Nullable Integer childSpanCount, + @Nullable Status status, + @Nullable Timestamp endTimestamp) { + return create( + context, + parentSpanId, + hasRemoteParent, + name, + null, + startTimestamp, + attributes, + annotations, + messageOrNetworkEvents, + links, + childSpanCount, + status, + endTimestamp); + } + /** * Returns a new immutable {@code SpanData}. * @@ -58,6 +95,7 @@ public abstract class SpanData { * @param hasRemoteParent {@code true} if the parent {@code Span} is remote. {@code null} if this * is a root span. * @param name the name of the {@code Span}. + * @param kind the kind of the {@code Span}. * @param startTimestamp the start {@code Timestamp} of the {@code Span}. * @param attributes the attributes associated with the {@code Span}. * @param annotations the annotations associated with the {@code Span}. @@ -70,14 +108,15 @@ public abstract class SpanData { * @param endTimestamp the end {@code Timestamp} of the {@code Span}. {@code null} if the {@code * Span} is still active. * @return a new immutable {@code SpanData}. - * @since 0.5 + * @since 0.14 */ - @SuppressWarnings("deprecation") + @SuppressWarnings({"deprecation", "InconsistentOverloads"}) public static SpanData create( SpanContext context, @Nullable SpanId parentSpanId, @Nullable Boolean hasRemoteParent, String name, + @Nullable Kind kind, Timestamp startTimestamp, Attributes attributes, TimedEvents annotations, @@ -111,6 +150,7 @@ public abstract class SpanData { parentSpanId, hasRemoteParent, name, + kind, startTimestamp, attributes, annotations, @@ -158,6 +198,15 @@ public abstract class SpanData { */ public abstract String getName(); + /** + * Returns the kind of this {@code Span}. + * + * @return the kind of this {@code Span}. + * @since 0.14 + */ + @Nullable + public abstract Kind getKind(); + /** * Returns the start {@code Timestamp} of this {@code Span}. * diff --git a/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java b/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java index 1403db15..a929ad97 100644 --- a/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java @@ -21,6 +21,9 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import io.opencensus.common.Scope; +import io.opencensus.trace.Span.Kind; +import io.opencensus.trace.samplers.Samplers; +import java.util.Collections; import java.util.concurrent.Callable; import org.junit.Before; import org.junit.Test; @@ -88,4 +91,14 @@ public class SpanBuilderTest { verify(span).end(EndSpanOptions.DEFAULT); assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE); } + + @Test + public void doNotCrash_NoopImplementation() throws Exception { + SpanBuilder spanBuilder = tracer.spanBuilder("MySpanName"); + spanBuilder.setParentLinks(Collections.emptyList()); + spanBuilder.setRecordEvents(true); + spanBuilder.setSampler(Samplers.alwaysSample()); + spanBuilder.setSpanKind(Kind.SERVER); + assertThat(spanBuilder.startSpan()).isSameAs(BlankSpan.INSTANCE); + } } diff --git a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java index 399b35e0..b991d145 100644 --- a/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java +++ b/api/src/test/java/io/opencensus/trace/export/SpanDataTest.java @@ -26,6 +26,7 @@ import io.opencensus.trace.Link; import io.opencensus.trace.Link.Type; import io.opencensus.trace.MessageEvent; import io.opencensus.trace.NetworkEvent; +import io.opencensus.trace.Span.Kind; import io.opencensus.trace.SpanContext; import io.opencensus.trace.SpanId; import io.opencensus.trace.Status; @@ -113,6 +114,7 @@ public class SpanDataTest { parentSpanId, true, SPAN_NAME, + Kind.SERVER, startTimestamp, attributes, annotations, @@ -125,6 +127,7 @@ public class SpanDataTest { assertThat(spanData.getParentSpanId()).isEqualTo(parentSpanId); assertThat(spanData.getHasRemoteParent()).isTrue(); assertThat(spanData.getName()).isEqualTo(SPAN_NAME); + assertThat(spanData.getKind()).isEqualTo(Kind.SERVER); assertThat(spanData.getStartTimestamp()).isEqualTo(startTimestamp); assertThat(spanData.getAttributes()).isEqualTo(attributes); assertThat(spanData.getAnnotations()).isEqualTo(annotations); @@ -144,6 +147,7 @@ public class SpanDataTest { parentSpanId, true, SPAN_NAME, + null, startTimestamp, attributes, annotations, @@ -175,6 +179,7 @@ public class SpanDataTest { null, null, SPAN_NAME, + null, startTimestamp, attributes, annotations, @@ -206,6 +211,7 @@ public class SpanDataTest { parentSpanId, false, SPAN_NAME, + null, startTimestamp, Attributes.create(Collections.emptyMap(), 0), TimedEvents.create(Collections.>emptyList(), 0), @@ -237,6 +243,7 @@ public class SpanDataTest { parentSpanId, false, SPAN_NAME, + Kind.CLIENT, startTimestamp, attributes, annotations, @@ -251,6 +258,7 @@ public class SpanDataTest { parentSpanId, false, SPAN_NAME, + Kind.CLIENT, startTimestamp, attributes, annotations, @@ -265,6 +273,7 @@ public class SpanDataTest { parentSpanId, false, SPAN_NAME, + null, startTimestamp, Attributes.create(Collections.emptyMap(), 0), TimedEvents.create(Collections.>emptyList(), 0), @@ -287,6 +296,7 @@ public class SpanDataTest { parentSpanId, false, SPAN_NAME, + Kind.CLIENT, startTimestamp, attributes, annotations, @@ -299,6 +309,7 @@ public class SpanDataTest { assertThat(spanDataString).contains(spanContext.toString()); assertThat(spanDataString).contains(parentSpanId.toString()); assertThat(spanDataString).contains(SPAN_NAME); + assertThat(spanDataString).contains(Kind.CLIENT.toString()); assertThat(spanDataString).contains(startTimestamp.toString()); assertThat(spanDataString).contains(attributes.toString()); assertThat(spanDataString).contains(annotations.toString()); -- cgit v1.2.3 From 2fd835b391e749745f0303c45d1affbe304b0974 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Fri, 1 Jun 2018 13:15:34 -0700 Subject: Add since for Span.Kind constants and make SpanBuilder.setSpanKind not abstract. (#1226) --- api/src/main/java/io/opencensus/trace/Span.java | 7 +++++-- api/src/main/java/io/opencensus/trace/SpanBuilder.java | 4 +++- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/Span.java b/api/src/main/java/io/opencensus/trace/Span.java index 4ec532e9..0fc62daf 100644 --- a/api/src/main/java/io/opencensus/trace/Span.java +++ b/api/src/main/java/io/opencensus/trace/Span.java @@ -268,13 +268,16 @@ public abstract class Span { */ public enum Kind { /** - * Indicates that the span covers server-side handling of an RPC or other remote network - * request. + * Indicates that the span covers server-side handling of an RPC or other remote request. + * + * @since 0.14 */ SERVER, /** * Indicates that the span covers the client-side wrapper around an RPC or other remote request. + * + * @since 0.14 */ CLIENT } diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java index e66adf57..00e11572 100644 --- a/api/src/main/java/io/opencensus/trace/SpanBuilder.java +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -147,7 +147,9 @@ public abstract class SpanBuilder { * @return this. * @since 0.14 */ - public abstract SpanBuilder setSpanKind(Span.Kind spanKind); + public SpanBuilder setSpanKind(@Nullable Span.Kind spanKind) { + return this; + } /** * Starts a new {@link Span}. -- cgit v1.2.3 From 70deecc0324adaced051b371abe288f9f7a45198 Mon Sep 17 00:00:00 2001 From: songy23 Date: Mon, 4 Jun 2018 17:44:33 -0700 Subject: Start 0.15.0 development cycle --- .../main/java/io/opencensus/common/OpenCensusLibraryInformation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java index f4aa8172..b3131338 100644 --- a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java +++ b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java @@ -29,7 +29,7 @@ public final class OpenCensusLibraryInformation { * * @since 0.8 */ - public static final String VERSION = "0.14.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION + public static final String VERSION = "0.15.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION private OpenCensusLibraryInformation() {} } -- cgit v1.2.3 From 4f1b11a7573c30fabfaa1a90244da7b8604dba61 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Tue, 5 Jun 2018 17:08:43 -0700 Subject: Metrics: Move Metrics to a separate artifact. (#1216) * Move Metrics to a separate artifact. * Fix review comments. * Update one TODO about the naming of the artifact. --- .../io/opencensus/stats/metrics/package-info.java | 31 ---------------------- 1 file changed, 31 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/stats/metrics/package-info.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/metrics/package-info.java b/api/src/main/java/io/opencensus/stats/metrics/package-info.java deleted file mode 100644 index ad7b7efb..00000000 --- a/api/src/main/java/io/opencensus/stats/metrics/package-info.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2018, 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. - */ - -/** - * This package describes the Metrics data model. Metrics are a data model for what stats exporters - * take as input. - * - *

    Currently all the public classes under this package are marked as {@link - * io.opencensus.common.ExperimentalApi}. This data model may eventually become the wire format for - * metrics. - * - *

    Please see - * https://github.com/census-instrumentation/opencensus-specs/blob/master/stats/Metrics.md and - * https://github.com/census-instrumentation/opencensus-proto/blob/master/opencensus/proto/stats/metrics/metrics.proto - * for more details. - */ -@io.opencensus.common.ExperimentalApi -package io.opencensus.stats.metrics; -- cgit v1.2.3 From 54198be41c52238977b24bd76eee3da2abf43b96 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Fri, 8 Jun 2018 13:05:49 -0700 Subject: Add package-info for all main packages in opencensus-api. (#1245) * Add package-info for all main packages in opencensus-api. * Fix format. --- .../java/io/opencensus/common/package-info.java | 18 ++++++++++++ .../java/io/opencensus/stats/package-info.java | 20 +++++++++++++ .../java/io/opencensus/trace/package-info.java | 33 ++++++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 api/src/main/java/io/opencensus/common/package-info.java create mode 100644 api/src/main/java/io/opencensus/stats/package-info.java create mode 100644 api/src/main/java/io/opencensus/trace/package-info.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/package-info.java b/api/src/main/java/io/opencensus/common/package-info.java new file mode 100644 index 00000000..1ebfd7cf --- /dev/null +++ b/api/src/main/java/io/opencensus/common/package-info.java @@ -0,0 +1,18 @@ +/* + * Copyright 2018, 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. + */ + +/** Common API between different packages in this artifact. */ +package io.opencensus.common; diff --git a/api/src/main/java/io/opencensus/stats/package-info.java b/api/src/main/java/io/opencensus/stats/package-info.java new file mode 100644 index 00000000..981daa0e --- /dev/null +++ b/api/src/main/java/io/opencensus/stats/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2018, 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. + */ + +/** API for stats recording. */ +// TODO: Add more details. +// TODO: Add code examples. +package io.opencensus.stats; diff --git a/api/src/main/java/io/opencensus/trace/package-info.java b/api/src/main/java/io/opencensus/trace/package-info.java new file mode 100644 index 00000000..77f39aba --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/package-info.java @@ -0,0 +1,33 @@ +/* + * Copyright 2018, 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. + */ + +/** + * API for distributed tracing. + * + *

    Distributed tracing, also called distributed request tracing, is a technique that helps + * debugging distributed applications. + * + *

    Trace represents a tree of spans. A trace has a root span that encapsulates all the spans from + * start to end, and the children spans being the distinct calls invoked in between. + * + *

    {@link io.opencensus.trace.Span} represents a single operation within a trace. + * + *

    {@link io.opencensus.trace.Span Spans} are propagated in-process in the {@code + * io.grpc.Context} and between process using one of the wire propagation formats supported in the + * {@code io.opencensus.trace.propagation} package. + */ +// TODO: Add code examples. +package io.opencensus.trace; -- cgit v1.2.3 From c788d4ee4774743cc6c5836d040672e4105eefea Mon Sep 17 00:00:00 2001 From: Yang Song Date: Wed, 13 Jun 2018 14:25:43 -0700 Subject: Tracing: fix typos in Tracer Javadoc. (#1256) --- api/src/main/java/io/opencensus/trace/Tracer.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/Tracer.java b/api/src/main/java/io/opencensus/trace/Tracer.java index b83fbed6..a2c0a239 100644 --- a/api/src/main/java/io/opencensus/trace/Tracer.java +++ b/api/src/main/java/io/opencensus/trace/Tracer.java @@ -40,7 +40,7 @@ import javax.annotation.Nullable; * class MyClass { * private static final Tracer tracer = Tracing.getTracer(); * void doWork() { - * try(Scope ss = tracer.spanBuilder("MyClass.DoWork").startScopedSpan) { + * try(Scope ss = tracer.spanBuilder("MyClass.DoWork").startScopedSpan()) { * tracer.getCurrentSpan().addAnnotation("Starting the work."); * doWorkInternal(); * tracer.getCurrentSpan().addAnnotation("Finished working."); @@ -174,7 +174,7 @@ public abstract class Tracer { * class MyClass { * private static Tracer tracer = Tracing.getTracer(); * void handleRequest(Executor executor) { - * Span span = new Tracer.spanBuilder("MyRunnableSpan"); + * Span span = tracer.spanBuilder("MyRunnableSpan").startSpan(); * executor.execute(tracer.withSpan(span, new Runnable() { * {@literal @}Override * public void run() { @@ -195,7 +195,7 @@ public abstract class Tracer { * class MyClass { * private static Tracer tracer = Tracing.getTracer(); * void handleRequest(Executor executor) { - * Span span = new Tracer.spanBuilder("MyRunnableSpan"); + * Span span = tracer.spanBuilder("MyRunnableSpan").startSpan(); * executor.execute(Context.wrap(tracer.withSpan(span, new Runnable() { * {@literal @}Override * public void run() { @@ -239,7 +239,7 @@ public abstract class Tracer { * class MyClass { * private static Tracer tracer = Tracing.getTracer(); * void handleRequest(Executor executor) { - * Span span = new Tracer.spanBuilder("MyRunnableSpan"); + * Span span = tracer.spanBuilder("MyRunnableSpan").startSpan(); * executor.execute(tracer.withSpan(span, {@code new Callable()} { * {@literal @}Override * public MyResult call() throws Exception { @@ -260,7 +260,7 @@ public abstract class Tracer { * class MyClass { * private static Tracer tracer = Tracing.getTracer(); * void handleRequest(Executor executor) { - * Span span = new Tracer.spanBuilder("MyRunnableSpan"); + * Span span = tracer.spanBuilder("MyRunnableSpan").startSpan(); * executor.execute(Context.wrap(tracer.withSpan(span, {@code new Callable()} { * {@literal @}Override * public MyResult call() throws Exception { -- cgit v1.2.3 From 372aa6d83035fb6d0bda2a2a8acaf0ce1825d4ba Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Wed, 13 Jun 2018 16:28:51 -0700 Subject: Error Prone: 2.2.0 -> 2.3.1 This commit contains several other changes as part of the upgrade: - Use -XepAllDisabledChecksAsWarnings to enable all available warnings so that we don't need to enable each warning explicitly. - Remove explicit suppression of warnings in generated code, since -XepDisableWarningsInGeneratedCode is now sufficient to suppress all warnings in AutoValue and Protocol Buffer generated classes. - Remove a suppression of "ConstructorLeaksThis", since https://github.com/google/error-prone/pull/789 was fixed. - Fix a few occurrences of "FieldCanBeFinal". --- api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java | 2 +- api/src/test/java/io/opencensus/tags/TagContextTest.java | 3 --- api/src/test/java/io/opencensus/trace/SpanBuilderTest.java | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java index a249d152..21511142 100644 --- a/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java +++ b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java @@ -78,7 +78,7 @@ final class CurrentSpanUtils { private static final class ScopeInSpan implements Scope { private final Context origContext; private final Span span; - private boolean endSpan; + private final boolean endSpan; /** * Constructs a new {@link ScopeInSpan}. diff --git a/api/src/test/java/io/opencensus/tags/TagContextTest.java b/api/src/test/java/io/opencensus/tags/TagContextTest.java index 05473255..025c7bae 100644 --- a/api/src/test/java/io/opencensus/tags/TagContextTest.java +++ b/api/src/test/java/io/opencensus/tags/TagContextTest.java @@ -86,9 +86,6 @@ public final class TagContextTest { private static final class SimpleTagContext extends TagContext { @Nullable private final List tags; - // This Error Prone warning doesn't seem correct, because the constructor is just calling - // another constructor. - @SuppressWarnings("ConstructorLeaksThis") SimpleTagContext(Tag... tags) { this(Lists.newArrayList(tags)); } diff --git a/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java b/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java index a929ad97..839c8945 100644 --- a/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanBuilderTest.java @@ -37,7 +37,7 @@ import org.mockito.MockitoAnnotations; // Need to suppress warnings for MustBeClosed because Java-6 does not support try-with-resources. @SuppressWarnings("MustBeClosedChecker") public class SpanBuilderTest { - private Tracer tracer = Tracing.getTracer(); + private final Tracer tracer = Tracing.getTracer(); @Mock private SpanBuilder spanBuilder; @Mock private Span span; -- cgit v1.2.3 From 9b82dc5a4a717766e245dffaeae9573844605215 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Wed, 20 Jun 2018 14:02:32 -0700 Subject: Stats: Only include the simple class name in the error message for ViewData.check methods. (#1267) * Stats: Only include the simple class name in the error message for ViewData.check methods. * Copy checkArgument and lazily create error message. * Rename help methods to avoid InconsistentOverloads. * Improve error messages in the unit tests. --- .../main/java/io/opencensus/stats/ViewData.java | 69 ++++++++++++---------- .../java/io/opencensus/stats/ViewDataTest.java | 27 ++++++--- 2 files changed, 57 insertions(+), 39 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/ViewData.java b/api/src/main/java/io/opencensus/stats/ViewData.java index 259f1068..df6edaa7 100644 --- a/api/src/main/java/io/opencensus/stats/ViewData.java +++ b/api/src/main/java/io/opencensus/stats/ViewData.java @@ -21,7 +21,6 @@ import io.opencensus.common.Duration; import io.opencensus.common.Function; import io.opencensus.common.Functions; import io.opencensus.common.Timestamp; -import io.opencensus.internal.Utils; import io.opencensus.stats.Aggregation.Count; import io.opencensus.stats.Aggregation.Distribution; import io.opencensus.stats.Aggregation.LastValue; @@ -210,31 +209,36 @@ public abstract class ViewData { new Function() { @Override public Void apply(View.AggregationWindow.Cumulative arg) { - Utils.checkArgument( - windowData instanceof AggregationWindowData.CumulativeData, - createErrorMessageForWindow(arg, windowData)); + throwIfWindowMismatch( + windowData instanceof AggregationWindowData.CumulativeData, arg, windowData); return null; } }, new Function() { @Override public Void apply(View.AggregationWindow.Interval arg) { - Utils.checkArgument( - windowData instanceof AggregationWindowData.IntervalData, - createErrorMessageForWindow(arg, windowData)); + throwIfWindowMismatch( + windowData instanceof AggregationWindowData.IntervalData, arg, windowData); return null; } }, Functions.throwAssertionError()); } + private static void throwIfWindowMismatch( + boolean isValid, View.AggregationWindow window, AggregationWindowData windowData) { + if (!isValid) { + throw new IllegalArgumentException(createErrorMessageForWindow(window, windowData)); + } + } + private static String createErrorMessageForWindow( View.AggregationWindow window, AggregationWindowData windowData) { return "AggregationWindow and AggregationWindowData types mismatch. " + "AggregationWindow: " - + window + + window.getClass().getSimpleName() + " AggregationWindowData: " - + windowData; + + windowData.getClass().getSimpleName(); } private static void checkAggregation( @@ -247,18 +251,16 @@ public abstract class ViewData { new Function() { @Override public Void apply(MeasureDouble arg) { - Utils.checkArgument( - aggregationData instanceof SumDataDouble, - createErrorMessageForAggregation(aggregation, aggregationData)); + throwIfAggregationMismatch( + aggregationData instanceof SumDataDouble, aggregation, aggregationData); return null; } }, new Function() { @Override public Void apply(MeasureLong arg) { - Utils.checkArgument( - aggregationData instanceof SumDataLong, - createErrorMessageForAggregation(aggregation, aggregationData)); + throwIfAggregationMismatch( + aggregationData instanceof SumDataLong, aggregation, aggregationData); return null; } }, @@ -269,18 +271,16 @@ public abstract class ViewData { new Function() { @Override public Void apply(Count arg) { - Utils.checkArgument( - aggregationData instanceof CountData, - createErrorMessageForAggregation(aggregation, aggregationData)); + throwIfAggregationMismatch( + aggregationData instanceof CountData, aggregation, aggregationData); return null; } }, new Function() { @Override public Void apply(Distribution arg) { - Utils.checkArgument( - aggregationData instanceof DistributionData, - createErrorMessageForAggregation(aggregation, aggregationData)); + throwIfAggregationMismatch( + aggregationData instanceof DistributionData, aggregation, aggregationData); return null; } }, @@ -291,18 +291,18 @@ public abstract class ViewData { new Function() { @Override public Void apply(MeasureDouble arg) { - Utils.checkArgument( + throwIfAggregationMismatch( aggregationData instanceof LastValueDataDouble, - createErrorMessageForAggregation(aggregation, aggregationData)); + aggregation, + aggregationData); return null; } }, new Function() { @Override public Void apply(MeasureLong arg) { - Utils.checkArgument( - aggregationData instanceof LastValueDataLong, - createErrorMessageForAggregation(aggregation, aggregationData)); + throwIfAggregationMismatch( + aggregationData instanceof LastValueDataLong, aggregation, aggregationData); return null; } }, @@ -317,9 +317,10 @@ public abstract class ViewData { // we need to continue supporting Mean, since it could still be used by users and some // deprecated RPC views. if (arg instanceof Aggregation.Mean) { - Utils.checkArgument( + throwIfAggregationMismatch( aggregationData instanceof AggregationData.MeanData, - createErrorMessageForAggregation(aggregation, aggregationData)); + aggregation, + aggregationData); return null; } throw new AssertionError(); @@ -327,13 +328,21 @@ public abstract class ViewData { }); } + private static void throwIfAggregationMismatch( + boolean isValid, Aggregation aggregation, AggregationData aggregationData) { + if (!isValid) { + throw new IllegalArgumentException( + createErrorMessageForAggregation(aggregation, aggregationData)); + } + } + private static String createErrorMessageForAggregation( Aggregation aggregation, AggregationData aggregationData) { return "Aggregation and AggregationData types mismatch. " + "Aggregation: " - + aggregation + + aggregation.getClass().getSimpleName() + " AggregationData: " - + aggregationData; + + aggregationData.getClass().getSimpleName(); } /** diff --git a/api/src/test/java/io/opencensus/stats/ViewDataTest.java b/api/src/test/java/io/opencensus/stats/ViewDataTest.java index 89009f34..0120ffea 100644 --- a/api/src/test/java/io/opencensus/stats/ViewDataTest.java +++ b/api/src/test/java/io/opencensus/stats/ViewDataTest.java @@ -160,12 +160,19 @@ public final class ViewDataTest { @Test public void preventWindowAndAggregationWindowDataMismatch() { + CumulativeData cumulativeData = + CumulativeData.create(Timestamp.fromMillis(1000), Timestamp.fromMillis(2000)); thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("AggregationWindow and AggregationWindowData types mismatch. "); + thrown.expectMessage( + "AggregationWindow and AggregationWindowData types mismatch. " + + "AggregationWindow: " + + INTERVAL_HOUR.getClass().getSimpleName() + + " AggregationWindowData: " + + cumulativeData.getClass().getSimpleName()); ViewData.create( View.create(NAME, DESCRIPTION, MEASURE_DOUBLE, DISTRIBUTION, TAG_KEYS, INTERVAL_HOUR), ENTRIES, - CumulativeData.create(Timestamp.fromMillis(1000), Timestamp.fromMillis(2000))); + cumulativeData); } @Test @@ -213,12 +220,7 @@ public final class ViewDataTest { @Test public void preventAggregationAndAggregationDataMismatch_Distribution_Count() { aggregationAndAggregationDataMismatch( - createView(DISTRIBUTION), - ImmutableMap.of( - Arrays.asList(V1, V2), - DistributionData.create(1, 1, 1, 1, 0, Arrays.asList(0L, 1L, 0L)), - Arrays.asList(V10, V20), - CountData.create(100))); + createView(DISTRIBUTION), ImmutableMap.of(Arrays.asList(V10, V20), CountData.create(100))); } @Test @@ -249,8 +251,15 @@ public final class ViewDataTest { View view, Map, ? extends AggregationData> entries) { CumulativeData cumulativeData = CumulativeData.create(Timestamp.fromMillis(1000), Timestamp.fromMillis(2000)); + Aggregation aggregation = view.getAggregation(); + AggregationData aggregationData = entries.values().iterator().next(); thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("Aggregation and AggregationData types mismatch. "); + thrown.expectMessage( + "Aggregation and AggregationData types mismatch. " + + "Aggregation: " + + aggregation.getClass().getSimpleName() + + " AggregationData: " + + aggregationData.getClass().getSimpleName()); ViewData.create(view, entries, cumulativeData); } -- cgit v1.2.3 From ee7d55ef4ea4551f3775531c457f05b0ae2264d5 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Wed, 20 Jun 2018 16:25:09 -0700 Subject: Start 0.16.0 development cycle --- .../main/java/io/opencensus/common/OpenCensusLibraryInformation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java index b3131338..35c62582 100644 --- a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java +++ b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java @@ -29,7 +29,7 @@ public final class OpenCensusLibraryInformation { * * @since 0.8 */ - public static final String VERSION = "0.15.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION + public static final String VERSION = "0.16.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION private OpenCensusLibraryInformation() {} } -- cgit v1.2.3 From bc143adc32e6db5e158485246d8d3aa6592b1cff Mon Sep 17 00:00:00 2001 From: rghetia Date: Thu, 21 Jun 2018 22:01:16 -0700 Subject: Summary Span: Add encoder/decoder for Server Stats. (#1272) * Summary Span: Add encoder/decoder for Server Stats. * Fixed build errors reported by Kokoro/Travis. * Fixed review comments. - Added missing javadoc annotation. - included version in encoder/decoder. - renamed get methods for ServerStats. * Change version from 0.15 to 0.16 - also fixed CURRENT_VERSION for encoder/decoder and added test for it. * Make ServerStatsEncoding public. * Add Test ServerStatsFieldEnum.Size replace traceOption() wiht getTraceOption() --- .../java/io/opencensus/common/ServerStats.java | 86 +++++++++++ .../ServerStatsDeserializationException.java | 47 ++++++ .../io/opencensus/common/ServerStatsEncoding.java | 125 ++++++++++++++++ .../opencensus/common/ServerStatsFieldEnums.java | 157 +++++++++++++++++++++ .../opencensus/common/ServerStatsEncodingTest.java | 155 ++++++++++++++++++++ .../common/ServerStatsFieldEnumsTest.java | 56 ++++++++ .../java/io/opencensus/common/ServerStatsTest.java | 78 ++++++++++ 7 files changed, 704 insertions(+) create mode 100644 api/src/main/java/io/opencensus/common/ServerStats.java create mode 100644 api/src/main/java/io/opencensus/common/ServerStatsDeserializationException.java create mode 100644 api/src/main/java/io/opencensus/common/ServerStatsEncoding.java create mode 100644 api/src/main/java/io/opencensus/common/ServerStatsFieldEnums.java create mode 100644 api/src/test/java/io/opencensus/common/ServerStatsEncodingTest.java create mode 100644 api/src/test/java/io/opencensus/common/ServerStatsFieldEnumsTest.java create mode 100644 api/src/test/java/io/opencensus/common/ServerStatsTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/ServerStats.java b/api/src/main/java/io/opencensus/common/ServerStats.java new file mode 100644 index 00000000..42efa1f2 --- /dev/null +++ b/api/src/main/java/io/opencensus/common/ServerStats.java @@ -0,0 +1,86 @@ +/* + * Copyright 2018, 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.common; + +import com.google.auto.value.AutoValue; +import javax.annotation.concurrent.Immutable; + +/** + * A representation of stats measured on the server side. + * + * @since 0.16 + */ +@Immutable +@AutoValue +public abstract class ServerStats { + + ServerStats() {} + + /** + * Returns Load Balancer latency, a latency observed at Load Balancer. + * + * @return Load Balancer latency in nanoseconds. + * @since 0.16 + */ + public abstract long getLbLatencyNs(); + + /** + * Returns Service latency, a latency observed at Server. + * + * @return Service latency in nanoseconds. + * @since 0.16 + */ + public abstract long getServiceLatencyNs(); + + /** + * Returns Trace options, a set of bits indicating properties of trace. + * + * @return Trace options a set of bits indicating properties of trace. + * @since 0.16 + */ + public abstract byte getTraceOption(); + + /** + * Creates new {@link ServerStats} from specified parameters. + * + * @param lbLatencyNs Represents request processing latency observed on Load Balancer. It is + * measured in nanoseconds. Must not be less than 0. Value of 0 represents that the latency is + * not measured. + * @param serviceLatencyNs Represents request processing latency observed on Server. It is + * measured in nanoseconds. Must not be less than 0. Value of 0 represents that the latency is + * not measured. + * @param traceOption Represents set of bits to indicate properties of trace. Currently it used + * only the least signification bit to represent sampling of the request on the server side. + * Other bits are ignored. + * @return new {@code ServerStats} with specified fields. + * @throws IllegalArgumentException if the arguments are out of range. + * @since 0.16 + */ + public static ServerStats create(long lbLatencyNs, long serviceLatencyNs, byte traceOption) { + + if (lbLatencyNs < 0) { + throw new IllegalArgumentException("'getLbLatencyNs' is less than zero: " + lbLatencyNs); + } + + if (serviceLatencyNs < 0) { + throw new IllegalArgumentException( + "'getServiceLatencyNs' is less than zero: " + serviceLatencyNs); + } + + return new AutoValue_ServerStats(lbLatencyNs, serviceLatencyNs, traceOption); + } +} diff --git a/api/src/main/java/io/opencensus/common/ServerStatsDeserializationException.java b/api/src/main/java/io/opencensus/common/ServerStatsDeserializationException.java new file mode 100644 index 00000000..2332733c --- /dev/null +++ b/api/src/main/java/io/opencensus/common/ServerStatsDeserializationException.java @@ -0,0 +1,47 @@ +/* + * Copyright 2018, 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.common; + +/** + * Exception thrown when a {@link ServerStats} cannot be parsed. + * + * @since 0.16 + */ +public final class ServerStatsDeserializationException extends Exception { + private static final long serialVersionUID = 0L; + + /** + * Constructs a new {@code ServerStatsDeserializationException} with the given message. + * + * @param message a message describing the error. + * @since 0.16 + */ + public ServerStatsDeserializationException(String message) { + super(message); + } + + /** + * Constructs a new {@code ServerStatsDeserializationException} with the given message and cause. + * + * @param message a message describing the error. + * @param cause the cause of the error. + * @since 0.16 + */ + public ServerStatsDeserializationException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/api/src/main/java/io/opencensus/common/ServerStatsEncoding.java b/api/src/main/java/io/opencensus/common/ServerStatsEncoding.java new file mode 100644 index 00000000..024a93f8 --- /dev/null +++ b/api/src/main/java/io/opencensus/common/ServerStatsEncoding.java @@ -0,0 +1,125 @@ +/* + * Copyright 2018, 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.common; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +/** + * A service class to encode/decode {@link ServerStats} as defined by the spec. + * + *

    See opencensus-server-stats-specs + * for encoding {@code ServerStats} + * + *

    Use {@code ServerStatsEncoding.toBytes(ServerStats stats)} to encode. + * + *

    Use {@code ServerStatsEncoding.parseBytes(byte[] serialized)} to decode. + * + * @since 0.16 + */ +public final class ServerStatsEncoding { + + private ServerStatsEncoding() {} + + /** + * The current encoding version. The value is {@value #CURRENT_VERSION} + * + * @since 0.16 + */ + public static final byte CURRENT_VERSION = (byte) 0; + + /** + * Encodes the {@link ServerStats} as per the Opencensus Summary Span specification. + * + * @param stats {@code ServerStats} to encode. + * @return encoded byte array. + * @since 0.16 + */ + public static byte[] toBytes(ServerStats stats) { + // Should this be optimized to not include invalid values? + + ByteBuffer bb = ByteBuffer.allocate(ServerStatsFieldEnums.getTotalSize() + 1); + bb.order(ByteOrder.LITTLE_ENDIAN); + + // put version + bb.put(CURRENT_VERSION); + + bb.put((byte) ServerStatsFieldEnums.Id.SERVER_STATS_LB_LATENCY_ID.value()); + bb.putLong(stats.getLbLatencyNs()); + + bb.put((byte) ServerStatsFieldEnums.Id.SERVER_STATS_SERVICE_LATENCY_ID.value()); + bb.putLong(stats.getServiceLatencyNs()); + + bb.put((byte) ServerStatsFieldEnums.Id.SERVER_STATS_TRACE_OPTION_ID.value()); + bb.put(stats.getTraceOption()); + return bb.array(); + } + + /** + * Decodes serialized byte array to create {@link ServerStats} as per Opencensus Summary Span + * specification. + * + * @param serialized encoded {@code ServerStats} in byte array. + * @return decoded {@code ServerStats}. null if decoding fails. + * @since 0.16 + */ + public static ServerStats parseBytes(byte[] serialized) + throws ServerStatsDeserializationException { + final ByteBuffer bb = ByteBuffer.wrap(serialized); + bb.order(ByteOrder.LITTLE_ENDIAN); + long serviceLatencyNs = 0L; + long lbLatencyNs = 0L; + byte traceOption = (byte) 0; + + // Check the version first. + if (!bb.hasRemaining()) { + throw new ServerStatsDeserializationException("Serialized ServerStats buffer is empty"); + } + byte version = bb.get(); + + if (version > CURRENT_VERSION || version < 0) { + throw new ServerStatsDeserializationException("Invalid ServerStats version: " + version); + } + + while (bb.hasRemaining()) { + ServerStatsFieldEnums.Id id = ServerStatsFieldEnums.Id.valueOf((int) bb.get() & 0xFF); + if (id == null) { + // Skip remaining; + bb.position(bb.limit()); + } else { + switch (id) { + case SERVER_STATS_LB_LATENCY_ID: + lbLatencyNs = bb.getLong(); + break; + case SERVER_STATS_SERVICE_LATENCY_ID: + serviceLatencyNs = bb.getLong(); + break; + case SERVER_STATS_TRACE_OPTION_ID: + traceOption = bb.get(); + break; + } + } + } + try { + return ServerStats.create(lbLatencyNs, serviceLatencyNs, traceOption); + } catch (IllegalArgumentException e) { + throw new ServerStatsDeserializationException( + "Serialized ServiceStats contains invalid values: " + e.getMessage()); + } + } +} diff --git a/api/src/main/java/io/opencensus/common/ServerStatsFieldEnums.java b/api/src/main/java/io/opencensus/common/ServerStatsFieldEnums.java new file mode 100644 index 00000000..92194d96 --- /dev/null +++ b/api/src/main/java/io/opencensus/common/ServerStatsFieldEnums.java @@ -0,0 +1,157 @@ +/* + * Copyright 2018, 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.common; + +import java.util.TreeMap; + +/** + * A Enum representation for Ids and Size for attributes of {@code ServerStats}. + * + *

    See opencensus-server-stats-specs + * for the field ids and their length defined for Server Stats + * + * @since 0.16 + */ +public final class ServerStatsFieldEnums { + + /** + * Available Ids for {@code ServerStats} attributes. + * + * @since 0.16 + */ + public enum Id { + /** + * Id for Latency observed at Load Balancer. + * + * @since 0.16 + */ + SERVER_STATS_LB_LATENCY_ID(0), + /** + * Id for Latency observed at Server. + * + * @since 0.16 + */ + SERVER_STATS_SERVICE_LATENCY_ID(1), + /** + * Id for Trace options. + * + * @since 0.16 + */ + SERVER_STATS_TRACE_OPTION_ID(2); + + private final int value; + + private Id(int value) { + this.value = value; + } + + /** + * Returns the numerical value of the {@link Id}. + * + * @return the numerical value of the {@code Id}. + * @since 0.16 + */ + public int value() { + return value; + } + + private static final TreeMap map = new TreeMap(); + + static { + for (Id id : Id.values()) { + map.put(id.value, id); + } + } + + /** + * Returns the {@link Id} representing the value value of the id. + * + * @param value integer value for which {@code Id} is being requested. + * @return the numerical value of the id. null if the id is not valid + * @since 0.16 + */ + public static Id valueOf(int value) { + return (Id) map.get(value); + } + } + + /** + * Size for each attributes in {@code ServerStats}. + * + * @since 0.16 + */ + public enum Size { + /** + * Number of bytes used to represent latency observed at Load Balancer + * + * @since 0.16 + */ + SERVER_STATS_LB_LATENCY_SIZE(8), + /** + * Number of bytes used to represent latency observed at Server + * + * @since 0.16 + */ + SERVER_STATS_SERVICE_LATENCY_SIZE(8), + /** + * Number of bytes used to represent Trace option + * + * @since 0.16 + */ + SERVER_STATS_TRACE_OPTION_SIZE(1); + + private final int value; + + private Size(int value) { + this.value = value; + } + + /** + * Returns the numerical value of the {@link Size}. + * + * @return the numerical value of the {@code Size}. + * @since 0.16 + */ + public int value() { + return value; + } + } + + private static final int TOTALSIZE = computeTotalSize(); + + private ServerStatsFieldEnums() {} + + private static int computeTotalSize() { + int sum = 0; + for (Size sizeValue : Size.values()) { + sum += sizeValue.value(); + sum += 1; // For Id + } + return sum; + } + + /** + * Returns the total size required to encode the {@code ServerStats} + * + * @return the total size required to encode all fields in {@code ServerStats}. + * @since 0.16 + */ + public static int getTotalSize() { + return TOTALSIZE; + } +} diff --git a/api/src/test/java/io/opencensus/common/ServerStatsEncodingTest.java b/api/src/test/java/io/opencensus/common/ServerStatsEncodingTest.java new file mode 100644 index 00000000..6db14a79 --- /dev/null +++ b/api/src/test/java/io/opencensus/common/ServerStatsEncodingTest.java @@ -0,0 +1,155 @@ +/* + * Copyright 2018, 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.common; + +import static com.google.common.truth.Truth.assertThat; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link ServerStatsEncoding}. */ +@RunWith(JUnit4.class) +public class ServerStatsEncodingTest { + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + @Test + public void encodeDecodeTest() throws ServerStatsDeserializationException { + ServerStats serverStatsToBeEncoded = null; + ServerStats serverStatsDecoded = null; + byte[] serialized = null; + + serverStatsToBeEncoded = ServerStats.create(31, 22, (byte) 1); + serialized = ServerStatsEncoding.toBytes(serverStatsToBeEncoded); + serverStatsDecoded = ServerStatsEncoding.parseBytes(serialized); + assertThat(serverStatsDecoded).isEqualTo(serverStatsToBeEncoded); + + serverStatsToBeEncoded = ServerStats.create(0, 22, (byte) 0); + serialized = ServerStatsEncoding.toBytes(serverStatsToBeEncoded); + serverStatsDecoded = ServerStatsEncoding.parseBytes(serialized); + assertThat(serverStatsDecoded).isEqualTo(serverStatsToBeEncoded); + + serverStatsToBeEncoded = ServerStats.create(450, 0, (byte) 0); + serialized = ServerStatsEncoding.toBytes(serverStatsToBeEncoded); + serverStatsDecoded = ServerStatsEncoding.parseBytes(serialized); + assertThat(serverStatsDecoded).isEqualTo(serverStatsToBeEncoded); + } + + @Test + public void skipUnknownFieldTest() throws ServerStatsDeserializationException { + ServerStats serverStatsToBeEncoded = null; + ServerStats serverStatsDecoded = null; + byte[] serialized = null; + + serverStatsToBeEncoded = ServerStats.create(31, 22, (byte) 1); + serialized = ServerStatsEncoding.toBytes(serverStatsToBeEncoded); + + // Add new field at the end. + byte[] serializedExpanded = new byte[serialized.length + 9]; + System.arraycopy(serialized, 0, serializedExpanded, 0, serialized.length); + final ByteBuffer bb = ByteBuffer.wrap(serializedExpanded); + bb.order(ByteOrder.LITTLE_ENDIAN); + bb.position(serialized.length); + bb.put((byte) 255); + bb.putLong(0L); + byte[] newSerialized = bb.array(); + + serverStatsDecoded = ServerStatsEncoding.parseBytes(newSerialized); + assertThat(serverStatsDecoded).isEqualTo(serverStatsToBeEncoded); + } + + @Test + public void negativeLbLatencyValueTest() throws ServerStatsDeserializationException { + ServerStats serverStatsToBeEncoded = null; + ServerStats serverStatsDecoded = null; + byte[] serialized = null; + + serverStatsToBeEncoded = ServerStats.create(31, 22, (byte) 1); + serialized = ServerStatsEncoding.toBytes(serverStatsToBeEncoded); + + // update serialized byte[] with negative value for lbLatency. + final ByteBuffer bb = ByteBuffer.wrap(serialized); + bb.order(ByteOrder.LITTLE_ENDIAN); + bb.position(2); + bb.putLong(-100L); + + byte[] newSerialized = bb.array(); + thrown.expect(ServerStatsDeserializationException.class); + thrown.expectMessage("Serialized ServiceStats contains invalid values"); + ServerStatsEncoding.parseBytes(newSerialized); + } + + @Test + public void negativeServerLatencyValueTest() throws ServerStatsDeserializationException { + ServerStats serverStatsToBeEncoded = null; + ServerStats serverStatsDecoded = null; + byte[] serialized = null; + + serverStatsToBeEncoded = ServerStats.create(31, 22, (byte) 1); + serialized = ServerStatsEncoding.toBytes(serverStatsToBeEncoded); + + // update serialized byte[] with negative value for serviceLatency. + final ByteBuffer bb = ByteBuffer.wrap(serialized); + bb.order(ByteOrder.LITTLE_ENDIAN); + bb.position(11); + bb.putLong(-101L); + + byte[] newSerialized = bb.array(); + thrown.expect(ServerStatsDeserializationException.class); + thrown.expectMessage("Serialized ServiceStats contains invalid values"); + ServerStatsEncoding.parseBytes(newSerialized); + } + + @Test + public void emptySerializedBuffer() throws ServerStatsDeserializationException { + final ByteBuffer bb = ByteBuffer.allocate(0); + bb.order(ByteOrder.LITTLE_ENDIAN); + + byte[] newSerialized = bb.array(); + thrown.expect(ServerStatsDeserializationException.class); + thrown.expectMessage("Serialized ServerStats buffer is empty"); + ServerStatsEncoding.parseBytes(newSerialized); + } + + @Test + public void invalidNegativeVersion() throws ServerStatsDeserializationException { + final ByteBuffer bb = ByteBuffer.allocate(10); + bb.order(ByteOrder.LITTLE_ENDIAN); + bb.put((byte) -1); + byte[] newSerialized = bb.array(); + thrown.expect(ServerStatsDeserializationException.class); + thrown.expectMessage("Invalid ServerStats version: -1"); + ServerStatsEncoding.parseBytes(newSerialized); + } + + @Test + public void invalidCompatibleVersion() throws ServerStatsDeserializationException { + final ByteBuffer bb = ByteBuffer.allocate(10); + bb.order(ByteOrder.LITTLE_ENDIAN); + bb.put((byte) (ServerStatsEncoding.CURRENT_VERSION + 1)); + byte[] newSerialized = bb.array(); + thrown.expect(ServerStatsDeserializationException.class); + thrown.expectMessage( + "Invalid ServerStats version: " + (ServerStatsEncoding.CURRENT_VERSION + 1)); + ServerStatsEncoding.parseBytes(newSerialized); + } +} diff --git a/api/src/test/java/io/opencensus/common/ServerStatsFieldEnumsTest.java b/api/src/test/java/io/opencensus/common/ServerStatsFieldEnumsTest.java new file mode 100644 index 00000000..ed786f6c --- /dev/null +++ b/api/src/test/java/io/opencensus/common/ServerStatsFieldEnumsTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 2018, 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.common; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.common.ServerStatsFieldEnums.Id; +import io.opencensus.common.ServerStatsFieldEnums.Size; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link ServerStatsFieldEnums}. */ +@RunWith(JUnit4.class) +public class ServerStatsFieldEnumsTest { + + @Test + public void enumIdValueOfTest() { + assertThat(Id.valueOf(0)).isEqualTo(Id.SERVER_STATS_LB_LATENCY_ID); + assertThat(Id.valueOf(1)).isEqualTo(Id.SERVER_STATS_SERVICE_LATENCY_ID); + assertThat(Id.valueOf(2)).isEqualTo(Id.SERVER_STATS_TRACE_OPTION_ID); + } + + @Test + public void enumIdInvalidValueOfTest() { + assertThat(Id.valueOf(-1)).isNull(); + assertThat(Id.valueOf(Id.values().length)).isNull(); + assertThat(Id.valueOf(Id.values().length + 1)).isNull(); + } + + @Test + public void enumSizeValueTest() { + assertThat(Size.SERVER_STATS_LB_LATENCY_SIZE.value()).isEqualTo(8); + assertThat(Size.SERVER_STATS_SERVICE_LATENCY_SIZE.value()).isEqualTo(8); + assertThat(Size.SERVER_STATS_TRACE_OPTION_SIZE.value()).isEqualTo(1); + } + + @Test + public void totalSizeTest() { + assertThat(ServerStatsFieldEnums.getTotalSize()).isEqualTo(20); + } +} diff --git a/api/src/test/java/io/opencensus/common/ServerStatsTest.java b/api/src/test/java/io/opencensus/common/ServerStatsTest.java new file mode 100644 index 00000000..620bbb4f --- /dev/null +++ b/api/src/test/java/io/opencensus/common/ServerStatsTest.java @@ -0,0 +1,78 @@ +/* + * Copyright 2018, 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.common; + +import static com.google.common.truth.Truth.assertThat; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link ServerStats}. */ +@RunWith(JUnit4.class) +public class ServerStatsTest { + + @Rule public ExpectedException thrown = ExpectedException.none(); + + @Test + public void serverStatsCreate() { + ServerStats serverStats = null; + + serverStats = ServerStats.create(31, 22, (byte) 0); + assertThat(serverStats.getLbLatencyNs()).isEqualTo(31); + assertThat(serverStats.getServiceLatencyNs()).isEqualTo(22); + assertThat(serverStats.getTraceOption()).isEqualTo((byte) 0); + + serverStats = ServerStats.create(1000011L, 900022L, (byte) 1); + assertThat(serverStats.getLbLatencyNs()).isEqualTo(1000011L); + assertThat(serverStats.getServiceLatencyNs()).isEqualTo(900022L); + assertThat(serverStats.getTraceOption()).isEqualTo((byte) 1); + + serverStats = ServerStats.create(0, 22, (byte) 0); + assertThat(serverStats.getLbLatencyNs()).isEqualTo(0); + assertThat(serverStats.getServiceLatencyNs()).isEqualTo(22); + assertThat(serverStats.getTraceOption()).isEqualTo((byte) 0); + + serverStats = ServerStats.create(1010, 0, (byte) 0); + assertThat(serverStats.getLbLatencyNs()).isEqualTo(1010); + assertThat(serverStats.getServiceLatencyNs()).isEqualTo(0); + assertThat(serverStats.getTraceOption()).isEqualTo((byte) 0); + } + + @Test + public void create_LbLatencyNegative() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("'getLbLatencyNs' is less than zero"); + ServerStats.create(-1L, 100, (byte) 0); + } + + @Test + public void create_ServerLatencyNegative() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("'getServiceLatencyNs' is less than zero"); + ServerStats.create(100L, -1L, (byte) 0); + } + + @Test + public void create_LbLatencyAndServerLatencyNegative() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("'getLbLatencyNs' is less than zero"); + ServerStats.create(-100L, -1L, (byte) 0); + } +} -- cgit v1.2.3 From 13a5c96d2602f5af2eafe9c23b9e92955ecf3dff Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Tue, 26 Jun 2018 17:22:19 -0700 Subject: Clarify Javadoc for Tagger.withTagContext. See census-instrumentation/opencensus-specs#99. --- api/src/main/java/io/opencensus/tags/Tagger.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/tags/Tagger.java b/api/src/main/java/io/opencensus/tags/Tagger.java index f3ba0f5b..f1e203ad 100644 --- a/api/src/main/java/io/opencensus/tags/Tagger.java +++ b/api/src/main/java/io/opencensus/tags/Tagger.java @@ -73,9 +73,9 @@ public abstract class Tagger { public abstract TagContextBuilder currentBuilder(); /** - * Enters the scope of code where the given {@code TagContext} is in the current context and - * returns an object that represents that scope. The scope is exited when the returned object is - * closed. + * Enters the scope of code where the given {@code TagContext} is in the current context + * (replacing the previous {@code TagContext}) and returns an object that represents that scope. + * The scope is exited when the returned object is closed. * * @param tags the {@code TagContext} to be set to the current context. * @return an object that defines a scope where the given {@code TagContext} is set to the current -- cgit v1.2.3 From 273c9536f9ec33af05830ce9d7aaf37e35fd86db Mon Sep 17 00:00:00 2001 From: Yang Song Date: Thu, 28 Jun 2018 09:30:42 -0700 Subject: Stats: Add API MeasureMap.putAttachment() for recording exemplars. (#1285) * Stats: Add API MeasureMap.withAttachments() for recording exemplars. * Add this change to CHANGELOG * Stats: implement the new API in impl. * Rename API and merge the string maps on multiple calls. * Update the API to putAttachment(String, String) for simplicity. * Fix a typo and add a TODO about making putAttachment abstract. --- .../main/java/io/opencensus/stats/MeasureMap.java | 20 ++++++++++++++++++++ .../test/java/io/opencensus/stats/NoopStatsTest.java | 17 +++++++++++++++++ 2 files changed, 37 insertions(+) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/MeasureMap.java b/api/src/main/java/io/opencensus/stats/MeasureMap.java index a7430537..beb84f06 100644 --- a/api/src/main/java/io/opencensus/stats/MeasureMap.java +++ b/api/src/main/java/io/opencensus/stats/MeasureMap.java @@ -16,6 +16,7 @@ package io.opencensus.stats; +import io.opencensus.internal.Utils; import io.opencensus.stats.Measure.MeasureDouble; import io.opencensus.stats.Measure.MeasureLong; import io.opencensus.tags.TagContext; @@ -51,6 +52,25 @@ public abstract class MeasureMap { */ public abstract MeasureMap put(MeasureLong measure, long value); + /** + * Associate the contextual information of an {@code Exemplar} to this {@link MeasureMap}. + * Contextual information is represented as {@code String} key-value pairs. + * + *

    If this method is called multiple times with the same key, only the last value will be kept. + * + * @param key the key of contextual information of an {@code Exemplar}. + * @param value the string representation of contextual information of an {@code Exemplar}. + * @return this + * @since 0.16 + */ + // TODO(songya): make this method abstract in the 0.17 release. + public MeasureMap putAttachment(String key, String value) { + // Provides a default no-op implementation to avoid breaking other existing sub-classes. + Utils.checkNotNull(key, "key"); + Utils.checkNotNull(value, "value"); + return this; + } + /** * Records all of the measures at the same time, with the current {@link TagContext}. * diff --git a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java index b3f81715..4bae14a6 100644 --- a/api/src/test/java/io/opencensus/stats/NoopStatsTest.java +++ b/api/src/test/java/io/opencensus/stats/NoopStatsTest.java @@ -93,6 +93,22 @@ public final class NoopStatsTest { noopStatsComponent.setState(StatsCollectionState.ENABLED); } + @Test + public void noopStatsRecorder_PutAttachmentNullKey() { + MeasureMap measureMap = NoopStats.getNoopStatsRecorder().newMeasureMap(); + thrown.expect(NullPointerException.class); + thrown.expectMessage("key"); + measureMap.putAttachment(null, "value"); + } + + @Test + public void noopStatsRecorder_PutAttachmentNullValue() { + MeasureMap measureMap = NoopStats.getNoopStatsRecorder().newMeasureMap(); + thrown.expect(NullPointerException.class); + thrown.expectMessage("value"); + measureMap.putAttachment("key", null); + } + // The NoopStatsRecorder should do nothing, so this test just checks that record doesn't throw an // exception. @Test @@ -111,6 +127,7 @@ public final class NoopStatsTest { public void noopStatsRecorder_Record_DisallowNullTagContext() { MeasureMap measureMap = NoopStats.getNoopStatsRecorder().newMeasureMap(); thrown.expect(NullPointerException.class); + thrown.expectMessage("tags"); measureMap.record(null); } } -- cgit v1.2.3 From a7893d2a3fc4ef7fae138b67b22f3ffd51e5f529 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Fri, 29 Jun 2018 11:48:27 -0700 Subject: Stats: Add Exemplar class to DistributionData. (#1287) --- .../java/io/opencensus/stats/AggregationData.java | 119 ++++++++++++++++++++- .../io/opencensus/stats/AggregationDataTest.java | 63 +++++++++++ 2 files changed, 179 insertions(+), 3 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/stats/AggregationData.java b/api/src/main/java/io/opencensus/stats/AggregationData.java index 95ac3282..eb7d40b3 100644 --- a/api/src/main/java/io/opencensus/stats/AggregationData.java +++ b/api/src/main/java/io/opencensus/stats/AggregationData.java @@ -18,10 +18,14 @@ package io.opencensus.stats; import com.google.auto.value.AutoValue; import io.opencensus.common.Function; +import io.opencensus.common.Timestamp; import io.opencensus.internal.Utils; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import javax.annotation.concurrent.Immutable; /** @@ -268,8 +272,9 @@ public abstract class AggregationData { * @param max max value. * @param sumOfSquaredDeviations sum of squared deviations. * @param bucketCounts histogram bucket counts. + * @param exemplars the exemplars associated with histogram buckets. * @return a {@code DistributionData}. - * @since 0.8 + * @since 0.16 */ public static DistributionData create( double mean, @@ -277,7 +282,8 @@ public abstract class AggregationData { double min, double max, double sumOfSquaredDeviations, - List bucketCounts) { + List bucketCounts, + List exemplars) { if (min != Double.POSITIVE_INFINITY || max != Double.NEGATIVE_INFINITY) { Utils.checkArgument(min <= max, "max should be greater or equal to min."); } @@ -288,8 +294,48 @@ public abstract class AggregationData { Utils.checkNotNull(bucket, "bucket should not be null."); } + Utils.checkNotNull(exemplars, "exemplar list should not be null."); + for (Exemplar exemplar : exemplars) { + Utils.checkNotNull(exemplar, "exemplar should not be null."); + } + return new AutoValue_AggregationData_DistributionData( - mean, count, min, max, sumOfSquaredDeviations, bucketCountsCopy); + mean, + count, + min, + max, + sumOfSquaredDeviations, + bucketCountsCopy, + Collections.unmodifiableList(new ArrayList(exemplars))); + } + + /** + * Creates a {@code DistributionData}. + * + * @param mean mean value. + * @param count count value. + * @param min min value. + * @param max max value. + * @param sumOfSquaredDeviations sum of squared deviations. + * @param bucketCounts histogram bucket counts. + * @return a {@code DistributionData}. + * @since 0.8 + */ + public static DistributionData create( + double mean, + long count, + double min, + double max, + double sumOfSquaredDeviations, + List bucketCounts) { + return create( + mean, + count, + min, + max, + sumOfSquaredDeviations, + bucketCounts, + Collections.emptyList()); } /** @@ -341,6 +387,14 @@ public abstract class AggregationData { */ public abstract List getBucketCounts(); + /** + * Returns the {@link Exemplar}s associated with histogram buckets. + * + * @return the {@code Exemplar}s associated with histogram buckets. + * @since 0.16 + */ + public abstract List getExemplars(); + @Override public final T match( Function p0, @@ -352,6 +406,65 @@ public abstract class AggregationData { Function defaultFunction) { return p3.apply(this); } + + /** + * An example point that may be used to annotate aggregated distribution values, associated with + * a histogram bucket. + * + * @since 0.16 + */ + @Immutable + @AutoValue + public abstract static class Exemplar { + + Exemplar() {} + + /** + * Returns value of the {@link Exemplar} point. + * + * @return value of the {@code Exemplar} point. + * @since 0.16 + */ + public abstract double getValue(); + + /** + * Returns the time that this {@link Exemplar}'s value was recorded. + * + * @return the time that this {@code Exemplar}'s value was recorded. + * @since 0.16 + */ + public abstract Timestamp getTimestamp(); + + /** + * Returns the contextual information about the example value, represented as a string map. + * + * @return the contextual information about the example value. + * @since 0.16 + */ + public abstract Map getAttachments(); + + /** + * Creates an {@link Exemplar}. + * + * @param value value of the {@link Exemplar} point. + * @param timestamp the time that this {@code Exemplar}'s value was recorded. + * @param attachments the contextual information about the example value. + * @return an {@code Exemplar}. + * @since 0.16 + */ + public static Exemplar create( + double value, Timestamp timestamp, Map attachments) { + Utils.checkNotNull(attachments, "attachments"); + Map attachmentsCopy = + Collections.unmodifiableMap(new HashMap(attachments)); + for (Entry entry : attachmentsCopy.entrySet()) { + Utils.checkNotNull(entry.getKey(), "key of attachments"); + Utils.checkNotNull(entry.getValue(), "value of attachments"); + } + return new AutoValue_AggregationData_DistributionData_Exemplar( + value, timestamp, attachmentsCopy); + } + } } /** diff --git a/api/src/test/java/io/opencensus/stats/AggregationDataTest.java b/api/src/test/java/io/opencensus/stats/AggregationDataTest.java index 9f2aa589..60551600 100644 --- a/api/src/test/java/io/opencensus/stats/AggregationDataTest.java +++ b/api/src/test/java/io/opencensus/stats/AggregationDataTest.java @@ -21,8 +21,10 @@ import static com.google.common.truth.Truth.assertThat; import com.google.common.testing.EqualsTester; import io.opencensus.common.Function; import io.opencensus.common.Functions; +import io.opencensus.common.Timestamp; import io.opencensus.stats.AggregationData.CountData; import io.opencensus.stats.AggregationData.DistributionData; +import io.opencensus.stats.AggregationData.DistributionData.Exemplar; import io.opencensus.stats.AggregationData.LastValueDataDouble; import io.opencensus.stats.AggregationData.LastValueDataLong; import io.opencensus.stats.AggregationData.MeanData; @@ -30,7 +32,9 @@ import io.opencensus.stats.AggregationData.SumDataDouble; import io.opencensus.stats.AggregationData.SumDataLong; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; +import java.util.Map; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -42,6 +46,9 @@ import org.junit.runners.JUnit4; public class AggregationDataTest { private static final double TOLERANCE = 1e-6; + private static final Timestamp TIMESTAMP_1 = Timestamp.create(1, 0); + private static final Timestamp TIMESTAMP_2 = Timestamp.create(2, 0); + private static final Map ATTACHMENTS = Collections.singletonMap("key", "value"); @Rule public ExpectedException thrown = ExpectedException.none(); @@ -57,6 +64,47 @@ public class AggregationDataTest { assertThat(distributionData.getBucketCounts()).containsExactly(4L, 1L, 5L).inOrder(); } + @Test + public void testCreateDistributionDataWithExemplar() { + Exemplar exemplar1 = Exemplar.create(4, TIMESTAMP_2, ATTACHMENTS); + Exemplar exemplar2 = Exemplar.create(1, TIMESTAMP_1, ATTACHMENTS); + DistributionData distributionData = + DistributionData.create( + 7.7, 10, 1.1, 9.9, 32.2, Arrays.asList(4L, 1L), Arrays.asList(exemplar1, exemplar2)); + assertThat(distributionData.getExemplars()).containsExactly(exemplar1, exemplar2).inOrder(); + } + + @Test + public void testExemplar() { + Exemplar exemplar = Exemplar.create(15.0, TIMESTAMP_1, ATTACHMENTS); + assertThat(exemplar.getValue()).isEqualTo(15.0); + assertThat(exemplar.getTimestamp()).isEqualTo(TIMESTAMP_1); + assertThat(exemplar.getAttachments()).isEqualTo(ATTACHMENTS); + } + + @Test + public void testExemplar_PreventNullAttachments() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("attachments"); + Exemplar.create(15, TIMESTAMP_1, null); + } + + @Test + public void testExemplar_PreventNullAttachmentKey() { + Map attachments = Collections.singletonMap(null, "value"); + thrown.expect(NullPointerException.class); + thrown.expectMessage("key of attachment"); + Exemplar.create(15, TIMESTAMP_1, attachments); + } + + @Test + public void testExemplar_PreventNullAttachmentValue() { + Map attachments = Collections.singletonMap("key", null); + thrown.expect(NullPointerException.class); + thrown.expectMessage("value of attachment"); + Exemplar.create(15, TIMESTAMP_1, attachments); + } + @Test public void preventNullBucketCountList() { thrown.expect(NullPointerException.class); @@ -71,6 +119,21 @@ public class AggregationDataTest { DistributionData.create(1, 1, 1, 1, 0, Arrays.asList(0L, 1L, null)); } + @Test + public void preventNullExemplarList() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("exemplar list should not be null."); + DistributionData.create(1, 1, 1, 1, 0, Arrays.asList(0L, 1L, 1L), null); + } + + @Test + public void preventNullExemplar() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("exemplar should not be null."); + DistributionData.create( + 1, 1, 1, 1, 0, Arrays.asList(0L, 1L, 1L), Collections.singletonList(null)); + } + @Test public void preventMinIsGreaterThanMax() { thrown.expect(IllegalArgumentException.class); -- cgit v1.2.3 From 1c46243de0bbb19ce5610daccf9bb0ad9d66c2a1 Mon Sep 17 00:00:00 2001 From: Kristen Kozak Date: Mon, 9 Jul 2018 15:56:07 -0700 Subject: Mention that SampledSpanStore.getRegisteredSpanNamesForCollection is for testing. This commit fixes the last part of #977. getRegisteredSpanNamesForCollection was originally public and annotated with VisibleForTesting because it was meant for testing code that uses OpenCensus. However, VisibleForTesting is not ideal because it adds a dependency on Guava and it does not appear in Javadocs. This commit instead describes the purpose of the method in the Javadocs. It also removes the temporary PublicForTesting annotation. --- .../io/opencensus/internal/PublicForTesting.java | 38 ---------------------- .../opencensus/trace/export/SampledSpanStore.java | 9 ++--- 2 files changed, 5 insertions(+), 42 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/internal/PublicForTesting.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/PublicForTesting.java b/api/src/main/java/io/opencensus/internal/PublicForTesting.java deleted file mode 100644 index cfd37ff2..00000000 --- a/api/src/main/java/io/opencensus/internal/PublicForTesting.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2018, 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.internal; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Indicates that an element is public instead of package-private only for the purpose of testing. - * This annotation is only meant to be used as documentation in the source code. - */ -// TODO(#977): All uses of this annotation should be removed or replaced with @Internal. -@Retention(RetentionPolicy.SOURCE) -@Target({ - ElementType.ANNOTATION_TYPE, - ElementType.CONSTRUCTOR, - ElementType.FIELD, - ElementType.METHOD, - ElementType.PACKAGE, - ElementType.TYPE -}) -public @interface PublicForTesting {} diff --git a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java index 99bc5288..2347061b 100644 --- a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java @@ -17,7 +17,6 @@ package io.opencensus.trace.export; import com.google.auto.value.AutoValue; -import io.opencensus.internal.PublicForTesting; import io.opencensus.internal.Utils; import io.opencensus.trace.Span; import io.opencensus.trace.Status; @@ -123,13 +122,15 @@ public abstract class SampledSpanStore { public abstract void unregisterSpanNamesForCollection(Collection spanNames); /** - * Returns the set of unique span names registered to the library. For this set of span names the - * library will collect latency based sampled spans and error based sampled spans. + * Returns the set of unique span names registered to the library, for use in tests. For this set + * of span names the library will collect latency based sampled spans and error based sampled + * spans. + * + *

    This method is only meant for testing code that uses OpenCensus, and it is not performant. * * @return the set of unique span names registered to the library. * @since 0.7 */ - @PublicForTesting public abstract Set getRegisteredSpanNamesForCollection(); /** -- cgit v1.2.3 From 02ade038e4c11dece33ad41cfd10dad0953a4f35 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Mon, 16 Jul 2018 17:18:42 -0700 Subject: Tracing: Reduce default limit on Links to 32. (#1315) * Tracing: Reduce default limit on Links to 32. * Add this change to CHANGELOG. --- api/src/main/java/io/opencensus/trace/config/TraceParams.java | 2 +- api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/config/TraceParams.java b/api/src/main/java/io/opencensus/trace/config/TraceParams.java index d10642a8..ff70f52d 100644 --- a/api/src/main/java/io/opencensus/trace/config/TraceParams.java +++ b/api/src/main/java/io/opencensus/trace/config/TraceParams.java @@ -40,7 +40,7 @@ public abstract class TraceParams { private static final int DEFAULT_SPAN_MAX_NUM_ATTRIBUTES = 32; private static final int DEFAULT_SPAN_MAX_NUM_ANNOTATIONS = 32; private static final int DEFAULT_SPAN_MAX_NUM_MESSAGE_EVENTS = 128; - private static final int DEFAULT_SPAN_MAX_NUM_LINKS = 128; + private static final int DEFAULT_SPAN_MAX_NUM_LINKS = 32; /** * Default {@code TraceParams}. diff --git a/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java b/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java index 6c216174..bdf07d53 100644 --- a/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java +++ b/api/src/test/java/io/opencensus/trace/config/TraceParamsTest.java @@ -33,7 +33,7 @@ public class TraceParamsTest { assertThat(TraceParams.DEFAULT.getMaxNumberOfAnnotations()).isEqualTo(32); assertThat(TraceParams.DEFAULT.getMaxNumberOfNetworkEvents()).isEqualTo(128); assertThat(TraceParams.DEFAULT.getMaxNumberOfMessageEvents()).isEqualTo(128); - assertThat(TraceParams.DEFAULT.getMaxNumberOfLinks()).isEqualTo(128); + assertThat(TraceParams.DEFAULT.getMaxNumberOfLinks()).isEqualTo(32); } @Test(expected = NullPointerException.class) -- cgit v1.2.3 From b3f059260c79502967efbc8a0c258ac4bd4e9fbd Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Fri, 20 Jul 2018 12:40:13 -0400 Subject: Remove copy of the internal.Utils. (#1332) --- api/src/main/java/io/opencensus/internal/Utils.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/Utils.java b/api/src/main/java/io/opencensus/internal/Utils.java index 1ac2324e..a2c09c82 100644 --- a/api/src/main/java/io/opencensus/internal/Utils.java +++ b/api/src/main/java/io/opencensus/internal/Utils.java @@ -16,6 +16,7 @@ package io.opencensus.internal; +import java.util.List; import javax.annotation.Nullable; /*>>> @@ -86,6 +87,21 @@ public final class Utils { return arg; } + /** + * Throws a {@link NullPointerException} if any of the list elements is null. + * + * @param list the argument list to check for null. + * @param message the message to use for the exception. + */ + public static >> extends @NonNull Object*/> void checkListElementNotNull( + List list, String message) { + for (T element : list) { + if (element == null) { + throw new NullPointerException(message); + } + } + } + /** * Compares two Objects for equality. This functionality is provided by {@code * Objects.equal(Object, Object)} in Java 7. -- cgit v1.2.3 From 8939d9fd639a8a7ff8b25e1a7e6c44d8b2e987db Mon Sep 17 00:00:00 2001 From: sebright Date: Wed, 1 Aug 2018 16:34:05 -0700 Subject: Fix incorrect argument to Checker Framework, and fix nullness warnings. (#1354) 709d97aa321d5729988fd63b960bbece04cfba10 modified the -AskipDefs argument to the Checker Framework (a regular expression) in a way that caused it to skip checking all files. This commit fixes the regular expression and the new Checker Framework warnings. --- api/src/main/java/io/opencensus/common/ServerStatsFieldEnums.java | 4 +++- api/src/main/java/io/opencensus/trace/SpanBuilder.java | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/ServerStatsFieldEnums.java b/api/src/main/java/io/opencensus/common/ServerStatsFieldEnums.java index 92194d96..79cb196e 100644 --- a/api/src/main/java/io/opencensus/common/ServerStatsFieldEnums.java +++ b/api/src/main/java/io/opencensus/common/ServerStatsFieldEnums.java @@ -17,6 +17,7 @@ package io.opencensus.common; import java.util.TreeMap; +import javax.annotation.Nullable; /** * A Enum representation for Ids and Size for attributes of {@code ServerStats}. @@ -85,8 +86,9 @@ public final class ServerStatsFieldEnums { * @return the numerical value of the id. null if the id is not valid * @since 0.16 */ + @Nullable public static Id valueOf(int value) { - return (Id) map.get(value); + return map.get(value); } } diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java index 00e11572..1a4e29e9 100644 --- a/api/src/main/java/io/opencensus/trace/SpanBuilder.java +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -335,7 +335,7 @@ public abstract class SpanBuilder { } @Override - public SpanBuilder setSpanKind(Span.Kind spanKind) { + public SpanBuilder setSpanKind(@Nullable Span.Kind spanKind) { return this; } -- cgit v1.2.3 From daa5d097e18211ad95a0e5bc63697e615db91902 Mon Sep 17 00:00:00 2001 From: sebright Date: Wed, 1 Aug 2018 17:54:30 -0700 Subject: Add Checker Framework stub file for gRPC Context.Key. (#1357) The stub file adds Nullable annotations to indicate that Context.Key.get can return null when the key has no default or the key has a nullable value type. --- api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java | 2 ++ api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java index 21511142..aa2f055a 100644 --- a/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java +++ b/api/src/main/java/io/opencensus/trace/CurrentSpanUtils.java @@ -20,6 +20,7 @@ import io.grpc.Context; import io.opencensus.common.Scope; import io.opencensus.trace.unsafe.ContextUtils; import java.util.concurrent.Callable; +import javax.annotation.Nullable; /** Util methods/functionality to interact with the {@link Span} in the {@link io.grpc.Context}. */ final class CurrentSpanUtils { @@ -31,6 +32,7 @@ final class CurrentSpanUtils { * * @return The {@code Span} from the current context. */ + @Nullable static Span getCurrentSpan() { return ContextUtils.CONTEXT_SPAN_KEY.get(); } diff --git a/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java b/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java index f7905c25..3f4b9889 100644 --- a/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java +++ b/api/src/main/java/io/opencensus/trace/unsafe/ContextUtils.java @@ -19,6 +19,10 @@ package io.opencensus.trace.unsafe; import io.grpc.Context; import io.opencensus.trace.Span; +/*>>> +import org.checkerframework.checker.nullness.qual.Nullable; +*/ + /** * Util methods/functionality to interact with the {@link io.grpc.Context}. * @@ -36,5 +40,6 @@ public final class ContextUtils { * * @since 0.5 */ - public static final Context.Key CONTEXT_SPAN_KEY = Context.key("opencensus-trace-span-key"); + public static final Context.Key CONTEXT_SPAN_KEY = + Context.key("opencensus-trace-span-key"); } -- cgit v1.2.3 From d0d836136149d7379b50bd6fb8d81e4749df3fd8 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Thu, 2 Aug 2018 15:57:31 +0300 Subject: Add the initial version of the TraceState class. (#1300) * Add the initial version of the TraceState class. * Add builder pattern. * Clean API and add tests. * Rename addOrUpdate to set and apply trailing rules for value. * Apply google java format. * Fix check framework. --- .../main/java/io/opencensus/trace/Tracestate.java | 265 +++++++++++++++++++++ .../java/io/opencensus/trace/TracestateTest.java | 235 ++++++++++++++++++ 2 files changed, 500 insertions(+) create mode 100644 api/src/main/java/io/opencensus/trace/Tracestate.java create mode 100644 api/src/test/java/io/opencensus/trace/TracestateTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/Tracestate.java b/api/src/main/java/io/opencensus/trace/Tracestate.java new file mode 100644 index 00000000..63d32fd3 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/Tracestate.java @@ -0,0 +1,265 @@ +/* + * Copyright 2018, 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; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.internal.Utils; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.annotation.concurrent.Immutable; + +/** + * Carries tracing-system specific context in a list of key-value pairs. TraceState allows different + * vendors propagate additional information and inter-operate with their legacy Id formats. + * + *

    Implementation is optimized for a small list of key-value pairs. + * + *

    Key is opaque string up to 256 characters printable. It MUST begin with a lowercase letter, + * and can only contain lowercase letters a-z, digits 0-9, underscores _, dashes -, asterisks *, and + * forward slashes /. + * + *

    Value is opaque string up to 256 characters printable ASCII RFC0020 characters (i.e., the + * range 0x20 to 0x7E) except comma , and =. + * + * @since 0.16 + */ +@Immutable +@AutoValue +@ExperimentalApi +public abstract class Tracestate { + private static final int KEY_MAX_SIZE = 256; + private static final int VALUE_MAX_SIZE = 256; + private static final int MAX_KEY_VALUE_PAIRS = 32; + + /** + * Returns the value to which the specified key is mapped, or null if this map contains no mapping + * for the key. + * + * @param key with which the specified value is to be associated + * @return the value to which the specified key is mapped, or null if this map contains no mapping + * for the key. + * @since 0.16 + */ + @javax.annotation.Nullable + public String get(String key) { + for (Entry entry : getEntries()) { + if (entry.getKey().equals(key)) { + return entry.getValue(); + } + } + return null; + } + + /** + * Returns a {@link List} view of the mappings contained in this {@code TraceState}. + * + * @return a {@link List} view of the mappings contained in this {@code TraceState}. + * @since 0.16 + */ + public abstract List getEntries(); + + /** + * Returns a builder based on this {@code Tracestate}. + * + * @return a builder based on this {@code Tracestate}. + * @since 0.16 + */ + public Builder toBuilder() { + return new Builder(this); + } + + /** + * Builder class for {@link MessageEvent}. + * + * @since 0.16 + */ + @ExperimentalApi + public static final class Builder { + private final Tracestate parent; + @javax.annotation.Nullable private ArrayList entries; + + private static final Tracestate EMPTY = create(Collections.emptyList()); + + public Builder() { + this(EMPTY); + } + + private Builder(Tracestate parent) { + Utils.checkNotNull(parent, "parent"); + this.parent = parent; + this.entries = null; + } + + /** + * Adds or updates the {@code Entry} that has the given {@code key} if it is present. The new + * {@code Entry} will always be added in the front of the list of entries. + * + * @param key the key for the {@code Entry} to be added. + * @param value the value for the {@code Entry} to be added. + * @return this. + * @since 0.16 + */ + @SuppressWarnings("nullness") + public Builder set(String key, String value) { + // Initially create the Entry to validate input. + Entry entry = Entry.create(key, value); + if (entries == null) { + // Copy entries from the parent. + entries = new ArrayList(parent.getEntries()); + } + for (int i = 0; i < entries.size(); i++) { + if (entries.get(i).getKey().equals(entry.getKey())) { + entries.remove(i); + // Exit now because the entries list cannot contain duplicates. + break; + } + } + // Inserts the element at the front of this list. + entries.add(0, entry); + return this; + } + + /** + * Removes the {@code Entry} that has the given {@code key} if it is present. + * + * @param key the key for the {@code Entry} to be removed. + * @return this. + * @since 0.16 + */ + @SuppressWarnings("nullness") + public Builder remove(String key) { + Utils.checkNotNull(key, "key"); + if (entries == null) { + // Copy entries from the parent. + entries = new ArrayList(parent.getEntries()); + } + for (int i = 0; i < entries.size(); i++) { + if (entries.get(i).getKey().equals(key)) { + entries.remove(i); + // Exit now because the entries list cannot contain duplicates. + break; + } + } + return this; + } + + /** + * Builds a TraceState by adding the entries to the parent in front of the key-value pairs list + * and removing duplicate entries. + * + * @return a TraceState with the new entries. + * @since 0.16 + */ + public Tracestate build() { + if (entries == null) { + return parent; + } + return Tracestate.create(entries); + } + } + + /** + * Immutable key-value pair for {@code Tracestate}. + * + * @since 0.16 + */ + @Immutable + @AutoValue + @ExperimentalApi + public abstract static class Entry { + /** + * Creates a new {@code Entry} for the {@code Tracestate}. + * + * @param key the Entry's key. + * @param value the Entry's value. + * @since 0.16 + */ + public static Entry create(String key, String value) { + Utils.checkNotNull(key, "key"); + Utils.checkNotNull(value, "value"); + Utils.checkArgument(validateKey(key), "Invalid key " + key); + Utils.checkArgument(validateValue(value), "Invalid value " + value); + return new AutoValue_Tracestate_Entry(key, value); + } + + /** + * Returns the key {@code String}. + * + * @return the key {@code String}. + * @since 0.16 + */ + public abstract String getKey(); + + /** + * Returns the value {@code String}. + * + * @return the value {@code String}. + * @since 0.16 + */ + public abstract String getValue(); + + Entry() {} + } + + // Key is opaque string up to 256 characters printable. It MUST begin with a lowercase letter, and + // can only contain lowercase letters a-z, digits 0-9, underscores _, dashes -, asterisks *, and + // forward slashes /. + private static boolean validateKey(String key) { + if (key.length() > KEY_MAX_SIZE + || key.isEmpty() + || key.charAt(0) < 'a' + || key.charAt(0) > 'z') { + return false; + } + for (int i = 1; i < key.length(); i++) { + char c = key.charAt(i); + if (!(c >= 'a' && c <= 'z') + && !(c >= '0' && c <= '9') + && c != '_' + && c != '-' + && c != '*' + && c != '/') { + return false; + } + } + return true; + } + + // Value is opaque string up to 256 characters printable ASCII RFC0020 characters (i.e., the range + // 0x20 to 0x7E) except comma , and =. + private static boolean validateValue(String value) { + if (value.length() > VALUE_MAX_SIZE || value.charAt(value.length() - 1) == ' ' /* '\u0020' */) { + return false; + } + for (int i = 0; i < value.length(); i++) { + char c = value.charAt(i); + if (c == ',' || c == '=' || c < ' ' /* '\u0020' */ || c > '~' /* '\u007E' */) { + return false; + } + } + return true; + } + + private static Tracestate create(List entries) { + Utils.checkState(entries.size() <= MAX_KEY_VALUE_PAIRS, "Invalid size"); + return new AutoValue_Tracestate(Collections.unmodifiableList(entries)); + } + + Tracestate() {} +} diff --git a/api/src/test/java/io/opencensus/trace/TracestateTest.java b/api/src/test/java/io/opencensus/trace/TracestateTest.java new file mode 100644 index 00000000..b347d8ad --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/TracestateTest.java @@ -0,0 +1,235 @@ +/* + * Copyright 2018, 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; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.trace.Tracestate.Entry; +import java.util.Arrays; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Tracestate}. */ +@RunWith(JUnit4.class) +public class TracestateTest { + private static final String FIRST_KEY = "key_1"; + private static final String SECOND_KEY = "key_2"; + private static final String FIRST_VALUE = "value.1"; + private static final String SECOND_VALUE = "value.2"; + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + private static final Tracestate EMPTY = new Tracestate.Builder().build(); + private final Tracestate firstTracestate = EMPTY.toBuilder().set(FIRST_KEY, FIRST_VALUE).build(); + private final Tracestate secondTracestate = + EMPTY.toBuilder().set(SECOND_KEY, SECOND_VALUE).build(); + private final Tracestate multiValueTracestate = + EMPTY.toBuilder().set(FIRST_KEY, FIRST_VALUE).set(SECOND_KEY, SECOND_VALUE).build(); + + @Test + public void get() { + assertThat(firstTracestate.get(FIRST_KEY)).isEqualTo(FIRST_VALUE); + assertThat(secondTracestate.get(SECOND_KEY)).isEqualTo(SECOND_VALUE); + assertThat(multiValueTracestate.get(FIRST_KEY)).isEqualTo(FIRST_VALUE); + assertThat(multiValueTracestate.get(SECOND_KEY)).isEqualTo(SECOND_VALUE); + } + + @Test + public void getEntries() { + assertThat(firstTracestate.getEntries()).containsExactly(Entry.create(FIRST_KEY, FIRST_VALUE)); + assertThat(secondTracestate.getEntries()) + .containsExactly(Entry.create(SECOND_KEY, SECOND_VALUE)); + assertThat(multiValueTracestate.getEntries()) + .containsExactly( + Entry.create(FIRST_KEY, FIRST_VALUE), Entry.create(SECOND_KEY, SECOND_VALUE)); + } + + @Test + public void disallowsNullKey() { + thrown.expect(NullPointerException.class); + EMPTY.toBuilder().set(null, FIRST_VALUE).build(); + } + + @Test + public void invalidFirstKeyCharacter() { + thrown.expect(IllegalArgumentException.class); + EMPTY.toBuilder().set("1_key", FIRST_VALUE).build(); + } + + @Test + public void invalidKeyCharacters() { + thrown.expect(IllegalArgumentException.class); + EMPTY.toBuilder().set("kEy_1", FIRST_VALUE).build(); + } + + @Test + public void invalidKeySize() { + char[] chars = new char[257]; + Arrays.fill(chars, 'a'); + String longKey = new String(chars); + thrown.expect(IllegalArgumentException.class); + EMPTY.toBuilder().set(longKey, FIRST_VALUE).build(); + } + + @Test + public void allAllowedKeyCharacters() { + StringBuilder stringBuilder = new StringBuilder(); + for (char c = 'a'; c <= 'z'; c++) { + stringBuilder.append(c); + } + for (char c = '0'; c <= '9'; c++) { + stringBuilder.append(c); + } + stringBuilder.append('_'); + stringBuilder.append('-'); + stringBuilder.append('*'); + stringBuilder.append('/'); + String allowedKey = stringBuilder.toString(); + assertThat(EMPTY.toBuilder().set(allowedKey, FIRST_VALUE).build().get(allowedKey)) + .isEqualTo(FIRST_VALUE); + } + + @Test + public void disallowsNullValue() { + thrown.expect(NullPointerException.class); + EMPTY.toBuilder().set(FIRST_KEY, null).build(); + } + + @Test + public void valueCannotContainEqual() { + thrown.expect(IllegalArgumentException.class); + EMPTY.toBuilder().set(FIRST_KEY, "my_vakue=5").build(); + } + + @Test + public void valueCannotContainComma() { + thrown.expect(IllegalArgumentException.class); + EMPTY.toBuilder().set(FIRST_KEY, "first,second").build(); + } + + @Test + public void valueCannotContainTrailingSpaces() { + thrown.expect(IllegalArgumentException.class); + EMPTY.toBuilder().set(FIRST_KEY, "first ").build(); + } + + @Test + public void invalidValueSize() { + char[] chars = new char[257]; + Arrays.fill(chars, 'a'); + String longValue = new String(chars); + thrown.expect(IllegalArgumentException.class); + EMPTY.toBuilder().set(FIRST_KEY, longValue).build(); + } + + @Test + public void allAllowedValueCharacters() { + StringBuilder stringBuilder = new StringBuilder(); + for (char c = ' ' /* '\u0020' */; c <= '~' /* '\u007E' */; c++) { + if (c == ',' || c == '=') { + continue; + } + stringBuilder.append(c); + } + String allowedValue = stringBuilder.toString(); + assertThat(EMPTY.toBuilder().set(FIRST_KEY, allowedValue).build().get(FIRST_KEY)) + .isEqualTo(allowedValue); + } + + @Test + public void addEntry() { + assertThat(firstTracestate.toBuilder().set(SECOND_KEY, SECOND_VALUE).build()) + .isEqualTo(multiValueTracestate); + } + + @Test + public void updateEntry() { + assertThat(firstTracestate.toBuilder().set(FIRST_KEY, SECOND_VALUE).build().get(FIRST_KEY)) + .isEqualTo(SECOND_VALUE); + Tracestate updatedMultiValueTracestate = + multiValueTracestate.toBuilder().set(FIRST_KEY, SECOND_VALUE).build(); + assertThat(updatedMultiValueTracestate.get(FIRST_KEY)).isEqualTo(SECOND_VALUE); + assertThat(updatedMultiValueTracestate.get(SECOND_KEY)).isEqualTo(SECOND_VALUE); + } + + @Test + public void addAndUpdateEntry() { + assertThat( + firstTracestate + .toBuilder() + .set(FIRST_KEY, SECOND_VALUE) // update the existing entry + .set(SECOND_KEY, FIRST_VALUE) // add a new entry + .build() + .getEntries()) + .containsExactly( + Entry.create(FIRST_KEY, SECOND_VALUE), Entry.create(SECOND_KEY, FIRST_VALUE)); + } + + @Test + public void addSameKey() { + assertThat( + EMPTY + .toBuilder() + .set(FIRST_KEY, SECOND_VALUE) // update the existing entry + .set(FIRST_KEY, FIRST_VALUE) // add a new entry + .build() + .getEntries()) + .containsExactly(Entry.create(FIRST_KEY, FIRST_VALUE)); + } + + @Test + public void remove() { + assertThat(multiValueTracestate.toBuilder().remove(SECOND_KEY).build()) + .isEqualTo(firstTracestate); + } + + @Test + public void addAndRemoveEntry() { + assertThat( + EMPTY + .toBuilder() + .set(FIRST_KEY, SECOND_VALUE) // update the existing entry + .remove(FIRST_KEY) // add a new entry + .build()) + .isEqualTo(EMPTY); + } + + @Test + public void remove_NullNotAllowed() { + thrown.expect(NullPointerException.class); + multiValueTracestate.toBuilder().remove(null).build(); + } + + @Test + public void tracestate_EqualsAndHashCode() { + EqualsTester tester = new EqualsTester(); + tester.addEqualityGroup(EMPTY, EMPTY); + tester.addEqualityGroup(firstTracestate, EMPTY.toBuilder().set(FIRST_KEY, FIRST_VALUE).build()); + tester.addEqualityGroup( + secondTracestate, EMPTY.toBuilder().set(SECOND_KEY, SECOND_VALUE).build()); + tester.testEquals(); + } + + @Test + public void tracestate_ToString() { + assertThat(EMPTY.toString()).isEqualTo("Tracestate{entries=[]}"); + } +} -- cgit v1.2.3 From b0c487b09287f7734f46d7b84afbd07d6c025f28 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Fri, 3 Aug 2018 12:37:46 +0300 Subject: Minor improvements for Tracestate. (#1358) --- api/src/main/java/io/opencensus/trace/Tracestate.java | 18 +++++++++++++++--- .../test/java/io/opencensus/trace/TracestateTest.java | 2 +- 2 files changed, 16 insertions(+), 4 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/Tracestate.java b/api/src/main/java/io/opencensus/trace/Tracestate.java index 63d32fd3..5535a0ac 100644 --- a/api/src/main/java/io/opencensus/trace/Tracestate.java +++ b/api/src/main/java/io/opencensus/trace/Tracestate.java @@ -75,9 +75,19 @@ public abstract class Tracestate { public abstract List getEntries(); /** - * Returns a builder based on this {@code Tracestate}. + * Returns a {@code Builder} based on an empty {@code Tracestate}. * - * @return a builder based on this {@code Tracestate}. + * @return a {@code Builder} based on an empty {@code Tracestate}. + * @since 0.16 + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Returns a {@code Builder} based on this {@code Tracestate}. + * + * @return a {@code Builder} based on this {@code Tracestate}. * @since 0.16 */ public Builder toBuilder() { @@ -94,9 +104,11 @@ public abstract class Tracestate { private final Tracestate parent; @javax.annotation.Nullable private ArrayList entries; + // Needs to be in this class to avoid initialization deadlock because super class depends on + // subclass (the auto-value generate class). private static final Tracestate EMPTY = create(Collections.emptyList()); - public Builder() { + private Builder() { this(EMPTY); } diff --git a/api/src/test/java/io/opencensus/trace/TracestateTest.java b/api/src/test/java/io/opencensus/trace/TracestateTest.java index b347d8ad..3374eb75 100644 --- a/api/src/test/java/io/opencensus/trace/TracestateTest.java +++ b/api/src/test/java/io/opencensus/trace/TracestateTest.java @@ -37,7 +37,7 @@ public class TracestateTest { @Rule public final ExpectedException thrown = ExpectedException.none(); - private static final Tracestate EMPTY = new Tracestate.Builder().build(); + private static final Tracestate EMPTY = Tracestate.builder().build(); private final Tracestate firstTracestate = EMPTY.toBuilder().set(FIRST_KEY, FIRST_VALUE).build(); private final Tracestate secondTracestate = EMPTY.toBuilder().set(SECOND_KEY, SECOND_VALUE).build(); -- cgit v1.2.3 From c943c6c63637cc866e92b90dae0e48dccd488130 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Tue, 7 Aug 2018 02:45:49 +0300 Subject: Add a warning about try-with-resource to auto-close spans. (#1362) --- api/src/main/java/io/opencensus/trace/SpanBuilder.java | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/SpanBuilder.java b/api/src/main/java/io/opencensus/trace/SpanBuilder.java index 1a4e29e9..f3a436a6 100644 --- a/api/src/main/java/io/opencensus/trace/SpanBuilder.java +++ b/api/src/main/java/io/opencensus/trace/SpanBuilder.java @@ -233,6 +233,16 @@ public abstract class SpanBuilder { * } * } * + *

    WARNING: The try-with-resources feature to auto-close spans as described above can sound + * very tempting due to its convenience, but it comes with an important and easy-to-miss + * trade-off: the span will be closed before any {@code catch} or {@code finally} blocks get a + * chance to execute. So if you need to catch any exceptions and log information about them (for + * example), then you do not want to use the try-with-resources shortcut because that logging will + * not be tagged with the span info of the span it logically falls under, and if you try to + * retrieve {@code Tracer.getCurrentSpan()} then you'll either get the parent span if one exists + * or {@code BlankSpan} if there was no parent span. This can be confusing and seem + * counter-intuitive, but it's the way try-with-resources works. + * * @return an object that defines a scope where the newly created {@code Span} will be set to the * current Context. * @since 0.5 -- cgit v1.2.3 From 52f38e48e2ac6cb65e28dcd97b4f7e9650357bba Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Thu, 9 Aug 2018 10:09:28 -0700 Subject: Add Tracestate into SpanContext. (#1359) * Add Tracestate into SpanContext. * Remove empty constructor from Tracestate.Builder * Add info in the changelog. --- .../main/java/io/opencensus/trace/SpanContext.java | 42 ++++++++++++++++++---- .../main/java/io/opencensus/trace/Tracestate.java | 6 +--- .../java/io/opencensus/trace/SpanContextTest.java | 20 ++++++++--- 3 files changed, 53 insertions(+), 15 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/SpanContext.java b/api/src/main/java/io/opencensus/trace/SpanContext.java index 66a6bfbc..49ed751b 100644 --- a/api/src/main/java/io/opencensus/trace/SpanContext.java +++ b/api/src/main/java/io/opencensus/trace/SpanContext.java @@ -30,9 +30,11 @@ import javax.annotation.concurrent.Immutable; */ @Immutable public final class SpanContext { + private static final Tracestate TRACESTATE_DEFAULT = Tracestate.builder().build(); private final TraceId traceId; private final SpanId spanId; private final TraceOptions traceOptions; + private final Tracestate tracestate; /** * The invalid {@code SpanContext}. @@ -40,7 +42,7 @@ public final class SpanContext { * @since 0.5 */ public static final SpanContext INVALID = - new SpanContext(TraceId.INVALID, SpanId.INVALID, TraceOptions.DEFAULT); + new SpanContext(TraceId.INVALID, SpanId.INVALID, TraceOptions.DEFAULT, TRACESTATE_DEFAULT); /** * Creates a new {@code SpanContext} with the given identifiers and options. @@ -49,10 +51,26 @@ public final class SpanContext { * @param spanId the span identifier of the span context. * @param traceOptions the trace options for the span context. * @return a new {@code SpanContext} with the given identifiers and options. - * @since 0.5 + * @deprecated use {@link #create(TraceId, SpanId, TraceOptions, Tracestate)}. */ + @Deprecated public static SpanContext create(TraceId traceId, SpanId spanId, TraceOptions traceOptions) { - return new SpanContext(traceId, spanId, traceOptions); + return create(traceId, spanId, traceOptions, TRACESTATE_DEFAULT); + } + + /** + * Creates a new {@code SpanContext} with the given identifiers and options. + * + * @param traceId the trace identifier of the span context. + * @param spanId the span identifier of the span context. + * @param traceOptions the trace options for the span context. + * @param tracestate the trace state for the span context. + * @return a new {@code SpanContext} with the given identifiers and options. + * @since 0.16 + */ + public static SpanContext create( + TraceId traceId, SpanId spanId, TraceOptions traceOptions, Tracestate tracestate) { + return new SpanContext(traceId, spanId, traceOptions, tracestate); } /** @@ -76,15 +94,25 @@ public final class SpanContext { } /** - * Returns the trace options associated with this {@code SpanContext}. + * Returns the {@code TraceOptions} associated with this {@code SpanContext}. * - * @return the trace options associated with this {@code SpanContext}. + * @return the {@code TraceOptions} associated with this {@code SpanContext}. * @since 0.5 */ public TraceOptions getTraceOptions() { return traceOptions; } + /** + * Returns the {@code Tracestate} associated with this {@code SpanContext}. + * + * @return the {@code Tracestate} associated with this {@code SpanContext}. + * @since 0.5 + */ + public Tracestate getTracestate() { + return tracestate; + } + /** * Returns true if this {@code SpanContext} is valid. * @@ -127,9 +155,11 @@ public final class SpanContext { + "}"; } - private SpanContext(TraceId traceId, SpanId spanId, TraceOptions traceOptions) { + private SpanContext( + TraceId traceId, SpanId spanId, TraceOptions traceOptions, Tracestate tracestate) { this.traceId = traceId; this.spanId = spanId; this.traceOptions = traceOptions; + this.tracestate = tracestate; } } diff --git a/api/src/main/java/io/opencensus/trace/Tracestate.java b/api/src/main/java/io/opencensus/trace/Tracestate.java index 5535a0ac..f88d3bd3 100644 --- a/api/src/main/java/io/opencensus/trace/Tracestate.java +++ b/api/src/main/java/io/opencensus/trace/Tracestate.java @@ -81,7 +81,7 @@ public abstract class Tracestate { * @since 0.16 */ public static Builder builder() { - return new Builder(); + return new Builder(Builder.EMPTY); } /** @@ -108,10 +108,6 @@ public abstract class Tracestate { // subclass (the auto-value generate class). private static final Tracestate EMPTY = create(Collections.emptyList()); - private Builder() { - this(EMPTY); - } - private Builder(Tracestate parent) { Utils.checkNotNull(parent, "parent"); this.parent = parent; diff --git a/api/src/test/java/io/opencensus/trace/SpanContextTest.java b/api/src/test/java/io/opencensus/trace/SpanContextTest.java index f5a9954f..54e188c8 100644 --- a/api/src/test/java/io/opencensus/trace/SpanContextTest.java +++ b/api/src/test/java/io/opencensus/trace/SpanContextTest.java @@ -32,16 +32,20 @@ public class SpanContextTest { new byte[] {0, 0, 0, 0, 0, 0, 0, '0', 0, 0, 0, 0, 0, 0, 0, 0}; private static final byte[] firstSpanIdBytes = new byte[] {0, 0, 0, 0, 0, 0, 0, 'a'}; private static final byte[] secondSpanIdBytes = new byte[] {'0', 0, 0, 0, 0, 0, 0, 0}; + private static final Tracestate firstTracestate = Tracestate.builder().set("foo", "bar").build(); + private static final Tracestate secondTracestate = Tracestate.builder().set("foo", "baz").build(); private static final SpanContext first = SpanContext.create( TraceId.fromBytes(firstTraceIdBytes), SpanId.fromBytes(firstSpanIdBytes), - TraceOptions.DEFAULT); + TraceOptions.DEFAULT, + firstTracestate); private static final SpanContext second = SpanContext.create( TraceId.fromBytes(secondTraceIdBytes), SpanId.fromBytes(secondSpanIdBytes), - TraceOptions.builder().setIsSampled(true).build()); + TraceOptions.builder().setIsSampled(true).build(), + secondTracestate); @Test public void invalidSpanContext() { @@ -86,6 +90,12 @@ public class SpanContextTest { .isEqualTo(TraceOptions.builder().setIsSampled(true).build()); } + @Test + public void getTracestate() { + assertThat(first.getTracestate()).isEqualTo(firstTracestate); + assertThat(second.getTracestate()).isEqualTo(secondTracestate); + } + @Test public void spanContext_EqualsAndHashCode() { EqualsTester tester = new EqualsTester(); @@ -98,13 +108,15 @@ public class SpanContextTest { SpanContext.create( TraceId.fromBytes(firstTraceIdBytes), SpanId.fromBytes(firstSpanIdBytes), - TraceOptions.builder().setIsSampled(false).build())); + TraceOptions.builder().setIsSampled(false).build(), + firstTracestate)); tester.addEqualityGroup( second, SpanContext.create( TraceId.fromBytes(secondTraceIdBytes), SpanId.fromBytes(secondSpanIdBytes), - TraceOptions.builder().setIsSampled(true).build())); + TraceOptions.builder().setIsSampled(true).build(), + secondTracestate)); tester.testEquals(); } -- cgit v1.2.3 From a804907c77858ff319ba059af968f6cfd8eb3925 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Fri, 10 Aug 2018 14:45:23 -0700 Subject: Add support for recording Gauges. (#1344) * Add support for Gauges in OpenCensus. * Minor comment fix. --- .../io/opencensus/common/ToDoubleFunction.java | 39 ++++++++++++++++++++++ .../java/io/opencensus/common/ToLongFunction.java | 38 +++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 api/src/main/java/io/opencensus/common/ToDoubleFunction.java create mode 100644 api/src/main/java/io/opencensus/common/ToLongFunction.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/ToDoubleFunction.java b/api/src/main/java/io/opencensus/common/ToDoubleFunction.java new file mode 100644 index 00000000..479270f1 --- /dev/null +++ b/api/src/main/java/io/opencensus/common/ToDoubleFunction.java @@ -0,0 +1,39 @@ +/* + * Copyright 2018, 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.common; + +// TODO(bdrutu): Change @code to @link when metrics is moved in the API. + +/** + * Represents a function that produces a double-valued result. See {@code + * io.opencensus.metrics.MetricRegistry} for an example of its use. + * + *

    Note: This class is based on the java.util.ToDoubleFunction class added in Java 1.8. We cannot + * use the Function from Java 1.8 because this library is Java 1.6 compatible. + * + * @since 0.16 + */ +public interface ToDoubleFunction { + + /** + * Applies this function to the given argument. + * + * @param value the function argument. + * @return the function result. + */ + double applyAsDouble(T value); +} diff --git a/api/src/main/java/io/opencensus/common/ToLongFunction.java b/api/src/main/java/io/opencensus/common/ToLongFunction.java new file mode 100644 index 00000000..9a6e9b19 --- /dev/null +++ b/api/src/main/java/io/opencensus/common/ToLongFunction.java @@ -0,0 +1,38 @@ +/* + * Copyright 2018, 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.common; + +// TODO(bdrutu): Change @code to @link when metrics is moved in the API. + +/** + * Represents a function that produces a long-valued result. See {@code + * io.opencensus.metrics.MetricRegistry} for an example of its use. + * + *

    Note: This class is based on the java.util.ToLongFunction class added in Java 1.8. We cannot + * use the Function from Java 1.8 because this library is Java 1.6 compatible. + * + * @since 0.16 + */ +public interface ToLongFunction { + /** + * Applies this function to the given argument. + * + * @param value the function argument. + * @return the function result. + */ + long applyAsLong(T value); +} -- cgit v1.2.3 From 81e8ded6d2f869980a7f80a27ead4bd2ccc45243 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Fri, 10 Aug 2018 15:43:52 -0700 Subject: Metrics: Move metrics to opencensus-api. (#1346) * Metrics: Move to api. * Update package-info to warn users on using metrics. --- .../java/io/opencensus/metrics/Distribution.java | 280 +++++++++++++++++++++ .../main/java/io/opencensus/metrics/LabelKey.java | 62 +++++ .../java/io/opencensus/metrics/LabelValue.java | 57 +++++ .../main/java/io/opencensus/metrics/Metric.java | 88 +++++++ .../io/opencensus/metrics/MetricDescriptor.java | 150 +++++++++++ .../java/io/opencensus/metrics/MetricProducer.java | 38 +++ .../java/io/opencensus/metrics/MetricRegistry.java | 117 +++++++++ .../main/java/io/opencensus/metrics/Metrics.java | 91 +++++++ .../io/opencensus/metrics/MetricsComponent.java | 71 ++++++ api/src/main/java/io/opencensus/metrics/Point.java | 63 +++++ .../java/io/opencensus/metrics/TimeSeries.java | 48 ++++ .../opencensus/metrics/TimeSeriesCumulative.java | 70 ++++++ .../io/opencensus/metrics/TimeSeriesGauge.java | 57 +++++ .../java/io/opencensus/metrics/TimeSeriesList.java | 134 ++++++++++ api/src/main/java/io/opencensus/metrics/Value.java | 196 +++++++++++++++ .../opencensus/metrics/export/ExportComponent.java | 60 +++++ .../metrics/export/MetricProducerManager.java | 89 +++++++ .../java/io/opencensus/metrics/package-info.java | 32 +++ .../io/opencensus/metrics/DistributionTest.java | 226 +++++++++++++++++ .../java/io/opencensus/metrics/LabelKeyTest.java | 86 +++++++ .../java/io/opencensus/metrics/LabelValueTest.java | 74 ++++++ .../opencensus/metrics/MetricDescriptorTest.java | 102 ++++++++ .../io/opencensus/metrics/MetricRegistryTest.java | 181 +++++++++++++ .../java/io/opencensus/metrics/MetricTest.java | 127 ++++++++++ .../opencensus/metrics/MetricsComponentTest.java | 40 +++ .../java/io/opencensus/metrics/MetricsTest.java | 65 +++++ .../test/java/io/opencensus/metrics/PointTest.java | 68 +++++ .../metrics/TimeSeriesCumulativeTest.java | 113 +++++++++ .../io/opencensus/metrics/TimeSeriesGaugeTest.java | 104 ++++++++ .../io/opencensus/metrics/TimeSeriesListTest.java | 135 ++++++++++ .../test/java/io/opencensus/metrics/ValueTest.java | 128 ++++++++++ .../metrics/export/ExportComponentTest.java | 33 +++ .../metrics/export/MetricProducerManagerTest.java | 113 +++++++++ 33 files changed, 3298 insertions(+) create mode 100644 api/src/main/java/io/opencensus/metrics/Distribution.java create mode 100644 api/src/main/java/io/opencensus/metrics/LabelKey.java create mode 100644 api/src/main/java/io/opencensus/metrics/LabelValue.java create mode 100644 api/src/main/java/io/opencensus/metrics/Metric.java create mode 100644 api/src/main/java/io/opencensus/metrics/MetricDescriptor.java create mode 100644 api/src/main/java/io/opencensus/metrics/MetricProducer.java create mode 100644 api/src/main/java/io/opencensus/metrics/MetricRegistry.java create mode 100644 api/src/main/java/io/opencensus/metrics/Metrics.java create mode 100644 api/src/main/java/io/opencensus/metrics/MetricsComponent.java create mode 100644 api/src/main/java/io/opencensus/metrics/Point.java create mode 100644 api/src/main/java/io/opencensus/metrics/TimeSeries.java create mode 100644 api/src/main/java/io/opencensus/metrics/TimeSeriesCumulative.java create mode 100644 api/src/main/java/io/opencensus/metrics/TimeSeriesGauge.java create mode 100644 api/src/main/java/io/opencensus/metrics/TimeSeriesList.java create mode 100644 api/src/main/java/io/opencensus/metrics/Value.java create mode 100644 api/src/main/java/io/opencensus/metrics/export/ExportComponent.java create mode 100644 api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java create mode 100644 api/src/main/java/io/opencensus/metrics/package-info.java create mode 100644 api/src/test/java/io/opencensus/metrics/DistributionTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/LabelKeyTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/LabelValueTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/MetricDescriptorTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/MetricTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/MetricsComponentTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/MetricsTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/PointTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/TimeSeriesCumulativeTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/TimeSeriesGaugeTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/TimeSeriesListTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/ValueTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/export/ExportComponentTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/metrics/Distribution.java b/api/src/main/java/io/opencensus/metrics/Distribution.java new file mode 100644 index 00000000..5334a8d8 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/Distribution.java @@ -0,0 +1,280 @@ +/* + * Copyright 2018, 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.metrics; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.common.Timestamp; +import io.opencensus.internal.Utils; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * {@link Distribution} contains summary statistics for a population of values. It optionally + * contains a histogram representing the distribution of those values across a set of buckets. + * + * @since 0.16 + */ +@ExperimentalApi +@AutoValue +@Immutable +public abstract class Distribution { + + Distribution() {} + + /** + * Creates a {@link Distribution}. + * + * @param mean mean of the population values. + * @param count count of the population values. + * @param sumOfSquaredDeviations sum of squared deviations of the population values. + * @param bucketBoundaries bucket boundaries of a histogram. + * @param buckets {@link Bucket}s of a histogram. + * @return a {@code Distribution}. + * @since 0.16 + */ + public static Distribution create( + double mean, + long count, + double sumOfSquaredDeviations, + List bucketBoundaries, + List buckets) { + Utils.checkArgument(count >= 0, "count should be non-negative."); + Utils.checkArgument( + sumOfSquaredDeviations >= 0, "sum of squared deviations should be non-negative."); + if (count == 0) { + Utils.checkArgument(mean == 0, "mean should be 0 if count is 0."); + Utils.checkArgument( + sumOfSquaredDeviations == 0, "sum of squared deviations should be 0 if count is 0."); + } + return new AutoValue_Distribution( + mean, + count, + sumOfSquaredDeviations, + copyBucketBounds(bucketBoundaries), + copyBucketCount(buckets)); + } + + private static List copyBucketBounds(List bucketBoundaries) { + Utils.checkNotNull(bucketBoundaries, "bucketBoundaries list should not be null."); + List bucketBoundariesCopy = new ArrayList(bucketBoundaries); // Deep copy. + // Check if sorted. + if (bucketBoundariesCopy.size() > 1) { + double lower = bucketBoundariesCopy.get(0); + for (int i = 1; i < bucketBoundariesCopy.size(); i++) { + double next = bucketBoundariesCopy.get(i); + Utils.checkArgument(lower < next, "bucket boundaries not sorted."); + lower = next; + } + } + return Collections.unmodifiableList(bucketBoundariesCopy); + } + + private static List copyBucketCount(List buckets) { + Utils.checkNotNull(buckets, "bucket list should not be null."); + List bucketsCopy = new ArrayList(buckets); + for (Bucket bucket : bucketsCopy) { + Utils.checkNotNull(bucket, "bucket should not be null."); + } + return Collections.unmodifiableList(bucketsCopy); + } + + /** + * Returns the aggregated mean. + * + * @return the aggregated mean. + * @since 0.16 + */ + public abstract double getMean(); + + /** + * Returns the aggregated count. + * + * @return the aggregated count. + * @since 0.16 + */ + public abstract long getCount(); + + /** + * Returns the aggregated sum of squared deviations. + * + *

    The sum of squared deviations from the mean of the values in the population. For values x_i + * this is: + * + *

    Sum[i=1..n]((x_i - mean)^2) + * + *

    If count is zero then this field must be zero. + * + * @return the aggregated sum of squared deviations. + * @since 0.16 + */ + public abstract double getSumOfSquaredDeviations(); + + /** + * Returns the bucket boundaries of this distribution. + * + *

    The bucket boundaries for that histogram are described by bucket_bounds. This defines + * size(bucket_bounds) + 1 (= N) buckets. The boundaries for bucket index i are: + * + *

      + *
    • {@code (-infinity, bucket_bounds[i]) for i == 0} + *
    • {@code [bucket_bounds[i-1], bucket_bounds[i]) for 0 < i < N-2} + *
    • {@code [bucket_bounds[i-1], +infinity) for i == N-1} + *
    + * + *

    i.e. an underflow bucket (number 0), zero or more finite buckets (1 through N - 2, and an + * overflow bucket (N - 1), with inclusive lower bounds and exclusive upper bounds. + * + *

    If bucket_bounds has no elements (zero size), then there is no histogram associated with the + * Distribution. If bucket_bounds has only one element, there are no finite buckets, and that + * single element is the common boundary of the overflow and underflow buckets. The values must be + * monotonically increasing. + * + * @return the bucket boundaries of this distribution. + * @since 0.16 + */ + public abstract List getBucketBoundaries(); + + /** + * Returns the the aggregated histogram {@link Bucket}s. + * + * @return the the aggregated histogram buckets. + * @since 0.16 + */ + public abstract List getBuckets(); + + /** + * The histogram bucket of the population values. + * + * @since 0.16 + */ + @AutoValue + @Immutable + public abstract static class Bucket { + + Bucket() {} + + /** + * Creates a {@link Bucket}. + * + * @param count the number of values in each bucket of the histogram. + * @return a {@code Bucket}. + * @since 0.16 + */ + public static Bucket create(long count) { + Utils.checkArgument(count >= 0, "bucket count should be non-negative."); + return new AutoValue_Distribution_Bucket(count, null); + } + + /** + * Creates a {@link Bucket} with an {@link Exemplar}. + * + * @param count the number of values in each bucket of the histogram. + * @param exemplar the {@code Exemplar} of this {@code Bucket}. + * @return a {@code Bucket}. + * @since 0.16 + */ + public static Bucket create(long count, Exemplar exemplar) { + Utils.checkArgument(count >= 0, "bucket count should be non-negative."); + Utils.checkNotNull(exemplar, "exemplar"); + return new AutoValue_Distribution_Bucket(count, exemplar); + } + + /** + * Returns the number of values in each bucket of the histogram. + * + * @return the number of values in each bucket of the histogram. + * @since 0.16 + */ + public abstract long getCount(); + + /** + * Returns the {@link Exemplar} associated with the {@link Bucket}, or {@code null} if there + * isn't one. + * + * @return the {@code Exemplar} associated with the {@code Bucket}, or {@code null} if there + * isn't one. + * @since 0.16 + */ + @Nullable + public abstract Exemplar getExemplar(); + } + + /** + * An example point that may be used to annotate aggregated distribution values, associated with a + * histogram bucket. + * + * @since 0.16 + */ + @Immutable + @AutoValue + public abstract static class Exemplar { + + Exemplar() {} + + /** + * Returns value of the {@link Exemplar} point. + * + * @return value of the {@code Exemplar} point. + * @since 0.16 + */ + public abstract double getValue(); + + /** + * Returns the time that this {@link Exemplar}'s value was recorded. + * + * @return the time that this {@code Exemplar}'s value was recorded. + * @since 0.16 + */ + public abstract Timestamp getTimestamp(); + + /** + * Returns the contextual information about the example value, represented as a string map. + * + * @return the contextual information about the example value. + * @since 0.16 + */ + public abstract Map getAttachments(); + + /** + * Creates an {@link Exemplar}. + * + * @param value value of the {@link Exemplar} point. + * @param timestamp the time that this {@code Exemplar}'s value was recorded. + * @param attachments the contextual information about the example value. + * @return an {@code Exemplar}. + * @since 0.16 + */ + public static Exemplar create( + double value, Timestamp timestamp, Map attachments) { + Utils.checkNotNull(attachments, "attachments"); + Map attachmentsCopy = + Collections.unmodifiableMap(new HashMap(attachments)); + for (Entry entry : attachmentsCopy.entrySet()) { + Utils.checkNotNull(entry.getKey(), "key of attachments"); + Utils.checkNotNull(entry.getValue(), "value of attachments"); + } + return new AutoValue_Distribution_Exemplar(value, timestamp, attachmentsCopy); + } + } +} diff --git a/api/src/main/java/io/opencensus/metrics/LabelKey.java b/api/src/main/java/io/opencensus/metrics/LabelKey.java new file mode 100644 index 00000000..01ef0b55 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/LabelKey.java @@ -0,0 +1,62 @@ +/* + * Copyright 2018, 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.metrics; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import javax.annotation.concurrent.Immutable; + +/** + * The key of a {@code Label} associated with a {@code MetricDescriptor}. + * + * @since 0.15 + */ +@ExperimentalApi +@Immutable +@AutoValue +public abstract class LabelKey { + + LabelKey() {} + + /** + * Creates a {@link LabelKey}. + * + * @param key the key of a {@code Label}. + * @param description a human-readable description of what this label key represents. + * @return a {@code LabelKey}. + * @since 0.15 + */ + public static LabelKey create(String key, String description) { + return new AutoValue_LabelKey(key, description); + } + + /** + * Returns the key of this {@link LabelKey}. + * + * @return the key. + * @since 0.15 + */ + public abstract String getKey(); + + /** + * Returns the description of this {@link LabelKey}. + * + * @return the description. + * @since 0.15 + */ + public abstract String getDescription(); +} diff --git a/api/src/main/java/io/opencensus/metrics/LabelValue.java b/api/src/main/java/io/opencensus/metrics/LabelValue.java new file mode 100644 index 00000000..e81b63d2 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/LabelValue.java @@ -0,0 +1,57 @@ +/* + * Copyright 2018, 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.metrics; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * The value of a {@code Label} associated with a {@code TimeSeries}. + * + * @since 0.15 + */ +@ExperimentalApi +@Immutable +@AutoValue +public abstract class LabelValue { + + LabelValue() {} + + /** + * Creates a {@link LabelValue}. + * + * @param value the value of a {@code Label}. {@code null} value indicates an unset {@code + * LabelValue}. + * @return a {@code LabelValue}. + * @since 0.15 + */ + public static LabelValue create(@Nullable String value) { + return new AutoValue_LabelValue(value); + } + + /** + * Returns the value of this {@link LabelValue}. Returns {@code null} if the value is unset and + * supposed to be ignored. + * + * @return the value. + * @since 0.15 + */ + @Nullable + public abstract String getValue(); +} diff --git a/api/src/main/java/io/opencensus/metrics/Metric.java b/api/src/main/java/io/opencensus/metrics/Metric.java new file mode 100644 index 00000000..e8be0b90 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/Metric.java @@ -0,0 +1,88 @@ +/* + * Copyright 2018, 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.metrics; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.internal.Utils; +import io.opencensus.metrics.TimeSeriesList.TimeSeriesCumulativeList; +import io.opencensus.metrics.TimeSeriesList.TimeSeriesGaugeList; +import javax.annotation.concurrent.Immutable; + +/** + * A {@link Metric} with one or more {@link TimeSeries}. + * + * @since 0.16 + */ +@ExperimentalApi +@Immutable +@AutoValue +public abstract class Metric { + + Metric() {} + + /** + * Creates a {@link Metric}. + * + * @param metricDescriptor the {@link MetricDescriptor}. + * @param timeSeriesList the {@link TimeSeriesList} for this metric. + * @return a {@code Metric}. + * @since 0.16 + */ + public static Metric create(MetricDescriptor metricDescriptor, TimeSeriesList timeSeriesList) { + checkTypeMatch(metricDescriptor.getType(), timeSeriesList); + return new AutoValue_Metric(metricDescriptor, timeSeriesList); + } + + /** + * Returns the {@link MetricDescriptor} of this metric. + * + * @return the {@code MetricDescriptor} of this metric. + * @since 0.16 + */ + public abstract MetricDescriptor getMetricDescriptor(); + + /** + * Returns the {@link TimeSeriesList} for this metric. + * + *

    The type of the {@link TimeSeriesList} must match {@link MetricDescriptor.Type}. + * + * @return the {@code TimeSeriesList} for this metric. + * @since 0.16 + */ + public abstract TimeSeriesList getTimeSeriesList(); + + private static void checkTypeMatch(MetricDescriptor.Type type, TimeSeriesList timeSeriesList) { + switch (type) { + case GAUGE_INT64: + case GAUGE_DOUBLE: + Utils.checkArgument( + timeSeriesList instanceof TimeSeriesGaugeList, + String.format( + "Type mismatch: %s, %s.", type, timeSeriesList.getClass().getSimpleName())); + break; + case CUMULATIVE_DISTRIBUTION: + case CUMULATIVE_DOUBLE: + case CUMULATIVE_INT64: + Utils.checkArgument( + timeSeriesList instanceof TimeSeriesCumulativeList, + String.format( + "Type mismatch: %s, %s.", type, timeSeriesList.getClass().getSimpleName())); + break; + } + } +} diff --git a/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java b/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java new file mode 100644 index 00000000..4558446a --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java @@ -0,0 +1,150 @@ +/* + * Copyright 2018, 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.metrics; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.internal.Utils; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.annotation.concurrent.Immutable; + +/** + * {@link MetricDescriptor} defines a {@code Metric} type and its schema. + * + * @since 0.16 + */ +@ExperimentalApi +@Immutable +@AutoValue +public abstract class MetricDescriptor { + + MetricDescriptor() {} + + /** + * Creates a {@link MetricDescriptor}. + * + * @param name name of {@code MetricDescriptor}. + * @param description description of {@code MetricDescriptor}. + * @param unit the metric unit. + * @param type type of {@code MetricDescriptor}. + * @param labelKeys the label keys associated with the {@code MetricDescriptor}. + * @return a {@code MetricDescriptor}. + * @since 0.16 + */ + public static MetricDescriptor create( + String name, String description, String unit, Type type, List labelKeys) { + Utils.checkNotNull(labelKeys, "labelKeys"); + Utils.checkListElementNotNull(labelKeys, "labelKey"); + return new AutoValue_MetricDescriptor( + name, + description, + unit, + type, + Collections.unmodifiableList(new ArrayList(labelKeys))); + } + + /** + * Returns the metric descriptor name. + * + * @return the metric descriptor name. + * @since 0.16 + */ + public abstract String getName(); + + /** + * Returns the description of this metric descriptor. + * + * @return the description of this metric descriptor. + * @since 0.16 + */ + public abstract String getDescription(); + + /** + * Returns the unit of this metric descriptor. + * + * @return the unit of this metric descriptor. + * @since 0.16 + */ + public abstract String getUnit(); + + /** + * Returns the type of this metric descriptor. + * + * @return the type of this metric descriptor. + * @since 0.16 + */ + public abstract Type getType(); + + /** + * Returns the label keys associated with this metric descriptor. + * + * @return the label keys associated with this metric descriptor. + * @since 0.16 + */ + public abstract List getLabelKeys(); + + /** + * The kind of metric. It describes how the data is reported. + * + *

    A gauge is an instantaneous measurement of a value. + * + *

    A cumulative measurement is a value accumulated over a time interval. In a time series, + * cumulative measurements should have the same start time and increasing end times, until an + * event resets the cumulative value to zero and sets a new start time for the following points. + * + * @since 0.16 + */ + public enum Type { + + /** + * An instantaneous measurement of an int64 value. + * + * @since 0.16 + */ + GAUGE_INT64, + + /** + * An instantaneous measurement of a double value. + * + * @since 0.16 + */ + GAUGE_DOUBLE, + + /** + * An cumulative measurement of an int64 value. + * + * @since 0.16 + */ + CUMULATIVE_INT64, + + /** + * An cumulative measurement of a double value. + * + * @since 0.16 + */ + CUMULATIVE_DOUBLE, + + /** + * An cumulative measurement of a distribution value. + * + * @since 0.16 + */ + CUMULATIVE_DISTRIBUTION, + } +} diff --git a/api/src/main/java/io/opencensus/metrics/MetricProducer.java b/api/src/main/java/io/opencensus/metrics/MetricProducer.java new file mode 100644 index 00000000..38b5d571 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/MetricProducer.java @@ -0,0 +1,38 @@ +/* + * Copyright 2018, 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.metrics; + +import io.opencensus.common.ExperimentalApi; +import io.opencensus.metrics.export.MetricProducerManager; +import java.util.Collection; + +/** + * A {@link io.opencensus.metrics.Metric} producer that can be registered for exporting using {@link + * MetricProducerManager}. + * + *

    All implementation MUST be thread-safe. + */ +@ExperimentalApi +public abstract class MetricProducer { + + /** + * Returns a collection of produced {@link io.opencensus.metrics.Metric}s to be exported. + * + * @return a collection of produced {@link io.opencensus.metrics.Metric}s to be exported. + */ + public abstract Collection getMetrics(); +} diff --git a/api/src/main/java/io/opencensus/metrics/MetricRegistry.java b/api/src/main/java/io/opencensus/metrics/MetricRegistry.java new file mode 100644 index 00000000..ae4d90b0 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/MetricRegistry.java @@ -0,0 +1,117 @@ +/* + * Copyright 2018, 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.metrics; + +import io.opencensus.common.ExperimentalApi; +import io.opencensus.common.ToDoubleFunction; +import io.opencensus.common.ToLongFunction; +import io.opencensus.internal.Utils; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; + +/** + * Creates and manages your application's set of metrics. Exporters use the metric registry to + * iterate over the set of metrics instrumenting your application, and then further export each + * metric to the backend of choice. + * + * @since 0.16 + */ +@ExperimentalApi +public abstract class MetricRegistry extends MetricProducer { + /** + * Build a new long gauge to be added to the registry. + * + *

    Must be called only once. + * + * @param name the name of the metric. + * @param description the description of the metric. + * @param unit the unit of the metric. + * @param obj the function argument. + * @param function the function to be called. + * @since 0.16 @ExperimentalApi + */ + public abstract void addLongGauge( + String name, + String description, + String unit, + LinkedHashMap labels, + T obj, + ToLongFunction function); + + /** + * Build a new double gauge to be added to the registry. + * + *

    Must be called only once. + * + * @param name the name of the metric. + * @param description the description of the metric. + * @param unit the unit of the metric. + * @param obj the function argument. + * @param function the function to be called. + * @since 0.16 @ExperimentalApi + */ + public abstract void addDoubleGauge( + String name, + String description, + String unit, + LinkedHashMap labels, + T obj, + ToDoubleFunction function); + + static MetricRegistry newNoopMetricRegistry() { + return new NoopMetricRegistry(); + } + + private static final class NoopMetricRegistry extends MetricRegistry { + + @Override + public void addLongGauge( + String name, + String description, + String unit, + LinkedHashMap labels, + T obj, + ToLongFunction function) { + Utils.checkNotNull(name, "name"); + Utils.checkNotNull(description, "description"); + Utils.checkNotNull(unit, "unit"); + Utils.checkNotNull(labels, "labels"); + Utils.checkNotNull(function, "function"); + } + + @Override + public void addDoubleGauge( + String name, + String description, + String unit, + LinkedHashMap labels, + T obj, + ToDoubleFunction function) { + Utils.checkNotNull(name, "name"); + Utils.checkNotNull(description, "description"); + Utils.checkNotNull(unit, "unit"); + Utils.checkNotNull(labels, "labels"); + Utils.checkNotNull(function, "function"); + } + + @Override + public Collection getMetrics() { + return Collections.emptyList(); + } + } +} diff --git a/api/src/main/java/io/opencensus/metrics/Metrics.java b/api/src/main/java/io/opencensus/metrics/Metrics.java new file mode 100644 index 00000000..ed7d6716 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/Metrics.java @@ -0,0 +1,91 @@ +/* + * Copyright 2018, 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.metrics; + +import io.opencensus.common.ExperimentalApi; +import io.opencensus.internal.DefaultVisibilityForTesting; +import io.opencensus.internal.Provider; +import io.opencensus.metrics.export.ExportComponent; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; + +@ExperimentalApi +public final class Metrics { + private static final Logger logger = Logger.getLogger(Metrics.class.getName()); + private static final MetricsComponent metricsComponent = + loadMetricsComponent(MetricsComponent.class.getClassLoader()); + + /** + * Returns the global {@link ExportComponent}. + * + * @return the global {@code ExportComponent}. + * @since 0.16 + */ + public static ExportComponent getExportComponent() { + return metricsComponent.getExportComponent(); + } + + /** + * Returns the global {@link MetricRegistry}. + * + *

    This {@code MetricRegistry} is already added to the global {@link + * io.opencensus.metrics.export.MetricProducerManager}. + * + * @return the global {@code MetricRegistry}. + * @since 0.16 + */ + public static MetricRegistry getMetricRegistry() { + return metricsComponent.getMetricRegistry(); + } + + // Any provider that may be used for MetricsComponent can be added here. + @DefaultVisibilityForTesting + static MetricsComponent loadMetricsComponent(@Nullable ClassLoader classLoader) { + try { + // Call Class.forName with literal string name of the class to help shading tools. + return Provider.createInstance( + Class.forName( + "io.opencensus.impl.metrics.MetricsComponentImpl", /*initialize=*/ true, classLoader), + MetricsComponent.class); + } catch (ClassNotFoundException e) { + logger.log( + Level.FINE, + "Couldn't load full implementation for MetricsComponent, now trying to load lite " + + "implementation.", + e); + } + try { + // Call Class.forName with literal string name of the class to help shading tools. + return Provider.createInstance( + Class.forName( + "io.opencensus.impllite.metrics.MetricsComponentImplLite", + /*initialize=*/ true, + classLoader), + MetricsComponent.class); + } catch (ClassNotFoundException e) { + logger.log( + Level.FINE, + "Couldn't load lite implementation for MetricsComponent, now using default " + + "implementation for MetricsComponent.", + e); + } + return MetricsComponent.newNoopMetricsComponent(); + } + + private Metrics() {} +} diff --git a/api/src/main/java/io/opencensus/metrics/MetricsComponent.java b/api/src/main/java/io/opencensus/metrics/MetricsComponent.java new file mode 100644 index 00000000..08d954ef --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/MetricsComponent.java @@ -0,0 +1,71 @@ +/* + * Copyright 2018, 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.metrics; + +import io.opencensus.common.ExperimentalApi; +import io.opencensus.metrics.export.ExportComponent; + +/** + * Class that holds the implementation instance for {@link ExportComponent}. + * + * @since 0.16 + */ +@ExperimentalApi +public abstract class MetricsComponent { + + /** + * Returns the {@link ExportComponent} with the provided implementation. If no implementation is + * provided then no-op implementations will be used. + * + * @return the {@link ExportComponent} implementation. + * @since 0.16 + */ + public abstract ExportComponent getExportComponent(); + + /** + * Returns the {@link MetricRegistry} with the provided implementation. + * + * @return the {@link MetricRegistry} implementation. + * @since 0.16 + */ + public abstract MetricRegistry getMetricRegistry(); + + /** + * Returns an instance that contains no-op implementations for all the instances. + * + * @return an instance that contains no-op implementations for all the instances. + */ + static MetricsComponent newNoopMetricsComponent() { + return new NoopMetricsComponent(); + } + + private static final class NoopMetricsComponent extends MetricsComponent { + private static final ExportComponent EXPORT_COMPONENT = + ExportComponent.newNoopExportComponent(); + private static final MetricRegistry METRIC_REGISTRY = MetricRegistry.newNoopMetricRegistry(); + + @Override + public ExportComponent getExportComponent() { + return EXPORT_COMPONENT; + } + + @Override + public MetricRegistry getMetricRegistry() { + return METRIC_REGISTRY; + } + } +} diff --git a/api/src/main/java/io/opencensus/metrics/Point.java b/api/src/main/java/io/opencensus/metrics/Point.java new file mode 100644 index 00000000..e66b273d --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/Point.java @@ -0,0 +1,63 @@ +/* + * Copyright 2018, 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.metrics; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.common.Timestamp; +import javax.annotation.concurrent.Immutable; + +/** + * A timestamped measurement of a {@code TimeSeries}. + * + * @since 0.16 + */ +@ExperimentalApi +@AutoValue +@Immutable +public abstract class Point { + + Point() {} + + /** + * Creates a {@link Point}. + * + * @param value the {@link Value} of this {@link Point}. + * @param timestamp the {@link Timestamp} when this {@link Point} was recorded. + * @return a {@code Point}. + * @since 0.16 + */ + public static Point create(Value value, Timestamp timestamp) { + return new AutoValue_Point(value, timestamp); + } + + /** + * Returns the {@link Value}. + * + * @return the {@code Value}. + * @since 0.16 + */ + public abstract Value getValue(); + + /** + * Returns the {@link Timestamp} when this {@link Point} was recorded. + * + * @return the {@code Timestamp}. + * @since 0.16 + */ + public abstract Timestamp getTimestamp(); +} diff --git a/api/src/main/java/io/opencensus/metrics/TimeSeries.java b/api/src/main/java/io/opencensus/metrics/TimeSeries.java new file mode 100644 index 00000000..bbbfe0e4 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/TimeSeries.java @@ -0,0 +1,48 @@ +/* + * Copyright 2018, 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.metrics; + +import java.util.List; +import javax.annotation.concurrent.Immutable; + +/** A collection of data points that describes the time-varying values of a {@code Metric}. */ +@Immutable +abstract class TimeSeries { + + TimeSeries() {} + + /** + * Returns the set of {@link LabelValue}s that uniquely identify this {@link TimeSeries}. + * + *

    Apply to all {@link Point}s. + * + *

    The order of {@link LabelValue}s must match that of {@link LabelKey}s in the {@code + * MetricDescriptor}. + * + * @return the {@code LabelValue}s. + * @since 0.16 + */ + public abstract List getLabelValues(); + + /** + * Returns the data {@link Point}s of this {@link TimeSeries}. + * + * @return the data {@code Point}s. + * @since 0.16 + */ + public abstract List getPoints(); +} diff --git a/api/src/main/java/io/opencensus/metrics/TimeSeriesCumulative.java b/api/src/main/java/io/opencensus/metrics/TimeSeriesCumulative.java new file mode 100644 index 00000000..5f48b770 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/TimeSeriesCumulative.java @@ -0,0 +1,70 @@ +/* + * Copyright 2018, 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.metrics; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.common.Timestamp; +import io.opencensus.internal.Utils; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.annotation.concurrent.Immutable; + +/** + * A collection of data points that describes the time-varying values of a cumulative {@code + * Metric}. + * + * @since 0.16 + */ +@ExperimentalApi +@Immutable +@AutoValue +public abstract class TimeSeriesCumulative extends TimeSeries { + + TimeSeriesCumulative() {} + + /** + * Creates a {@link TimeSeriesCumulative}. + * + * @param labelValues the {@code LabelValue}s that uniquely identify this {@code TimeSeries}. + * @param points the data {@code Point}s of this {@code TimeSeries}. + * @param startTimestamp the start {@code Timestamp} of this {@code TimeSeriesCumulative}. + * @return a {@code TimeSeriesCumulative}. + * @since 0.16 + */ + public static TimeSeriesCumulative create( + List labelValues, List points, Timestamp startTimestamp) { + // Fail fast on null lists to prevent NullPointerException when copying the lists. + Utils.checkNotNull(labelValues, "labelValues"); + Utils.checkNotNull(points, "points"); + Utils.checkListElementNotNull(labelValues, "labelValue"); + Utils.checkListElementNotNull(points, "point"); + return new AutoValue_TimeSeriesCumulative( + Collections.unmodifiableList(new ArrayList(labelValues)), + Collections.unmodifiableList(new ArrayList(points)), + startTimestamp); + } + + /** + * Returns the start {@link Timestamp} of this {@link TimeSeriesCumulative}. + * + * @return the start {@code Timestamp}. + * @since 0.16 + */ + public abstract Timestamp getStartTimestamp(); +} diff --git a/api/src/main/java/io/opencensus/metrics/TimeSeriesGauge.java b/api/src/main/java/io/opencensus/metrics/TimeSeriesGauge.java new file mode 100644 index 00000000..717505a4 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/TimeSeriesGauge.java @@ -0,0 +1,57 @@ +/* + * Copyright 2018, 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.metrics; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.internal.Utils; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.annotation.concurrent.Immutable; + +/** + * A collection of data points that describes the time-varying values of a gauge {@code Metric}. + * + * @since 0.16 + */ +@ExperimentalApi +@Immutable +@AutoValue +public abstract class TimeSeriesGauge extends TimeSeries { + + TimeSeriesGauge() {} + + /** + * Creates a {@link TimeSeriesGauge}. + * + * @param labelValues the {@code LabelValue}s that uniquely identify this {@code TimeSeries}. + * @param points the data {@code Point}s of this {@code TimeSeries}. + * @return a {@code TimeSeriesGauge}. + * @since 0.16 + */ + public static TimeSeriesGauge create(List labelValues, List points) { + // Fail fast on null lists to prevent NullPointerException when copying the lists. + Utils.checkNotNull(labelValues, "labelValues"); + Utils.checkNotNull(points, "points"); + Utils.checkListElementNotNull(labelValues, "labelValue"); + Utils.checkListElementNotNull(points, "point"); + return new AutoValue_TimeSeriesGauge( + Collections.unmodifiableList(new ArrayList(labelValues)), + Collections.unmodifiableList(new ArrayList(points))); + } +} diff --git a/api/src/main/java/io/opencensus/metrics/TimeSeriesList.java b/api/src/main/java/io/opencensus/metrics/TimeSeriesList.java new file mode 100644 index 00000000..6138eac2 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/TimeSeriesList.java @@ -0,0 +1,134 @@ +/* + * Copyright 2018, 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.metrics; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.common.Function; +import io.opencensus.internal.Utils; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.annotation.concurrent.Immutable; + +/** + * Class that holds a list of either {@link TimeSeriesGauge} or {@link TimeSeriesCumulative}. + * + * @since 0.16 + */ +@ExperimentalApi +@Immutable +public abstract class TimeSeriesList { + + TimeSeriesList() {} + + /** + * Applies the given match function to the underlying data type. + * + * @since 0.16 + */ + public abstract T match( + Function gaugeListFunction, + Function cumulativeListFunction, + Function defaultFunction); + + /** + * Class that holds a list of {@link TimeSeriesGauge}. + * + * @since 0.16 + */ + @ExperimentalApi + @Immutable + @AutoValue + public abstract static class TimeSeriesGaugeList extends TimeSeriesList { + + TimeSeriesGaugeList() {} + + @Override + public final T match( + Function gaugeListFunction, + Function cumulativeListFunction, + Function defaultFunction) { + return gaugeListFunction.apply(this); + } + + /** + * Creates a {@link TimeSeriesGaugeList}. + * + * @param list a list of {@link TimeSeriesGauge}. + * @return a {code TimeSeriesGaugeList}. + * @since 0.16 + */ + public static TimeSeriesGaugeList create(List list) { + Utils.checkNotNull(list, "list"); + Utils.checkListElementNotNull(list, "timeSeriesGauge"); + return new AutoValue_TimeSeriesList_TimeSeriesGaugeList( + Collections.unmodifiableList(new ArrayList(list))); + } + + /** + * Returns the list of {@link TimeSeriesGauge}. + * + * @return the list of {@code TimeSeriesGauge}. + * @since 0.16 + */ + public abstract List getList(); + } + + /** + * Class that holds a list of {@link TimeSeriesCumulative}. + * + * @since 0.16 + */ + @ExperimentalApi + @Immutable + @AutoValue + public abstract static class TimeSeriesCumulativeList extends TimeSeriesList { + + TimeSeriesCumulativeList() {} + + @Override + public final T match( + Function gaugeListFunction, + Function cumulativeListFunction, + Function defaultFunction) { + return cumulativeListFunction.apply(this); + } + + /** + * Creates a {@link TimeSeriesCumulativeList}. + * + * @param list a list of {@link TimeSeriesCumulative}. + * @return a {code TimeSeriesCumulativeList}. + * @since 0.16 + */ + public static TimeSeriesCumulativeList create(List list) { + Utils.checkNotNull(list, "list"); + Utils.checkListElementNotNull(list, "timeSeriesCumulative"); + return new AutoValue_TimeSeriesList_TimeSeriesCumulativeList( + Collections.unmodifiableList(new ArrayList(list))); + } + + /** + * Returns the list of {@link TimeSeriesCumulative}. + * + * @return the list of {@code TimeSeriesCumulative}. + * @since 0.16 + */ + public abstract List getList(); + } +} diff --git a/api/src/main/java/io/opencensus/metrics/Value.java b/api/src/main/java/io/opencensus/metrics/Value.java new file mode 100644 index 00000000..c8fe48f8 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/Value.java @@ -0,0 +1,196 @@ +/* + * Copyright 2018, 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.metrics; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.common.Function; +import javax.annotation.concurrent.Immutable; + +/** + * The actual point value for a {@link Point}. + * + *

    Currently there are three types of {@link Value}: + * + *

      + *
    • {@code double} + *
    • {@code long} + *
    • {@link Distribution} + *
    + * + *

    Each {@link Point} contains exactly one of the three {@link Value} types. + * + * @since 0.16 + */ +@ExperimentalApi +@Immutable +public abstract class Value { + + Value() {} + + /** + * Returns a double {@link Value}. + * + * @param value value in double. + * @return a double {@code Value}. + * @since 0.16 + */ + public static Value doubleValue(double value) { + return ValueDouble.create(value); + } + + /** + * Returns a long {@link Value}. + * + * @param value value in long. + * @return a long {@code Value}. + * @since 0.16 + */ + public static Value longValue(long value) { + return ValueLong.create(value); + } + + /** + * Returns a {@link Distribution} {@link Value}. + * + * @param value value in {@link Distribution}. + * @return a {@code Distribution} {@code Value}. + * @since 0.16 + */ + public static Value distributionValue(Distribution value) { + return ValueDistribution.create(value); + } + + /** + * Applies the given match function to the underlying data type. + * + * @since 0.16 + */ + public abstract T match( + Function doubleFunction, + Function longFunction, + Function distributionFunction, + Function defaultFunction); + + /** A 64-bit double-precision floating-point {@link Value}. */ + @AutoValue + @Immutable + abstract static class ValueDouble extends Value { + + ValueDouble() {} + + @Override + public final T match( + Function doubleFunction, + Function longFunction, + Function distributionFunction, + Function defaultFunction) { + return doubleFunction.apply(getValue()); + } + + /** + * Creates a {@link ValueDouble}. + * + * @param value the value in double. + * @return a {@code ValueDouble}. + */ + static ValueDouble create(double value) { + return new AutoValue_Value_ValueDouble(value); + } + + /** + * Returns the double value. + * + * @return the double value. + */ + abstract double getValue(); + } + + /** A 64-bit integer {@link Value}. */ + @AutoValue + @Immutable + abstract static class ValueLong extends Value { + + ValueLong() {} + + @Override + public final T match( + Function doubleFunction, + Function longFunction, + Function distributionFunction, + Function defaultFunction) { + return longFunction.apply(getValue()); + } + + /** + * Creates a {@link ValueLong}. + * + * @param value the value in long. + * @return a {@code ValueLong}. + */ + static ValueLong create(long value) { + return new AutoValue_Value_ValueLong(value); + } + + /** + * Returns the long value. + * + * @return the long value. + */ + abstract long getValue(); + } + + /** + * {@link ValueDistribution} contains summary statistics for a population of values. It optionally + * contains a histogram representing the distribution of those values across a set of buckets. + */ + @AutoValue + @Immutable + abstract static class ValueDistribution extends Value { + + ValueDistribution() {} + + @Override + public final T match( + Function doubleFunction, + Function longFunction, + Function distributionFunction, + Function defaultFunction) { + return distributionFunction.apply(getValue()); + } + + /** + * Creates a {@link ValueDistribution}. + * + * @param value the {@link Distribution} value. + * @return a {@code ValueDistribution}. + */ + static ValueDistribution create(Distribution value) { + return new AutoValue_Value_ValueDistribution(value); + } + + /** + * Returns the {@link Distribution} value. + * + * @return the {@code Distribution} value. + */ + abstract Distribution getValue(); + } + + // TODO(songya): Add support for Summary type. + // This is an aggregation that produces percentiles directly. +} diff --git a/api/src/main/java/io/opencensus/metrics/export/ExportComponent.java b/api/src/main/java/io/opencensus/metrics/export/ExportComponent.java new file mode 100644 index 00000000..f1511543 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/export/ExportComponent.java @@ -0,0 +1,60 @@ +/* + * Copyright 2018, 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.metrics.export; + +import io.opencensus.common.ExperimentalApi; + +/** + * Class that holds the implementation instance for {@link MetricProducerManager}. + * + *

    Unless otherwise noted all methods (on component) results are cacheable. + * + * @since 0.16 + */ +@ExperimentalApi +public abstract class ExportComponent { + /** + * Returns the no-op implementation of the {@code ExportComponent}. + * + * @return the no-op implementation of the {@code ExportComponent}. + * @since 0.16 + */ + public static ExportComponent newNoopExportComponent() { + return new NoopExportComponent(); + } + + /** + * Returns the global {@link MetricProducerManager} which can be used to register handlers to + * export all the recorded metrics. + * + * @return the implementation of the {@code MetricExporter} or no-op if no implementation linked + * in the binary. + * @since 0.16 + */ + public abstract MetricProducerManager getMetricProducerManager(); + + private static final class NoopExportComponent extends ExportComponent { + + private static final MetricProducerManager METRIC_PRODUCER_MANAGER = + new MetricProducerManager(); + + @Override + public MetricProducerManager getMetricProducerManager() { + return METRIC_PRODUCER_MANAGER; + } + } +} diff --git a/api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java b/api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java new file mode 100644 index 00000000..9600a023 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java @@ -0,0 +1,89 @@ +/* + * Copyright 2018, 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.metrics.export; + +import io.opencensus.common.ExperimentalApi; +import io.opencensus.internal.Utils; +import io.opencensus.metrics.MetricProducer; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; +import javax.annotation.concurrent.ThreadSafe; + +/** + * Keeps a set of {@link MetricProducer} that is used by exporters to determine the metrics that + * need to be exported. + * + * @since 0.16 + */ +@ExperimentalApi +@ThreadSafe +public final class MetricProducerManager { + private volatile Set metricProducers = + Collections.unmodifiableSet(new LinkedHashSet()); + + /** + * Adds the {@link MetricProducer} to the manager if it is not already present. + * + * @param metricProducer the {@code MetricProducer} to be added to the manager. + * @since 0.16 + */ + public synchronized void add(MetricProducer metricProducer) { + Utils.checkNotNull(metricProducer, "metricProducer"); + // Updating the set of MetricProducers happens under a lock to avoid multiple add or remove + // operations to happen in the same time. + Set newMetricProducers = new LinkedHashSet(metricProducers); + if (!newMetricProducers.add(metricProducer)) { + // The element already present, no need to update the current set of MetricProducers. + return; + } + metricProducers = Collections.unmodifiableSet(newMetricProducers); + } + + /** + * Removes the {@link MetricProducer} to the manager if it is present. + * + * @param metricProducer the {@code MetricProducer} to be removed from the manager. + */ + public synchronized void remove(MetricProducer metricProducer) { + Utils.checkNotNull(metricProducer, "metricProducer"); + // Updating the set of MetricProducers happens under a lock to avoid multiple add or remove + // operations to happen in the same time. + Set newMetricProducers = new LinkedHashSet(metricProducers); + if (!newMetricProducers.remove(metricProducer)) { + // The element not present, no need to update the current set of MetricProducers. + return; + } + metricProducers = Collections.unmodifiableSet(newMetricProducers); + } + + /** + * Returns all registered {@link MetricProducer}s that should be exported. + * + *

    This method should be used by any metrics exporter that automatically exports data for + * {@code MetricProducer} registered with the {@code MetricProducerManager}. + * + * @return all registered {@code MetricProducer}s that should be exported. + */ + public Set getAllMetricProducer() { + return metricProducers; + } + + // Package protected to allow us to possibly change this to an abstract class in the future. This + // ensures that nobody can create an instance of this class except ExportComponent. + MetricProducerManager() {} +} diff --git a/api/src/main/java/io/opencensus/metrics/package-info.java b/api/src/main/java/io/opencensus/metrics/package-info.java new file mode 100644 index 00000000..33eadf0c --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/package-info.java @@ -0,0 +1,32 @@ +/* + * Copyright 2018, 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. + */ + +/** + * This package describes the Metrics data model. Metrics are a data model for what stats exporters + * take as input. This data model may eventually become the wire format for metrics. + * + *

    WARNING: Currently all the public classes under this package are marked as {@link + * io.opencensus.common.ExperimentalApi}. The classes and APIs under {@link io.opencensus.metrics} + * are likely to get backwards-incompatible updates in the future. DO NOT USE except for + * experimental purposes. + * + *

    Please see + * https://github.com/census-instrumentation/opencensus-specs/blob/master/stats/Metrics.md and + * https://github.com/census-instrumentation/opencensus-proto/blob/master/opencensus/proto/stats/metrics/metrics.proto + * for more details. + */ +@io.opencensus.common.ExperimentalApi +package io.opencensus.metrics; diff --git a/api/src/test/java/io/opencensus/metrics/DistributionTest.java b/api/src/test/java/io/opencensus/metrics/DistributionTest.java new file mode 100644 index 00000000..d511e317 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/DistributionTest.java @@ -0,0 +1,226 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Timestamp; +import io.opencensus.metrics.Distribution.Bucket; +import io.opencensus.metrics.Distribution.Exemplar; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Value}. */ +@RunWith(JUnit4.class) +public class DistributionTest { + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + private static final Timestamp TIMESTAMP = Timestamp.create(1, 0); + private static final Map ATTACHMENTS = Collections.singletonMap("key", "value"); + + @Test + public void createAndGet_Bucket() { + Bucket bucket = Bucket.create(98); + assertThat(bucket.getCount()).isEqualTo(98); + assertThat(bucket.getExemplar()).isNull(); + } + + @Test + public void createAndGet_BucketWithExemplar() { + Exemplar exemplar = Exemplar.create(12.2, TIMESTAMP, ATTACHMENTS); + Bucket bucket = Bucket.create(7, exemplar); + assertThat(bucket.getCount()).isEqualTo(7); + assertThat(bucket.getExemplar()).isEqualTo(exemplar); + } + + @Test + public void createBucket_preventNullExemplar() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("exemplar"); + Bucket.create(1, null); + } + + @Test + public void createAndGet_Exemplar() { + Exemplar exemplar = Exemplar.create(-9.9, TIMESTAMP, ATTACHMENTS); + assertThat(exemplar.getValue()).isEqualTo(-9.9); + assertThat(exemplar.getTimestamp()).isEqualTo(TIMESTAMP); + assertThat(exemplar.getAttachments()).isEqualTo(ATTACHMENTS); + } + + @Test + public void createAndGet_Distribution() { + Exemplar exemplar = Exemplar.create(15.0, TIMESTAMP, ATTACHMENTS); + List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List buckets = + Arrays.asList( + Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4, exemplar)); + Distribution distribution = Distribution.create(6.6, 10, 678.54, bucketBounds, buckets); + assertThat(distribution.getMean()).isEqualTo(6.6); + assertThat(distribution.getCount()).isEqualTo(10); + assertThat(distribution.getSumOfSquaredDeviations()).isEqualTo(678.54); + assertThat(distribution.getBucketBoundaries()) + .containsExactlyElementsIn(bucketBounds) + .inOrder(); + assertThat(distribution.getBuckets()).containsExactlyElementsIn(buckets).inOrder(); + } + + @Test + public void createBucket_NegativeCount() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("bucket count should be non-negative."); + Bucket.create(-5); + } + + @Test + public void createExemplar_PreventNullAttachments() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("attachments"); + Exemplar.create(15, TIMESTAMP, null); + } + + @Test + public void createExemplar_PreventNullAttachmentKey() { + Map attachments = Collections.singletonMap(null, "value"); + thrown.expect(NullPointerException.class); + thrown.expectMessage("key of attachment"); + Exemplar.create(15, TIMESTAMP, attachments); + } + + @Test + public void createExemplar_PreventNullAttachmentValue() { + Map attachments = Collections.singletonMap("key", null); + thrown.expect(NullPointerException.class); + thrown.expectMessage("value of attachment"); + Exemplar.create(15, TIMESTAMP, attachments); + } + + @Test + public void createDistribution_NegativeCount() { + List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List buckets = + Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("count should be non-negative."); + Distribution.create(6.6, -10, 678.54, bucketBounds, buckets); + } + + @Test + public void createDistribution_NegativeSumOfSquaredDeviations() { + List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List buckets = + Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0)); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("sum of squared deviations should be non-negative."); + Distribution.create(6.6, 0, -678.54, bucketBounds, buckets); + } + + @Test + public void createDistribution_ZeroCountAndPositiveMean() { + List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List buckets = + Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0)); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("mean should be 0 if count is 0."); + Distribution.create(6.6, 0, 0, bucketBounds, buckets); + } + + @Test + public void createDistribution_ZeroCountAndSumOfSquaredDeviations() { + List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List buckets = + Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0)); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("sum of squared deviations should be 0 if count is 0."); + Distribution.create(0, 0, 678.54, bucketBounds, buckets); + } + + @Test + public void createDistribution_NullBucketBounds() { + List buckets = + Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); + thrown.expect(NullPointerException.class); + thrown.expectMessage("bucketBoundaries list should not be null."); + Distribution.create(6.6, 10, 678.54, null, buckets); + } + + @Test + public void createDistribution_UnorderedBucketBounds() { + List bucketBounds = Arrays.asList(0.0, -1.0, 1.0); + List buckets = + Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("bucket boundaries not sorted."); + Distribution.create(6.6, 10, 678.54, bucketBounds, buckets); + } + + @Test + public void createDistribution_NullBucketList() { + List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + thrown.expect(NullPointerException.class); + thrown.expectMessage("bucket list should not be null."); + Distribution.create(6.6, 10, 678.54, bucketBounds, null); + } + + @Test + public void createDistribution_NullBucket() { + List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List buckets = + Arrays.asList(Bucket.create(3), Bucket.create(1), null, Bucket.create(4)); + thrown.expect(NullPointerException.class); + thrown.expectMessage("bucket should not be null."); + Distribution.create(6.6, 10, 678.54, bucketBounds, buckets); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + Distribution.create( + 10, + 10, + 1, + Arrays.asList(-5.0, 0.0, 5.0), + Arrays.asList( + Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))), + Distribution.create( + 10, + 10, + 1, + Arrays.asList(-5.0, 0.0, 5.0), + Arrays.asList( + Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)))) + .addEqualityGroup( + Distribution.create( + -7, + 10, + 23.456, + Arrays.asList(-5.0, 0.0, 5.0), + Arrays.asList( + Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)))) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/LabelKeyTest.java b/api/src/test/java/io/opencensus/metrics/LabelKeyTest.java new file mode 100644 index 00000000..83f2b59a --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/LabelKeyTest.java @@ -0,0 +1,86 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import java.util.Arrays; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link LabelKey}. */ +@RunWith(JUnit4.class) +public class LabelKeyTest { + + private static final LabelKey KEY = LabelKey.create("key", "description"); + + @Test + public void testGetKey() { + assertThat(KEY.getKey()).isEqualTo("key"); + } + + @Test + public void testGetDescription() { + assertThat(KEY.getDescription()).isEqualTo("description"); + } + + @Test + public void create_NoLengthConstraint() { + // We have a length constraint of 256-characters for TagKey. That constraint doesn't apply to + // LabelKey. + char[] chars = new char[300]; + Arrays.fill(chars, 'k'); + String key = new String(chars); + assertThat(LabelKey.create(key, "").getKey()).isEqualTo(key); + } + + @Test + public void create_WithUnprintableChars() { + String key = "\2ab\3cd"; + String description = "\4ef\5gh"; + LabelKey labelKey = LabelKey.create(key, description); + assertThat(labelKey.getKey()).isEqualTo(key); + assertThat(labelKey.getDescription()).isEqualTo(description); + } + + @Test + public void create_WithNonAsciiChars() { + String key = "键"; + String description = "测试用键"; + LabelKey nonAsciiKey = LabelKey.create(key, description); + assertThat(nonAsciiKey.getKey()).isEqualTo(key); + assertThat(nonAsciiKey.getDescription()).isEqualTo(description); + } + + @Test + public void create_Empty() { + LabelKey emptyKey = LabelKey.create("", ""); + assertThat(emptyKey.getKey()).isEmpty(); + assertThat(emptyKey.getDescription()).isEmpty(); + } + + @Test + public void testLabelKeyEquals() { + new EqualsTester() + .addEqualityGroup(LabelKey.create("foo", ""), LabelKey.create("foo", "")) + .addEqualityGroup(LabelKey.create("foo", "description")) + .addEqualityGroup(LabelKey.create("bar", "")) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/LabelValueTest.java b/api/src/test/java/io/opencensus/metrics/LabelValueTest.java new file mode 100644 index 00000000..e5526b2f --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/LabelValueTest.java @@ -0,0 +1,74 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import java.util.Arrays; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link LabelValue}. */ +@RunWith(JUnit4.class) +public class LabelValueTest { + + private static final LabelValue VALUE = LabelValue.create("value"); + private static final LabelValue UNSET = LabelValue.create(null); + private static final LabelValue EMPTY = LabelValue.create(""); + + @Test + public void testGetValue() { + assertThat(VALUE.getValue()).isEqualTo("value"); + assertThat(UNSET.getValue()).isNull(); + assertThat(EMPTY.getValue()).isEmpty(); + } + + @Test + public void create_NoLengthConstraint() { + // We have a length constraint of 256-characters for TagValue. That constraint doesn't apply to + // LabelValue. + char[] chars = new char[300]; + Arrays.fill(chars, 'v'); + String value = new String(chars); + assertThat(LabelValue.create(value).getValue()).isEqualTo(value); + } + + @Test + public void create_WithUnprintableChars() { + String value = "\2ab\3cd"; + assertThat(LabelValue.create(value).getValue()).isEqualTo(value); + } + + @Test + public void create_WithNonAsciiChars() { + String value = "值"; + LabelValue nonAsciiValue = LabelValue.create(value); + assertThat(nonAsciiValue.getValue()).isEqualTo(value); + } + + @Test + public void testLabelValueEquals() { + new EqualsTester() + .addEqualityGroup(LabelValue.create("foo"), LabelValue.create("foo")) + .addEqualityGroup(UNSET) + .addEqualityGroup(EMPTY) + .addEqualityGroup(LabelValue.create("bar")) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/MetricDescriptorTest.java b/api/src/test/java/io/opencensus/metrics/MetricDescriptorTest.java new file mode 100644 index 00000000..9c0a42fc --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/MetricDescriptorTest.java @@ -0,0 +1,102 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.metrics.MetricDescriptor.Type; +import java.util.Arrays; +import java.util.List; +import org.hamcrest.CoreMatchers; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link MetricDescriptor}. */ +@RunWith(JUnit4.class) +public class MetricDescriptorTest { + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + private static final String METRIC_NAME_1 = "metric1"; + private static final String METRIC_NAME_2 = "metric2"; + private static final String DESCRIPTION = "Metric description."; + private static final String UNIT = "kb/s"; + private static final LabelKey KEY_1 = LabelKey.create("key1", "some key"); + private static final LabelKey KEY_2 = LabelKey.create("key2", "some other key"); + + @Test + public void testGet() { + MetricDescriptor metricDescriptor = + MetricDescriptor.create( + METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2)); + assertThat(metricDescriptor.getName()).isEqualTo(METRIC_NAME_1); + assertThat(metricDescriptor.getDescription()).isEqualTo(DESCRIPTION); + assertThat(metricDescriptor.getUnit()).isEqualTo(UNIT); + assertThat(metricDescriptor.getType()).isEqualTo(Type.GAUGE_DOUBLE); + assertThat(metricDescriptor.getLabelKeys()).containsExactly(KEY_1, KEY_2).inOrder(); + } + + @Test + public void preventNullLabelKeyList() { + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("labelKeys")); + MetricDescriptor.create(METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, null); + } + + @Test + public void preventNullLabelKey() { + List keys = Arrays.asList(KEY_1, null); + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("labelKey")); + MetricDescriptor.create(METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, keys); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + MetricDescriptor.create( + METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2)), + MetricDescriptor.create( + METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2))) + .addEqualityGroup( + MetricDescriptor.create( + METRIC_NAME_2, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2))) + .addEqualityGroup( + MetricDescriptor.create( + METRIC_NAME_2, DESCRIPTION, UNIT, Type.GAUGE_INT64, Arrays.asList(KEY_1, KEY_2))) + .addEqualityGroup( + MetricDescriptor.create( + METRIC_NAME_1, + DESCRIPTION, + UNIT, + Type.CUMULATIVE_DISTRIBUTION, + Arrays.asList(KEY_1, KEY_2))) + .addEqualityGroup( + MetricDescriptor.create( + METRIC_NAME_1, + DESCRIPTION, + UNIT, + Type.CUMULATIVE_DISTRIBUTION, + Arrays.asList(KEY_1))) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java b/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java new file mode 100644 index 00000000..0e467dc8 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java @@ -0,0 +1,181 @@ +/* + * Copyright 2018, 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.metrics; + +import io.opencensus.common.ToDoubleFunction; +import io.opencensus.common.ToLongFunction; +import java.util.LinkedHashMap; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +public class MetricRegistryTest { + @Rule public ExpectedException thrown = ExpectedException.none(); + + private final MetricRegistry metricRegistry = + MetricsComponent.newNoopMetricsComponent().getMetricRegistry(); + + @Test + public void addDoubleGauge_NullName() { + thrown.expect(NullPointerException.class); + metricRegistry.addDoubleGauge( + null, + "description", + "1", + new LinkedHashMap(), + null, + new ToDoubleFunction() { + @Override + public double applyAsDouble(Object value) { + return 5.0; + } + }); + } + + @Test + public void addDoubleGauge_NullDescription() { + thrown.expect(NullPointerException.class); + metricRegistry.addDoubleGauge( + "name", + null, + "1", + new LinkedHashMap(), + null, + new ToDoubleFunction() { + @Override + public double applyAsDouble(Object value) { + return 5.0; + } + }); + } + + @Test + public void addDoubleGauge_NullUnit() { + thrown.expect(NullPointerException.class); + metricRegistry.addDoubleGauge( + "name", + "description", + null, + new LinkedHashMap(), + null, + new ToDoubleFunction() { + @Override + public double applyAsDouble(Object value) { + return 5.0; + } + }); + } + + @Test + public void addDoubleGauge_NullLabels() { + thrown.expect(NullPointerException.class); + metricRegistry.addDoubleGauge( + "name", + "description", + "1", + null, + null, + new ToDoubleFunction() { + @Override + public double applyAsDouble(Object value) { + return 5.0; + } + }); + } + + @Test + public void addDoubleGauge_NullFunction() { + thrown.expect(NullPointerException.class); + metricRegistry.addDoubleGauge( + "name", "description", "1", new LinkedHashMap(), null, null); + } + + @Test + public void addLongGauge_NullName() { + thrown.expect(NullPointerException.class); + metricRegistry.addLongGauge( + null, + "description", + "1", + new LinkedHashMap(), + null, + new ToLongFunction() { + @Override + public long applyAsLong(Object value) { + return 5; + } + }); + } + + @Test + public void addLongGauge_NullDescription() { + thrown.expect(NullPointerException.class); + metricRegistry.addLongGauge( + "name", + null, + "1", + new LinkedHashMap(), + null, + new ToLongFunction() { + @Override + public long applyAsLong(Object value) { + return 5; + } + }); + } + + @Test + public void addLongGauge_NullUnit() { + thrown.expect(NullPointerException.class); + metricRegistry.addLongGauge( + "name", + "description", + null, + new LinkedHashMap(), + null, + new ToLongFunction() { + @Override + public long applyAsLong(Object value) { + return 5; + } + }); + } + + @Test + public void addLongGauge_NullLabels() { + thrown.expect(NullPointerException.class); + metricRegistry.addLongGauge( + "name", + "description", + "1", + null, + null, + new ToLongFunction() { + @Override + public long applyAsLong(Object value) { + return 5; + } + }); + } + + @Test + public void addLongGauge_NullFunction() { + thrown.expect(NullPointerException.class); + metricRegistry.addLongGauge( + "name", "description", "1", new LinkedHashMap(), null, null); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/MetricTest.java b/api/src/test/java/io/opencensus/metrics/MetricTest.java new file mode 100644 index 00000000..59838ef4 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/MetricTest.java @@ -0,0 +1,127 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Timestamp; +import io.opencensus.metrics.MetricDescriptor.Type; +import io.opencensus.metrics.TimeSeriesList.TimeSeriesCumulativeList; +import io.opencensus.metrics.TimeSeriesList.TimeSeriesGaugeList; +import java.util.Arrays; +import java.util.Collections; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Metric}. */ +@RunWith(JUnit4.class) +public class MetricTest { + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + private static final String METRIC_NAME_1 = "metric1"; + private static final String METRIC_NAME_2 = "metric2"; + private static final String DESCRIPTION = "Metric description."; + private static final String UNIT = "kb/s"; + private static final LabelKey KEY_1 = LabelKey.create("key1", "some key"); + private static final LabelKey KEY_2 = LabelKey.create("key1", "some other key"); + private static final MetricDescriptor METRIC_DESCRIPTOR_1 = + MetricDescriptor.create( + METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2)); + private static final MetricDescriptor METRIC_DESCRIPTOR_2 = + MetricDescriptor.create( + METRIC_NAME_2, DESCRIPTION, UNIT, Type.CUMULATIVE_INT64, Arrays.asList(KEY_1)); + private static final LabelValue LABEL_VALUE_1 = LabelValue.create("value1"); + private static final LabelValue LABEL_VALUE_2 = LabelValue.create("value1"); + private static final LabelValue LABEL_VALUE_EMPTY = LabelValue.create(""); + private static final Value VALUE_LONG = Value.longValue(12345678); + private static final Value VALUE_DOUBLE_1 = Value.doubleValue(-345.77); + private static final Value VALUE_DOUBLE_2 = Value.doubleValue(133.79); + private static final Timestamp TIMESTAMP_1 = Timestamp.fromMillis(1000); + private static final Timestamp TIMESTAMP_2 = Timestamp.fromMillis(2000); + private static final Timestamp TIMESTAMP_3 = Timestamp.fromMillis(3000); + private static final Point POINT_1 = Point.create(VALUE_DOUBLE_1, TIMESTAMP_2); + private static final Point POINT_2 = Point.create(VALUE_DOUBLE_2, TIMESTAMP_3); + private static final Point POINT_3 = Point.create(VALUE_LONG, TIMESTAMP_3); + private static final TimeSeriesGauge GAUGE_TIME_SERIES_1 = + TimeSeriesGauge.create(Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1)); + private static final TimeSeriesGauge GAUGE_TIME_SERIES_2 = + TimeSeriesGauge.create(Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_2)); + private static final TimeSeriesCumulative CUMULATIVE_TIME_SERIES = + TimeSeriesCumulative.create( + Arrays.asList(LABEL_VALUE_EMPTY), Arrays.asList(POINT_3), TIMESTAMP_1); + private static final TimeSeriesGaugeList TIME_SERIES_GAUGE_LIST = + TimeSeriesGaugeList.create(Arrays.asList(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2)); + private static final TimeSeriesCumulativeList TIME_SERIES_CUMULATIVE_LIST = + TimeSeriesCumulativeList.create(Arrays.asList(CUMULATIVE_TIME_SERIES)); + + @Test + public void testGet() { + Metric metric = Metric.create(METRIC_DESCRIPTOR_1, TIME_SERIES_GAUGE_LIST); + assertThat(metric.getMetricDescriptor()).isEqualTo(METRIC_DESCRIPTOR_1); + assertThat(metric.getTimeSeriesList()).isEqualTo(TIME_SERIES_GAUGE_LIST); + } + + @Test + public void typeMismatch_GaugeDouble_TimeSeriesCumulative() { + typeMismatch( + METRIC_DESCRIPTOR_1, + TIME_SERIES_CUMULATIVE_LIST, + String.format( + "Type mismatch: %s, %s.", + Type.GAUGE_DOUBLE, TIME_SERIES_CUMULATIVE_LIST.getClass().getSimpleName())); + } + + @Test + public void typeMismatch_CumulativeInt64_TimeSeriesGauge() { + typeMismatch( + METRIC_DESCRIPTOR_2, + TIME_SERIES_GAUGE_LIST, + String.format( + "Type mismatch: %s, %s.", + Type.CUMULATIVE_INT64, TIME_SERIES_GAUGE_LIST.getClass().getSimpleName())); + } + + private void typeMismatch( + MetricDescriptor metricDescriptor, TimeSeriesList timeSeriesList, String errorMessage) { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage(errorMessage); + Metric.create(metricDescriptor, timeSeriesList); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + Metric.create(METRIC_DESCRIPTOR_1, TIME_SERIES_GAUGE_LIST), + Metric.create(METRIC_DESCRIPTOR_1, TIME_SERIES_GAUGE_LIST)) + .addEqualityGroup( + Metric.create( + METRIC_DESCRIPTOR_1, + TimeSeriesGaugeList.create(Collections.emptyList()))) + .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_2, TIME_SERIES_CUMULATIVE_LIST)) + .addEqualityGroup( + Metric.create( + METRIC_DESCRIPTOR_2, + TimeSeriesCumulativeList.create(Collections.emptyList()))) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/MetricsComponentTest.java b/api/src/test/java/io/opencensus/metrics/MetricsComponentTest.java new file mode 100644 index 00000000..1c4e70f7 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/MetricsComponentTest.java @@ -0,0 +1,40 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.metrics.export.ExportComponent; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link MetricsComponent}. */ +@RunWith(JUnit4.class) +public class MetricsComponentTest { + @Test + public void defaultExportComponent() { + assertThat(MetricsComponent.newNoopMetricsComponent().getExportComponent()) + .isInstanceOf(ExportComponent.newNoopExportComponent().getClass()); + } + + @Test + public void defaultMetricRegistry() { + assertThat(MetricsComponent.newNoopMetricsComponent().getMetricRegistry()) + .isInstanceOf(MetricRegistry.newNoopMetricRegistry().getClass()); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/MetricsTest.java b/api/src/test/java/io/opencensus/metrics/MetricsTest.java new file mode 100644 index 00000000..9a56f257 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/MetricsTest.java @@ -0,0 +1,65 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.metrics.export.ExportComponent; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Metrics}. */ +@RunWith(JUnit4.class) +public class MetricsTest { + @Rule public ExpectedException thrown = ExpectedException.none(); + + @Test + public void loadMetricsComponent_UsesProvidedClassLoader() { + final RuntimeException toThrow = new RuntimeException("UseClassLoader"); + thrown.expect(RuntimeException.class); + thrown.expectMessage("UseClassLoader"); + Metrics.loadMetricsComponent( + new ClassLoader() { + @Override + public Class loadClass(String name) { + throw toThrow; + } + }); + } + + @Test + public void loadMetricsComponent_IgnoresMissingClasses() { + ClassLoader classLoader = + new ClassLoader() { + @Override + public Class loadClass(String name) throws ClassNotFoundException { + throw new ClassNotFoundException(); + } + }; + assertThat(Metrics.loadMetricsComponent(classLoader).getClass().getName()) + .isEqualTo("io.opencensus.metrics.MetricsComponent$NoopMetricsComponent"); + } + + @Test + public void defaultExportComponent() { + assertThat(Metrics.getExportComponent()) + .isInstanceOf(ExportComponent.newNoopExportComponent().getClass()); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/PointTest.java b/api/src/test/java/io/opencensus/metrics/PointTest.java new file mode 100644 index 00000000..cb6175c1 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/PointTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Timestamp; +import io.opencensus.metrics.Distribution.Bucket; +import java.util.Arrays; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Point}. */ +@RunWith(JUnit4.class) +public class PointTest { + + private static final Value DOUBLE_VALUE = Value.doubleValue(55.5); + private static final Value LONG_VALUE = Value.longValue(9876543210L); + private static final Value DISTRIBUTION_VALUE = + Value.distributionValue( + Distribution.create( + 6.6, + 10, + 678.54, + Arrays.asList(-1.0, 0.0, 1.0), + Arrays.asList( + Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)))); + private static final Timestamp TIMESTAMP_1 = Timestamp.create(1, 2); + private static final Timestamp TIMESTAMP_2 = Timestamp.create(3, 4); + private static final Timestamp TIMESTAMP_3 = Timestamp.create(5, 6); + + @Test + public void testGet() { + Point point = Point.create(DOUBLE_VALUE, TIMESTAMP_1); + assertThat(point.getValue()).isEqualTo(DOUBLE_VALUE); + assertThat(point.getTimestamp()).isEqualTo(TIMESTAMP_1); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + Point.create(DOUBLE_VALUE, TIMESTAMP_1), Point.create(DOUBLE_VALUE, TIMESTAMP_1)) + .addEqualityGroup(Point.create(LONG_VALUE, TIMESTAMP_1)) + .addEqualityGroup(Point.create(LONG_VALUE, TIMESTAMP_2)) + .addEqualityGroup( + Point.create(DISTRIBUTION_VALUE, TIMESTAMP_2), + Point.create(DISTRIBUTION_VALUE, TIMESTAMP_2)) + .addEqualityGroup(Point.create(DISTRIBUTION_VALUE, TIMESTAMP_3)) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/TimeSeriesCumulativeTest.java b/api/src/test/java/io/opencensus/metrics/TimeSeriesCumulativeTest.java new file mode 100644 index 00000000..3532a5a5 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/TimeSeriesCumulativeTest.java @@ -0,0 +1,113 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Timestamp; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.hamcrest.CoreMatchers; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TimeSeriesCumulative}. */ +@RunWith(JUnit4.class) +public class TimeSeriesCumulativeTest { + + @Rule public ExpectedException thrown = ExpectedException.none(); + + private static final LabelValue LABEL_VALUE_1 = LabelValue.create("value1"); + private static final LabelValue LABEL_VALUE_2 = LabelValue.create("value2"); + private static final Value VALUE_LONG = Value.longValue(12345678); + private static final Value VALUE_DOUBLE = Value.doubleValue(-345.77); + private static final Timestamp TIMESTAMP_1 = Timestamp.fromMillis(1000); + private static final Timestamp TIMESTAMP_2 = Timestamp.fromMillis(2000); + private static final Timestamp TIMESTAMP_3 = Timestamp.fromMillis(3000); + private static final Point POINT_1 = Point.create(VALUE_DOUBLE, TIMESTAMP_2); + private static final Point POINT_2 = Point.create(VALUE_LONG, TIMESTAMP_3); + + @Test + public void testGet_TimeSeriesCumulative() { + TimeSeriesCumulative cumulativeTimeSeries = + TimeSeriesCumulative.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1); + assertThat(cumulativeTimeSeries.getStartTimestamp()).isEqualTo(TIMESTAMP_1); + assertThat(cumulativeTimeSeries.getLabelValues()) + .containsExactly(LABEL_VALUE_1, LABEL_VALUE_2) + .inOrder(); + assertThat(cumulativeTimeSeries.getPoints()).containsExactly(POINT_1).inOrder(); + } + + @Test + public void create_WithNullLabelValueList() { + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("labelValues")); + TimeSeriesCumulative.create(null, Collections.emptyList(), TIMESTAMP_1); + } + + @Test + public void create_WithNullLabelValue() { + List labelValues = Arrays.asList(LABEL_VALUE_1, null); + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("labelValue")); + TimeSeriesCumulative.create(labelValues, Collections.emptyList(), TIMESTAMP_1); + } + + @Test + public void create_WithNullPointList() { + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("points")); + TimeSeriesCumulative.create(Collections.emptyList(), null, TIMESTAMP_1); + } + + @Test + public void create_WithNullPoint() { + List points = Arrays.asList(POINT_1, null); + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("point")); + TimeSeriesCumulative.create(Collections.emptyList(), points, TIMESTAMP_1); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + TimeSeriesCumulative.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1), + TimeSeriesCumulative.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1)) + .addEqualityGroup( + TimeSeriesCumulative.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_2)) + .addEqualityGroup( + TimeSeriesCumulative.create( + Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_1), TIMESTAMP_2)) + .addEqualityGroup( + TimeSeriesCumulative.create( + Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_2), TIMESTAMP_2)) + .addEqualityGroup( + TimeSeriesCumulative.create( + Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_1, POINT_2), TIMESTAMP_2)) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/TimeSeriesGaugeTest.java b/api/src/test/java/io/opencensus/metrics/TimeSeriesGaugeTest.java new file mode 100644 index 00000000..83f7c267 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/TimeSeriesGaugeTest.java @@ -0,0 +1,104 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Timestamp; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.hamcrest.CoreMatchers; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TimeSeriesGauge}. */ +@RunWith(JUnit4.class) +public class TimeSeriesGaugeTest { + + @Rule public ExpectedException thrown = ExpectedException.none(); + + private static final LabelValue LABEL_VALUE_1 = LabelValue.create("value1"); + private static final LabelValue LABEL_VALUE_2 = LabelValue.create("value2"); + private static final Value VALUE_LONG = Value.longValue(12345678); + private static final Value VALUE_DOUBLE = Value.doubleValue(-345.77); + private static final Timestamp TIMESTAMP_1 = Timestamp.fromMillis(1000); + private static final Timestamp TIMESTAMP_2 = Timestamp.fromMillis(2000); + private static final Point POINT_1 = Point.create(VALUE_DOUBLE, TIMESTAMP_1); + private static final Point POINT_2 = Point.create(VALUE_LONG, TIMESTAMP_2); + + @Test + public void testGet_TimeSeriesGauge() { + TimeSeriesGauge gaugeTimeSeries = + TimeSeriesGauge.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1, POINT_2)); + assertThat(gaugeTimeSeries.getLabelValues()) + .containsExactly(LABEL_VALUE_1, LABEL_VALUE_2) + .inOrder(); + assertThat(gaugeTimeSeries.getPoints()).containsExactly(POINT_1, POINT_2).inOrder(); + } + + @Test + public void create_WithNullLabelValueList() { + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("labelValues")); + TimeSeriesGauge.create(null, Collections.emptyList()); + } + + @Test + public void create_WithNullLabelValue() { + List labelValues = Arrays.asList(LABEL_VALUE_1, null); + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("labelValue")); + TimeSeriesGauge.create(labelValues, Collections.emptyList()); + } + + @Test + public void create_WithNullPointList() { + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("points")); + TimeSeriesGauge.create(Collections.emptyList(), null); + } + + @Test + public void create_WithNullPoint() { + List points = Arrays.asList(POINT_1, null); + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("point")); + TimeSeriesGauge.create(Collections.emptyList(), points); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + TimeSeriesGauge.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1, POINT_2)), + TimeSeriesGauge.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1, POINT_2))) + .addEqualityGroup( + TimeSeriesGauge.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1))) + .addEqualityGroup( + TimeSeriesGauge.create(Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_1))) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/TimeSeriesListTest.java b/api/src/test/java/io/opencensus/metrics/TimeSeriesListTest.java new file mode 100644 index 00000000..46ace50f --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/TimeSeriesListTest.java @@ -0,0 +1,135 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Functions; +import io.opencensus.common.Timestamp; +import io.opencensus.metrics.TimeSeriesList.TimeSeriesCumulativeList; +import io.opencensus.metrics.TimeSeriesList.TimeSeriesGaugeList; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.hamcrest.CoreMatchers; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TimeSeries}. */ +@RunWith(JUnit4.class) +public class TimeSeriesListTest { + + @Rule public ExpectedException thrown = ExpectedException.none(); + + private static final LabelValue LABEL_VALUE_1 = LabelValue.create("value1"); + private static final LabelValue LABEL_VALUE_2 = LabelValue.create("value2"); + private static final LabelValue LABEL_VALUE_EMPTY = LabelValue.create(""); + private static final Value VALUE_LONG = Value.longValue(12345678); + private static final Value VALUE_DOUBLE = Value.doubleValue(-345.77); + private static final Timestamp TIMESTAMP_1 = Timestamp.fromMillis(1000); + private static final Timestamp TIMESTAMP_2 = Timestamp.fromMillis(2000); + private static final Timestamp TIMESTAMP_3 = Timestamp.fromMillis(3000); + private static final Point POINT_1 = Point.create(VALUE_DOUBLE, TIMESTAMP_2); + private static final Point POINT_2 = Point.create(VALUE_LONG, TIMESTAMP_3); + private static final TimeSeriesGauge TIME_SERIES_GAUGE = + TimeSeriesGauge.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1, POINT_2)); + private static final TimeSeriesCumulative TIME_SERIES_CUMULATIVE = + TimeSeriesCumulative.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_EMPTY), Arrays.asList(POINT_1), TIMESTAMP_1); + + @Test + public void testGet_TimeSeriesGaugeList() { + TimeSeriesGaugeList gaugeTimeSeriesList = + TimeSeriesGaugeList.create(Collections.singletonList(TIME_SERIES_GAUGE)); + assertThat(gaugeTimeSeriesList.getList()).containsExactly(TIME_SERIES_GAUGE); + } + + @Test + public void testGet_TimeSeriesCumulativeList() { + TimeSeriesCumulativeList cumulativeTimeSeriesList = + TimeSeriesCumulativeList.create(Collections.singletonList(TIME_SERIES_CUMULATIVE)); + assertThat(cumulativeTimeSeriesList.getList()).containsExactly(TIME_SERIES_CUMULATIVE); + } + + @Test + public void createGaugeList_WithNullList() { + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("list")); + TimeSeriesGaugeList.create(null); + } + + @Test + public void createGaugeList_WithNullTimeSeries() { + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("timeSeriesGauge")); + TimeSeriesGaugeList.create(Arrays.asList(TIME_SERIES_GAUGE, null)); + } + + @Test + public void createCumulativeList_WithNullList() { + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("list")); + TimeSeriesCumulativeList.create(null); + } + + @Test + public void createCumulativeList_WithNullTimeSeries() { + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("timeSeriesCumulative")); + TimeSeriesCumulativeList.create(Arrays.asList(TIME_SERIES_CUMULATIVE, null)); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + TimeSeriesGaugeList.create(Collections.singletonList(TIME_SERIES_GAUGE)), + TimeSeriesGaugeList.create(Collections.singletonList(TIME_SERIES_GAUGE))) + .addEqualityGroup( + TimeSeriesCumulativeList.create(Collections.singletonList(TIME_SERIES_CUMULATIVE)), + TimeSeriesCumulativeList.create(Collections.singletonList(TIME_SERIES_CUMULATIVE))) + .addEqualityGroup(TimeSeriesGaugeList.create(Collections.emptyList())) + .addEqualityGroup( + TimeSeriesCumulativeList.create(Collections.emptyList())) + .testEquals(); + } + + @Test + public void testMatch() { + TimeSeriesList gaugeTimeSeriesList = + TimeSeriesGaugeList.create(Collections.singletonList(TIME_SERIES_GAUGE)); + TimeSeriesList cumulativeTimeSeriesList = + TimeSeriesCumulativeList.create(Collections.singletonList(TIME_SERIES_CUMULATIVE)); + + final List actual = new ArrayList(); + for (TimeSeriesList timeSeriesList : + Arrays.asList(cumulativeTimeSeriesList, gaugeTimeSeriesList)) { + actual.add( + timeSeriesList.match( + Functions.returnConstant("TimeSeriesGaugeList"), + Functions.returnConstant("TimeSeriesCumulativeList"), + Functions.throwAssertionError())); + } + assertThat(actual).containsExactly("TimeSeriesCumulativeList", "TimeSeriesGaugeList").inOrder(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/ValueTest.java b/api/src/test/java/io/opencensus/metrics/ValueTest.java new file mode 100644 index 00000000..63430b28 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/ValueTest.java @@ -0,0 +1,128 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Function; +import io.opencensus.common.Functions; +import io.opencensus.metrics.Distribution.Bucket; +import io.opencensus.metrics.Value.ValueDistribution; +import io.opencensus.metrics.Value.ValueDouble; +import io.opencensus.metrics.Value.ValueLong; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Value}. */ +@RunWith(JUnit4.class) +public class ValueTest { + + private static final Distribution DISTRIBUTION = + Distribution.create( + 10, + 10, + 1, + Arrays.asList(-5.0, 0.0, 5.0), + Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))); + + @Test + public void createAndGet_ValueDouble() { + Value value = Value.doubleValue(-34.56); + assertThat(value).isInstanceOf(ValueDouble.class); + assertThat(((ValueDouble) value).getValue()).isEqualTo(-34.56); + } + + @Test + public void createAndGet_ValueLong() { + Value value = Value.longValue(123456789); + assertThat(value).isInstanceOf(ValueLong.class); + assertThat(((ValueLong) value).getValue()).isEqualTo(123456789); + } + + @Test + public void createAndGet_ValueDistribution() { + Value value = Value.distributionValue(DISTRIBUTION); + assertThat(value).isInstanceOf(ValueDistribution.class); + assertThat(((ValueDistribution) value).getValue()).isEqualTo(DISTRIBUTION); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup(Value.doubleValue(1.0), Value.doubleValue(1.0)) + .addEqualityGroup(Value.doubleValue(2.0)) + .addEqualityGroup(Value.longValue(1L)) + .addEqualityGroup(Value.longValue(2L)) + .addEqualityGroup( + Value.distributionValue( + Distribution.create( + -7, + 10, + 23.456, + Arrays.asList(-5.0, 0.0, 5.0), + Arrays.asList( + Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))))) + .testEquals(); + } + + @Test + public void testMatch() { + List values = + Arrays.asList( + ValueDouble.create(1.0), ValueLong.create(-1), ValueDistribution.create(DISTRIBUTION)); + List expected = + Arrays.asList(1.0, -1L, 10.0, 10L, 1.0, -5.0, 0.0, 5.0, 3L, 1L, 2L, 4L); + final List actual = new ArrayList(); + for (Value value : values) { + value.match( + new Function() { + @Override + public Object apply(Double arg) { + actual.add(arg); + return null; + } + }, + new Function() { + @Override + public Object apply(Long arg) { + actual.add(arg); + return null; + } + }, + new Function() { + @Override + public Object apply(Distribution arg) { + actual.add(arg.getMean()); + actual.add(arg.getCount()); + actual.add(arg.getSumOfSquaredDeviations()); + actual.addAll(arg.getBucketBoundaries()); + for (Bucket bucket : arg.getBuckets()) { + actual.add(bucket.getCount()); + } + return null; + } + }, + Functions.throwAssertionError()); + } + assertThat(actual).containsExactlyElementsIn(expected).inOrder(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/export/ExportComponentTest.java b/api/src/test/java/io/opencensus/metrics/export/ExportComponentTest.java new file mode 100644 index 00000000..15c6e883 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/export/ExportComponentTest.java @@ -0,0 +1,33 @@ +/* + * Copyright 2018, 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.metrics.export; + +import static com.google.common.truth.Truth.assertThat; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link ExportComponent}. */ +@RunWith(JUnit4.class) +public class ExportComponentTest { + @Test + public void defaultMetricExporter() { + assertThat(ExportComponent.newNoopExportComponent().getMetricProducerManager()) + .isInstanceOf(MetricProducerManager.class); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java b/api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java new file mode 100644 index 00000000..b79de213 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java @@ -0,0 +1,113 @@ +/* + * Copyright 2018, 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.metrics.export; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.metrics.MetricProducer; +import java.util.Set; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** Unit tests for {@link MetricProducerManager}. */ +@RunWith(JUnit4.class) +public class MetricProducerManagerTest { + private final MetricProducerManager metricProducerManager = new MetricProducerManager(); + @Mock private MetricProducer metricProducer; + @Mock private MetricProducer metricProducerOther; + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void add_DisallowsNull() { + thrown.expect(NullPointerException.class); + metricProducerManager.add(null); + } + + @Test + public void add() { + metricProducerManager.add(metricProducer); + assertThat(metricProducerManager.getAllMetricProducer()).containsExactly(metricProducer); + } + + @Test + public void add_DuplicateElement() { + metricProducerManager.add(metricProducer); + Set metricProducerSet = metricProducerManager.getAllMetricProducer(); + assertThat(metricProducerSet).containsExactly(metricProducer); + metricProducerManager.add(metricProducer); + // Returns the same object. + assertThat(metricProducerManager.getAllMetricProducer()).isSameAs(metricProducerSet); + } + + @Test + public void add_MultipleElements() { + metricProducerManager.add(metricProducer); + Set metricProducerSet = metricProducerManager.getAllMetricProducer(); + assertThat(metricProducerSet).containsExactly(metricProducer); + metricProducerManager.add(metricProducerOther); + // Returns the same object. + assertThat(metricProducerManager.getAllMetricProducer()) + .containsExactly(metricProducer, metricProducerOther); + } + + @Test + public void addAndRemove() { + metricProducerManager.add(metricProducer); + assertThat(metricProducerManager.getAllMetricProducer()).containsExactly(metricProducer); + metricProducerManager.remove(metricProducer); + assertThat(metricProducerManager.getAllMetricProducer()).isEmpty(); + } + + @Test + public void remove_DisallowsNull() { + thrown.expect(NullPointerException.class); + metricProducerManager.remove(null); + } + + @Test + public void remove_FromEmpty() { + metricProducerManager.remove(metricProducer); + assertThat(metricProducerManager.getAllMetricProducer()).isEmpty(); + } + + @Test + public void remove_NotPresent() { + metricProducerManager.add(metricProducer); + Set metricProducerSet = metricProducerManager.getAllMetricProducer(); + assertThat(metricProducerSet).containsExactly(metricProducer); + metricProducerManager.remove(metricProducerOther); + // Returns the same object. + assertThat(metricProducerManager.getAllMetricProducer()).isSameAs(metricProducerSet); + } + + @Test + public void getAllMetricProducer_empty() { + assertThat(metricProducerManager.getAllMetricProducer()).isEmpty(); + } +} -- cgit v1.2.3 From 66ae2eed952579e6982b05c0bcebe0670afb0afe Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Sat, 11 Aug 2018 09:49:07 -0700 Subject: Fix metrics tests by adding the RunWith annotation. (#1364) --- api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java | 4 ++++ api/src/test/java/io/opencensus/metrics/MetricsTest.java | 6 ++++++ 2 files changed, 10 insertions(+) (limited to 'api') diff --git a/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java b/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java index 0e467dc8..49e8ce02 100644 --- a/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java +++ b/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java @@ -22,7 +22,11 @@ import java.util.LinkedHashMap; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +/** Unit tests for {@link MetricRegistry}. */ +@RunWith(JUnit4.class) public class MetricRegistryTest { @Rule public ExpectedException thrown = ExpectedException.none(); diff --git a/api/src/test/java/io/opencensus/metrics/MetricsTest.java b/api/src/test/java/io/opencensus/metrics/MetricsTest.java index 9a56f257..9e0eee1f 100644 --- a/api/src/test/java/io/opencensus/metrics/MetricsTest.java +++ b/api/src/test/java/io/opencensus/metrics/MetricsTest.java @@ -62,4 +62,10 @@ public class MetricsTest { assertThat(Metrics.getExportComponent()) .isInstanceOf(ExportComponent.newNoopExportComponent().getClass()); } + + @Test + public void defaultMetricRegistry() { + assertThat(Metrics.getMetricRegistry()) + .isInstanceOf(MetricRegistry.newNoopMetricRegistry().getClass()); + } } -- cgit v1.2.3 From 775816d699bd4f02788db5609a87386940e34aff Mon Sep 17 00:00:00 2001 From: Yang Song Date: Mon, 13 Aug 2018 11:36:27 -0700 Subject: Metrics: Implement ExportComponent, make ProducerManager abstract. (#1347) * Metrics: Implement ExportComponent, make ProducerManager abstract. * Metrics: Add impl and impllite. * Resolve two TODOs. * Fix import path, leave a TODO for getMetricRegistry. * Make NoopMetricProducerManager private. Add missing since tag. --- .../io/opencensus/common/ToDoubleFunction.java | 4 +- .../java/io/opencensus/common/ToLongFunction.java | 4 +- .../opencensus/metrics/export/ExportComponent.java | 2 +- .../metrics/export/MetricProducerManager.java | 62 +++++++++++----------- .../metrics/export/MetricProducerManagerTest.java | 40 ++------------ 5 files changed, 38 insertions(+), 74 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/ToDoubleFunction.java b/api/src/main/java/io/opencensus/common/ToDoubleFunction.java index 479270f1..eac85793 100644 --- a/api/src/main/java/io/opencensus/common/ToDoubleFunction.java +++ b/api/src/main/java/io/opencensus/common/ToDoubleFunction.java @@ -16,10 +16,8 @@ package io.opencensus.common; -// TODO(bdrutu): Change @code to @link when metrics is moved in the API. - /** - * Represents a function that produces a double-valued result. See {@code + * Represents a function that produces a double-valued result. See {@link * io.opencensus.metrics.MetricRegistry} for an example of its use. * *

    Note: This class is based on the java.util.ToDoubleFunction class added in Java 1.8. We cannot diff --git a/api/src/main/java/io/opencensus/common/ToLongFunction.java b/api/src/main/java/io/opencensus/common/ToLongFunction.java index 9a6e9b19..26a27b18 100644 --- a/api/src/main/java/io/opencensus/common/ToLongFunction.java +++ b/api/src/main/java/io/opencensus/common/ToLongFunction.java @@ -16,10 +16,8 @@ package io.opencensus.common; -// TODO(bdrutu): Change @code to @link when metrics is moved in the API. - /** - * Represents a function that produces a long-valued result. See {@code + * Represents a function that produces a long-valued result. See {@link * io.opencensus.metrics.MetricRegistry} for an example of its use. * *

    Note: This class is based on the java.util.ToLongFunction class added in Java 1.8. We cannot diff --git a/api/src/main/java/io/opencensus/metrics/export/ExportComponent.java b/api/src/main/java/io/opencensus/metrics/export/ExportComponent.java index f1511543..bab65d13 100644 --- a/api/src/main/java/io/opencensus/metrics/export/ExportComponent.java +++ b/api/src/main/java/io/opencensus/metrics/export/ExportComponent.java @@ -50,7 +50,7 @@ public abstract class ExportComponent { private static final class NoopExportComponent extends ExportComponent { private static final MetricProducerManager METRIC_PRODUCER_MANAGER = - new MetricProducerManager(); + MetricProducerManager.newNoopMetricProducerManager(); @Override public MetricProducerManager getMetricProducerManager() { diff --git a/api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java b/api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java index 9600a023..c5acf174 100644 --- a/api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java +++ b/api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java @@ -20,7 +20,6 @@ import io.opencensus.common.ExperimentalApi; import io.opencensus.internal.Utils; import io.opencensus.metrics.MetricProducer; import java.util.Collections; -import java.util.LinkedHashSet; import java.util.Set; import javax.annotation.concurrent.ThreadSafe; @@ -32,9 +31,7 @@ import javax.annotation.concurrent.ThreadSafe; */ @ExperimentalApi @ThreadSafe -public final class MetricProducerManager { - private volatile Set metricProducers = - Collections.unmodifiableSet(new LinkedHashSet()); +public abstract class MetricProducerManager { /** * Adds the {@link MetricProducer} to the manager if it is not already present. @@ -42,34 +39,15 @@ public final class MetricProducerManager { * @param metricProducer the {@code MetricProducer} to be added to the manager. * @since 0.16 */ - public synchronized void add(MetricProducer metricProducer) { - Utils.checkNotNull(metricProducer, "metricProducer"); - // Updating the set of MetricProducers happens under a lock to avoid multiple add or remove - // operations to happen in the same time. - Set newMetricProducers = new LinkedHashSet(metricProducers); - if (!newMetricProducers.add(metricProducer)) { - // The element already present, no need to update the current set of MetricProducers. - return; - } - metricProducers = Collections.unmodifiableSet(newMetricProducers); - } + public abstract void add(MetricProducer metricProducer); /** * Removes the {@link MetricProducer} to the manager if it is present. * * @param metricProducer the {@code MetricProducer} to be removed from the manager. + * @since 0.16 */ - public synchronized void remove(MetricProducer metricProducer) { - Utils.checkNotNull(metricProducer, "metricProducer"); - // Updating the set of MetricProducers happens under a lock to avoid multiple add or remove - // operations to happen in the same time. - Set newMetricProducers = new LinkedHashSet(metricProducers); - if (!newMetricProducers.remove(metricProducer)) { - // The element not present, no need to update the current set of MetricProducers. - return; - } - metricProducers = Collections.unmodifiableSet(newMetricProducers); - } + public abstract void remove(MetricProducer metricProducer); /** * Returns all registered {@link MetricProducer}s that should be exported. @@ -78,12 +56,34 @@ public final class MetricProducerManager { * {@code MetricProducer} registered with the {@code MetricProducerManager}. * * @return all registered {@code MetricProducer}s that should be exported. + * @since 0.16 */ - public Set getAllMetricProducer() { - return metricProducers; + public abstract Set getAllMetricProducer(); + + /** + * Returns a no-op implementation for {@link MetricProducerManager}. + * + * @return a no-op implementation for {@code MetricProducerManager}. + */ + static MetricProducerManager newNoopMetricProducerManager() { + return new NoopMetricProducerManager(); } - // Package protected to allow us to possibly change this to an abstract class in the future. This - // ensures that nobody can create an instance of this class except ExportComponent. - MetricProducerManager() {} + private static final class NoopMetricProducerManager extends MetricProducerManager { + + @Override + public void add(MetricProducer metricProducer) { + Utils.checkNotNull(metricProducer, "metricProducer"); + } + + @Override + public void remove(MetricProducer metricProducer) { + Utils.checkNotNull(metricProducer, "metricProducer"); + } + + @Override + public Set getAllMetricProducer() { + return Collections.emptySet(); + } + } } diff --git a/api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java b/api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java index b79de213..07854927 100644 --- a/api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java +++ b/api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java @@ -19,7 +19,6 @@ package io.opencensus.metrics.export; import static com.google.common.truth.Truth.assertThat; import io.opencensus.metrics.MetricProducer; -import java.util.Set; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -32,9 +31,9 @@ import org.mockito.MockitoAnnotations; /** Unit tests for {@link MetricProducerManager}. */ @RunWith(JUnit4.class) public class MetricProducerManagerTest { - private final MetricProducerManager metricProducerManager = new MetricProducerManager(); + private final MetricProducerManager metricProducerManager = + MetricProducerManager.newNoopMetricProducerManager(); @Mock private MetricProducer metricProducer; - @Mock private MetricProducer metricProducerOther; @Rule public final ExpectedException thrown = ExpectedException.none(); @@ -52,34 +51,13 @@ public class MetricProducerManagerTest { @Test public void add() { metricProducerManager.add(metricProducer); - assertThat(metricProducerManager.getAllMetricProducer()).containsExactly(metricProducer); - } - - @Test - public void add_DuplicateElement() { - metricProducerManager.add(metricProducer); - Set metricProducerSet = metricProducerManager.getAllMetricProducer(); - assertThat(metricProducerSet).containsExactly(metricProducer); - metricProducerManager.add(metricProducer); - // Returns the same object. - assertThat(metricProducerManager.getAllMetricProducer()).isSameAs(metricProducerSet); - } - - @Test - public void add_MultipleElements() { - metricProducerManager.add(metricProducer); - Set metricProducerSet = metricProducerManager.getAllMetricProducer(); - assertThat(metricProducerSet).containsExactly(metricProducer); - metricProducerManager.add(metricProducerOther); - // Returns the same object. - assertThat(metricProducerManager.getAllMetricProducer()) - .containsExactly(metricProducer, metricProducerOther); + assertThat(metricProducerManager.getAllMetricProducer()).isEmpty(); } @Test public void addAndRemove() { metricProducerManager.add(metricProducer); - assertThat(metricProducerManager.getAllMetricProducer()).containsExactly(metricProducer); + assertThat(metricProducerManager.getAllMetricProducer()).isEmpty(); metricProducerManager.remove(metricProducer); assertThat(metricProducerManager.getAllMetricProducer()).isEmpty(); } @@ -96,16 +74,6 @@ public class MetricProducerManagerTest { assertThat(metricProducerManager.getAllMetricProducer()).isEmpty(); } - @Test - public void remove_NotPresent() { - metricProducerManager.add(metricProducer); - Set metricProducerSet = metricProducerManager.getAllMetricProducer(); - assertThat(metricProducerSet).containsExactly(metricProducer); - metricProducerManager.remove(metricProducerOther); - // Returns the same object. - assertThat(metricProducerManager.getAllMetricProducer()).isSameAs(metricProducerSet); - } - @Test public void getAllMetricProducer_empty() { assertThat(metricProducerManager.getAllMetricProducer()).isEmpty(); -- cgit v1.2.3 From 0a2f5799a2809b84e4c0da4b2cb743b798ca0fc8 Mon Sep 17 00:00:00 2001 From: sebright Date: Thu, 16 Aug 2018 15:04:02 -0700 Subject: checkstyle: 8.0 -> 8.12 (#1369) This commit also merges new changes to checkstyle.xml and fixes new checkstyle warnings related to Javadocs. --- .../io/opencensus/common/ServerStatsFieldEnums.java | 8 ++++---- .../java/io/opencensus/stats/BucketBoundaries.java | 2 ++ .../main/java/io/opencensus/trace/NetworkEvent.java | 4 ++++ api/src/main/java/io/opencensus/trace/Span.java | 4 ++++ .../main/java/io/opencensus/trace/TraceOptions.java | 2 ++ .../io/opencensus/trace/export/SampledSpanStore.java | 18 +++++++++--------- .../io/opencensus/trace/propagation/BinaryFormat.java | 4 ++++ 7 files changed, 29 insertions(+), 13 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/ServerStatsFieldEnums.java b/api/src/main/java/io/opencensus/common/ServerStatsFieldEnums.java index 79cb196e..ff3cfda9 100644 --- a/api/src/main/java/io/opencensus/common/ServerStatsFieldEnums.java +++ b/api/src/main/java/io/opencensus/common/ServerStatsFieldEnums.java @@ -99,19 +99,19 @@ public final class ServerStatsFieldEnums { */ public enum Size { /** - * Number of bytes used to represent latency observed at Load Balancer + * Number of bytes used to represent latency observed at Load Balancer. * * @since 0.16 */ SERVER_STATS_LB_LATENCY_SIZE(8), /** - * Number of bytes used to represent latency observed at Server + * Number of bytes used to represent latency observed at Server. * * @since 0.16 */ SERVER_STATS_SERVICE_LATENCY_SIZE(8), /** - * Number of bytes used to represent Trace option + * Number of bytes used to represent Trace option. * * @since 0.16 */ @@ -148,7 +148,7 @@ public final class ServerStatsFieldEnums { } /** - * Returns the total size required to encode the {@code ServerStats} + * Returns the total size required to encode the {@code ServerStats}. * * @return the total size required to encode all fields in {@code ServerStats}. * @since 0.16 diff --git a/api/src/main/java/io/opencensus/stats/BucketBoundaries.java b/api/src/main/java/io/opencensus/stats/BucketBoundaries.java index 20588d59..573a9e10 100644 --- a/api/src/main/java/io/opencensus/stats/BucketBoundaries.java +++ b/api/src/main/java/io/opencensus/stats/BucketBoundaries.java @@ -33,6 +33,8 @@ import javax.annotation.concurrent.Immutable; public abstract class BucketBoundaries { /** + * Returns a {@code BucketBoundaries} with the given buckets. + * * @param bucketBoundaries the boundaries for the buckets in the underlying histogram. * @return a new {@code BucketBoundaries} with the specified boundaries. * @throws NullPointerException if {@code bucketBoundaries} is null. diff --git a/api/src/main/java/io/opencensus/trace/NetworkEvent.java b/api/src/main/java/io/opencensus/trace/NetworkEvent.java index fafedf8e..722029e5 100644 --- a/api/src/main/java/io/opencensus/trace/NetworkEvent.java +++ b/api/src/main/java/io/opencensus/trace/NetworkEvent.java @@ -118,6 +118,8 @@ public abstract class NetworkEvent extends io.opencensus.trace.BaseMessageEvent public abstract long getCompressedMessageSize(); /** + * Returns the uncompressed size in bytes of the {@code NetworkEvent}. + * * @deprecated Use {@link #getUncompressedMessageSize}. * @return the uncompressed size in bytes of the {@code NetworkEvent}. * @since 0.5 @@ -153,6 +155,8 @@ public abstract class NetworkEvent extends io.opencensus.trace.BaseMessageEvent public abstract Builder setKernelTimestamp(@Nullable Timestamp kernelTimestamp); /** + * Sets the uncompressed message size. + * * @deprecated Use {@link #setUncompressedMessageSize}. * @param messageSize represents the uncompressed size in bytes of this message. * @return this. diff --git a/api/src/main/java/io/opencensus/trace/Span.java b/api/src/main/java/io/opencensus/trace/Span.java index 0fc62daf..8f8253b4 100644 --- a/api/src/main/java/io/opencensus/trace/Span.java +++ b/api/src/main/java/io/opencensus/trace/Span.java @@ -117,6 +117,10 @@ public abstract class Span { } /** + * Sets a set of attributes to the {@code Span}. The effect of this call is equivalent to that of + * calling {@link #putAttribute(String, AttributeValue)} once for each element in the specified + * map. + * * @deprecated Use {@link #putAttributes(Map)} * @param attributes the attributes that will be added and associated with the {@code Span}. * @since 0.5 diff --git a/api/src/main/java/io/opencensus/trace/TraceOptions.java b/api/src/main/java/io/opencensus/trace/TraceOptions.java index cdae92b3..f34ba190 100644 --- a/api/src/main/java/io/opencensus/trace/TraceOptions.java +++ b/api/src/main/java/io/opencensus/trace/TraceOptions.java @@ -202,6 +202,8 @@ public final class TraceOptions { } /** + * Sets the sampling bit in the options to true. + * * @deprecated Use {@code Builder.setIsSampled(true)}. * @return this. * @since 0.5 diff --git a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java index 2347061b..5d00a45d 100644 --- a/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java +++ b/api/src/main/java/io/opencensus/trace/export/SampledSpanStore.java @@ -234,63 +234,63 @@ public abstract class SampledSpanStore { */ public enum LatencyBucketBoundaries { /** - * Stores finished successful requests of duration within the interval [0, 10us) + * Stores finished successful requests of duration within the interval [0, 10us). * * @since 0.5 */ ZERO_MICROSx10(0, TimeUnit.MICROSECONDS.toNanos(10)), /** - * Stores finished successful requests of duration within the interval [10us, 100us) + * Stores finished successful requests of duration within the interval [10us, 100us). * * @since 0.5 */ MICROSx10_MICROSx100(TimeUnit.MICROSECONDS.toNanos(10), TimeUnit.MICROSECONDS.toNanos(100)), /** - * Stores finished successful requests of duration within the interval [100us, 1ms) + * Stores finished successful requests of duration within the interval [100us, 1ms). * * @since 0.5 */ MICROSx100_MILLIx1(TimeUnit.MICROSECONDS.toNanos(100), TimeUnit.MILLISECONDS.toNanos(1)), /** - * Stores finished successful requests of duration within the interval [1ms, 10ms) + * Stores finished successful requests of duration within the interval [1ms, 10ms). * * @since 0.5 */ MILLIx1_MILLIx10(TimeUnit.MILLISECONDS.toNanos(1), TimeUnit.MILLISECONDS.toNanos(10)), /** - * Stores finished successful requests of duration within the interval [10ms, 100ms) + * Stores finished successful requests of duration within the interval [10ms, 100ms). * * @since 0.5 */ MILLIx10_MILLIx100(TimeUnit.MILLISECONDS.toNanos(10), TimeUnit.MILLISECONDS.toNanos(100)), /** - * Stores finished successful requests of duration within the interval [100ms, 1sec) + * Stores finished successful requests of duration within the interval [100ms, 1sec). * * @since 0.5 */ MILLIx100_SECONDx1(TimeUnit.MILLISECONDS.toNanos(100), TimeUnit.SECONDS.toNanos(1)), /** - * Stores finished successful requests of duration within the interval [1sec, 10sec) + * Stores finished successful requests of duration within the interval [1sec, 10sec). * * @since 0.5 */ SECONDx1_SECONDx10(TimeUnit.SECONDS.toNanos(1), TimeUnit.SECONDS.toNanos(10)), /** - * Stores finished successful requests of duration within the interval [10sec, 100sec) + * Stores finished successful requests of duration within the interval [10sec, 100sec). * * @since 0.5 */ SECONDx10_SECONDx100(TimeUnit.SECONDS.toNanos(10), TimeUnit.SECONDS.toNanos(100)), /** - * Stores finished successful requests of duration >= 100sec + * Stores finished successful requests of duration >= 100sec. * * @since 0.5 */ diff --git a/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java b/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java index 9b6c9632..7e875fd6 100644 --- a/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java +++ b/api/src/main/java/io/opencensus/trace/propagation/BinaryFormat.java @@ -66,6 +66,8 @@ public abstract class BinaryFormat { static final NoopBinaryFormat NOOP_BINARY_FORMAT = new NoopBinaryFormat(); /** + * Serializes a {@link SpanContext} into a byte array using the binary format. + * * @deprecated use {@link #toByteArray(SpanContext)}. * @param spanContext the {@code SpanContext} to serialize. * @return the serialized binary value. @@ -91,6 +93,8 @@ public abstract class BinaryFormat { } /** + * Parses the {@link SpanContext} from a byte array using the binary format. + * * @deprecated use {@link #fromByteArray(byte[])}. * @param bytes a binary encoded buffer from which the {@code SpanContext} will be parsed. * @return the parsed {@code SpanContext}. -- cgit v1.2.3 From 50b0e198702022ffd887416f6550f0218982bb15 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Sat, 18 Aug 2018 13:52:19 -0700 Subject: Update all targets to at least java7 and android14 (#1367) * Update all targets to at least java7 and android14 * Change code to be android14 compatible. * Select a specific version for each signature. --- api/build.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'api') diff --git a/api/build.gradle b/api/build.gradle index 3834f051..6d527c06 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -6,7 +6,8 @@ dependencies { compileOnly libraries.auto_value - signature "org.codehaus.mojo.signature:java16:+@signature" + signature "org.codehaus.mojo.signature:java17:1.0@signature" + signature "net.sf.androidscents.signature:android-api-level-14:4.0_r4@signature" } javadoc.exclude 'io/opencensus/internal/**' -- cgit v1.2.3 From 8d75c101ab0ae0efd5faea9906ce399f00fb4394 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Tue, 21 Aug 2018 13:14:31 -0700 Subject: Metrics: Combine TimeSeriesCumulative and TimeSeriesGauge. (#1380) --- .../main/java/io/opencensus/metrics/Metric.java | 61 ++++++---- .../java/io/opencensus/metrics/TimeSeries.java | 50 +++++++- .../opencensus/metrics/TimeSeriesCumulative.java | 70 ----------- .../io/opencensus/metrics/TimeSeriesGauge.java | 57 --------- .../java/io/opencensus/metrics/TimeSeriesList.java | 134 -------------------- .../java/io/opencensus/metrics/MetricTest.java | 59 ++++----- .../metrics/TimeSeriesCumulativeTest.java | 113 ----------------- .../io/opencensus/metrics/TimeSeriesGaugeTest.java | 104 ---------------- .../io/opencensus/metrics/TimeSeriesListTest.java | 135 --------------------- .../java/io/opencensus/metrics/TimeSeriesTest.java | 116 ++++++++++++++++++ 10 files changed, 225 insertions(+), 674 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/metrics/TimeSeriesCumulative.java delete mode 100644 api/src/main/java/io/opencensus/metrics/TimeSeriesGauge.java delete mode 100644 api/src/main/java/io/opencensus/metrics/TimeSeriesList.java delete mode 100644 api/src/test/java/io/opencensus/metrics/TimeSeriesCumulativeTest.java delete mode 100644 api/src/test/java/io/opencensus/metrics/TimeSeriesGaugeTest.java delete mode 100644 api/src/test/java/io/opencensus/metrics/TimeSeriesListTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/TimeSeriesTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/metrics/Metric.java b/api/src/main/java/io/opencensus/metrics/Metric.java index e8be0b90..9cbd418b 100644 --- a/api/src/main/java/io/opencensus/metrics/Metric.java +++ b/api/src/main/java/io/opencensus/metrics/Metric.java @@ -19,8 +19,10 @@ package io.opencensus.metrics; import com.google.auto.value.AutoValue; import io.opencensus.common.ExperimentalApi; import io.opencensus.internal.Utils; -import io.opencensus.metrics.TimeSeriesList.TimeSeriesCumulativeList; -import io.opencensus.metrics.TimeSeriesList.TimeSeriesGaugeList; +import io.opencensus.metrics.Value.ValueDistribution; +import io.opencensus.metrics.Value.ValueDouble; +import io.opencensus.metrics.Value.ValueLong; +import java.util.List; import javax.annotation.concurrent.Immutable; /** @@ -39,11 +41,11 @@ public abstract class Metric { * Creates a {@link Metric}. * * @param metricDescriptor the {@link MetricDescriptor}. - * @param timeSeriesList the {@link TimeSeriesList} for this metric. + * @param timeSeriesList the {@link TimeSeries} list for this metric. * @return a {@code Metric}. * @since 0.16 */ - public static Metric create(MetricDescriptor metricDescriptor, TimeSeriesList timeSeriesList) { + public static Metric create(MetricDescriptor metricDescriptor, List timeSeriesList) { checkTypeMatch(metricDescriptor.getType(), timeSeriesList); return new AutoValue_Metric(metricDescriptor, timeSeriesList); } @@ -57,32 +59,43 @@ public abstract class Metric { public abstract MetricDescriptor getMetricDescriptor(); /** - * Returns the {@link TimeSeriesList} for this metric. + * Returns the {@link TimeSeries} list for this metric. * - *

    The type of the {@link TimeSeriesList} must match {@link MetricDescriptor.Type}. + *

    The type of the {@link TimeSeries#getPoints()} must match {@link MetricDescriptor.Type}. * * @return the {@code TimeSeriesList} for this metric. * @since 0.16 */ - public abstract TimeSeriesList getTimeSeriesList(); + public abstract List getTimeSeriesList(); - private static void checkTypeMatch(MetricDescriptor.Type type, TimeSeriesList timeSeriesList) { - switch (type) { - case GAUGE_INT64: - case GAUGE_DOUBLE: - Utils.checkArgument( - timeSeriesList instanceof TimeSeriesGaugeList, - String.format( - "Type mismatch: %s, %s.", type, timeSeriesList.getClass().getSimpleName())); - break; - case CUMULATIVE_DISTRIBUTION: - case CUMULATIVE_DOUBLE: - case CUMULATIVE_INT64: - Utils.checkArgument( - timeSeriesList instanceof TimeSeriesCumulativeList, - String.format( - "Type mismatch: %s, %s.", type, timeSeriesList.getClass().getSimpleName())); - break; + private static void checkTypeMatch(MetricDescriptor.Type type, List timeSeriesList) { + for (TimeSeries timeSeries : timeSeriesList) { + for (Point point : timeSeries.getPoints()) { + Value value = point.getValue(); + String valueClassName = ""; + if (value.getClass().getSuperclass() != null) { // work around nullness check + // AutoValue classes should always have a super class. + valueClassName = value.getClass().getSuperclass().getSimpleName(); + } + switch (type) { + case GAUGE_INT64: + case CUMULATIVE_INT64: + Utils.checkArgument( + value instanceof ValueLong, + String.format("Type mismatch: %s, %s.", type, valueClassName)); + break; + case CUMULATIVE_DOUBLE: + case GAUGE_DOUBLE: + Utils.checkArgument( + value instanceof ValueDouble, + String.format("Type mismatch: %s, %s.", type, valueClassName)); + break; + case CUMULATIVE_DISTRIBUTION: + Utils.checkArgument( + value instanceof ValueDistribution, + String.format("Type mismatch: %s, %s.", type, valueClassName)); + } + } } } } diff --git a/api/src/main/java/io/opencensus/metrics/TimeSeries.java b/api/src/main/java/io/opencensus/metrics/TimeSeries.java index bbbfe0e4..c62b6b72 100644 --- a/api/src/main/java/io/opencensus/metrics/TimeSeries.java +++ b/api/src/main/java/io/opencensus/metrics/TimeSeries.java @@ -16,15 +16,51 @@ package io.opencensus.metrics; +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.common.Timestamp; +import io.opencensus.internal.Utils; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; -/** A collection of data points that describes the time-varying values of a {@code Metric}. */ +/** + * A collection of data points that describes the time-varying values of a {@code Metric}. + * + * @since 0.16 + */ +@ExperimentalApi @Immutable -abstract class TimeSeries { +@AutoValue +public abstract class TimeSeries { TimeSeries() {} + /** + * Creates a {@link TimeSeries}. + * + * @param labelValues the {@code LabelValue}s that uniquely identify this {@code TimeSeries}. + * @param points the data {@code Point}s of this {@code TimeSeries}. + * @param startTimestamp the start {@code Timestamp} of this {@code TimeSeries}. Must be non-null + * for cumulative {@code Point}s. + * @return a {@code TimeSeries}. + * @since 0.16 + */ + public static TimeSeries create( + List labelValues, List points, @Nullable Timestamp startTimestamp) { + // Fail fast on null lists to prevent NullPointerException when copying the lists. + Utils.checkNotNull(labelValues, "labelValues"); + Utils.checkNotNull(points, "points"); + Utils.checkListElementNotNull(labelValues, "labelValue"); + Utils.checkListElementNotNull(points, "point"); + return new AutoValue_TimeSeries( + Collections.unmodifiableList(new ArrayList(labelValues)), + Collections.unmodifiableList(new ArrayList(points)), + startTimestamp); + } + /** * Returns the set of {@link LabelValue}s that uniquely identify this {@link TimeSeries}. * @@ -45,4 +81,14 @@ abstract class TimeSeries { * @since 0.16 */ public abstract List getPoints(); + + /** + * Returns the start {@link Timestamp} of this {@link TimeSeries} if the {@link Point}s are + * cumulative, or {@code null} if the {@link Point}s are gauge. + * + * @return the start {@code Timestamp} or {@code null}. + * @since 0.16 + */ + @Nullable + public abstract Timestamp getStartTimestamp(); } diff --git a/api/src/main/java/io/opencensus/metrics/TimeSeriesCumulative.java b/api/src/main/java/io/opencensus/metrics/TimeSeriesCumulative.java deleted file mode 100644 index 5f48b770..00000000 --- a/api/src/main/java/io/opencensus/metrics/TimeSeriesCumulative.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import com.google.auto.value.AutoValue; -import io.opencensus.common.ExperimentalApi; -import io.opencensus.common.Timestamp; -import io.opencensus.internal.Utils; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.annotation.concurrent.Immutable; - -/** - * A collection of data points that describes the time-varying values of a cumulative {@code - * Metric}. - * - * @since 0.16 - */ -@ExperimentalApi -@Immutable -@AutoValue -public abstract class TimeSeriesCumulative extends TimeSeries { - - TimeSeriesCumulative() {} - - /** - * Creates a {@link TimeSeriesCumulative}. - * - * @param labelValues the {@code LabelValue}s that uniquely identify this {@code TimeSeries}. - * @param points the data {@code Point}s of this {@code TimeSeries}. - * @param startTimestamp the start {@code Timestamp} of this {@code TimeSeriesCumulative}. - * @return a {@code TimeSeriesCumulative}. - * @since 0.16 - */ - public static TimeSeriesCumulative create( - List labelValues, List points, Timestamp startTimestamp) { - // Fail fast on null lists to prevent NullPointerException when copying the lists. - Utils.checkNotNull(labelValues, "labelValues"); - Utils.checkNotNull(points, "points"); - Utils.checkListElementNotNull(labelValues, "labelValue"); - Utils.checkListElementNotNull(points, "point"); - return new AutoValue_TimeSeriesCumulative( - Collections.unmodifiableList(new ArrayList(labelValues)), - Collections.unmodifiableList(new ArrayList(points)), - startTimestamp); - } - - /** - * Returns the start {@link Timestamp} of this {@link TimeSeriesCumulative}. - * - * @return the start {@code Timestamp}. - * @since 0.16 - */ - public abstract Timestamp getStartTimestamp(); -} diff --git a/api/src/main/java/io/opencensus/metrics/TimeSeriesGauge.java b/api/src/main/java/io/opencensus/metrics/TimeSeriesGauge.java deleted file mode 100644 index 717505a4..00000000 --- a/api/src/main/java/io/opencensus/metrics/TimeSeriesGauge.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import com.google.auto.value.AutoValue; -import io.opencensus.common.ExperimentalApi; -import io.opencensus.internal.Utils; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.annotation.concurrent.Immutable; - -/** - * A collection of data points that describes the time-varying values of a gauge {@code Metric}. - * - * @since 0.16 - */ -@ExperimentalApi -@Immutable -@AutoValue -public abstract class TimeSeriesGauge extends TimeSeries { - - TimeSeriesGauge() {} - - /** - * Creates a {@link TimeSeriesGauge}. - * - * @param labelValues the {@code LabelValue}s that uniquely identify this {@code TimeSeries}. - * @param points the data {@code Point}s of this {@code TimeSeries}. - * @return a {@code TimeSeriesGauge}. - * @since 0.16 - */ - public static TimeSeriesGauge create(List labelValues, List points) { - // Fail fast on null lists to prevent NullPointerException when copying the lists. - Utils.checkNotNull(labelValues, "labelValues"); - Utils.checkNotNull(points, "points"); - Utils.checkListElementNotNull(labelValues, "labelValue"); - Utils.checkListElementNotNull(points, "point"); - return new AutoValue_TimeSeriesGauge( - Collections.unmodifiableList(new ArrayList(labelValues)), - Collections.unmodifiableList(new ArrayList(points))); - } -} diff --git a/api/src/main/java/io/opencensus/metrics/TimeSeriesList.java b/api/src/main/java/io/opencensus/metrics/TimeSeriesList.java deleted file mode 100644 index 6138eac2..00000000 --- a/api/src/main/java/io/opencensus/metrics/TimeSeriesList.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import com.google.auto.value.AutoValue; -import io.opencensus.common.ExperimentalApi; -import io.opencensus.common.Function; -import io.opencensus.internal.Utils; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.annotation.concurrent.Immutable; - -/** - * Class that holds a list of either {@link TimeSeriesGauge} or {@link TimeSeriesCumulative}. - * - * @since 0.16 - */ -@ExperimentalApi -@Immutable -public abstract class TimeSeriesList { - - TimeSeriesList() {} - - /** - * Applies the given match function to the underlying data type. - * - * @since 0.16 - */ - public abstract T match( - Function gaugeListFunction, - Function cumulativeListFunction, - Function defaultFunction); - - /** - * Class that holds a list of {@link TimeSeriesGauge}. - * - * @since 0.16 - */ - @ExperimentalApi - @Immutable - @AutoValue - public abstract static class TimeSeriesGaugeList extends TimeSeriesList { - - TimeSeriesGaugeList() {} - - @Override - public final T match( - Function gaugeListFunction, - Function cumulativeListFunction, - Function defaultFunction) { - return gaugeListFunction.apply(this); - } - - /** - * Creates a {@link TimeSeriesGaugeList}. - * - * @param list a list of {@link TimeSeriesGauge}. - * @return a {code TimeSeriesGaugeList}. - * @since 0.16 - */ - public static TimeSeriesGaugeList create(List list) { - Utils.checkNotNull(list, "list"); - Utils.checkListElementNotNull(list, "timeSeriesGauge"); - return new AutoValue_TimeSeriesList_TimeSeriesGaugeList( - Collections.unmodifiableList(new ArrayList(list))); - } - - /** - * Returns the list of {@link TimeSeriesGauge}. - * - * @return the list of {@code TimeSeriesGauge}. - * @since 0.16 - */ - public abstract List getList(); - } - - /** - * Class that holds a list of {@link TimeSeriesCumulative}. - * - * @since 0.16 - */ - @ExperimentalApi - @Immutable - @AutoValue - public abstract static class TimeSeriesCumulativeList extends TimeSeriesList { - - TimeSeriesCumulativeList() {} - - @Override - public final T match( - Function gaugeListFunction, - Function cumulativeListFunction, - Function defaultFunction) { - return cumulativeListFunction.apply(this); - } - - /** - * Creates a {@link TimeSeriesCumulativeList}. - * - * @param list a list of {@link TimeSeriesCumulative}. - * @return a {code TimeSeriesCumulativeList}. - * @since 0.16 - */ - public static TimeSeriesCumulativeList create(List list) { - Utils.checkNotNull(list, "list"); - Utils.checkListElementNotNull(list, "timeSeriesCumulative"); - return new AutoValue_TimeSeriesList_TimeSeriesCumulativeList( - Collections.unmodifiableList(new ArrayList(list))); - } - - /** - * Returns the list of {@link TimeSeriesCumulative}. - * - * @return the list of {@code TimeSeriesCumulative}. - * @since 0.16 - */ - public abstract List getList(); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/MetricTest.java b/api/src/test/java/io/opencensus/metrics/MetricTest.java index 59838ef4..37deed4b 100644 --- a/api/src/test/java/io/opencensus/metrics/MetricTest.java +++ b/api/src/test/java/io/opencensus/metrics/MetricTest.java @@ -21,10 +21,9 @@ import static com.google.common.truth.Truth.assertThat; import com.google.common.testing.EqualsTester; import io.opencensus.common.Timestamp; import io.opencensus.metrics.MetricDescriptor.Type; -import io.opencensus.metrics.TimeSeriesList.TimeSeriesCumulativeList; -import io.opencensus.metrics.TimeSeriesList.TimeSeriesGaugeList; import java.util.Arrays; import java.util.Collections; +import java.util.List; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -61,47 +60,41 @@ public class MetricTest { private static final Point POINT_1 = Point.create(VALUE_DOUBLE_1, TIMESTAMP_2); private static final Point POINT_2 = Point.create(VALUE_DOUBLE_2, TIMESTAMP_3); private static final Point POINT_3 = Point.create(VALUE_LONG, TIMESTAMP_3); - private static final TimeSeriesGauge GAUGE_TIME_SERIES_1 = - TimeSeriesGauge.create(Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1)); - private static final TimeSeriesGauge GAUGE_TIME_SERIES_2 = - TimeSeriesGauge.create(Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_2)); - private static final TimeSeriesCumulative CUMULATIVE_TIME_SERIES = - TimeSeriesCumulative.create( - Arrays.asList(LABEL_VALUE_EMPTY), Arrays.asList(POINT_3), TIMESTAMP_1); - private static final TimeSeriesGaugeList TIME_SERIES_GAUGE_LIST = - TimeSeriesGaugeList.create(Arrays.asList(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2)); - private static final TimeSeriesCumulativeList TIME_SERIES_CUMULATIVE_LIST = - TimeSeriesCumulativeList.create(Arrays.asList(CUMULATIVE_TIME_SERIES)); + private static final TimeSeries GAUGE_TIME_SERIES_1 = + TimeSeries.create(Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), null); + private static final TimeSeries GAUGE_TIME_SERIES_2 = + TimeSeries.create(Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_2), null); + private static final TimeSeries CUMULATIVE_TIME_SERIES = + TimeSeries.create(Arrays.asList(LABEL_VALUE_EMPTY), Arrays.asList(POINT_3), TIMESTAMP_1); @Test public void testGet() { - Metric metric = Metric.create(METRIC_DESCRIPTOR_1, TIME_SERIES_GAUGE_LIST); + Metric metric = + Metric.create(METRIC_DESCRIPTOR_1, Arrays.asList(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2)); assertThat(metric.getMetricDescriptor()).isEqualTo(METRIC_DESCRIPTOR_1); - assertThat(metric.getTimeSeriesList()).isEqualTo(TIME_SERIES_GAUGE_LIST); + assertThat(metric.getTimeSeriesList()) + .containsExactly(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2) + .inOrder(); } @Test - public void typeMismatch_GaugeDouble_TimeSeriesCumulative() { + public void typeMismatch_GaugeDouble_Long() { typeMismatch( METRIC_DESCRIPTOR_1, - TIME_SERIES_CUMULATIVE_LIST, - String.format( - "Type mismatch: %s, %s.", - Type.GAUGE_DOUBLE, TIME_SERIES_CUMULATIVE_LIST.getClass().getSimpleName())); + Arrays.asList(CUMULATIVE_TIME_SERIES), + String.format("Type mismatch: %s, %s.", Type.GAUGE_DOUBLE, "ValueLong")); } @Test - public void typeMismatch_CumulativeInt64_TimeSeriesGauge() { + public void typeMismatch_CumulativeInt64_Double() { typeMismatch( METRIC_DESCRIPTOR_2, - TIME_SERIES_GAUGE_LIST, - String.format( - "Type mismatch: %s, %s.", - Type.CUMULATIVE_INT64, TIME_SERIES_GAUGE_LIST.getClass().getSimpleName())); + Arrays.asList(GAUGE_TIME_SERIES_1), + String.format("Type mismatch: %s, %s.", Type.CUMULATIVE_INT64, "ValueDouble")); } private void typeMismatch( - MetricDescriptor metricDescriptor, TimeSeriesList timeSeriesList, String errorMessage) { + MetricDescriptor metricDescriptor, List timeSeriesList, String errorMessage) { thrown.expect(IllegalArgumentException.class); thrown.expectMessage(errorMessage); Metric.create(metricDescriptor, timeSeriesList); @@ -110,18 +103,14 @@ public class MetricTest { @Test public void testEquals() { new EqualsTester() - .addEqualityGroup( - Metric.create(METRIC_DESCRIPTOR_1, TIME_SERIES_GAUGE_LIST), - Metric.create(METRIC_DESCRIPTOR_1, TIME_SERIES_GAUGE_LIST)) .addEqualityGroup( Metric.create( - METRIC_DESCRIPTOR_1, - TimeSeriesGaugeList.create(Collections.emptyList()))) - .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_2, TIME_SERIES_CUMULATIVE_LIST)) - .addEqualityGroup( + METRIC_DESCRIPTOR_1, Arrays.asList(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2)), Metric.create( - METRIC_DESCRIPTOR_2, - TimeSeriesCumulativeList.create(Collections.emptyList()))) + METRIC_DESCRIPTOR_1, Arrays.asList(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2))) + .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_1, Collections.emptyList())) + .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_2, Arrays.asList(CUMULATIVE_TIME_SERIES))) + .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_2, Collections.emptyList())) .testEquals(); } } diff --git a/api/src/test/java/io/opencensus/metrics/TimeSeriesCumulativeTest.java b/api/src/test/java/io/opencensus/metrics/TimeSeriesCumulativeTest.java deleted file mode 100644 index 3532a5a5..00000000 --- a/api/src/test/java/io/opencensus/metrics/TimeSeriesCumulativeTest.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import io.opencensus.common.Timestamp; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import org.hamcrest.CoreMatchers; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link TimeSeriesCumulative}. */ -@RunWith(JUnit4.class) -public class TimeSeriesCumulativeTest { - - @Rule public ExpectedException thrown = ExpectedException.none(); - - private static final LabelValue LABEL_VALUE_1 = LabelValue.create("value1"); - private static final LabelValue LABEL_VALUE_2 = LabelValue.create("value2"); - private static final Value VALUE_LONG = Value.longValue(12345678); - private static final Value VALUE_DOUBLE = Value.doubleValue(-345.77); - private static final Timestamp TIMESTAMP_1 = Timestamp.fromMillis(1000); - private static final Timestamp TIMESTAMP_2 = Timestamp.fromMillis(2000); - private static final Timestamp TIMESTAMP_3 = Timestamp.fromMillis(3000); - private static final Point POINT_1 = Point.create(VALUE_DOUBLE, TIMESTAMP_2); - private static final Point POINT_2 = Point.create(VALUE_LONG, TIMESTAMP_3); - - @Test - public void testGet_TimeSeriesCumulative() { - TimeSeriesCumulative cumulativeTimeSeries = - TimeSeriesCumulative.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1); - assertThat(cumulativeTimeSeries.getStartTimestamp()).isEqualTo(TIMESTAMP_1); - assertThat(cumulativeTimeSeries.getLabelValues()) - .containsExactly(LABEL_VALUE_1, LABEL_VALUE_2) - .inOrder(); - assertThat(cumulativeTimeSeries.getPoints()).containsExactly(POINT_1).inOrder(); - } - - @Test - public void create_WithNullLabelValueList() { - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("labelValues")); - TimeSeriesCumulative.create(null, Collections.emptyList(), TIMESTAMP_1); - } - - @Test - public void create_WithNullLabelValue() { - List labelValues = Arrays.asList(LABEL_VALUE_1, null); - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("labelValue")); - TimeSeriesCumulative.create(labelValues, Collections.emptyList(), TIMESTAMP_1); - } - - @Test - public void create_WithNullPointList() { - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("points")); - TimeSeriesCumulative.create(Collections.emptyList(), null, TIMESTAMP_1); - } - - @Test - public void create_WithNullPoint() { - List points = Arrays.asList(POINT_1, null); - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("point")); - TimeSeriesCumulative.create(Collections.emptyList(), points, TIMESTAMP_1); - } - - @Test - public void testEquals() { - new EqualsTester() - .addEqualityGroup( - TimeSeriesCumulative.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1), - TimeSeriesCumulative.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1)) - .addEqualityGroup( - TimeSeriesCumulative.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_2)) - .addEqualityGroup( - TimeSeriesCumulative.create( - Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_1), TIMESTAMP_2)) - .addEqualityGroup( - TimeSeriesCumulative.create( - Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_2), TIMESTAMP_2)) - .addEqualityGroup( - TimeSeriesCumulative.create( - Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_1, POINT_2), TIMESTAMP_2)) - .testEquals(); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/TimeSeriesGaugeTest.java b/api/src/test/java/io/opencensus/metrics/TimeSeriesGaugeTest.java deleted file mode 100644 index 83f7c267..00000000 --- a/api/src/test/java/io/opencensus/metrics/TimeSeriesGaugeTest.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import io.opencensus.common.Timestamp; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import org.hamcrest.CoreMatchers; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link TimeSeriesGauge}. */ -@RunWith(JUnit4.class) -public class TimeSeriesGaugeTest { - - @Rule public ExpectedException thrown = ExpectedException.none(); - - private static final LabelValue LABEL_VALUE_1 = LabelValue.create("value1"); - private static final LabelValue LABEL_VALUE_2 = LabelValue.create("value2"); - private static final Value VALUE_LONG = Value.longValue(12345678); - private static final Value VALUE_DOUBLE = Value.doubleValue(-345.77); - private static final Timestamp TIMESTAMP_1 = Timestamp.fromMillis(1000); - private static final Timestamp TIMESTAMP_2 = Timestamp.fromMillis(2000); - private static final Point POINT_1 = Point.create(VALUE_DOUBLE, TIMESTAMP_1); - private static final Point POINT_2 = Point.create(VALUE_LONG, TIMESTAMP_2); - - @Test - public void testGet_TimeSeriesGauge() { - TimeSeriesGauge gaugeTimeSeries = - TimeSeriesGauge.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1, POINT_2)); - assertThat(gaugeTimeSeries.getLabelValues()) - .containsExactly(LABEL_VALUE_1, LABEL_VALUE_2) - .inOrder(); - assertThat(gaugeTimeSeries.getPoints()).containsExactly(POINT_1, POINT_2).inOrder(); - } - - @Test - public void create_WithNullLabelValueList() { - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("labelValues")); - TimeSeriesGauge.create(null, Collections.emptyList()); - } - - @Test - public void create_WithNullLabelValue() { - List labelValues = Arrays.asList(LABEL_VALUE_1, null); - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("labelValue")); - TimeSeriesGauge.create(labelValues, Collections.emptyList()); - } - - @Test - public void create_WithNullPointList() { - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("points")); - TimeSeriesGauge.create(Collections.emptyList(), null); - } - - @Test - public void create_WithNullPoint() { - List points = Arrays.asList(POINT_1, null); - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("point")); - TimeSeriesGauge.create(Collections.emptyList(), points); - } - - @Test - public void testEquals() { - new EqualsTester() - .addEqualityGroup( - TimeSeriesGauge.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1, POINT_2)), - TimeSeriesGauge.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1, POINT_2))) - .addEqualityGroup( - TimeSeriesGauge.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1))) - .addEqualityGroup( - TimeSeriesGauge.create(Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_1))) - .testEquals(); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/TimeSeriesListTest.java b/api/src/test/java/io/opencensus/metrics/TimeSeriesListTest.java deleted file mode 100644 index 46ace50f..00000000 --- a/api/src/test/java/io/opencensus/metrics/TimeSeriesListTest.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import io.opencensus.common.Functions; -import io.opencensus.common.Timestamp; -import io.opencensus.metrics.TimeSeriesList.TimeSeriesCumulativeList; -import io.opencensus.metrics.TimeSeriesList.TimeSeriesGaugeList; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import org.hamcrest.CoreMatchers; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link TimeSeries}. */ -@RunWith(JUnit4.class) -public class TimeSeriesListTest { - - @Rule public ExpectedException thrown = ExpectedException.none(); - - private static final LabelValue LABEL_VALUE_1 = LabelValue.create("value1"); - private static final LabelValue LABEL_VALUE_2 = LabelValue.create("value2"); - private static final LabelValue LABEL_VALUE_EMPTY = LabelValue.create(""); - private static final Value VALUE_LONG = Value.longValue(12345678); - private static final Value VALUE_DOUBLE = Value.doubleValue(-345.77); - private static final Timestamp TIMESTAMP_1 = Timestamp.fromMillis(1000); - private static final Timestamp TIMESTAMP_2 = Timestamp.fromMillis(2000); - private static final Timestamp TIMESTAMP_3 = Timestamp.fromMillis(3000); - private static final Point POINT_1 = Point.create(VALUE_DOUBLE, TIMESTAMP_2); - private static final Point POINT_2 = Point.create(VALUE_LONG, TIMESTAMP_3); - private static final TimeSeriesGauge TIME_SERIES_GAUGE = - TimeSeriesGauge.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1, POINT_2)); - private static final TimeSeriesCumulative TIME_SERIES_CUMULATIVE = - TimeSeriesCumulative.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_EMPTY), Arrays.asList(POINT_1), TIMESTAMP_1); - - @Test - public void testGet_TimeSeriesGaugeList() { - TimeSeriesGaugeList gaugeTimeSeriesList = - TimeSeriesGaugeList.create(Collections.singletonList(TIME_SERIES_GAUGE)); - assertThat(gaugeTimeSeriesList.getList()).containsExactly(TIME_SERIES_GAUGE); - } - - @Test - public void testGet_TimeSeriesCumulativeList() { - TimeSeriesCumulativeList cumulativeTimeSeriesList = - TimeSeriesCumulativeList.create(Collections.singletonList(TIME_SERIES_CUMULATIVE)); - assertThat(cumulativeTimeSeriesList.getList()).containsExactly(TIME_SERIES_CUMULATIVE); - } - - @Test - public void createGaugeList_WithNullList() { - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("list")); - TimeSeriesGaugeList.create(null); - } - - @Test - public void createGaugeList_WithNullTimeSeries() { - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("timeSeriesGauge")); - TimeSeriesGaugeList.create(Arrays.asList(TIME_SERIES_GAUGE, null)); - } - - @Test - public void createCumulativeList_WithNullList() { - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("list")); - TimeSeriesCumulativeList.create(null); - } - - @Test - public void createCumulativeList_WithNullTimeSeries() { - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("timeSeriesCumulative")); - TimeSeriesCumulativeList.create(Arrays.asList(TIME_SERIES_CUMULATIVE, null)); - } - - @Test - public void testEquals() { - new EqualsTester() - .addEqualityGroup( - TimeSeriesGaugeList.create(Collections.singletonList(TIME_SERIES_GAUGE)), - TimeSeriesGaugeList.create(Collections.singletonList(TIME_SERIES_GAUGE))) - .addEqualityGroup( - TimeSeriesCumulativeList.create(Collections.singletonList(TIME_SERIES_CUMULATIVE)), - TimeSeriesCumulativeList.create(Collections.singletonList(TIME_SERIES_CUMULATIVE))) - .addEqualityGroup(TimeSeriesGaugeList.create(Collections.emptyList())) - .addEqualityGroup( - TimeSeriesCumulativeList.create(Collections.emptyList())) - .testEquals(); - } - - @Test - public void testMatch() { - TimeSeriesList gaugeTimeSeriesList = - TimeSeriesGaugeList.create(Collections.singletonList(TIME_SERIES_GAUGE)); - TimeSeriesList cumulativeTimeSeriesList = - TimeSeriesCumulativeList.create(Collections.singletonList(TIME_SERIES_CUMULATIVE)); - - final List actual = new ArrayList(); - for (TimeSeriesList timeSeriesList : - Arrays.asList(cumulativeTimeSeriesList, gaugeTimeSeriesList)) { - actual.add( - timeSeriesList.match( - Functions.returnConstant("TimeSeriesGaugeList"), - Functions.returnConstant("TimeSeriesCumulativeList"), - Functions.throwAssertionError())); - } - assertThat(actual).containsExactly("TimeSeriesCumulativeList", "TimeSeriesGaugeList").inOrder(); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/TimeSeriesTest.java b/api/src/test/java/io/opencensus/metrics/TimeSeriesTest.java new file mode 100644 index 00000000..07dff97d --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/TimeSeriesTest.java @@ -0,0 +1,116 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Timestamp; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.hamcrest.CoreMatchers; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TimeSeries}. */ +@RunWith(JUnit4.class) +public class TimeSeriesTest { + + @Rule public ExpectedException thrown = ExpectedException.none(); + + private static final LabelValue LABEL_VALUE_1 = LabelValue.create("value1"); + private static final LabelValue LABEL_VALUE_2 = LabelValue.create("value2"); + private static final Value VALUE_LONG = Value.longValue(12345678); + private static final Value VALUE_DOUBLE = Value.doubleValue(-345.77); + private static final Timestamp TIMESTAMP_1 = Timestamp.fromMillis(1000); + private static final Timestamp TIMESTAMP_2 = Timestamp.fromMillis(2000); + private static final Timestamp TIMESTAMP_3 = Timestamp.fromMillis(3000); + private static final Point POINT_1 = Point.create(VALUE_DOUBLE, TIMESTAMP_2); + private static final Point POINT_2 = Point.create(VALUE_LONG, TIMESTAMP_3); + + @Test + public void testGet_TimeSeries() { + TimeSeries cumulativeTimeSeries = + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1); + assertThat(cumulativeTimeSeries.getStartTimestamp()).isEqualTo(TIMESTAMP_1); + assertThat(cumulativeTimeSeries.getLabelValues()) + .containsExactly(LABEL_VALUE_1, LABEL_VALUE_2) + .inOrder(); + assertThat(cumulativeTimeSeries.getPoints()).containsExactly(POINT_1).inOrder(); + } + + @Test + public void create_WithNullLabelValueList() { + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("labelValues")); + TimeSeries.create(null, Collections.emptyList(), TIMESTAMP_1); + } + + @Test + public void create_WithNullLabelValue() { + List labelValues = Arrays.asList(LABEL_VALUE_1, null); + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("labelValue")); + TimeSeries.create(labelValues, Collections.emptyList(), TIMESTAMP_1); + } + + @Test + public void create_WithNullPointList() { + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("points")); + TimeSeries.create(Collections.emptyList(), null, TIMESTAMP_1); + } + + @Test + public void create_WithNullPoint() { + List points = Arrays.asList(POINT_1, null); + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("point")); + TimeSeries.create(Collections.emptyList(), points, TIMESTAMP_1); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1), + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1)) + .addEqualityGroup( + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), null), + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), null)) + .addEqualityGroup( + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_2)) + .addEqualityGroup( + TimeSeries.create(Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_1), TIMESTAMP_2)) + .addEqualityGroup( + TimeSeries.create(Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_2), TIMESTAMP_2)) + .addEqualityGroup( + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_1, POINT_2), TIMESTAMP_2)) + .testEquals(); + } +} -- cgit v1.2.3 From 01f2d7503e0d33abd930e0191f92b5a4a8f0fcd3 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Wed, 22 Aug 2018 13:22:14 -0700 Subject: Add missing Javadoc. (#1383) --- api/src/main/java/io/opencensus/metrics/Distribution.java | 4 ++-- api/src/main/java/io/opencensus/metrics/Metrics.java | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/metrics/Distribution.java b/api/src/main/java/io/opencensus/metrics/Distribution.java index 5334a8d8..bdea7762 100644 --- a/api/src/main/java/io/opencensus/metrics/Distribution.java +++ b/api/src/main/java/io/opencensus/metrics/Distribution.java @@ -156,9 +156,9 @@ public abstract class Distribution { public abstract List getBucketBoundaries(); /** - * Returns the the aggregated histogram {@link Bucket}s. + * Returns the aggregated histogram {@link Bucket}s. * - * @return the the aggregated histogram buckets. + * @return the aggregated histogram buckets. * @since 0.16 */ public abstract List getBuckets(); diff --git a/api/src/main/java/io/opencensus/metrics/Metrics.java b/api/src/main/java/io/opencensus/metrics/Metrics.java index ed7d6716..521fbd08 100644 --- a/api/src/main/java/io/opencensus/metrics/Metrics.java +++ b/api/src/main/java/io/opencensus/metrics/Metrics.java @@ -24,6 +24,11 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; +/** + * Class for accessing the default {@link MetricsComponent}. + * + * @since 0.16 + */ @ExperimentalApi public final class Metrics { private static final Logger logger = Logger.getLogger(Metrics.class.getName()); -- cgit v1.2.3 From 217a1e86dd1082296b7278253f5f51633191fb06 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Mon, 27 Aug 2018 10:09:52 -0700 Subject: Use Utils.checkNotNull instead of writing the null check. (#1385) --- api/src/main/java/io/opencensus/trace/export/SpanData.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/export/SpanData.java b/api/src/main/java/io/opencensus/trace/export/SpanData.java index f0a51bf3..f4dd4682 100644 --- a/api/src/main/java/io/opencensus/trace/export/SpanData.java +++ b/api/src/main/java/io/opencensus/trace/export/SpanData.java @@ -125,9 +125,7 @@ public abstract class SpanData { @Nullable Integer childSpanCount, @Nullable Status status, @Nullable Timestamp endTimestamp) { - if (messageOrNetworkEvents == null) { - throw new NullPointerException("Null messageOrNetworkEvents"); - } + Utils.checkNotNull(messageOrNetworkEvents, "messageOrNetworkEvents"); List> messageEventsList = new ArrayList>(); for (TimedEvent timedEvent : messageOrNetworkEvents.getEvents()) { -- cgit v1.2.3 From 8901e4eb583785efaa2c3adea882d850662d93fc Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Mon, 27 Aug 2018 15:40:12 -0700 Subject: Add get/from{Byte} methods on TraceOptions and deprecate get/from{Bytes}. (#1392) * Add get/from{Byte} methods on TraceOptions and deprecate get/from{Bytes}. * Update changelog. --- .../java/io/opencensus/trace/TraceOptions.java | 36 ++++++++++++++++--- .../java/io/opencensus/trace/TraceOptionsTest.java | 40 +++++++++++++++------- 2 files changed, 59 insertions(+), 17 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/TraceOptions.java b/api/src/main/java/io/opencensus/trace/TraceOptions.java index f34ba190..86379f1e 100644 --- a/api/src/main/java/io/opencensus/trace/TraceOptions.java +++ b/api/src/main/java/io/opencensus/trace/TraceOptions.java @@ -48,7 +48,7 @@ public final class TraceOptions { * * @since 0.5 */ - public static final TraceOptions DEFAULT = new TraceOptions(DEFAULT_OPTIONS); + public static final TraceOptions DEFAULT = fromByte(DEFAULT_OPTIONS); // The set of enabled features is determined by all the enabled bits. private final byte options; @@ -72,13 +72,15 @@ public final class TraceOptions { * @throws NullPointerException if {@code buffer} is null. * @throws IllegalArgumentException if {@code buffer.length} is not {@link TraceOptions#SIZE}. * @since 0.5 + * @deprecated use {@link #fromByte(byte)}. */ + @Deprecated public static TraceOptions fromBytes(byte[] buffer) { Utils.checkNotNull(buffer, "buffer"); Utils.checkArgument( buffer.length == SIZE, String.format("Invalid size: expected %s, got %s", SIZE, buffer.length)); - return new TraceOptions(buffer[0]); + return fromByte(buffer[0]); } /** @@ -93,10 +95,34 @@ public final class TraceOptions { * @throws IndexOutOfBoundsException if {@code srcOffset+TraceOptions.SIZE} is greater than {@code * src.length}. * @since 0.5 + * @deprecated use {@link #fromByte(byte)}. */ + @Deprecated public static TraceOptions fromBytes(byte[] src, int srcOffset) { Utils.checkIndex(srcOffset, src.length); - return new TraceOptions(src[srcOffset]); + return fromByte(src[srcOffset]); + } + + /** + * Returns a {@code TraceOptions} whose representation is {@code src}. + * + * @param src the byte representation of the {@code TraceOptions}. + * @return a {@code TraceOptions} whose representation is {@code src}. + * @since 0.16 + */ + public static TraceOptions fromByte(byte src) { + // TODO(bdrutu): OPTIMIZATION: Cache all the 256 possible objects and return from the cache. + return new TraceOptions(src); + } + + /** + * Returns the one byte representation of the {@code TraceOptions}. + * + * @return the one byte representation of the {@code TraceOptions}. + * @since 0.16 + */ + public byte getByte() { + return options; } /** @@ -104,7 +130,9 @@ public final class TraceOptions { * * @return the 1-byte array representation of the {@code TraceOptions}. * @since 0.5 + * @deprecated use {@link #getByte()}. */ + @Deprecated public byte[] getBytes() { byte[] bytes = new byte[SIZE]; bytes[0] = options; @@ -237,7 +265,7 @@ public final class TraceOptions { * @since 0.5 */ public TraceOptions build() { - return new TraceOptions(options); + return fromByte(options); } } diff --git a/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java b/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java index a892384b..3c46d097 100644 --- a/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java +++ b/api/src/test/java/io/opencensus/trace/TraceOptionsTest.java @@ -26,9 +26,9 @@ import org.junit.runners.JUnit4; /** Unit tests for {@link TraceOptions}. */ @RunWith(JUnit4.class) public class TraceOptionsTest { - private static final byte[] firstBytes = {(byte) 0xff}; - private static final byte[] secondBytes = {1}; - private static final byte[] thirdBytes = {6}; + private static final byte FIRST_BYTE = (byte) 0xff; + private static final byte SECOND_BYTE = 1; + private static final byte THIRD_BYTE = 6; @Test public void getOptions() { @@ -37,9 +37,9 @@ public class TraceOptionsTest { assertThat(TraceOptions.builder().setIsSampled(true).build().getOptions()).isEqualTo(1); assertThat(TraceOptions.builder().setIsSampled(true).setIsSampled(false).build().getOptions()) .isEqualTo(0); - assertThat(TraceOptions.fromBytes(firstBytes).getOptions()).isEqualTo(-1); - assertThat(TraceOptions.fromBytes(secondBytes).getOptions()).isEqualTo(1); - assertThat(TraceOptions.fromBytes(thirdBytes).getOptions()).isEqualTo(6); + assertThat(TraceOptions.fromByte(FIRST_BYTE).getOptions()).isEqualTo(-1); + assertThat(TraceOptions.fromByte(SECOND_BYTE).getOptions()).isEqualTo(1); + assertThat(TraceOptions.fromByte(THIRD_BYTE).getOptions()).isEqualTo(6); } @Test @@ -49,16 +49,30 @@ public class TraceOptionsTest { } @Test - public void toFromBytes() { - assertThat(TraceOptions.fromBytes(firstBytes).getBytes()).isEqualTo(firstBytes); - assertThat(TraceOptions.fromBytes(secondBytes).getBytes()).isEqualTo(secondBytes); - assertThat(TraceOptions.fromBytes(thirdBytes).getBytes()).isEqualTo(thirdBytes); + public void toFromByte() { + assertThat(TraceOptions.fromByte(FIRST_BYTE).getByte()).isEqualTo(FIRST_BYTE); + assertThat(TraceOptions.fromByte(SECOND_BYTE).getByte()).isEqualTo(SECOND_BYTE); + assertThat(TraceOptions.fromByte(THIRD_BYTE).getByte()).isEqualTo(THIRD_BYTE); + } + + @Test + @SuppressWarnings("deprecation") + public void deprecated_fromBytes() { + assertThat(TraceOptions.fromBytes(new byte[] {FIRST_BYTE}).getByte()).isEqualTo(FIRST_BYTE); + assertThat(TraceOptions.fromBytes(new byte[] {1, FIRST_BYTE}, 1).getByte()) + .isEqualTo(FIRST_BYTE); + } + + @Test + @SuppressWarnings("deprecation") + public void deprecated_getBytes() { + assertThat(TraceOptions.fromByte(FIRST_BYTE).getBytes()).isEqualTo(new byte[] {FIRST_BYTE}); } @Test public void builder_FromOptions() { assertThat( - TraceOptions.builder(TraceOptions.fromBytes(thirdBytes)) + TraceOptions.builder(TraceOptions.fromByte(THIRD_BYTE)) .setIsSampled(true) .build() .getOptions()) @@ -70,8 +84,8 @@ public class TraceOptionsTest { EqualsTester tester = new EqualsTester(); tester.addEqualityGroup(TraceOptions.DEFAULT); tester.addEqualityGroup( - TraceOptions.fromBytes(secondBytes), TraceOptions.builder().setIsSampled(true).build()); - tester.addEqualityGroup(TraceOptions.fromBytes(firstBytes)); + TraceOptions.fromByte(SECOND_BYTE), TraceOptions.builder().setIsSampled(true).build()); + tester.addEqualityGroup(TraceOptions.fromByte(FIRST_BYTE)); tester.testEquals(); } -- cgit v1.2.3 From eabc800c3749ca6f8e3a17f057ae11c8d1385d0c Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Tue, 28 Aug 2018 14:40:27 -0700 Subject: Avoid doing string formatting when calling checkArgument. (#1394) --- .../main/java/io/opencensus/internal/Utils.java | 107 ++++++++++++++++++--- api/src/main/java/io/opencensus/stats/Measure.java | 13 ++- api/src/main/java/io/opencensus/tags/TagKey.java | 2 +- api/src/main/java/io/opencensus/tags/TagValue.java | 2 +- api/src/main/java/io/opencensus/trace/SpanId.java | 8 +- api/src/main/java/io/opencensus/trace/TraceId.java | 8 +- .../java/io/opencensus/trace/TraceOptions.java | 3 +- .../main/java/io/opencensus/trace/Tracestate.java | 4 +- .../java/io/opencensus/internal/UtilsTest.java | 39 ++++++++ 9 files changed, 151 insertions(+), 35 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/internal/Utils.java b/api/src/main/java/io/opencensus/internal/Utils.java index a2c09c82..df5c9840 100644 --- a/api/src/main/java/io/opencensus/internal/Utils.java +++ b/api/src/main/java/io/opencensus/internal/Utils.java @@ -17,7 +17,6 @@ package io.opencensus.internal; import java.util.List; -import javax.annotation.Nullable; /*>>> import org.checkerframework.checker.nullness.qual.NonNull; @@ -33,11 +32,38 @@ public final class Utils { * {@code Preconditions.checkArgument(boolean, Object)} from Guava. * * @param isValid whether the argument check passed. - * @param message the message to use for the exception. + * @param errorMessage the message to use for the exception. Will be converted to a string using + * {@link String#valueOf(Object)}. */ - public static void checkArgument(boolean isValid, String message) { + public static void checkArgument( + boolean isValid, @javax.annotation.Nullable Object errorMessage) { if (!isValid) { - throw new IllegalArgumentException(message); + throw new IllegalArgumentException(String.valueOf(errorMessage)); + } + } + + /** + * Throws an {@link IllegalArgumentException} if the argument is false. This method is similar to + * {@code Preconditions.checkArgument(boolean, Object)} from Guava. + * + * @param expression a boolean expression + * @param errorMessageTemplate a template for the exception message should the check fail. The + * message is formed by replacing each {@code %s} placeholder in the template with an + * argument. These are matched by position - the first {@code %s} gets {@code + * errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message in + * square braces. Unmatched placeholders will be left as-is. + * @param errorMessageArgs the arguments to be substituted into the message template. Arguments + * are converted to strings using {@link String#valueOf(Object)}. + * @throws IllegalArgumentException if {@code expression} is false + * @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or + * {@code errorMessageArgs} is null (don't let this happen) + */ + public static void checkArgument( + boolean expression, + String errorMessageTemplate, + @javax.annotation.Nullable Object... errorMessageArgs) { + if (!expression) { + throw new IllegalArgumentException(format(errorMessageTemplate, errorMessageArgs)); } } @@ -46,11 +72,12 @@ public final class Utils { * {@code Preconditions.checkState(boolean, Object)} from Guava. * * @param isValid whether the state check passed. - * @param message the message to use for the exception. + * @param errorMessage the message to use for the exception. Will be converted to a string using + * {@link String#valueOf(Object)}. */ - public static void checkState(boolean isValid, String message) { + public static void checkState(boolean isValid, @javax.annotation.Nullable Object errorMessage) { if (!isValid) { - throw new IllegalStateException(message); + throw new IllegalStateException(String.valueOf(errorMessage)); } } @@ -77,12 +104,14 @@ public final class Utils { * Preconditions.checkNotNull(Object, Object)} from Guava. * * @param arg the argument to check for null. - * @param message the message to use for the exception. + * @param errorMessage the message to use for the exception. Will be converted to a string using + * {@link String#valueOf(Object)}. * @return the argument, if it passes the null check. */ - public static >> extends @NonNull Object*/> T checkNotNull(T arg, String message) { + public static >> extends @NonNull Object*/> T checkNotNull( + T arg, @javax.annotation.Nullable Object errorMessage) { if (arg == null) { - throw new NullPointerException(message); + throw new NullPointerException(String.valueOf(errorMessage)); } return arg; } @@ -91,13 +120,14 @@ public final class Utils { * Throws a {@link NullPointerException} if any of the list elements is null. * * @param list the argument list to check for null. - * @param message the message to use for the exception. + * @param errorMessage the message to use for the exception. Will be converted to a string using + * {@link String#valueOf(Object)}. */ public static >> extends @NonNull Object*/> void checkListElementNotNull( - List list, String message) { + List list, @javax.annotation.Nullable Object errorMessage) { for (T element : list) { if (element == null) { - throw new NullPointerException(message); + throw new NullPointerException(String.valueOf(errorMessage)); } } } @@ -106,7 +136,56 @@ public final class Utils { * Compares two Objects for equality. This functionality is provided by {@code * Objects.equal(Object, Object)} in Java 7. */ - public static boolean equalsObjects(@Nullable Object x, @Nullable Object y) { + public static boolean equalsObjects( + @javax.annotation.Nullable Object x, @javax.annotation.Nullable Object y) { return x == null ? y == null : x.equals(y); } + + /** + * Substitutes each {@code %s} in {@code template} with an argument. These are matched by + * position: the first {@code %s} gets {@code args[0]}, etc. If there are more arguments than + * placeholders, the unmatched arguments will be appended to the end of the formatted message in + * square braces. + * + *

    Copied from {@code Preconditions.format(String, Object...)} from Guava + * + * @param template a non-null string containing 0 or more {@code %s} placeholders. + * @param args the arguments to be substituted into the message template. Arguments are converted + * to strings using {@link String#valueOf(Object)}. Arguments can be null. + */ + // Note that this is somewhat-improperly used from Verify.java as well. + private static String format(String template, @javax.annotation.Nullable Object... args) { + // If no arguments return the template. + if (args == null) { + return template; + } + + // start substituting the arguments into the '%s' placeholders + StringBuilder builder = new StringBuilder(template.length() + 16 * args.length); + int templateStart = 0; + int i = 0; + while (i < args.length) { + int placeholderStart = template.indexOf("%s", templateStart); + if (placeholderStart == -1) { + break; + } + builder.append(template, templateStart, placeholderStart); + builder.append(args[i++]); + templateStart = placeholderStart + 2; + } + builder.append(template, templateStart, template.length()); + + // if we run out of placeholders, append the extra args in square braces + if (i < args.length) { + builder.append(" ["); + builder.append(args[i++]); + while (i < args.length) { + builder.append(", "); + builder.append(args[i++]); + } + builder.append(']'); + } + + return builder.toString(); + } } diff --git a/api/src/main/java/io/opencensus/stats/Measure.java b/api/src/main/java/io/opencensus/stats/Measure.java index 4b47cd79..2de7fd70 100644 --- a/api/src/main/java/io/opencensus/stats/Measure.java +++ b/api/src/main/java/io/opencensus/stats/Measure.java @@ -30,8 +30,11 @@ import javax.annotation.concurrent.Immutable; */ @Immutable public abstract class Measure { - @DefaultVisibilityForTesting static final int NAME_MAX_LENGTH = 255; + private static final String ERROR_MESSAGE_INVALID_NAME = + "Name should be a ASCII string with a length no greater than " + + NAME_MAX_LENGTH + + " characters."; /** * Applies the given match function to the underlying data type. @@ -105,9 +108,7 @@ public abstract class Measure { public static MeasureDouble create(String name, String description, String unit) { Utils.checkArgument( StringUtils.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, - "Name should be a ASCII string with a length no greater than " - + NAME_MAX_LENGTH - + " characters."); + ERROR_MESSAGE_INVALID_NAME); return new AutoValue_Measure_MeasureDouble(name, description, unit); } @@ -152,9 +153,7 @@ public abstract class Measure { public static MeasureLong create(String name, String description, String unit) { Utils.checkArgument( StringUtils.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, - "Name should be a ASCII string with a length no greater than " - + NAME_MAX_LENGTH - + " characters."); + ERROR_MESSAGE_INVALID_NAME); return new AutoValue_Measure_MeasureLong(name, description, unit); } diff --git a/api/src/main/java/io/opencensus/tags/TagKey.java b/api/src/main/java/io/opencensus/tags/TagKey.java index 615c2d46..ca4582bd 100644 --- a/api/src/main/java/io/opencensus/tags/TagKey.java +++ b/api/src/main/java/io/opencensus/tags/TagKey.java @@ -60,7 +60,7 @@ public abstract class TagKey { * @since 0.8 */ public static TagKey create(String name) { - Utils.checkArgument(isValid(name), "Invalid TagKey name: " + name); + Utils.checkArgument(isValid(name), "Invalid TagKey name: %s", name); return new AutoValue_TagKey(name); } diff --git a/api/src/main/java/io/opencensus/tags/TagValue.java b/api/src/main/java/io/opencensus/tags/TagValue.java index 5c1019ff..9111ca28 100644 --- a/api/src/main/java/io/opencensus/tags/TagValue.java +++ b/api/src/main/java/io/opencensus/tags/TagValue.java @@ -55,7 +55,7 @@ public abstract class TagValue { * @since 0.8 */ public static TagValue create(String value) { - Utils.checkArgument(isValid(value), "Invalid TagValue: " + value); + Utils.checkArgument(isValid(value), "Invalid TagValue: %s", value); return new AutoValue_TagValue(value); } diff --git a/api/src/main/java/io/opencensus/trace/SpanId.java b/api/src/main/java/io/opencensus/trace/SpanId.java index 1556bde0..06ff0458 100644 --- a/api/src/main/java/io/opencensus/trace/SpanId.java +++ b/api/src/main/java/io/opencensus/trace/SpanId.java @@ -38,6 +38,8 @@ public final class SpanId implements Comparable { */ public static final int SIZE = 8; + private static final int HEX_SIZE = 2 * SIZE; + /** * The invalid {@code SpanId}. All bytes are 0. * @@ -70,8 +72,7 @@ public final class SpanId implements Comparable { public static SpanId fromBytes(byte[] buffer) { Utils.checkNotNull(buffer, "buffer"); Utils.checkArgument( - buffer.length == SIZE, - String.format("Invalid size: expected %s, got %s", SIZE, buffer.length)); + buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); byte[] bytesCopied = Arrays.copyOf(buffer, SIZE); return new SpanId(bytesCopied); } @@ -107,8 +108,7 @@ public final class SpanId implements Comparable { */ public static SpanId fromLowerBase16(CharSequence src) { Utils.checkArgument( - src.length() == 2 * SIZE, - String.format("Invalid size: expected %s, got %s", 2 * SIZE, src.length())); + src.length() == HEX_SIZE, "Invalid size: expected %s, got %s", HEX_SIZE, src.length()); byte[] bytes = BaseEncoding.base16().lowerCase().decode(src); return new SpanId(bytes); } diff --git a/api/src/main/java/io/opencensus/trace/TraceId.java b/api/src/main/java/io/opencensus/trace/TraceId.java index a02a4e05..c7aa48f0 100644 --- a/api/src/main/java/io/opencensus/trace/TraceId.java +++ b/api/src/main/java/io/opencensus/trace/TraceId.java @@ -39,6 +39,8 @@ public final class TraceId implements Comparable { */ public static final int SIZE = 16; + private static final int HEX_SIZE = 32; + /** * The invalid {@code TraceId}. All bytes are '\0'. * @@ -71,8 +73,7 @@ public final class TraceId implements Comparable { public static TraceId fromBytes(byte[] buffer) { Utils.checkNotNull(buffer, "buffer"); Utils.checkArgument( - buffer.length == SIZE, - String.format("Invalid size: expected %s, got %s", SIZE, buffer.length)); + buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); byte[] bytesCopied = Arrays.copyOf(buffer, SIZE); return new TraceId(bytesCopied); } @@ -108,8 +109,7 @@ public final class TraceId implements Comparable { */ public static TraceId fromLowerBase16(CharSequence src) { Utils.checkArgument( - src.length() == 2 * SIZE, - String.format("Invalid size: expected %s, got %s", 2 * SIZE, src.length())); + src.length() == HEX_SIZE, "Invalid size: expected %s, got %s", HEX_SIZE, src.length()); byte[] bytes = BaseEncoding.base16().lowerCase().decode(src); return new TraceId(bytes); } diff --git a/api/src/main/java/io/opencensus/trace/TraceOptions.java b/api/src/main/java/io/opencensus/trace/TraceOptions.java index 86379f1e..218f4dab 100644 --- a/api/src/main/java/io/opencensus/trace/TraceOptions.java +++ b/api/src/main/java/io/opencensus/trace/TraceOptions.java @@ -78,8 +78,7 @@ public final class TraceOptions { public static TraceOptions fromBytes(byte[] buffer) { Utils.checkNotNull(buffer, "buffer"); Utils.checkArgument( - buffer.length == SIZE, - String.format("Invalid size: expected %s, got %s", SIZE, buffer.length)); + buffer.length == SIZE, "Invalid size: expected %s, got %s", SIZE, buffer.length); return fromByte(buffer[0]); } diff --git a/api/src/main/java/io/opencensus/trace/Tracestate.java b/api/src/main/java/io/opencensus/trace/Tracestate.java index f88d3bd3..dae587c8 100644 --- a/api/src/main/java/io/opencensus/trace/Tracestate.java +++ b/api/src/main/java/io/opencensus/trace/Tracestate.java @@ -201,8 +201,8 @@ public abstract class Tracestate { public static Entry create(String key, String value) { Utils.checkNotNull(key, "key"); Utils.checkNotNull(value, "value"); - Utils.checkArgument(validateKey(key), "Invalid key " + key); - Utils.checkArgument(validateValue(value), "Invalid value " + value); + Utils.checkArgument(validateKey(key), "Invalid key %s", key); + Utils.checkArgument(validateValue(value), "Invalid value %s", value); return new AutoValue_Tracestate_Entry(key, value); } diff --git a/api/src/test/java/io/opencensus/internal/UtilsTest.java b/api/src/test/java/io/opencensus/internal/UtilsTest.java index 983264f6..608a8fe0 100644 --- a/api/src/test/java/io/opencensus/internal/UtilsTest.java +++ b/api/src/test/java/io/opencensus/internal/UtilsTest.java @@ -30,6 +30,10 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public final class UtilsTest { private static final String TEST_MESSAGE = "test message"; + private static final String TEST_MESSAGE_TEMPLATE = "I ate %s eggs."; + private static final int TEST_MESSAGE_VALUE = 2; + private static final String FORMATED_SIMPLE_TEST_MESSAGE = "I ate 2 eggs."; + private static final String FORMATED_COMPLEX_TEST_MESSAGE = "I ate 2 eggs. [2]"; @Rule public ExpectedException thrown = ExpectedException.none(); @@ -41,6 +45,27 @@ public final class UtilsTest { Utils.checkArgument(false, TEST_MESSAGE); } + @Test + public void checkArgument_NullErrorMessage() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("null"); + Utils.checkArgument(false, null); + } + + @Test + public void checkArgument_WithSimpleFormat() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage(FORMATED_SIMPLE_TEST_MESSAGE); + Utils.checkArgument(false, TEST_MESSAGE_TEMPLATE, TEST_MESSAGE_VALUE); + } + + @Test + public void checkArgument_WithComplexFormat() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage(FORMATED_COMPLEX_TEST_MESSAGE); + Utils.checkArgument(false, TEST_MESSAGE_TEMPLATE, TEST_MESSAGE_VALUE, TEST_MESSAGE_VALUE); + } + @Test public void checkState() { Utils.checkNotNull(true, TEST_MESSAGE); @@ -49,6 +74,13 @@ public final class UtilsTest { Utils.checkState(false, TEST_MESSAGE); } + @Test + public void checkState_NullErrorMessage() { + thrown.expect(IllegalStateException.class); + thrown.expectMessage("null"); + Utils.checkState(false, null); + } + @Test public void checkNotNull() { Utils.checkNotNull(new Object(), TEST_MESSAGE); @@ -57,6 +89,13 @@ public final class UtilsTest { Utils.checkNotNull(null, TEST_MESSAGE); } + @Test + public void checkNotNull_NullErrorMessage() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("null"); + Utils.checkNotNull(null, null); + } + @Test public void checkIndex_Valid() { Utils.checkIndex(1, 2); -- cgit v1.2.3 From 658c63ad26317f1551338efb9fa95a944de0e55c Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Tue, 28 Aug 2018 15:22:20 -0700 Subject: Avoid doing string formatting when calling checkArgument for Metrics package. (#1395) --- api/src/main/java/io/opencensus/metrics/Metric.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/metrics/Metric.java b/api/src/main/java/io/opencensus/metrics/Metric.java index 9cbd418b..fa0018b3 100644 --- a/api/src/main/java/io/opencensus/metrics/Metric.java +++ b/api/src/main/java/io/opencensus/metrics/Metric.java @@ -81,19 +81,16 @@ public abstract class Metric { case GAUGE_INT64: case CUMULATIVE_INT64: Utils.checkArgument( - value instanceof ValueLong, - String.format("Type mismatch: %s, %s.", type, valueClassName)); + value instanceof ValueLong, "Type mismatch: %s, %s.", type, valueClassName); break; case CUMULATIVE_DOUBLE: case GAUGE_DOUBLE: Utils.checkArgument( - value instanceof ValueDouble, - String.format("Type mismatch: %s, %s.", type, valueClassName)); + value instanceof ValueDouble, "Type mismatch: %s, %s.", type, valueClassName); break; case CUMULATIVE_DISTRIBUTION: Utils.checkArgument( - value instanceof ValueDistribution, - String.format("Type mismatch: %s, %s.", type, valueClassName)); + value instanceof ValueDistribution, "Type mismatch: %s, %s.", type, valueClassName); } } } -- cgit v1.2.3 From d2af3ddd9f8bd10d8dbdec0d1d2b238c7e9cd175 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Tue, 28 Aug 2018 15:49:51 -0700 Subject: Remove guava dependency from the API artifact. (#1393) * Remove guava dependency from the API artifact. * Make LowerCaseBase16Encoding static and remove import control. --- api/build.gradle | 3 +- api/src/main/java/io/opencensus/trace/SpanId.java | 13 +-- api/src/main/java/io/opencensus/trace/TraceId.java | 13 +-- .../trace/internal/LowerCaseBase16Encoding.java | 93 ++++++++++++++++++++++ .../internal/LowerCaseBase16EncodingTest.java | 83 +++++++++++++++++++ 5 files changed, 185 insertions(+), 20 deletions(-) create mode 100644 api/src/main/java/io/opencensus/trace/internal/LowerCaseBase16Encoding.java create mode 100644 api/src/test/java/io/opencensus/trace/internal/LowerCaseBase16EncodingTest.java (limited to 'api') diff --git a/api/build.gradle b/api/build.gradle index 6d527c06..e494ce08 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -1,8 +1,7 @@ description = 'OpenCensus API' dependencies { - compile libraries.grpc_context, - libraries.guava + compile libraries.grpc_context compileOnly libraries.auto_value diff --git a/api/src/main/java/io/opencensus/trace/SpanId.java b/api/src/main/java/io/opencensus/trace/SpanId.java index 06ff0458..44119d6b 100644 --- a/api/src/main/java/io/opencensus/trace/SpanId.java +++ b/api/src/main/java/io/opencensus/trace/SpanId.java @@ -16,8 +16,8 @@ package io.opencensus.trace; -import com.google.common.io.BaseEncoding; import io.opencensus.internal.Utils; +import io.opencensus.trace.internal.LowerCaseBase16Encoding; import java.util.Arrays; import java.util.Random; import javax.annotation.Nullable; @@ -109,8 +109,7 @@ public final class SpanId implements Comparable { public static SpanId fromLowerBase16(CharSequence src) { Utils.checkArgument( src.length() == HEX_SIZE, "Invalid size: expected %s, got %s", HEX_SIZE, src.length()); - byte[] bytes = BaseEncoding.base16().lowerCase().decode(src); - return new SpanId(bytes); + return new SpanId(LowerCaseBase16Encoding.decodeToBytes(src)); } /** @@ -177,11 +176,7 @@ public final class SpanId implements Comparable { * @since 0.11 */ public String toLowerBase16() { - return toLowerBase16(bytes); - } - - private static String toLowerBase16(byte[] bytes) { - return BaseEncoding.base16().lowerCase().encode(bytes); + return LowerCaseBase16Encoding.encodeToString(bytes); } @Override @@ -205,7 +200,7 @@ public final class SpanId implements Comparable { @Override public String toString() { - return "SpanId{spanId=" + toLowerBase16(bytes) + "}"; + return "SpanId{spanId=" + toLowerBase16() + "}"; } @Override diff --git a/api/src/main/java/io/opencensus/trace/TraceId.java b/api/src/main/java/io/opencensus/trace/TraceId.java index c7aa48f0..983b21c3 100644 --- a/api/src/main/java/io/opencensus/trace/TraceId.java +++ b/api/src/main/java/io/opencensus/trace/TraceId.java @@ -16,9 +16,9 @@ package io.opencensus.trace; -import com.google.common.io.BaseEncoding; import io.opencensus.common.Internal; import io.opencensus.internal.Utils; +import io.opencensus.trace.internal.LowerCaseBase16Encoding; import java.util.Arrays; import java.util.Random; import javax.annotation.Nullable; @@ -110,8 +110,7 @@ public final class TraceId implements Comparable { public static TraceId fromLowerBase16(CharSequence src) { Utils.checkArgument( src.length() == HEX_SIZE, "Invalid size: expected %s, got %s", HEX_SIZE, src.length()); - byte[] bytes = BaseEncoding.base16().lowerCase().decode(src); - return new TraceId(bytes); + return new TraceId(LowerCaseBase16Encoding.decodeToBytes(src)); } /** @@ -178,11 +177,7 @@ public final class TraceId implements Comparable { * @since 0.11 */ public String toLowerBase16() { - return toLowerBase16(bytes); - } - - private static String toLowerBase16(byte[] bytes) { - return BaseEncoding.base16().lowerCase().encode(bytes); + return LowerCaseBase16Encoding.encodeToString(bytes); } /** @@ -227,7 +222,7 @@ public final class TraceId implements Comparable { @Override public String toString() { - return "TraceId{traceId=" + toLowerBase16(bytes) + "}"; + return "TraceId{traceId=" + toLowerBase16() + "}"; } @Override diff --git a/api/src/main/java/io/opencensus/trace/internal/LowerCaseBase16Encoding.java b/api/src/main/java/io/opencensus/trace/internal/LowerCaseBase16Encoding.java new file mode 100644 index 00000000..d9b2cf09 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/internal/LowerCaseBase16Encoding.java @@ -0,0 +1,93 @@ +/* + * Copyright 2018, 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.internal; + +import io.opencensus.common.Internal; +import io.opencensus.internal.Utils; +import java.util.Arrays; + +/** Internal copy of the Guava implementation of the {@code BaseEncoding.base16().lowerCase()}. */ +@Internal +public final class LowerCaseBase16Encoding { + private static final String ALPHABET = "0123456789abcdef"; + private static final int ASCII_CHARACTERS = 128; + private static final char[] ENCODING = buildEncodingArray(); + private static final byte[] DECODING = buildDecodingArray(); + + private static char[] buildEncodingArray() { + char[] encoding = new char[512]; + for (int i = 0; i < 256; ++i) { + encoding[i] = ALPHABET.charAt(i >>> 4); + encoding[i | 0x100] = ALPHABET.charAt(i & 0xF); + } + return encoding; + } + + private static byte[] buildDecodingArray() { + byte[] decoding = new byte[ASCII_CHARACTERS]; + Arrays.fill(decoding, (byte) -1); + for (int i = 0; i < ALPHABET.length(); i++) { + char c = ALPHABET.charAt(i); + decoding[c] = (byte) i; + } + return decoding; + } + + /** + * Encodes the specified byte array, and returns the encoded {@code String}. + * + * @param bytes byte array to be encoded. + * @return the encoded {@code String}. + */ + public static String encodeToString(byte[] bytes) { + StringBuilder stringBuilder = new StringBuilder(bytes.length * 2); + for (byte byteVal : bytes) { + int b = byteVal & 0xFF; + stringBuilder.append(ENCODING[b]); + stringBuilder.append(ENCODING[b | 0x100]); + } + return stringBuilder.toString(); + } + + /** + * Decodes the specified character sequence, and returns the resulting {@code byte[]}. + * + * @param chars the character sequence to be decoded. + * @return the resulting {@code byte[]} + * @throws IllegalArgumentException if the input is not a valid encoded string according to this + * encoding. + */ + public static byte[] decodeToBytes(CharSequence chars) { + Utils.checkArgument(chars.length() % 2 == 0, "Invalid input length " + chars.length()); + int bytesWritten = 0; + byte[] bytes = new byte[chars.length() / 2]; + for (int i = 0; i < chars.length(); i += 2) { + bytes[bytesWritten++] = decodeByte(chars.charAt(i), chars.charAt(i + 1)); + } + return bytes; + } + + private static byte decodeByte(char hi, char lo) { + Utils.checkArgument(lo < ASCII_CHARACTERS && DECODING[lo] != -1, "Invalid character " + lo); + Utils.checkArgument(hi < ASCII_CHARACTERS && DECODING[hi] != -1, "Invalid character " + hi); + int decoded = DECODING[hi] << 4 | DECODING[lo]; + return (byte) decoded; + } + + // Private constructor to disallow instances. + private LowerCaseBase16Encoding() {} +} diff --git a/api/src/test/java/io/opencensus/trace/internal/LowerCaseBase16EncodingTest.java b/api/src/test/java/io/opencensus/trace/internal/LowerCaseBase16EncodingTest.java new file mode 100644 index 00000000..bcc51ab6 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/internal/LowerCaseBase16EncodingTest.java @@ -0,0 +1,83 @@ +/* + * Copyright 2018, 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.internal; + +import static com.google.common.truth.Truth.assertThat; + +import java.nio.charset.Charset; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link LowerCaseBase16Encoding}. */ +@RunWith(JUnit4.class) +public class LowerCaseBase16EncodingTest { + private static final Charset CHARSET = Charset.forName("UTF-8"); + + @Rule public ExpectedException thrown = ExpectedException.none(); + + @Test + public void valid_EncodeDecode() { + testEncoding("", ""); + testEncoding("f", "66"); + testEncoding("fo", "666f"); + testEncoding("foo", "666f6f"); + testEncoding("foob", "666f6f62"); + testEncoding("fooba", "666f6f6261"); + testEncoding("foobar", "666f6f626172"); + } + + @Test + public void invalidDecodings_UnrecongnizedCharacters() { + // These contain bytes not in the decoding. + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Invalid character g"); + LowerCaseBase16Encoding.decodeToBytes("efhg"); + } + + @Test + public void invalidDecodings_InvalidInputLength() { + // Valid base16 strings always have an even length. + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Invalid input length 3"); + LowerCaseBase16Encoding.decodeToBytes("abc"); + } + + @Test + public void invalidDecodings_InvalidInputLengthAndCharacter() { + // These have a combination of invalid length and unrecognized characters. + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Invalid input length 1"); + LowerCaseBase16Encoding.decodeToBytes("?"); + } + + private static void testEncoding(String decoded, String encoded) { + testEncodes(decoded, encoded); + testDecodes(encoded, decoded); + } + + private static void testEncodes(String decoded, String encoded) { + assertThat(LowerCaseBase16Encoding.encodeToString(decoded.getBytes(CHARSET))) + .isEqualTo(encoded); + } + + private static void testDecodes(String encoded, String decoded) { + assertThat(LowerCaseBase16Encoding.decodeToBytes(encoded)).isEqualTo(decoded.getBytes(CHARSET)); + } +} -- cgit v1.2.3 From c0e0b225a5230036b3dc09134f94eece81d3f96d Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Tue, 11 Sep 2018 00:08:18 -0700 Subject: Make jmh available for all subprojects. (#1425) --- api/build.gradle | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'api') diff --git a/api/build.gradle b/api/build.gradle index e494ce08..31274ca0 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -9,5 +9,7 @@ dependencies { signature "net.sf.androidscents.signature:android-api-level-14:4.0_r4@signature" } -javadoc.exclude 'io/opencensus/internal/**' -javadoc.exclude 'io/opencensus/trace/internal/**' \ No newline at end of file +javadoc { + exclude 'io/opencensus/internal/**' + exclude 'io/opencensus/trace/internal/**' +} -- cgit v1.2.3 From d3fa0e5c60903f95c184d7c7bafae8fdd12156ad Mon Sep 17 00:00:00 2001 From: sebright Date: Wed, 12 Sep 2018 12:13:14 -0700 Subject: Temporarily move "metrics" package into impl_core/ for release. (#1426) The "metrics" package isn't ready to be released yet, so this commit moves it out of the API artifact. The package can still be accessed by the stats implementation in impl_core/. This commit can be reverted once the package is ready to be exposed. The moved package names also contain "temporary" so that there is no possibility of class name conflicts between different versions of opencensus-api and opencensus-impl-core. For example, io.opencensus.metrics.export is renamed to io.opencensus.implcore.temporary.metrics.export. --- .../io/opencensus/common/ToDoubleFunction.java | 2 +- .../java/io/opencensus/common/ToLongFunction.java | 2 +- .../java/io/opencensus/metrics/Distribution.java | 280 --------------------- .../main/java/io/opencensus/metrics/LabelKey.java | 62 ----- .../java/io/opencensus/metrics/LabelValue.java | 57 ----- .../main/java/io/opencensus/metrics/Metric.java | 98 -------- .../io/opencensus/metrics/MetricDescriptor.java | 150 ----------- .../java/io/opencensus/metrics/MetricProducer.java | 38 --- .../java/io/opencensus/metrics/MetricRegistry.java | 117 --------- .../main/java/io/opencensus/metrics/Metrics.java | 96 ------- .../io/opencensus/metrics/MetricsComponent.java | 71 ------ api/src/main/java/io/opencensus/metrics/Point.java | 63 ----- .../java/io/opencensus/metrics/TimeSeries.java | 94 ------- api/src/main/java/io/opencensus/metrics/Value.java | 196 --------------- .../opencensus/metrics/export/ExportComponent.java | 60 ----- .../metrics/export/MetricProducerManager.java | 89 ------- .../java/io/opencensus/metrics/package-info.java | 32 --- .../io/opencensus/metrics/DistributionTest.java | 226 ----------------- .../java/io/opencensus/metrics/LabelKeyTest.java | 86 ------- .../java/io/opencensus/metrics/LabelValueTest.java | 74 ------ .../opencensus/metrics/MetricDescriptorTest.java | 102 -------- .../io/opencensus/metrics/MetricRegistryTest.java | 185 -------------- .../java/io/opencensus/metrics/MetricTest.java | 116 --------- .../opencensus/metrics/MetricsComponentTest.java | 40 --- .../java/io/opencensus/metrics/MetricsTest.java | 71 ------ .../test/java/io/opencensus/metrics/PointTest.java | 68 ----- .../java/io/opencensus/metrics/TimeSeriesTest.java | 116 --------- .../test/java/io/opencensus/metrics/ValueTest.java | 128 ---------- .../metrics/export/ExportComponentTest.java | 33 --- .../metrics/export/MetricProducerManagerTest.java | 81 ------ 30 files changed, 2 insertions(+), 2831 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/metrics/Distribution.java delete mode 100644 api/src/main/java/io/opencensus/metrics/LabelKey.java delete mode 100644 api/src/main/java/io/opencensus/metrics/LabelValue.java delete mode 100644 api/src/main/java/io/opencensus/metrics/Metric.java delete mode 100644 api/src/main/java/io/opencensus/metrics/MetricDescriptor.java delete mode 100644 api/src/main/java/io/opencensus/metrics/MetricProducer.java delete mode 100644 api/src/main/java/io/opencensus/metrics/MetricRegistry.java delete mode 100644 api/src/main/java/io/opencensus/metrics/Metrics.java delete mode 100644 api/src/main/java/io/opencensus/metrics/MetricsComponent.java delete mode 100644 api/src/main/java/io/opencensus/metrics/Point.java delete mode 100644 api/src/main/java/io/opencensus/metrics/TimeSeries.java delete mode 100644 api/src/main/java/io/opencensus/metrics/Value.java delete mode 100644 api/src/main/java/io/opencensus/metrics/export/ExportComponent.java delete mode 100644 api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java delete mode 100644 api/src/main/java/io/opencensus/metrics/package-info.java delete mode 100644 api/src/test/java/io/opencensus/metrics/DistributionTest.java delete mode 100644 api/src/test/java/io/opencensus/metrics/LabelKeyTest.java delete mode 100644 api/src/test/java/io/opencensus/metrics/LabelValueTest.java delete mode 100644 api/src/test/java/io/opencensus/metrics/MetricDescriptorTest.java delete mode 100644 api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java delete mode 100644 api/src/test/java/io/opencensus/metrics/MetricTest.java delete mode 100644 api/src/test/java/io/opencensus/metrics/MetricsComponentTest.java delete mode 100644 api/src/test/java/io/opencensus/metrics/MetricsTest.java delete mode 100644 api/src/test/java/io/opencensus/metrics/PointTest.java delete mode 100644 api/src/test/java/io/opencensus/metrics/TimeSeriesTest.java delete mode 100644 api/src/test/java/io/opencensus/metrics/ValueTest.java delete mode 100644 api/src/test/java/io/opencensus/metrics/export/ExportComponentTest.java delete mode 100644 api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/ToDoubleFunction.java b/api/src/main/java/io/opencensus/common/ToDoubleFunction.java index eac85793..415f8ca9 100644 --- a/api/src/main/java/io/opencensus/common/ToDoubleFunction.java +++ b/api/src/main/java/io/opencensus/common/ToDoubleFunction.java @@ -17,7 +17,7 @@ package io.opencensus.common; /** - * Represents a function that produces a double-valued result. See {@link + * Represents a function that produces a double-valued result. See {@code * io.opencensus.metrics.MetricRegistry} for an example of its use. * *

    Note: This class is based on the java.util.ToDoubleFunction class added in Java 1.8. We cannot diff --git a/api/src/main/java/io/opencensus/common/ToLongFunction.java b/api/src/main/java/io/opencensus/common/ToLongFunction.java index 26a27b18..727a8b44 100644 --- a/api/src/main/java/io/opencensus/common/ToLongFunction.java +++ b/api/src/main/java/io/opencensus/common/ToLongFunction.java @@ -17,7 +17,7 @@ package io.opencensus.common; /** - * Represents a function that produces a long-valued result. See {@link + * Represents a function that produces a long-valued result. See {@code * io.opencensus.metrics.MetricRegistry} for an example of its use. * *

    Note: This class is based on the java.util.ToLongFunction class added in Java 1.8. We cannot diff --git a/api/src/main/java/io/opencensus/metrics/Distribution.java b/api/src/main/java/io/opencensus/metrics/Distribution.java deleted file mode 100644 index bdea7762..00000000 --- a/api/src/main/java/io/opencensus/metrics/Distribution.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import com.google.auto.value.AutoValue; -import io.opencensus.common.ExperimentalApi; -import io.opencensus.common.Timestamp; -import io.opencensus.internal.Utils; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; - -/** - * {@link Distribution} contains summary statistics for a population of values. It optionally - * contains a histogram representing the distribution of those values across a set of buckets. - * - * @since 0.16 - */ -@ExperimentalApi -@AutoValue -@Immutable -public abstract class Distribution { - - Distribution() {} - - /** - * Creates a {@link Distribution}. - * - * @param mean mean of the population values. - * @param count count of the population values. - * @param sumOfSquaredDeviations sum of squared deviations of the population values. - * @param bucketBoundaries bucket boundaries of a histogram. - * @param buckets {@link Bucket}s of a histogram. - * @return a {@code Distribution}. - * @since 0.16 - */ - public static Distribution create( - double mean, - long count, - double sumOfSquaredDeviations, - List bucketBoundaries, - List buckets) { - Utils.checkArgument(count >= 0, "count should be non-negative."); - Utils.checkArgument( - sumOfSquaredDeviations >= 0, "sum of squared deviations should be non-negative."); - if (count == 0) { - Utils.checkArgument(mean == 0, "mean should be 0 if count is 0."); - Utils.checkArgument( - sumOfSquaredDeviations == 0, "sum of squared deviations should be 0 if count is 0."); - } - return new AutoValue_Distribution( - mean, - count, - sumOfSquaredDeviations, - copyBucketBounds(bucketBoundaries), - copyBucketCount(buckets)); - } - - private static List copyBucketBounds(List bucketBoundaries) { - Utils.checkNotNull(bucketBoundaries, "bucketBoundaries list should not be null."); - List bucketBoundariesCopy = new ArrayList(bucketBoundaries); // Deep copy. - // Check if sorted. - if (bucketBoundariesCopy.size() > 1) { - double lower = bucketBoundariesCopy.get(0); - for (int i = 1; i < bucketBoundariesCopy.size(); i++) { - double next = bucketBoundariesCopy.get(i); - Utils.checkArgument(lower < next, "bucket boundaries not sorted."); - lower = next; - } - } - return Collections.unmodifiableList(bucketBoundariesCopy); - } - - private static List copyBucketCount(List buckets) { - Utils.checkNotNull(buckets, "bucket list should not be null."); - List bucketsCopy = new ArrayList(buckets); - for (Bucket bucket : bucketsCopy) { - Utils.checkNotNull(bucket, "bucket should not be null."); - } - return Collections.unmodifiableList(bucketsCopy); - } - - /** - * Returns the aggregated mean. - * - * @return the aggregated mean. - * @since 0.16 - */ - public abstract double getMean(); - - /** - * Returns the aggregated count. - * - * @return the aggregated count. - * @since 0.16 - */ - public abstract long getCount(); - - /** - * Returns the aggregated sum of squared deviations. - * - *

    The sum of squared deviations from the mean of the values in the population. For values x_i - * this is: - * - *

    Sum[i=1..n]((x_i - mean)^2) - * - *

    If count is zero then this field must be zero. - * - * @return the aggregated sum of squared deviations. - * @since 0.16 - */ - public abstract double getSumOfSquaredDeviations(); - - /** - * Returns the bucket boundaries of this distribution. - * - *

    The bucket boundaries for that histogram are described by bucket_bounds. This defines - * size(bucket_bounds) + 1 (= N) buckets. The boundaries for bucket index i are: - * - *

      - *
    • {@code (-infinity, bucket_bounds[i]) for i == 0} - *
    • {@code [bucket_bounds[i-1], bucket_bounds[i]) for 0 < i < N-2} - *
    • {@code [bucket_bounds[i-1], +infinity) for i == N-1} - *
    - * - *

    i.e. an underflow bucket (number 0), zero or more finite buckets (1 through N - 2, and an - * overflow bucket (N - 1), with inclusive lower bounds and exclusive upper bounds. - * - *

    If bucket_bounds has no elements (zero size), then there is no histogram associated with the - * Distribution. If bucket_bounds has only one element, there are no finite buckets, and that - * single element is the common boundary of the overflow and underflow buckets. The values must be - * monotonically increasing. - * - * @return the bucket boundaries of this distribution. - * @since 0.16 - */ - public abstract List getBucketBoundaries(); - - /** - * Returns the aggregated histogram {@link Bucket}s. - * - * @return the aggregated histogram buckets. - * @since 0.16 - */ - public abstract List getBuckets(); - - /** - * The histogram bucket of the population values. - * - * @since 0.16 - */ - @AutoValue - @Immutable - public abstract static class Bucket { - - Bucket() {} - - /** - * Creates a {@link Bucket}. - * - * @param count the number of values in each bucket of the histogram. - * @return a {@code Bucket}. - * @since 0.16 - */ - public static Bucket create(long count) { - Utils.checkArgument(count >= 0, "bucket count should be non-negative."); - return new AutoValue_Distribution_Bucket(count, null); - } - - /** - * Creates a {@link Bucket} with an {@link Exemplar}. - * - * @param count the number of values in each bucket of the histogram. - * @param exemplar the {@code Exemplar} of this {@code Bucket}. - * @return a {@code Bucket}. - * @since 0.16 - */ - public static Bucket create(long count, Exemplar exemplar) { - Utils.checkArgument(count >= 0, "bucket count should be non-negative."); - Utils.checkNotNull(exemplar, "exemplar"); - return new AutoValue_Distribution_Bucket(count, exemplar); - } - - /** - * Returns the number of values in each bucket of the histogram. - * - * @return the number of values in each bucket of the histogram. - * @since 0.16 - */ - public abstract long getCount(); - - /** - * Returns the {@link Exemplar} associated with the {@link Bucket}, or {@code null} if there - * isn't one. - * - * @return the {@code Exemplar} associated with the {@code Bucket}, or {@code null} if there - * isn't one. - * @since 0.16 - */ - @Nullable - public abstract Exemplar getExemplar(); - } - - /** - * An example point that may be used to annotate aggregated distribution values, associated with a - * histogram bucket. - * - * @since 0.16 - */ - @Immutable - @AutoValue - public abstract static class Exemplar { - - Exemplar() {} - - /** - * Returns value of the {@link Exemplar} point. - * - * @return value of the {@code Exemplar} point. - * @since 0.16 - */ - public abstract double getValue(); - - /** - * Returns the time that this {@link Exemplar}'s value was recorded. - * - * @return the time that this {@code Exemplar}'s value was recorded. - * @since 0.16 - */ - public abstract Timestamp getTimestamp(); - - /** - * Returns the contextual information about the example value, represented as a string map. - * - * @return the contextual information about the example value. - * @since 0.16 - */ - public abstract Map getAttachments(); - - /** - * Creates an {@link Exemplar}. - * - * @param value value of the {@link Exemplar} point. - * @param timestamp the time that this {@code Exemplar}'s value was recorded. - * @param attachments the contextual information about the example value. - * @return an {@code Exemplar}. - * @since 0.16 - */ - public static Exemplar create( - double value, Timestamp timestamp, Map attachments) { - Utils.checkNotNull(attachments, "attachments"); - Map attachmentsCopy = - Collections.unmodifiableMap(new HashMap(attachments)); - for (Entry entry : attachmentsCopy.entrySet()) { - Utils.checkNotNull(entry.getKey(), "key of attachments"); - Utils.checkNotNull(entry.getValue(), "value of attachments"); - } - return new AutoValue_Distribution_Exemplar(value, timestamp, attachmentsCopy); - } - } -} diff --git a/api/src/main/java/io/opencensus/metrics/LabelKey.java b/api/src/main/java/io/opencensus/metrics/LabelKey.java deleted file mode 100644 index 01ef0b55..00000000 --- a/api/src/main/java/io/opencensus/metrics/LabelKey.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import com.google.auto.value.AutoValue; -import io.opencensus.common.ExperimentalApi; -import javax.annotation.concurrent.Immutable; - -/** - * The key of a {@code Label} associated with a {@code MetricDescriptor}. - * - * @since 0.15 - */ -@ExperimentalApi -@Immutable -@AutoValue -public abstract class LabelKey { - - LabelKey() {} - - /** - * Creates a {@link LabelKey}. - * - * @param key the key of a {@code Label}. - * @param description a human-readable description of what this label key represents. - * @return a {@code LabelKey}. - * @since 0.15 - */ - public static LabelKey create(String key, String description) { - return new AutoValue_LabelKey(key, description); - } - - /** - * Returns the key of this {@link LabelKey}. - * - * @return the key. - * @since 0.15 - */ - public abstract String getKey(); - - /** - * Returns the description of this {@link LabelKey}. - * - * @return the description. - * @since 0.15 - */ - public abstract String getDescription(); -} diff --git a/api/src/main/java/io/opencensus/metrics/LabelValue.java b/api/src/main/java/io/opencensus/metrics/LabelValue.java deleted file mode 100644 index e81b63d2..00000000 --- a/api/src/main/java/io/opencensus/metrics/LabelValue.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import com.google.auto.value.AutoValue; -import io.opencensus.common.ExperimentalApi; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; - -/** - * The value of a {@code Label} associated with a {@code TimeSeries}. - * - * @since 0.15 - */ -@ExperimentalApi -@Immutable -@AutoValue -public abstract class LabelValue { - - LabelValue() {} - - /** - * Creates a {@link LabelValue}. - * - * @param value the value of a {@code Label}. {@code null} value indicates an unset {@code - * LabelValue}. - * @return a {@code LabelValue}. - * @since 0.15 - */ - public static LabelValue create(@Nullable String value) { - return new AutoValue_LabelValue(value); - } - - /** - * Returns the value of this {@link LabelValue}. Returns {@code null} if the value is unset and - * supposed to be ignored. - * - * @return the value. - * @since 0.15 - */ - @Nullable - public abstract String getValue(); -} diff --git a/api/src/main/java/io/opencensus/metrics/Metric.java b/api/src/main/java/io/opencensus/metrics/Metric.java deleted file mode 100644 index fa0018b3..00000000 --- a/api/src/main/java/io/opencensus/metrics/Metric.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import com.google.auto.value.AutoValue; -import io.opencensus.common.ExperimentalApi; -import io.opencensus.internal.Utils; -import io.opencensus.metrics.Value.ValueDistribution; -import io.opencensus.metrics.Value.ValueDouble; -import io.opencensus.metrics.Value.ValueLong; -import java.util.List; -import javax.annotation.concurrent.Immutable; - -/** - * A {@link Metric} with one or more {@link TimeSeries}. - * - * @since 0.16 - */ -@ExperimentalApi -@Immutable -@AutoValue -public abstract class Metric { - - Metric() {} - - /** - * Creates a {@link Metric}. - * - * @param metricDescriptor the {@link MetricDescriptor}. - * @param timeSeriesList the {@link TimeSeries} list for this metric. - * @return a {@code Metric}. - * @since 0.16 - */ - public static Metric create(MetricDescriptor metricDescriptor, List timeSeriesList) { - checkTypeMatch(metricDescriptor.getType(), timeSeriesList); - return new AutoValue_Metric(metricDescriptor, timeSeriesList); - } - - /** - * Returns the {@link MetricDescriptor} of this metric. - * - * @return the {@code MetricDescriptor} of this metric. - * @since 0.16 - */ - public abstract MetricDescriptor getMetricDescriptor(); - - /** - * Returns the {@link TimeSeries} list for this metric. - * - *

    The type of the {@link TimeSeries#getPoints()} must match {@link MetricDescriptor.Type}. - * - * @return the {@code TimeSeriesList} for this metric. - * @since 0.16 - */ - public abstract List getTimeSeriesList(); - - private static void checkTypeMatch(MetricDescriptor.Type type, List timeSeriesList) { - for (TimeSeries timeSeries : timeSeriesList) { - for (Point point : timeSeries.getPoints()) { - Value value = point.getValue(); - String valueClassName = ""; - if (value.getClass().getSuperclass() != null) { // work around nullness check - // AutoValue classes should always have a super class. - valueClassName = value.getClass().getSuperclass().getSimpleName(); - } - switch (type) { - case GAUGE_INT64: - case CUMULATIVE_INT64: - Utils.checkArgument( - value instanceof ValueLong, "Type mismatch: %s, %s.", type, valueClassName); - break; - case CUMULATIVE_DOUBLE: - case GAUGE_DOUBLE: - Utils.checkArgument( - value instanceof ValueDouble, "Type mismatch: %s, %s.", type, valueClassName); - break; - case CUMULATIVE_DISTRIBUTION: - Utils.checkArgument( - value instanceof ValueDistribution, "Type mismatch: %s, %s.", type, valueClassName); - } - } - } - } -} diff --git a/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java b/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java deleted file mode 100644 index 4558446a..00000000 --- a/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import com.google.auto.value.AutoValue; -import io.opencensus.common.ExperimentalApi; -import io.opencensus.internal.Utils; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.annotation.concurrent.Immutable; - -/** - * {@link MetricDescriptor} defines a {@code Metric} type and its schema. - * - * @since 0.16 - */ -@ExperimentalApi -@Immutable -@AutoValue -public abstract class MetricDescriptor { - - MetricDescriptor() {} - - /** - * Creates a {@link MetricDescriptor}. - * - * @param name name of {@code MetricDescriptor}. - * @param description description of {@code MetricDescriptor}. - * @param unit the metric unit. - * @param type type of {@code MetricDescriptor}. - * @param labelKeys the label keys associated with the {@code MetricDescriptor}. - * @return a {@code MetricDescriptor}. - * @since 0.16 - */ - public static MetricDescriptor create( - String name, String description, String unit, Type type, List labelKeys) { - Utils.checkNotNull(labelKeys, "labelKeys"); - Utils.checkListElementNotNull(labelKeys, "labelKey"); - return new AutoValue_MetricDescriptor( - name, - description, - unit, - type, - Collections.unmodifiableList(new ArrayList(labelKeys))); - } - - /** - * Returns the metric descriptor name. - * - * @return the metric descriptor name. - * @since 0.16 - */ - public abstract String getName(); - - /** - * Returns the description of this metric descriptor. - * - * @return the description of this metric descriptor. - * @since 0.16 - */ - public abstract String getDescription(); - - /** - * Returns the unit of this metric descriptor. - * - * @return the unit of this metric descriptor. - * @since 0.16 - */ - public abstract String getUnit(); - - /** - * Returns the type of this metric descriptor. - * - * @return the type of this metric descriptor. - * @since 0.16 - */ - public abstract Type getType(); - - /** - * Returns the label keys associated with this metric descriptor. - * - * @return the label keys associated with this metric descriptor. - * @since 0.16 - */ - public abstract List getLabelKeys(); - - /** - * The kind of metric. It describes how the data is reported. - * - *

    A gauge is an instantaneous measurement of a value. - * - *

    A cumulative measurement is a value accumulated over a time interval. In a time series, - * cumulative measurements should have the same start time and increasing end times, until an - * event resets the cumulative value to zero and sets a new start time for the following points. - * - * @since 0.16 - */ - public enum Type { - - /** - * An instantaneous measurement of an int64 value. - * - * @since 0.16 - */ - GAUGE_INT64, - - /** - * An instantaneous measurement of a double value. - * - * @since 0.16 - */ - GAUGE_DOUBLE, - - /** - * An cumulative measurement of an int64 value. - * - * @since 0.16 - */ - CUMULATIVE_INT64, - - /** - * An cumulative measurement of a double value. - * - * @since 0.16 - */ - CUMULATIVE_DOUBLE, - - /** - * An cumulative measurement of a distribution value. - * - * @since 0.16 - */ - CUMULATIVE_DISTRIBUTION, - } -} diff --git a/api/src/main/java/io/opencensus/metrics/MetricProducer.java b/api/src/main/java/io/opencensus/metrics/MetricProducer.java deleted file mode 100644 index 38b5d571..00000000 --- a/api/src/main/java/io/opencensus/metrics/MetricProducer.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import io.opencensus.common.ExperimentalApi; -import io.opencensus.metrics.export.MetricProducerManager; -import java.util.Collection; - -/** - * A {@link io.opencensus.metrics.Metric} producer that can be registered for exporting using {@link - * MetricProducerManager}. - * - *

    All implementation MUST be thread-safe. - */ -@ExperimentalApi -public abstract class MetricProducer { - - /** - * Returns a collection of produced {@link io.opencensus.metrics.Metric}s to be exported. - * - * @return a collection of produced {@link io.opencensus.metrics.Metric}s to be exported. - */ - public abstract Collection getMetrics(); -} diff --git a/api/src/main/java/io/opencensus/metrics/MetricRegistry.java b/api/src/main/java/io/opencensus/metrics/MetricRegistry.java deleted file mode 100644 index ae4d90b0..00000000 --- a/api/src/main/java/io/opencensus/metrics/MetricRegistry.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import io.opencensus.common.ExperimentalApi; -import io.opencensus.common.ToDoubleFunction; -import io.opencensus.common.ToLongFunction; -import io.opencensus.internal.Utils; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashMap; - -/** - * Creates and manages your application's set of metrics. Exporters use the metric registry to - * iterate over the set of metrics instrumenting your application, and then further export each - * metric to the backend of choice. - * - * @since 0.16 - */ -@ExperimentalApi -public abstract class MetricRegistry extends MetricProducer { - /** - * Build a new long gauge to be added to the registry. - * - *

    Must be called only once. - * - * @param name the name of the metric. - * @param description the description of the metric. - * @param unit the unit of the metric. - * @param obj the function argument. - * @param function the function to be called. - * @since 0.16 @ExperimentalApi - */ - public abstract void addLongGauge( - String name, - String description, - String unit, - LinkedHashMap labels, - T obj, - ToLongFunction function); - - /** - * Build a new double gauge to be added to the registry. - * - *

    Must be called only once. - * - * @param name the name of the metric. - * @param description the description of the metric. - * @param unit the unit of the metric. - * @param obj the function argument. - * @param function the function to be called. - * @since 0.16 @ExperimentalApi - */ - public abstract void addDoubleGauge( - String name, - String description, - String unit, - LinkedHashMap labels, - T obj, - ToDoubleFunction function); - - static MetricRegistry newNoopMetricRegistry() { - return new NoopMetricRegistry(); - } - - private static final class NoopMetricRegistry extends MetricRegistry { - - @Override - public void addLongGauge( - String name, - String description, - String unit, - LinkedHashMap labels, - T obj, - ToLongFunction function) { - Utils.checkNotNull(name, "name"); - Utils.checkNotNull(description, "description"); - Utils.checkNotNull(unit, "unit"); - Utils.checkNotNull(labels, "labels"); - Utils.checkNotNull(function, "function"); - } - - @Override - public void addDoubleGauge( - String name, - String description, - String unit, - LinkedHashMap labels, - T obj, - ToDoubleFunction function) { - Utils.checkNotNull(name, "name"); - Utils.checkNotNull(description, "description"); - Utils.checkNotNull(unit, "unit"); - Utils.checkNotNull(labels, "labels"); - Utils.checkNotNull(function, "function"); - } - - @Override - public Collection getMetrics() { - return Collections.emptyList(); - } - } -} diff --git a/api/src/main/java/io/opencensus/metrics/Metrics.java b/api/src/main/java/io/opencensus/metrics/Metrics.java deleted file mode 100644 index 521fbd08..00000000 --- a/api/src/main/java/io/opencensus/metrics/Metrics.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import io.opencensus.common.ExperimentalApi; -import io.opencensus.internal.DefaultVisibilityForTesting; -import io.opencensus.internal.Provider; -import io.opencensus.metrics.export.ExportComponent; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.annotation.Nullable; - -/** - * Class for accessing the default {@link MetricsComponent}. - * - * @since 0.16 - */ -@ExperimentalApi -public final class Metrics { - private static final Logger logger = Logger.getLogger(Metrics.class.getName()); - private static final MetricsComponent metricsComponent = - loadMetricsComponent(MetricsComponent.class.getClassLoader()); - - /** - * Returns the global {@link ExportComponent}. - * - * @return the global {@code ExportComponent}. - * @since 0.16 - */ - public static ExportComponent getExportComponent() { - return metricsComponent.getExportComponent(); - } - - /** - * Returns the global {@link MetricRegistry}. - * - *

    This {@code MetricRegistry} is already added to the global {@link - * io.opencensus.metrics.export.MetricProducerManager}. - * - * @return the global {@code MetricRegistry}. - * @since 0.16 - */ - public static MetricRegistry getMetricRegistry() { - return metricsComponent.getMetricRegistry(); - } - - // Any provider that may be used for MetricsComponent can be added here. - @DefaultVisibilityForTesting - static MetricsComponent loadMetricsComponent(@Nullable ClassLoader classLoader) { - try { - // Call Class.forName with literal string name of the class to help shading tools. - return Provider.createInstance( - Class.forName( - "io.opencensus.impl.metrics.MetricsComponentImpl", /*initialize=*/ true, classLoader), - MetricsComponent.class); - } catch (ClassNotFoundException e) { - logger.log( - Level.FINE, - "Couldn't load full implementation for MetricsComponent, now trying to load lite " - + "implementation.", - e); - } - try { - // Call Class.forName with literal string name of the class to help shading tools. - return Provider.createInstance( - Class.forName( - "io.opencensus.impllite.metrics.MetricsComponentImplLite", - /*initialize=*/ true, - classLoader), - MetricsComponent.class); - } catch (ClassNotFoundException e) { - logger.log( - Level.FINE, - "Couldn't load lite implementation for MetricsComponent, now using default " - + "implementation for MetricsComponent.", - e); - } - return MetricsComponent.newNoopMetricsComponent(); - } - - private Metrics() {} -} diff --git a/api/src/main/java/io/opencensus/metrics/MetricsComponent.java b/api/src/main/java/io/opencensus/metrics/MetricsComponent.java deleted file mode 100644 index 08d954ef..00000000 --- a/api/src/main/java/io/opencensus/metrics/MetricsComponent.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import io.opencensus.common.ExperimentalApi; -import io.opencensus.metrics.export.ExportComponent; - -/** - * Class that holds the implementation instance for {@link ExportComponent}. - * - * @since 0.16 - */ -@ExperimentalApi -public abstract class MetricsComponent { - - /** - * Returns the {@link ExportComponent} with the provided implementation. If no implementation is - * provided then no-op implementations will be used. - * - * @return the {@link ExportComponent} implementation. - * @since 0.16 - */ - public abstract ExportComponent getExportComponent(); - - /** - * Returns the {@link MetricRegistry} with the provided implementation. - * - * @return the {@link MetricRegistry} implementation. - * @since 0.16 - */ - public abstract MetricRegistry getMetricRegistry(); - - /** - * Returns an instance that contains no-op implementations for all the instances. - * - * @return an instance that contains no-op implementations for all the instances. - */ - static MetricsComponent newNoopMetricsComponent() { - return new NoopMetricsComponent(); - } - - private static final class NoopMetricsComponent extends MetricsComponent { - private static final ExportComponent EXPORT_COMPONENT = - ExportComponent.newNoopExportComponent(); - private static final MetricRegistry METRIC_REGISTRY = MetricRegistry.newNoopMetricRegistry(); - - @Override - public ExportComponent getExportComponent() { - return EXPORT_COMPONENT; - } - - @Override - public MetricRegistry getMetricRegistry() { - return METRIC_REGISTRY; - } - } -} diff --git a/api/src/main/java/io/opencensus/metrics/Point.java b/api/src/main/java/io/opencensus/metrics/Point.java deleted file mode 100644 index e66b273d..00000000 --- a/api/src/main/java/io/opencensus/metrics/Point.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import com.google.auto.value.AutoValue; -import io.opencensus.common.ExperimentalApi; -import io.opencensus.common.Timestamp; -import javax.annotation.concurrent.Immutable; - -/** - * A timestamped measurement of a {@code TimeSeries}. - * - * @since 0.16 - */ -@ExperimentalApi -@AutoValue -@Immutable -public abstract class Point { - - Point() {} - - /** - * Creates a {@link Point}. - * - * @param value the {@link Value} of this {@link Point}. - * @param timestamp the {@link Timestamp} when this {@link Point} was recorded. - * @return a {@code Point}. - * @since 0.16 - */ - public static Point create(Value value, Timestamp timestamp) { - return new AutoValue_Point(value, timestamp); - } - - /** - * Returns the {@link Value}. - * - * @return the {@code Value}. - * @since 0.16 - */ - public abstract Value getValue(); - - /** - * Returns the {@link Timestamp} when this {@link Point} was recorded. - * - * @return the {@code Timestamp}. - * @since 0.16 - */ - public abstract Timestamp getTimestamp(); -} diff --git a/api/src/main/java/io/opencensus/metrics/TimeSeries.java b/api/src/main/java/io/opencensus/metrics/TimeSeries.java deleted file mode 100644 index c62b6b72..00000000 --- a/api/src/main/java/io/opencensus/metrics/TimeSeries.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import com.google.auto.value.AutoValue; -import io.opencensus.common.ExperimentalApi; -import io.opencensus.common.Timestamp; -import io.opencensus.internal.Utils; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; - -/** - * A collection of data points that describes the time-varying values of a {@code Metric}. - * - * @since 0.16 - */ -@ExperimentalApi -@Immutable -@AutoValue -public abstract class TimeSeries { - - TimeSeries() {} - - /** - * Creates a {@link TimeSeries}. - * - * @param labelValues the {@code LabelValue}s that uniquely identify this {@code TimeSeries}. - * @param points the data {@code Point}s of this {@code TimeSeries}. - * @param startTimestamp the start {@code Timestamp} of this {@code TimeSeries}. Must be non-null - * for cumulative {@code Point}s. - * @return a {@code TimeSeries}. - * @since 0.16 - */ - public static TimeSeries create( - List labelValues, List points, @Nullable Timestamp startTimestamp) { - // Fail fast on null lists to prevent NullPointerException when copying the lists. - Utils.checkNotNull(labelValues, "labelValues"); - Utils.checkNotNull(points, "points"); - Utils.checkListElementNotNull(labelValues, "labelValue"); - Utils.checkListElementNotNull(points, "point"); - return new AutoValue_TimeSeries( - Collections.unmodifiableList(new ArrayList(labelValues)), - Collections.unmodifiableList(new ArrayList(points)), - startTimestamp); - } - - /** - * Returns the set of {@link LabelValue}s that uniquely identify this {@link TimeSeries}. - * - *

    Apply to all {@link Point}s. - * - *

    The order of {@link LabelValue}s must match that of {@link LabelKey}s in the {@code - * MetricDescriptor}. - * - * @return the {@code LabelValue}s. - * @since 0.16 - */ - public abstract List getLabelValues(); - - /** - * Returns the data {@link Point}s of this {@link TimeSeries}. - * - * @return the data {@code Point}s. - * @since 0.16 - */ - public abstract List getPoints(); - - /** - * Returns the start {@link Timestamp} of this {@link TimeSeries} if the {@link Point}s are - * cumulative, or {@code null} if the {@link Point}s are gauge. - * - * @return the start {@code Timestamp} or {@code null}. - * @since 0.16 - */ - @Nullable - public abstract Timestamp getStartTimestamp(); -} diff --git a/api/src/main/java/io/opencensus/metrics/Value.java b/api/src/main/java/io/opencensus/metrics/Value.java deleted file mode 100644 index c8fe48f8..00000000 --- a/api/src/main/java/io/opencensus/metrics/Value.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import com.google.auto.value.AutoValue; -import io.opencensus.common.ExperimentalApi; -import io.opencensus.common.Function; -import javax.annotation.concurrent.Immutable; - -/** - * The actual point value for a {@link Point}. - * - *

    Currently there are three types of {@link Value}: - * - *

      - *
    • {@code double} - *
    • {@code long} - *
    • {@link Distribution} - *
    - * - *

    Each {@link Point} contains exactly one of the three {@link Value} types. - * - * @since 0.16 - */ -@ExperimentalApi -@Immutable -public abstract class Value { - - Value() {} - - /** - * Returns a double {@link Value}. - * - * @param value value in double. - * @return a double {@code Value}. - * @since 0.16 - */ - public static Value doubleValue(double value) { - return ValueDouble.create(value); - } - - /** - * Returns a long {@link Value}. - * - * @param value value in long. - * @return a long {@code Value}. - * @since 0.16 - */ - public static Value longValue(long value) { - return ValueLong.create(value); - } - - /** - * Returns a {@link Distribution} {@link Value}. - * - * @param value value in {@link Distribution}. - * @return a {@code Distribution} {@code Value}. - * @since 0.16 - */ - public static Value distributionValue(Distribution value) { - return ValueDistribution.create(value); - } - - /** - * Applies the given match function to the underlying data type. - * - * @since 0.16 - */ - public abstract T match( - Function doubleFunction, - Function longFunction, - Function distributionFunction, - Function defaultFunction); - - /** A 64-bit double-precision floating-point {@link Value}. */ - @AutoValue - @Immutable - abstract static class ValueDouble extends Value { - - ValueDouble() {} - - @Override - public final T match( - Function doubleFunction, - Function longFunction, - Function distributionFunction, - Function defaultFunction) { - return doubleFunction.apply(getValue()); - } - - /** - * Creates a {@link ValueDouble}. - * - * @param value the value in double. - * @return a {@code ValueDouble}. - */ - static ValueDouble create(double value) { - return new AutoValue_Value_ValueDouble(value); - } - - /** - * Returns the double value. - * - * @return the double value. - */ - abstract double getValue(); - } - - /** A 64-bit integer {@link Value}. */ - @AutoValue - @Immutable - abstract static class ValueLong extends Value { - - ValueLong() {} - - @Override - public final T match( - Function doubleFunction, - Function longFunction, - Function distributionFunction, - Function defaultFunction) { - return longFunction.apply(getValue()); - } - - /** - * Creates a {@link ValueLong}. - * - * @param value the value in long. - * @return a {@code ValueLong}. - */ - static ValueLong create(long value) { - return new AutoValue_Value_ValueLong(value); - } - - /** - * Returns the long value. - * - * @return the long value. - */ - abstract long getValue(); - } - - /** - * {@link ValueDistribution} contains summary statistics for a population of values. It optionally - * contains a histogram representing the distribution of those values across a set of buckets. - */ - @AutoValue - @Immutable - abstract static class ValueDistribution extends Value { - - ValueDistribution() {} - - @Override - public final T match( - Function doubleFunction, - Function longFunction, - Function distributionFunction, - Function defaultFunction) { - return distributionFunction.apply(getValue()); - } - - /** - * Creates a {@link ValueDistribution}. - * - * @param value the {@link Distribution} value. - * @return a {@code ValueDistribution}. - */ - static ValueDistribution create(Distribution value) { - return new AutoValue_Value_ValueDistribution(value); - } - - /** - * Returns the {@link Distribution} value. - * - * @return the {@code Distribution} value. - */ - abstract Distribution getValue(); - } - - // TODO(songya): Add support for Summary type. - // This is an aggregation that produces percentiles directly. -} diff --git a/api/src/main/java/io/opencensus/metrics/export/ExportComponent.java b/api/src/main/java/io/opencensus/metrics/export/ExportComponent.java deleted file mode 100644 index bab65d13..00000000 --- a/api/src/main/java/io/opencensus/metrics/export/ExportComponent.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2018, 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.metrics.export; - -import io.opencensus.common.ExperimentalApi; - -/** - * Class that holds the implementation instance for {@link MetricProducerManager}. - * - *

    Unless otherwise noted all methods (on component) results are cacheable. - * - * @since 0.16 - */ -@ExperimentalApi -public abstract class ExportComponent { - /** - * Returns the no-op implementation of the {@code ExportComponent}. - * - * @return the no-op implementation of the {@code ExportComponent}. - * @since 0.16 - */ - public static ExportComponent newNoopExportComponent() { - return new NoopExportComponent(); - } - - /** - * Returns the global {@link MetricProducerManager} which can be used to register handlers to - * export all the recorded metrics. - * - * @return the implementation of the {@code MetricExporter} or no-op if no implementation linked - * in the binary. - * @since 0.16 - */ - public abstract MetricProducerManager getMetricProducerManager(); - - private static final class NoopExportComponent extends ExportComponent { - - private static final MetricProducerManager METRIC_PRODUCER_MANAGER = - MetricProducerManager.newNoopMetricProducerManager(); - - @Override - public MetricProducerManager getMetricProducerManager() { - return METRIC_PRODUCER_MANAGER; - } - } -} diff --git a/api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java b/api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java deleted file mode 100644 index c5acf174..00000000 --- a/api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2018, 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.metrics.export; - -import io.opencensus.common.ExperimentalApi; -import io.opencensus.internal.Utils; -import io.opencensus.metrics.MetricProducer; -import java.util.Collections; -import java.util.Set; -import javax.annotation.concurrent.ThreadSafe; - -/** - * Keeps a set of {@link MetricProducer} that is used by exporters to determine the metrics that - * need to be exported. - * - * @since 0.16 - */ -@ExperimentalApi -@ThreadSafe -public abstract class MetricProducerManager { - - /** - * Adds the {@link MetricProducer} to the manager if it is not already present. - * - * @param metricProducer the {@code MetricProducer} to be added to the manager. - * @since 0.16 - */ - public abstract void add(MetricProducer metricProducer); - - /** - * Removes the {@link MetricProducer} to the manager if it is present. - * - * @param metricProducer the {@code MetricProducer} to be removed from the manager. - * @since 0.16 - */ - public abstract void remove(MetricProducer metricProducer); - - /** - * Returns all registered {@link MetricProducer}s that should be exported. - * - *

    This method should be used by any metrics exporter that automatically exports data for - * {@code MetricProducer} registered with the {@code MetricProducerManager}. - * - * @return all registered {@code MetricProducer}s that should be exported. - * @since 0.16 - */ - public abstract Set getAllMetricProducer(); - - /** - * Returns a no-op implementation for {@link MetricProducerManager}. - * - * @return a no-op implementation for {@code MetricProducerManager}. - */ - static MetricProducerManager newNoopMetricProducerManager() { - return new NoopMetricProducerManager(); - } - - private static final class NoopMetricProducerManager extends MetricProducerManager { - - @Override - public void add(MetricProducer metricProducer) { - Utils.checkNotNull(metricProducer, "metricProducer"); - } - - @Override - public void remove(MetricProducer metricProducer) { - Utils.checkNotNull(metricProducer, "metricProducer"); - } - - @Override - public Set getAllMetricProducer() { - return Collections.emptySet(); - } - } -} diff --git a/api/src/main/java/io/opencensus/metrics/package-info.java b/api/src/main/java/io/opencensus/metrics/package-info.java deleted file mode 100644 index 33eadf0c..00000000 --- a/api/src/main/java/io/opencensus/metrics/package-info.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2018, 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. - */ - -/** - * This package describes the Metrics data model. Metrics are a data model for what stats exporters - * take as input. This data model may eventually become the wire format for metrics. - * - *

    WARNING: Currently all the public classes under this package are marked as {@link - * io.opencensus.common.ExperimentalApi}. The classes and APIs under {@link io.opencensus.metrics} - * are likely to get backwards-incompatible updates in the future. DO NOT USE except for - * experimental purposes. - * - *

    Please see - * https://github.com/census-instrumentation/opencensus-specs/blob/master/stats/Metrics.md and - * https://github.com/census-instrumentation/opencensus-proto/blob/master/opencensus/proto/stats/metrics/metrics.proto - * for more details. - */ -@io.opencensus.common.ExperimentalApi -package io.opencensus.metrics; diff --git a/api/src/test/java/io/opencensus/metrics/DistributionTest.java b/api/src/test/java/io/opencensus/metrics/DistributionTest.java deleted file mode 100644 index d511e317..00000000 --- a/api/src/test/java/io/opencensus/metrics/DistributionTest.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import io.opencensus.common.Timestamp; -import io.opencensus.metrics.Distribution.Bucket; -import io.opencensus.metrics.Distribution.Exemplar; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link Value}. */ -@RunWith(JUnit4.class) -public class DistributionTest { - - @Rule public final ExpectedException thrown = ExpectedException.none(); - - private static final Timestamp TIMESTAMP = Timestamp.create(1, 0); - private static final Map ATTACHMENTS = Collections.singletonMap("key", "value"); - - @Test - public void createAndGet_Bucket() { - Bucket bucket = Bucket.create(98); - assertThat(bucket.getCount()).isEqualTo(98); - assertThat(bucket.getExemplar()).isNull(); - } - - @Test - public void createAndGet_BucketWithExemplar() { - Exemplar exemplar = Exemplar.create(12.2, TIMESTAMP, ATTACHMENTS); - Bucket bucket = Bucket.create(7, exemplar); - assertThat(bucket.getCount()).isEqualTo(7); - assertThat(bucket.getExemplar()).isEqualTo(exemplar); - } - - @Test - public void createBucket_preventNullExemplar() { - thrown.expect(NullPointerException.class); - thrown.expectMessage("exemplar"); - Bucket.create(1, null); - } - - @Test - public void createAndGet_Exemplar() { - Exemplar exemplar = Exemplar.create(-9.9, TIMESTAMP, ATTACHMENTS); - assertThat(exemplar.getValue()).isEqualTo(-9.9); - assertThat(exemplar.getTimestamp()).isEqualTo(TIMESTAMP); - assertThat(exemplar.getAttachments()).isEqualTo(ATTACHMENTS); - } - - @Test - public void createAndGet_Distribution() { - Exemplar exemplar = Exemplar.create(15.0, TIMESTAMP, ATTACHMENTS); - List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); - List buckets = - Arrays.asList( - Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4, exemplar)); - Distribution distribution = Distribution.create(6.6, 10, 678.54, bucketBounds, buckets); - assertThat(distribution.getMean()).isEqualTo(6.6); - assertThat(distribution.getCount()).isEqualTo(10); - assertThat(distribution.getSumOfSquaredDeviations()).isEqualTo(678.54); - assertThat(distribution.getBucketBoundaries()) - .containsExactlyElementsIn(bucketBounds) - .inOrder(); - assertThat(distribution.getBuckets()).containsExactlyElementsIn(buckets).inOrder(); - } - - @Test - public void createBucket_NegativeCount() { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("bucket count should be non-negative."); - Bucket.create(-5); - } - - @Test - public void createExemplar_PreventNullAttachments() { - thrown.expect(NullPointerException.class); - thrown.expectMessage("attachments"); - Exemplar.create(15, TIMESTAMP, null); - } - - @Test - public void createExemplar_PreventNullAttachmentKey() { - Map attachments = Collections.singletonMap(null, "value"); - thrown.expect(NullPointerException.class); - thrown.expectMessage("key of attachment"); - Exemplar.create(15, TIMESTAMP, attachments); - } - - @Test - public void createExemplar_PreventNullAttachmentValue() { - Map attachments = Collections.singletonMap("key", null); - thrown.expect(NullPointerException.class); - thrown.expectMessage("value of attachment"); - Exemplar.create(15, TIMESTAMP, attachments); - } - - @Test - public void createDistribution_NegativeCount() { - List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); - List buckets = - Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("count should be non-negative."); - Distribution.create(6.6, -10, 678.54, bucketBounds, buckets); - } - - @Test - public void createDistribution_NegativeSumOfSquaredDeviations() { - List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); - List buckets = - Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0)); - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("sum of squared deviations should be non-negative."); - Distribution.create(6.6, 0, -678.54, bucketBounds, buckets); - } - - @Test - public void createDistribution_ZeroCountAndPositiveMean() { - List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); - List buckets = - Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0)); - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("mean should be 0 if count is 0."); - Distribution.create(6.6, 0, 0, bucketBounds, buckets); - } - - @Test - public void createDistribution_ZeroCountAndSumOfSquaredDeviations() { - List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); - List buckets = - Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0)); - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("sum of squared deviations should be 0 if count is 0."); - Distribution.create(0, 0, 678.54, bucketBounds, buckets); - } - - @Test - public void createDistribution_NullBucketBounds() { - List buckets = - Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); - thrown.expect(NullPointerException.class); - thrown.expectMessage("bucketBoundaries list should not be null."); - Distribution.create(6.6, 10, 678.54, null, buckets); - } - - @Test - public void createDistribution_UnorderedBucketBounds() { - List bucketBounds = Arrays.asList(0.0, -1.0, 1.0); - List buckets = - Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("bucket boundaries not sorted."); - Distribution.create(6.6, 10, 678.54, bucketBounds, buckets); - } - - @Test - public void createDistribution_NullBucketList() { - List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); - thrown.expect(NullPointerException.class); - thrown.expectMessage("bucket list should not be null."); - Distribution.create(6.6, 10, 678.54, bucketBounds, null); - } - - @Test - public void createDistribution_NullBucket() { - List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); - List buckets = - Arrays.asList(Bucket.create(3), Bucket.create(1), null, Bucket.create(4)); - thrown.expect(NullPointerException.class); - thrown.expectMessage("bucket should not be null."); - Distribution.create(6.6, 10, 678.54, bucketBounds, buckets); - } - - @Test - public void testEquals() { - new EqualsTester() - .addEqualityGroup( - Distribution.create( - 10, - 10, - 1, - Arrays.asList(-5.0, 0.0, 5.0), - Arrays.asList( - Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))), - Distribution.create( - 10, - 10, - 1, - Arrays.asList(-5.0, 0.0, 5.0), - Arrays.asList( - Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)))) - .addEqualityGroup( - Distribution.create( - -7, - 10, - 23.456, - Arrays.asList(-5.0, 0.0, 5.0), - Arrays.asList( - Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)))) - .testEquals(); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/LabelKeyTest.java b/api/src/test/java/io/opencensus/metrics/LabelKeyTest.java deleted file mode 100644 index 83f2b59a..00000000 --- a/api/src/test/java/io/opencensus/metrics/LabelKeyTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import java.util.Arrays; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link LabelKey}. */ -@RunWith(JUnit4.class) -public class LabelKeyTest { - - private static final LabelKey KEY = LabelKey.create("key", "description"); - - @Test - public void testGetKey() { - assertThat(KEY.getKey()).isEqualTo("key"); - } - - @Test - public void testGetDescription() { - assertThat(KEY.getDescription()).isEqualTo("description"); - } - - @Test - public void create_NoLengthConstraint() { - // We have a length constraint of 256-characters for TagKey. That constraint doesn't apply to - // LabelKey. - char[] chars = new char[300]; - Arrays.fill(chars, 'k'); - String key = new String(chars); - assertThat(LabelKey.create(key, "").getKey()).isEqualTo(key); - } - - @Test - public void create_WithUnprintableChars() { - String key = "\2ab\3cd"; - String description = "\4ef\5gh"; - LabelKey labelKey = LabelKey.create(key, description); - assertThat(labelKey.getKey()).isEqualTo(key); - assertThat(labelKey.getDescription()).isEqualTo(description); - } - - @Test - public void create_WithNonAsciiChars() { - String key = "键"; - String description = "测试用键"; - LabelKey nonAsciiKey = LabelKey.create(key, description); - assertThat(nonAsciiKey.getKey()).isEqualTo(key); - assertThat(nonAsciiKey.getDescription()).isEqualTo(description); - } - - @Test - public void create_Empty() { - LabelKey emptyKey = LabelKey.create("", ""); - assertThat(emptyKey.getKey()).isEmpty(); - assertThat(emptyKey.getDescription()).isEmpty(); - } - - @Test - public void testLabelKeyEquals() { - new EqualsTester() - .addEqualityGroup(LabelKey.create("foo", ""), LabelKey.create("foo", "")) - .addEqualityGroup(LabelKey.create("foo", "description")) - .addEqualityGroup(LabelKey.create("bar", "")) - .testEquals(); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/LabelValueTest.java b/api/src/test/java/io/opencensus/metrics/LabelValueTest.java deleted file mode 100644 index e5526b2f..00000000 --- a/api/src/test/java/io/opencensus/metrics/LabelValueTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import java.util.Arrays; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link LabelValue}. */ -@RunWith(JUnit4.class) -public class LabelValueTest { - - private static final LabelValue VALUE = LabelValue.create("value"); - private static final LabelValue UNSET = LabelValue.create(null); - private static final LabelValue EMPTY = LabelValue.create(""); - - @Test - public void testGetValue() { - assertThat(VALUE.getValue()).isEqualTo("value"); - assertThat(UNSET.getValue()).isNull(); - assertThat(EMPTY.getValue()).isEmpty(); - } - - @Test - public void create_NoLengthConstraint() { - // We have a length constraint of 256-characters for TagValue. That constraint doesn't apply to - // LabelValue. - char[] chars = new char[300]; - Arrays.fill(chars, 'v'); - String value = new String(chars); - assertThat(LabelValue.create(value).getValue()).isEqualTo(value); - } - - @Test - public void create_WithUnprintableChars() { - String value = "\2ab\3cd"; - assertThat(LabelValue.create(value).getValue()).isEqualTo(value); - } - - @Test - public void create_WithNonAsciiChars() { - String value = "值"; - LabelValue nonAsciiValue = LabelValue.create(value); - assertThat(nonAsciiValue.getValue()).isEqualTo(value); - } - - @Test - public void testLabelValueEquals() { - new EqualsTester() - .addEqualityGroup(LabelValue.create("foo"), LabelValue.create("foo")) - .addEqualityGroup(UNSET) - .addEqualityGroup(EMPTY) - .addEqualityGroup(LabelValue.create("bar")) - .testEquals(); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/MetricDescriptorTest.java b/api/src/test/java/io/opencensus/metrics/MetricDescriptorTest.java deleted file mode 100644 index 9c0a42fc..00000000 --- a/api/src/test/java/io/opencensus/metrics/MetricDescriptorTest.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import io.opencensus.metrics.MetricDescriptor.Type; -import java.util.Arrays; -import java.util.List; -import org.hamcrest.CoreMatchers; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link MetricDescriptor}. */ -@RunWith(JUnit4.class) -public class MetricDescriptorTest { - - @Rule public final ExpectedException thrown = ExpectedException.none(); - - private static final String METRIC_NAME_1 = "metric1"; - private static final String METRIC_NAME_2 = "metric2"; - private static final String DESCRIPTION = "Metric description."; - private static final String UNIT = "kb/s"; - private static final LabelKey KEY_1 = LabelKey.create("key1", "some key"); - private static final LabelKey KEY_2 = LabelKey.create("key2", "some other key"); - - @Test - public void testGet() { - MetricDescriptor metricDescriptor = - MetricDescriptor.create( - METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2)); - assertThat(metricDescriptor.getName()).isEqualTo(METRIC_NAME_1); - assertThat(metricDescriptor.getDescription()).isEqualTo(DESCRIPTION); - assertThat(metricDescriptor.getUnit()).isEqualTo(UNIT); - assertThat(metricDescriptor.getType()).isEqualTo(Type.GAUGE_DOUBLE); - assertThat(metricDescriptor.getLabelKeys()).containsExactly(KEY_1, KEY_2).inOrder(); - } - - @Test - public void preventNullLabelKeyList() { - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("labelKeys")); - MetricDescriptor.create(METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, null); - } - - @Test - public void preventNullLabelKey() { - List keys = Arrays.asList(KEY_1, null); - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("labelKey")); - MetricDescriptor.create(METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, keys); - } - - @Test - public void testEquals() { - new EqualsTester() - .addEqualityGroup( - MetricDescriptor.create( - METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2)), - MetricDescriptor.create( - METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2))) - .addEqualityGroup( - MetricDescriptor.create( - METRIC_NAME_2, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2))) - .addEqualityGroup( - MetricDescriptor.create( - METRIC_NAME_2, DESCRIPTION, UNIT, Type.GAUGE_INT64, Arrays.asList(KEY_1, KEY_2))) - .addEqualityGroup( - MetricDescriptor.create( - METRIC_NAME_1, - DESCRIPTION, - UNIT, - Type.CUMULATIVE_DISTRIBUTION, - Arrays.asList(KEY_1, KEY_2))) - .addEqualityGroup( - MetricDescriptor.create( - METRIC_NAME_1, - DESCRIPTION, - UNIT, - Type.CUMULATIVE_DISTRIBUTION, - Arrays.asList(KEY_1))) - .testEquals(); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java b/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java deleted file mode 100644 index 49e8ce02..00000000 --- a/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import io.opencensus.common.ToDoubleFunction; -import io.opencensus.common.ToLongFunction; -import java.util.LinkedHashMap; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link MetricRegistry}. */ -@RunWith(JUnit4.class) -public class MetricRegistryTest { - @Rule public ExpectedException thrown = ExpectedException.none(); - - private final MetricRegistry metricRegistry = - MetricsComponent.newNoopMetricsComponent().getMetricRegistry(); - - @Test - public void addDoubleGauge_NullName() { - thrown.expect(NullPointerException.class); - metricRegistry.addDoubleGauge( - null, - "description", - "1", - new LinkedHashMap(), - null, - new ToDoubleFunction() { - @Override - public double applyAsDouble(Object value) { - return 5.0; - } - }); - } - - @Test - public void addDoubleGauge_NullDescription() { - thrown.expect(NullPointerException.class); - metricRegistry.addDoubleGauge( - "name", - null, - "1", - new LinkedHashMap(), - null, - new ToDoubleFunction() { - @Override - public double applyAsDouble(Object value) { - return 5.0; - } - }); - } - - @Test - public void addDoubleGauge_NullUnit() { - thrown.expect(NullPointerException.class); - metricRegistry.addDoubleGauge( - "name", - "description", - null, - new LinkedHashMap(), - null, - new ToDoubleFunction() { - @Override - public double applyAsDouble(Object value) { - return 5.0; - } - }); - } - - @Test - public void addDoubleGauge_NullLabels() { - thrown.expect(NullPointerException.class); - metricRegistry.addDoubleGauge( - "name", - "description", - "1", - null, - null, - new ToDoubleFunction() { - @Override - public double applyAsDouble(Object value) { - return 5.0; - } - }); - } - - @Test - public void addDoubleGauge_NullFunction() { - thrown.expect(NullPointerException.class); - metricRegistry.addDoubleGauge( - "name", "description", "1", new LinkedHashMap(), null, null); - } - - @Test - public void addLongGauge_NullName() { - thrown.expect(NullPointerException.class); - metricRegistry.addLongGauge( - null, - "description", - "1", - new LinkedHashMap(), - null, - new ToLongFunction() { - @Override - public long applyAsLong(Object value) { - return 5; - } - }); - } - - @Test - public void addLongGauge_NullDescription() { - thrown.expect(NullPointerException.class); - metricRegistry.addLongGauge( - "name", - null, - "1", - new LinkedHashMap(), - null, - new ToLongFunction() { - @Override - public long applyAsLong(Object value) { - return 5; - } - }); - } - - @Test - public void addLongGauge_NullUnit() { - thrown.expect(NullPointerException.class); - metricRegistry.addLongGauge( - "name", - "description", - null, - new LinkedHashMap(), - null, - new ToLongFunction() { - @Override - public long applyAsLong(Object value) { - return 5; - } - }); - } - - @Test - public void addLongGauge_NullLabels() { - thrown.expect(NullPointerException.class); - metricRegistry.addLongGauge( - "name", - "description", - "1", - null, - null, - new ToLongFunction() { - @Override - public long applyAsLong(Object value) { - return 5; - } - }); - } - - @Test - public void addLongGauge_NullFunction() { - thrown.expect(NullPointerException.class); - metricRegistry.addLongGauge( - "name", "description", "1", new LinkedHashMap(), null, null); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/MetricTest.java b/api/src/test/java/io/opencensus/metrics/MetricTest.java deleted file mode 100644 index 37deed4b..00000000 --- a/api/src/test/java/io/opencensus/metrics/MetricTest.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import io.opencensus.common.Timestamp; -import io.opencensus.metrics.MetricDescriptor.Type; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link Metric}. */ -@RunWith(JUnit4.class) -public class MetricTest { - - @Rule public final ExpectedException thrown = ExpectedException.none(); - - private static final String METRIC_NAME_1 = "metric1"; - private static final String METRIC_NAME_2 = "metric2"; - private static final String DESCRIPTION = "Metric description."; - private static final String UNIT = "kb/s"; - private static final LabelKey KEY_1 = LabelKey.create("key1", "some key"); - private static final LabelKey KEY_2 = LabelKey.create("key1", "some other key"); - private static final MetricDescriptor METRIC_DESCRIPTOR_1 = - MetricDescriptor.create( - METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2)); - private static final MetricDescriptor METRIC_DESCRIPTOR_2 = - MetricDescriptor.create( - METRIC_NAME_2, DESCRIPTION, UNIT, Type.CUMULATIVE_INT64, Arrays.asList(KEY_1)); - private static final LabelValue LABEL_VALUE_1 = LabelValue.create("value1"); - private static final LabelValue LABEL_VALUE_2 = LabelValue.create("value1"); - private static final LabelValue LABEL_VALUE_EMPTY = LabelValue.create(""); - private static final Value VALUE_LONG = Value.longValue(12345678); - private static final Value VALUE_DOUBLE_1 = Value.doubleValue(-345.77); - private static final Value VALUE_DOUBLE_2 = Value.doubleValue(133.79); - private static final Timestamp TIMESTAMP_1 = Timestamp.fromMillis(1000); - private static final Timestamp TIMESTAMP_2 = Timestamp.fromMillis(2000); - private static final Timestamp TIMESTAMP_3 = Timestamp.fromMillis(3000); - private static final Point POINT_1 = Point.create(VALUE_DOUBLE_1, TIMESTAMP_2); - private static final Point POINT_2 = Point.create(VALUE_DOUBLE_2, TIMESTAMP_3); - private static final Point POINT_3 = Point.create(VALUE_LONG, TIMESTAMP_3); - private static final TimeSeries GAUGE_TIME_SERIES_1 = - TimeSeries.create(Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), null); - private static final TimeSeries GAUGE_TIME_SERIES_2 = - TimeSeries.create(Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_2), null); - private static final TimeSeries CUMULATIVE_TIME_SERIES = - TimeSeries.create(Arrays.asList(LABEL_VALUE_EMPTY), Arrays.asList(POINT_3), TIMESTAMP_1); - - @Test - public void testGet() { - Metric metric = - Metric.create(METRIC_DESCRIPTOR_1, Arrays.asList(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2)); - assertThat(metric.getMetricDescriptor()).isEqualTo(METRIC_DESCRIPTOR_1); - assertThat(metric.getTimeSeriesList()) - .containsExactly(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2) - .inOrder(); - } - - @Test - public void typeMismatch_GaugeDouble_Long() { - typeMismatch( - METRIC_DESCRIPTOR_1, - Arrays.asList(CUMULATIVE_TIME_SERIES), - String.format("Type mismatch: %s, %s.", Type.GAUGE_DOUBLE, "ValueLong")); - } - - @Test - public void typeMismatch_CumulativeInt64_Double() { - typeMismatch( - METRIC_DESCRIPTOR_2, - Arrays.asList(GAUGE_TIME_SERIES_1), - String.format("Type mismatch: %s, %s.", Type.CUMULATIVE_INT64, "ValueDouble")); - } - - private void typeMismatch( - MetricDescriptor metricDescriptor, List timeSeriesList, String errorMessage) { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage(errorMessage); - Metric.create(metricDescriptor, timeSeriesList); - } - - @Test - public void testEquals() { - new EqualsTester() - .addEqualityGroup( - Metric.create( - METRIC_DESCRIPTOR_1, Arrays.asList(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2)), - Metric.create( - METRIC_DESCRIPTOR_1, Arrays.asList(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2))) - .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_1, Collections.emptyList())) - .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_2, Arrays.asList(CUMULATIVE_TIME_SERIES))) - .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_2, Collections.emptyList())) - .testEquals(); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/MetricsComponentTest.java b/api/src/test/java/io/opencensus/metrics/MetricsComponentTest.java deleted file mode 100644 index 1c4e70f7..00000000 --- a/api/src/test/java/io/opencensus/metrics/MetricsComponentTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import static com.google.common.truth.Truth.assertThat; - -import io.opencensus.metrics.export.ExportComponent; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link MetricsComponent}. */ -@RunWith(JUnit4.class) -public class MetricsComponentTest { - @Test - public void defaultExportComponent() { - assertThat(MetricsComponent.newNoopMetricsComponent().getExportComponent()) - .isInstanceOf(ExportComponent.newNoopExportComponent().getClass()); - } - - @Test - public void defaultMetricRegistry() { - assertThat(MetricsComponent.newNoopMetricsComponent().getMetricRegistry()) - .isInstanceOf(MetricRegistry.newNoopMetricRegistry().getClass()); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/MetricsTest.java b/api/src/test/java/io/opencensus/metrics/MetricsTest.java deleted file mode 100644 index 9e0eee1f..00000000 --- a/api/src/test/java/io/opencensus/metrics/MetricsTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import static com.google.common.truth.Truth.assertThat; - -import io.opencensus.metrics.export.ExportComponent; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link Metrics}. */ -@RunWith(JUnit4.class) -public class MetricsTest { - @Rule public ExpectedException thrown = ExpectedException.none(); - - @Test - public void loadMetricsComponent_UsesProvidedClassLoader() { - final RuntimeException toThrow = new RuntimeException("UseClassLoader"); - thrown.expect(RuntimeException.class); - thrown.expectMessage("UseClassLoader"); - Metrics.loadMetricsComponent( - new ClassLoader() { - @Override - public Class loadClass(String name) { - throw toThrow; - } - }); - } - - @Test - public void loadMetricsComponent_IgnoresMissingClasses() { - ClassLoader classLoader = - new ClassLoader() { - @Override - public Class loadClass(String name) throws ClassNotFoundException { - throw new ClassNotFoundException(); - } - }; - assertThat(Metrics.loadMetricsComponent(classLoader).getClass().getName()) - .isEqualTo("io.opencensus.metrics.MetricsComponent$NoopMetricsComponent"); - } - - @Test - public void defaultExportComponent() { - assertThat(Metrics.getExportComponent()) - .isInstanceOf(ExportComponent.newNoopExportComponent().getClass()); - } - - @Test - public void defaultMetricRegistry() { - assertThat(Metrics.getMetricRegistry()) - .isInstanceOf(MetricRegistry.newNoopMetricRegistry().getClass()); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/PointTest.java b/api/src/test/java/io/opencensus/metrics/PointTest.java deleted file mode 100644 index cb6175c1..00000000 --- a/api/src/test/java/io/opencensus/metrics/PointTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import io.opencensus.common.Timestamp; -import io.opencensus.metrics.Distribution.Bucket; -import java.util.Arrays; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link Point}. */ -@RunWith(JUnit4.class) -public class PointTest { - - private static final Value DOUBLE_VALUE = Value.doubleValue(55.5); - private static final Value LONG_VALUE = Value.longValue(9876543210L); - private static final Value DISTRIBUTION_VALUE = - Value.distributionValue( - Distribution.create( - 6.6, - 10, - 678.54, - Arrays.asList(-1.0, 0.0, 1.0), - Arrays.asList( - Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)))); - private static final Timestamp TIMESTAMP_1 = Timestamp.create(1, 2); - private static final Timestamp TIMESTAMP_2 = Timestamp.create(3, 4); - private static final Timestamp TIMESTAMP_3 = Timestamp.create(5, 6); - - @Test - public void testGet() { - Point point = Point.create(DOUBLE_VALUE, TIMESTAMP_1); - assertThat(point.getValue()).isEqualTo(DOUBLE_VALUE); - assertThat(point.getTimestamp()).isEqualTo(TIMESTAMP_1); - } - - @Test - public void testEquals() { - new EqualsTester() - .addEqualityGroup( - Point.create(DOUBLE_VALUE, TIMESTAMP_1), Point.create(DOUBLE_VALUE, TIMESTAMP_1)) - .addEqualityGroup(Point.create(LONG_VALUE, TIMESTAMP_1)) - .addEqualityGroup(Point.create(LONG_VALUE, TIMESTAMP_2)) - .addEqualityGroup( - Point.create(DISTRIBUTION_VALUE, TIMESTAMP_2), - Point.create(DISTRIBUTION_VALUE, TIMESTAMP_2)) - .addEqualityGroup(Point.create(DISTRIBUTION_VALUE, TIMESTAMP_3)) - .testEquals(); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/TimeSeriesTest.java b/api/src/test/java/io/opencensus/metrics/TimeSeriesTest.java deleted file mode 100644 index 07dff97d..00000000 --- a/api/src/test/java/io/opencensus/metrics/TimeSeriesTest.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import io.opencensus.common.Timestamp; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import org.hamcrest.CoreMatchers; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link TimeSeries}. */ -@RunWith(JUnit4.class) -public class TimeSeriesTest { - - @Rule public ExpectedException thrown = ExpectedException.none(); - - private static final LabelValue LABEL_VALUE_1 = LabelValue.create("value1"); - private static final LabelValue LABEL_VALUE_2 = LabelValue.create("value2"); - private static final Value VALUE_LONG = Value.longValue(12345678); - private static final Value VALUE_DOUBLE = Value.doubleValue(-345.77); - private static final Timestamp TIMESTAMP_1 = Timestamp.fromMillis(1000); - private static final Timestamp TIMESTAMP_2 = Timestamp.fromMillis(2000); - private static final Timestamp TIMESTAMP_3 = Timestamp.fromMillis(3000); - private static final Point POINT_1 = Point.create(VALUE_DOUBLE, TIMESTAMP_2); - private static final Point POINT_2 = Point.create(VALUE_LONG, TIMESTAMP_3); - - @Test - public void testGet_TimeSeries() { - TimeSeries cumulativeTimeSeries = - TimeSeries.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1); - assertThat(cumulativeTimeSeries.getStartTimestamp()).isEqualTo(TIMESTAMP_1); - assertThat(cumulativeTimeSeries.getLabelValues()) - .containsExactly(LABEL_VALUE_1, LABEL_VALUE_2) - .inOrder(); - assertThat(cumulativeTimeSeries.getPoints()).containsExactly(POINT_1).inOrder(); - } - - @Test - public void create_WithNullLabelValueList() { - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("labelValues")); - TimeSeries.create(null, Collections.emptyList(), TIMESTAMP_1); - } - - @Test - public void create_WithNullLabelValue() { - List labelValues = Arrays.asList(LABEL_VALUE_1, null); - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("labelValue")); - TimeSeries.create(labelValues, Collections.emptyList(), TIMESTAMP_1); - } - - @Test - public void create_WithNullPointList() { - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("points")); - TimeSeries.create(Collections.emptyList(), null, TIMESTAMP_1); - } - - @Test - public void create_WithNullPoint() { - List points = Arrays.asList(POINT_1, null); - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("point")); - TimeSeries.create(Collections.emptyList(), points, TIMESTAMP_1); - } - - @Test - public void testEquals() { - new EqualsTester() - .addEqualityGroup( - TimeSeries.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1), - TimeSeries.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1)) - .addEqualityGroup( - TimeSeries.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), null), - TimeSeries.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), null)) - .addEqualityGroup( - TimeSeries.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_2)) - .addEqualityGroup( - TimeSeries.create(Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_1), TIMESTAMP_2)) - .addEqualityGroup( - TimeSeries.create(Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_2), TIMESTAMP_2)) - .addEqualityGroup( - TimeSeries.create( - Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_1, POINT_2), TIMESTAMP_2)) - .testEquals(); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/ValueTest.java b/api/src/test/java/io/opencensus/metrics/ValueTest.java deleted file mode 100644 index 63430b28..00000000 --- a/api/src/test/java/io/opencensus/metrics/ValueTest.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import io.opencensus.common.Function; -import io.opencensus.common.Functions; -import io.opencensus.metrics.Distribution.Bucket; -import io.opencensus.metrics.Value.ValueDistribution; -import io.opencensus.metrics.Value.ValueDouble; -import io.opencensus.metrics.Value.ValueLong; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link Value}. */ -@RunWith(JUnit4.class) -public class ValueTest { - - private static final Distribution DISTRIBUTION = - Distribution.create( - 10, - 10, - 1, - Arrays.asList(-5.0, 0.0, 5.0), - Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))); - - @Test - public void createAndGet_ValueDouble() { - Value value = Value.doubleValue(-34.56); - assertThat(value).isInstanceOf(ValueDouble.class); - assertThat(((ValueDouble) value).getValue()).isEqualTo(-34.56); - } - - @Test - public void createAndGet_ValueLong() { - Value value = Value.longValue(123456789); - assertThat(value).isInstanceOf(ValueLong.class); - assertThat(((ValueLong) value).getValue()).isEqualTo(123456789); - } - - @Test - public void createAndGet_ValueDistribution() { - Value value = Value.distributionValue(DISTRIBUTION); - assertThat(value).isInstanceOf(ValueDistribution.class); - assertThat(((ValueDistribution) value).getValue()).isEqualTo(DISTRIBUTION); - } - - @Test - public void testEquals() { - new EqualsTester() - .addEqualityGroup(Value.doubleValue(1.0), Value.doubleValue(1.0)) - .addEqualityGroup(Value.doubleValue(2.0)) - .addEqualityGroup(Value.longValue(1L)) - .addEqualityGroup(Value.longValue(2L)) - .addEqualityGroup( - Value.distributionValue( - Distribution.create( - -7, - 10, - 23.456, - Arrays.asList(-5.0, 0.0, 5.0), - Arrays.asList( - Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))))) - .testEquals(); - } - - @Test - public void testMatch() { - List values = - Arrays.asList( - ValueDouble.create(1.0), ValueLong.create(-1), ValueDistribution.create(DISTRIBUTION)); - List expected = - Arrays.asList(1.0, -1L, 10.0, 10L, 1.0, -5.0, 0.0, 5.0, 3L, 1L, 2L, 4L); - final List actual = new ArrayList(); - for (Value value : values) { - value.match( - new Function() { - @Override - public Object apply(Double arg) { - actual.add(arg); - return null; - } - }, - new Function() { - @Override - public Object apply(Long arg) { - actual.add(arg); - return null; - } - }, - new Function() { - @Override - public Object apply(Distribution arg) { - actual.add(arg.getMean()); - actual.add(arg.getCount()); - actual.add(arg.getSumOfSquaredDeviations()); - actual.addAll(arg.getBucketBoundaries()); - for (Bucket bucket : arg.getBuckets()) { - actual.add(bucket.getCount()); - } - return null; - } - }, - Functions.throwAssertionError()); - } - assertThat(actual).containsExactlyElementsIn(expected).inOrder(); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/export/ExportComponentTest.java b/api/src/test/java/io/opencensus/metrics/export/ExportComponentTest.java deleted file mode 100644 index 15c6e883..00000000 --- a/api/src/test/java/io/opencensus/metrics/export/ExportComponentTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2018, 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.metrics.export; - -import static com.google.common.truth.Truth.assertThat; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link ExportComponent}. */ -@RunWith(JUnit4.class) -public class ExportComponentTest { - @Test - public void defaultMetricExporter() { - assertThat(ExportComponent.newNoopExportComponent().getMetricProducerManager()) - .isInstanceOf(MetricProducerManager.class); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java b/api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java deleted file mode 100644 index 07854927..00000000 --- a/api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2018, 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.metrics.export; - -import static com.google.common.truth.Truth.assertThat; - -import io.opencensus.metrics.MetricProducer; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** Unit tests for {@link MetricProducerManager}. */ -@RunWith(JUnit4.class) -public class MetricProducerManagerTest { - private final MetricProducerManager metricProducerManager = - MetricProducerManager.newNoopMetricProducerManager(); - @Mock private MetricProducer metricProducer; - - @Rule public final ExpectedException thrown = ExpectedException.none(); - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void add_DisallowsNull() { - thrown.expect(NullPointerException.class); - metricProducerManager.add(null); - } - - @Test - public void add() { - metricProducerManager.add(metricProducer); - assertThat(metricProducerManager.getAllMetricProducer()).isEmpty(); - } - - @Test - public void addAndRemove() { - metricProducerManager.add(metricProducer); - assertThat(metricProducerManager.getAllMetricProducer()).isEmpty(); - metricProducerManager.remove(metricProducer); - assertThat(metricProducerManager.getAllMetricProducer()).isEmpty(); - } - - @Test - public void remove_DisallowsNull() { - thrown.expect(NullPointerException.class); - metricProducerManager.remove(null); - } - - @Test - public void remove_FromEmpty() { - metricProducerManager.remove(metricProducer); - assertThat(metricProducerManager.getAllMetricProducer()).isEmpty(); - } - - @Test - public void getAllMetricProducer_empty() { - assertThat(metricProducerManager.getAllMetricProducer()).isEmpty(); - } -} -- cgit v1.2.3 From 4ddf824f81d1e4b5ebdfd988ccc140686b9fa3f5 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Wed, 12 Sep 2018 18:01:17 -0700 Subject: Make LowerCaseBase16Encoding package protected. (#1427) --- .../opencensus/trace/LowerCaseBase16Encoding.java | 91 +++++++++++++++++++++ api/src/main/java/io/opencensus/trace/SpanId.java | 1 - api/src/main/java/io/opencensus/trace/TraceId.java | 1 - .../trace/internal/LowerCaseBase16Encoding.java | 93 ---------------------- .../trace/LowerCaseBase16EncodingTest.java | 83 +++++++++++++++++++ .../internal/LowerCaseBase16EncodingTest.java | 83 ------------------- 6 files changed, 174 insertions(+), 178 deletions(-) create mode 100644 api/src/main/java/io/opencensus/trace/LowerCaseBase16Encoding.java delete mode 100644 api/src/main/java/io/opencensus/trace/internal/LowerCaseBase16Encoding.java create mode 100644 api/src/test/java/io/opencensus/trace/LowerCaseBase16EncodingTest.java delete mode 100644 api/src/test/java/io/opencensus/trace/internal/LowerCaseBase16EncodingTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/LowerCaseBase16Encoding.java b/api/src/main/java/io/opencensus/trace/LowerCaseBase16Encoding.java new file mode 100644 index 00000000..bca95868 --- /dev/null +++ b/api/src/main/java/io/opencensus/trace/LowerCaseBase16Encoding.java @@ -0,0 +1,91 @@ +/* + * Copyright 2018, 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; + +import io.opencensus.internal.Utils; +import java.util.Arrays; + +/** Internal copy of the Guava implementation of the {@code BaseEncoding.base16().lowerCase()}. */ +final class LowerCaseBase16Encoding { + private static final String ALPHABET = "0123456789abcdef"; + private static final int ASCII_CHARACTERS = 128; + private static final char[] ENCODING = buildEncodingArray(); + private static final byte[] DECODING = buildDecodingArray(); + + private static char[] buildEncodingArray() { + char[] encoding = new char[512]; + for (int i = 0; i < 256; ++i) { + encoding[i] = ALPHABET.charAt(i >>> 4); + encoding[i | 0x100] = ALPHABET.charAt(i & 0xF); + } + return encoding; + } + + private static byte[] buildDecodingArray() { + byte[] decoding = new byte[ASCII_CHARACTERS]; + Arrays.fill(decoding, (byte) -1); + for (int i = 0; i < ALPHABET.length(); i++) { + char c = ALPHABET.charAt(i); + decoding[c] = (byte) i; + } + return decoding; + } + + /** + * Encodes the specified byte array, and returns the encoded {@code String}. + * + * @param bytes byte array to be encoded. + * @return the encoded {@code String}. + */ + static String encodeToString(byte[] bytes) { + StringBuilder stringBuilder = new StringBuilder(bytes.length * 2); + for (byte byteVal : bytes) { + int b = byteVal & 0xFF; + stringBuilder.append(ENCODING[b]); + stringBuilder.append(ENCODING[b | 0x100]); + } + return stringBuilder.toString(); + } + + /** + * Decodes the specified character sequence, and returns the resulting {@code byte[]}. + * + * @param chars the character sequence to be decoded. + * @return the resulting {@code byte[]} + * @throws IllegalArgumentException if the input is not a valid encoded string according to this + * encoding. + */ + static byte[] decodeToBytes(CharSequence chars) { + Utils.checkArgument(chars.length() % 2 == 0, "Invalid input length " + chars.length()); + int bytesWritten = 0; + byte[] bytes = new byte[chars.length() / 2]; + for (int i = 0; i < chars.length(); i += 2) { + bytes[bytesWritten++] = decodeByte(chars.charAt(i), chars.charAt(i + 1)); + } + return bytes; + } + + private static byte decodeByte(char hi, char lo) { + Utils.checkArgument(lo < ASCII_CHARACTERS && DECODING[lo] != -1, "Invalid character " + lo); + Utils.checkArgument(hi < ASCII_CHARACTERS && DECODING[hi] != -1, "Invalid character " + hi); + int decoded = DECODING[hi] << 4 | DECODING[lo]; + return (byte) decoded; + } + + // Private constructor to disallow instances. + private LowerCaseBase16Encoding() {} +} diff --git a/api/src/main/java/io/opencensus/trace/SpanId.java b/api/src/main/java/io/opencensus/trace/SpanId.java index 44119d6b..c43fa6b0 100644 --- a/api/src/main/java/io/opencensus/trace/SpanId.java +++ b/api/src/main/java/io/opencensus/trace/SpanId.java @@ -17,7 +17,6 @@ package io.opencensus.trace; import io.opencensus.internal.Utils; -import io.opencensus.trace.internal.LowerCaseBase16Encoding; import java.util.Arrays; import java.util.Random; import javax.annotation.Nullable; diff --git a/api/src/main/java/io/opencensus/trace/TraceId.java b/api/src/main/java/io/opencensus/trace/TraceId.java index 983b21c3..465e4d4a 100644 --- a/api/src/main/java/io/opencensus/trace/TraceId.java +++ b/api/src/main/java/io/opencensus/trace/TraceId.java @@ -18,7 +18,6 @@ package io.opencensus.trace; import io.opencensus.common.Internal; import io.opencensus.internal.Utils; -import io.opencensus.trace.internal.LowerCaseBase16Encoding; import java.util.Arrays; import java.util.Random; import javax.annotation.Nullable; diff --git a/api/src/main/java/io/opencensus/trace/internal/LowerCaseBase16Encoding.java b/api/src/main/java/io/opencensus/trace/internal/LowerCaseBase16Encoding.java deleted file mode 100644 index d9b2cf09..00000000 --- a/api/src/main/java/io/opencensus/trace/internal/LowerCaseBase16Encoding.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2018, 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.internal; - -import io.opencensus.common.Internal; -import io.opencensus.internal.Utils; -import java.util.Arrays; - -/** Internal copy of the Guava implementation of the {@code BaseEncoding.base16().lowerCase()}. */ -@Internal -public final class LowerCaseBase16Encoding { - private static final String ALPHABET = "0123456789abcdef"; - private static final int ASCII_CHARACTERS = 128; - private static final char[] ENCODING = buildEncodingArray(); - private static final byte[] DECODING = buildDecodingArray(); - - private static char[] buildEncodingArray() { - char[] encoding = new char[512]; - for (int i = 0; i < 256; ++i) { - encoding[i] = ALPHABET.charAt(i >>> 4); - encoding[i | 0x100] = ALPHABET.charAt(i & 0xF); - } - return encoding; - } - - private static byte[] buildDecodingArray() { - byte[] decoding = new byte[ASCII_CHARACTERS]; - Arrays.fill(decoding, (byte) -1); - for (int i = 0; i < ALPHABET.length(); i++) { - char c = ALPHABET.charAt(i); - decoding[c] = (byte) i; - } - return decoding; - } - - /** - * Encodes the specified byte array, and returns the encoded {@code String}. - * - * @param bytes byte array to be encoded. - * @return the encoded {@code String}. - */ - public static String encodeToString(byte[] bytes) { - StringBuilder stringBuilder = new StringBuilder(bytes.length * 2); - for (byte byteVal : bytes) { - int b = byteVal & 0xFF; - stringBuilder.append(ENCODING[b]); - stringBuilder.append(ENCODING[b | 0x100]); - } - return stringBuilder.toString(); - } - - /** - * Decodes the specified character sequence, and returns the resulting {@code byte[]}. - * - * @param chars the character sequence to be decoded. - * @return the resulting {@code byte[]} - * @throws IllegalArgumentException if the input is not a valid encoded string according to this - * encoding. - */ - public static byte[] decodeToBytes(CharSequence chars) { - Utils.checkArgument(chars.length() % 2 == 0, "Invalid input length " + chars.length()); - int bytesWritten = 0; - byte[] bytes = new byte[chars.length() / 2]; - for (int i = 0; i < chars.length(); i += 2) { - bytes[bytesWritten++] = decodeByte(chars.charAt(i), chars.charAt(i + 1)); - } - return bytes; - } - - private static byte decodeByte(char hi, char lo) { - Utils.checkArgument(lo < ASCII_CHARACTERS && DECODING[lo] != -1, "Invalid character " + lo); - Utils.checkArgument(hi < ASCII_CHARACTERS && DECODING[hi] != -1, "Invalid character " + hi); - int decoded = DECODING[hi] << 4 | DECODING[lo]; - return (byte) decoded; - } - - // Private constructor to disallow instances. - private LowerCaseBase16Encoding() {} -} diff --git a/api/src/test/java/io/opencensus/trace/LowerCaseBase16EncodingTest.java b/api/src/test/java/io/opencensus/trace/LowerCaseBase16EncodingTest.java new file mode 100644 index 00000000..3444d2b3 --- /dev/null +++ b/api/src/test/java/io/opencensus/trace/LowerCaseBase16EncodingTest.java @@ -0,0 +1,83 @@ +/* + * Copyright 2018, 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; + +import static com.google.common.truth.Truth.assertThat; + +import java.nio.charset.Charset; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link io.opencensus.trace.LowerCaseBase16Encoding}. */ +@RunWith(JUnit4.class) +public class LowerCaseBase16EncodingTest { + private static final Charset CHARSET = Charset.forName("UTF-8"); + + @Rule public ExpectedException thrown = ExpectedException.none(); + + @Test + public void valid_EncodeDecode() { + testEncoding("", ""); + testEncoding("f", "66"); + testEncoding("fo", "666f"); + testEncoding("foo", "666f6f"); + testEncoding("foob", "666f6f62"); + testEncoding("fooba", "666f6f6261"); + testEncoding("foobar", "666f6f626172"); + } + + @Test + public void invalidDecodings_UnrecongnizedCharacters() { + // These contain bytes not in the decoding. + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Invalid character g"); + LowerCaseBase16Encoding.decodeToBytes("efhg"); + } + + @Test + public void invalidDecodings_InvalidInputLength() { + // Valid base16 strings always have an even length. + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Invalid input length 3"); + LowerCaseBase16Encoding.decodeToBytes("abc"); + } + + @Test + public void invalidDecodings_InvalidInputLengthAndCharacter() { + // These have a combination of invalid length and unrecognized characters. + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Invalid input length 1"); + LowerCaseBase16Encoding.decodeToBytes("?"); + } + + private static void testEncoding(String decoded, String encoded) { + testEncodes(decoded, encoded); + testDecodes(encoded, decoded); + } + + private static void testEncodes(String decoded, String encoded) { + assertThat(LowerCaseBase16Encoding.encodeToString(decoded.getBytes(CHARSET))) + .isEqualTo(encoded); + } + + private static void testDecodes(String encoded, String decoded) { + assertThat(LowerCaseBase16Encoding.decodeToBytes(encoded)).isEqualTo(decoded.getBytes(CHARSET)); + } +} diff --git a/api/src/test/java/io/opencensus/trace/internal/LowerCaseBase16EncodingTest.java b/api/src/test/java/io/opencensus/trace/internal/LowerCaseBase16EncodingTest.java deleted file mode 100644 index bcc51ab6..00000000 --- a/api/src/test/java/io/opencensus/trace/internal/LowerCaseBase16EncodingTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2018, 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.internal; - -import static com.google.common.truth.Truth.assertThat; - -import java.nio.charset.Charset; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link LowerCaseBase16Encoding}. */ -@RunWith(JUnit4.class) -public class LowerCaseBase16EncodingTest { - private static final Charset CHARSET = Charset.forName("UTF-8"); - - @Rule public ExpectedException thrown = ExpectedException.none(); - - @Test - public void valid_EncodeDecode() { - testEncoding("", ""); - testEncoding("f", "66"); - testEncoding("fo", "666f"); - testEncoding("foo", "666f6f"); - testEncoding("foob", "666f6f62"); - testEncoding("fooba", "666f6f6261"); - testEncoding("foobar", "666f6f626172"); - } - - @Test - public void invalidDecodings_UnrecongnizedCharacters() { - // These contain bytes not in the decoding. - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("Invalid character g"); - LowerCaseBase16Encoding.decodeToBytes("efhg"); - } - - @Test - public void invalidDecodings_InvalidInputLength() { - // Valid base16 strings always have an even length. - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("Invalid input length 3"); - LowerCaseBase16Encoding.decodeToBytes("abc"); - } - - @Test - public void invalidDecodings_InvalidInputLengthAndCharacter() { - // These have a combination of invalid length and unrecognized characters. - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("Invalid input length 1"); - LowerCaseBase16Encoding.decodeToBytes("?"); - } - - private static void testEncoding(String decoded, String encoded) { - testEncodes(decoded, encoded); - testDecodes(encoded, decoded); - } - - private static void testEncodes(String decoded, String encoded) { - assertThat(LowerCaseBase16Encoding.encodeToString(decoded.getBytes(CHARSET))) - .isEqualTo(encoded); - } - - private static void testDecodes(String encoded, String decoded) { - assertThat(LowerCaseBase16Encoding.decodeToBytes(encoded)).isEqualTo(decoded.getBytes(CHARSET)); - } -} -- cgit v1.2.3 From 7b1665e6f1323b8e5cfa6f2bd72b6bac97a027c4 Mon Sep 17 00:00:00 2001 From: sebright Date: Fri, 14 Sep 2018 13:41:30 -0700 Subject: Start 0.17.0 development cycle (#1429) --- .../main/java/io/opencensus/common/OpenCensusLibraryInformation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java index 35c62582..3f659c12 100644 --- a/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java +++ b/api/src/main/java/io/opencensus/common/OpenCensusLibraryInformation.java @@ -29,7 +29,7 @@ public final class OpenCensusLibraryInformation { * * @since 0.8 */ - public static final String VERSION = "0.16.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION + public static final String VERSION = "0.17.0-SNAPSHOT"; // CURRENT_OPENCENSUS_VERSION private OpenCensusLibraryInformation() {} } -- cgit v1.2.3 From 937d2296642d9bcdae23a2be469d1d0f367ae3de Mon Sep 17 00:00:00 2001 From: Yang Song Date: Fri, 14 Sep 2018 15:45:30 -0700 Subject: Revert "Temporarily move "metrics" package into impl_core/ for release. (#1426)" (#1432) This reverts commit d3fa0e5c60903f95c184d7c7bafae8fdd12156ad. --- .../io/opencensus/common/ToDoubleFunction.java | 2 +- .../java/io/opencensus/common/ToLongFunction.java | 2 +- .../java/io/opencensus/metrics/Distribution.java | 280 +++++++++++++++++++++ .../main/java/io/opencensus/metrics/LabelKey.java | 62 +++++ .../java/io/opencensus/metrics/LabelValue.java | 57 +++++ .../main/java/io/opencensus/metrics/Metric.java | 98 ++++++++ .../io/opencensus/metrics/MetricDescriptor.java | 150 +++++++++++ .../java/io/opencensus/metrics/MetricProducer.java | 38 +++ .../java/io/opencensus/metrics/MetricRegistry.java | 117 +++++++++ .../main/java/io/opencensus/metrics/Metrics.java | 96 +++++++ .../io/opencensus/metrics/MetricsComponent.java | 71 ++++++ api/src/main/java/io/opencensus/metrics/Point.java | 63 +++++ .../java/io/opencensus/metrics/TimeSeries.java | 94 +++++++ api/src/main/java/io/opencensus/metrics/Value.java | 196 +++++++++++++++ .../opencensus/metrics/export/ExportComponent.java | 60 +++++ .../metrics/export/MetricProducerManager.java | 89 +++++++ .../java/io/opencensus/metrics/package-info.java | 32 +++ .../io/opencensus/metrics/DistributionTest.java | 226 +++++++++++++++++ .../java/io/opencensus/metrics/LabelKeyTest.java | 86 +++++++ .../java/io/opencensus/metrics/LabelValueTest.java | 74 ++++++ .../opencensus/metrics/MetricDescriptorTest.java | 102 ++++++++ .../io/opencensus/metrics/MetricRegistryTest.java | 185 ++++++++++++++ .../java/io/opencensus/metrics/MetricTest.java | 116 +++++++++ .../opencensus/metrics/MetricsComponentTest.java | 40 +++ .../java/io/opencensus/metrics/MetricsTest.java | 71 ++++++ .../test/java/io/opencensus/metrics/PointTest.java | 68 +++++ .../java/io/opencensus/metrics/TimeSeriesTest.java | 116 +++++++++ .../test/java/io/opencensus/metrics/ValueTest.java | 128 ++++++++++ .../metrics/export/ExportComponentTest.java | 33 +++ .../metrics/export/MetricProducerManagerTest.java | 81 ++++++ 30 files changed, 2831 insertions(+), 2 deletions(-) create mode 100644 api/src/main/java/io/opencensus/metrics/Distribution.java create mode 100644 api/src/main/java/io/opencensus/metrics/LabelKey.java create mode 100644 api/src/main/java/io/opencensus/metrics/LabelValue.java create mode 100644 api/src/main/java/io/opencensus/metrics/Metric.java create mode 100644 api/src/main/java/io/opencensus/metrics/MetricDescriptor.java create mode 100644 api/src/main/java/io/opencensus/metrics/MetricProducer.java create mode 100644 api/src/main/java/io/opencensus/metrics/MetricRegistry.java create mode 100644 api/src/main/java/io/opencensus/metrics/Metrics.java create mode 100644 api/src/main/java/io/opencensus/metrics/MetricsComponent.java create mode 100644 api/src/main/java/io/opencensus/metrics/Point.java create mode 100644 api/src/main/java/io/opencensus/metrics/TimeSeries.java create mode 100644 api/src/main/java/io/opencensus/metrics/Value.java create mode 100644 api/src/main/java/io/opencensus/metrics/export/ExportComponent.java create mode 100644 api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java create mode 100644 api/src/main/java/io/opencensus/metrics/package-info.java create mode 100644 api/src/test/java/io/opencensus/metrics/DistributionTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/LabelKeyTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/LabelValueTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/MetricDescriptorTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/MetricTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/MetricsComponentTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/MetricsTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/PointTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/TimeSeriesTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/ValueTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/export/ExportComponentTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/ToDoubleFunction.java b/api/src/main/java/io/opencensus/common/ToDoubleFunction.java index 415f8ca9..eac85793 100644 --- a/api/src/main/java/io/opencensus/common/ToDoubleFunction.java +++ b/api/src/main/java/io/opencensus/common/ToDoubleFunction.java @@ -17,7 +17,7 @@ package io.opencensus.common; /** - * Represents a function that produces a double-valued result. See {@code + * Represents a function that produces a double-valued result. See {@link * io.opencensus.metrics.MetricRegistry} for an example of its use. * *

    Note: This class is based on the java.util.ToDoubleFunction class added in Java 1.8. We cannot diff --git a/api/src/main/java/io/opencensus/common/ToLongFunction.java b/api/src/main/java/io/opencensus/common/ToLongFunction.java index 727a8b44..26a27b18 100644 --- a/api/src/main/java/io/opencensus/common/ToLongFunction.java +++ b/api/src/main/java/io/opencensus/common/ToLongFunction.java @@ -17,7 +17,7 @@ package io.opencensus.common; /** - * Represents a function that produces a long-valued result. See {@code + * Represents a function that produces a long-valued result. See {@link * io.opencensus.metrics.MetricRegistry} for an example of its use. * *

    Note: This class is based on the java.util.ToLongFunction class added in Java 1.8. We cannot diff --git a/api/src/main/java/io/opencensus/metrics/Distribution.java b/api/src/main/java/io/opencensus/metrics/Distribution.java new file mode 100644 index 00000000..bdea7762 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/Distribution.java @@ -0,0 +1,280 @@ +/* + * Copyright 2018, 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.metrics; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.common.Timestamp; +import io.opencensus.internal.Utils; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * {@link Distribution} contains summary statistics for a population of values. It optionally + * contains a histogram representing the distribution of those values across a set of buckets. + * + * @since 0.16 + */ +@ExperimentalApi +@AutoValue +@Immutable +public abstract class Distribution { + + Distribution() {} + + /** + * Creates a {@link Distribution}. + * + * @param mean mean of the population values. + * @param count count of the population values. + * @param sumOfSquaredDeviations sum of squared deviations of the population values. + * @param bucketBoundaries bucket boundaries of a histogram. + * @param buckets {@link Bucket}s of a histogram. + * @return a {@code Distribution}. + * @since 0.16 + */ + public static Distribution create( + double mean, + long count, + double sumOfSquaredDeviations, + List bucketBoundaries, + List buckets) { + Utils.checkArgument(count >= 0, "count should be non-negative."); + Utils.checkArgument( + sumOfSquaredDeviations >= 0, "sum of squared deviations should be non-negative."); + if (count == 0) { + Utils.checkArgument(mean == 0, "mean should be 0 if count is 0."); + Utils.checkArgument( + sumOfSquaredDeviations == 0, "sum of squared deviations should be 0 if count is 0."); + } + return new AutoValue_Distribution( + mean, + count, + sumOfSquaredDeviations, + copyBucketBounds(bucketBoundaries), + copyBucketCount(buckets)); + } + + private static List copyBucketBounds(List bucketBoundaries) { + Utils.checkNotNull(bucketBoundaries, "bucketBoundaries list should not be null."); + List bucketBoundariesCopy = new ArrayList(bucketBoundaries); // Deep copy. + // Check if sorted. + if (bucketBoundariesCopy.size() > 1) { + double lower = bucketBoundariesCopy.get(0); + for (int i = 1; i < bucketBoundariesCopy.size(); i++) { + double next = bucketBoundariesCopy.get(i); + Utils.checkArgument(lower < next, "bucket boundaries not sorted."); + lower = next; + } + } + return Collections.unmodifiableList(bucketBoundariesCopy); + } + + private static List copyBucketCount(List buckets) { + Utils.checkNotNull(buckets, "bucket list should not be null."); + List bucketsCopy = new ArrayList(buckets); + for (Bucket bucket : bucketsCopy) { + Utils.checkNotNull(bucket, "bucket should not be null."); + } + return Collections.unmodifiableList(bucketsCopy); + } + + /** + * Returns the aggregated mean. + * + * @return the aggregated mean. + * @since 0.16 + */ + public abstract double getMean(); + + /** + * Returns the aggregated count. + * + * @return the aggregated count. + * @since 0.16 + */ + public abstract long getCount(); + + /** + * Returns the aggregated sum of squared deviations. + * + *

    The sum of squared deviations from the mean of the values in the population. For values x_i + * this is: + * + *

    Sum[i=1..n]((x_i - mean)^2) + * + *

    If count is zero then this field must be zero. + * + * @return the aggregated sum of squared deviations. + * @since 0.16 + */ + public abstract double getSumOfSquaredDeviations(); + + /** + * Returns the bucket boundaries of this distribution. + * + *

    The bucket boundaries for that histogram are described by bucket_bounds. This defines + * size(bucket_bounds) + 1 (= N) buckets. The boundaries for bucket index i are: + * + *

      + *
    • {@code (-infinity, bucket_bounds[i]) for i == 0} + *
    • {@code [bucket_bounds[i-1], bucket_bounds[i]) for 0 < i < N-2} + *
    • {@code [bucket_bounds[i-1], +infinity) for i == N-1} + *
    + * + *

    i.e. an underflow bucket (number 0), zero or more finite buckets (1 through N - 2, and an + * overflow bucket (N - 1), with inclusive lower bounds and exclusive upper bounds. + * + *

    If bucket_bounds has no elements (zero size), then there is no histogram associated with the + * Distribution. If bucket_bounds has only one element, there are no finite buckets, and that + * single element is the common boundary of the overflow and underflow buckets. The values must be + * monotonically increasing. + * + * @return the bucket boundaries of this distribution. + * @since 0.16 + */ + public abstract List getBucketBoundaries(); + + /** + * Returns the aggregated histogram {@link Bucket}s. + * + * @return the aggregated histogram buckets. + * @since 0.16 + */ + public abstract List getBuckets(); + + /** + * The histogram bucket of the population values. + * + * @since 0.16 + */ + @AutoValue + @Immutable + public abstract static class Bucket { + + Bucket() {} + + /** + * Creates a {@link Bucket}. + * + * @param count the number of values in each bucket of the histogram. + * @return a {@code Bucket}. + * @since 0.16 + */ + public static Bucket create(long count) { + Utils.checkArgument(count >= 0, "bucket count should be non-negative."); + return new AutoValue_Distribution_Bucket(count, null); + } + + /** + * Creates a {@link Bucket} with an {@link Exemplar}. + * + * @param count the number of values in each bucket of the histogram. + * @param exemplar the {@code Exemplar} of this {@code Bucket}. + * @return a {@code Bucket}. + * @since 0.16 + */ + public static Bucket create(long count, Exemplar exemplar) { + Utils.checkArgument(count >= 0, "bucket count should be non-negative."); + Utils.checkNotNull(exemplar, "exemplar"); + return new AutoValue_Distribution_Bucket(count, exemplar); + } + + /** + * Returns the number of values in each bucket of the histogram. + * + * @return the number of values in each bucket of the histogram. + * @since 0.16 + */ + public abstract long getCount(); + + /** + * Returns the {@link Exemplar} associated with the {@link Bucket}, or {@code null} if there + * isn't one. + * + * @return the {@code Exemplar} associated with the {@code Bucket}, or {@code null} if there + * isn't one. + * @since 0.16 + */ + @Nullable + public abstract Exemplar getExemplar(); + } + + /** + * An example point that may be used to annotate aggregated distribution values, associated with a + * histogram bucket. + * + * @since 0.16 + */ + @Immutable + @AutoValue + public abstract static class Exemplar { + + Exemplar() {} + + /** + * Returns value of the {@link Exemplar} point. + * + * @return value of the {@code Exemplar} point. + * @since 0.16 + */ + public abstract double getValue(); + + /** + * Returns the time that this {@link Exemplar}'s value was recorded. + * + * @return the time that this {@code Exemplar}'s value was recorded. + * @since 0.16 + */ + public abstract Timestamp getTimestamp(); + + /** + * Returns the contextual information about the example value, represented as a string map. + * + * @return the contextual information about the example value. + * @since 0.16 + */ + public abstract Map getAttachments(); + + /** + * Creates an {@link Exemplar}. + * + * @param value value of the {@link Exemplar} point. + * @param timestamp the time that this {@code Exemplar}'s value was recorded. + * @param attachments the contextual information about the example value. + * @return an {@code Exemplar}. + * @since 0.16 + */ + public static Exemplar create( + double value, Timestamp timestamp, Map attachments) { + Utils.checkNotNull(attachments, "attachments"); + Map attachmentsCopy = + Collections.unmodifiableMap(new HashMap(attachments)); + for (Entry entry : attachmentsCopy.entrySet()) { + Utils.checkNotNull(entry.getKey(), "key of attachments"); + Utils.checkNotNull(entry.getValue(), "value of attachments"); + } + return new AutoValue_Distribution_Exemplar(value, timestamp, attachmentsCopy); + } + } +} diff --git a/api/src/main/java/io/opencensus/metrics/LabelKey.java b/api/src/main/java/io/opencensus/metrics/LabelKey.java new file mode 100644 index 00000000..01ef0b55 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/LabelKey.java @@ -0,0 +1,62 @@ +/* + * Copyright 2018, 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.metrics; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import javax.annotation.concurrent.Immutable; + +/** + * The key of a {@code Label} associated with a {@code MetricDescriptor}. + * + * @since 0.15 + */ +@ExperimentalApi +@Immutable +@AutoValue +public abstract class LabelKey { + + LabelKey() {} + + /** + * Creates a {@link LabelKey}. + * + * @param key the key of a {@code Label}. + * @param description a human-readable description of what this label key represents. + * @return a {@code LabelKey}. + * @since 0.15 + */ + public static LabelKey create(String key, String description) { + return new AutoValue_LabelKey(key, description); + } + + /** + * Returns the key of this {@link LabelKey}. + * + * @return the key. + * @since 0.15 + */ + public abstract String getKey(); + + /** + * Returns the description of this {@link LabelKey}. + * + * @return the description. + * @since 0.15 + */ + public abstract String getDescription(); +} diff --git a/api/src/main/java/io/opencensus/metrics/LabelValue.java b/api/src/main/java/io/opencensus/metrics/LabelValue.java new file mode 100644 index 00000000..e81b63d2 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/LabelValue.java @@ -0,0 +1,57 @@ +/* + * Copyright 2018, 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.metrics; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * The value of a {@code Label} associated with a {@code TimeSeries}. + * + * @since 0.15 + */ +@ExperimentalApi +@Immutable +@AutoValue +public abstract class LabelValue { + + LabelValue() {} + + /** + * Creates a {@link LabelValue}. + * + * @param value the value of a {@code Label}. {@code null} value indicates an unset {@code + * LabelValue}. + * @return a {@code LabelValue}. + * @since 0.15 + */ + public static LabelValue create(@Nullable String value) { + return new AutoValue_LabelValue(value); + } + + /** + * Returns the value of this {@link LabelValue}. Returns {@code null} if the value is unset and + * supposed to be ignored. + * + * @return the value. + * @since 0.15 + */ + @Nullable + public abstract String getValue(); +} diff --git a/api/src/main/java/io/opencensus/metrics/Metric.java b/api/src/main/java/io/opencensus/metrics/Metric.java new file mode 100644 index 00000000..fa0018b3 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/Metric.java @@ -0,0 +1,98 @@ +/* + * Copyright 2018, 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.metrics; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.internal.Utils; +import io.opencensus.metrics.Value.ValueDistribution; +import io.opencensus.metrics.Value.ValueDouble; +import io.opencensus.metrics.Value.ValueLong; +import java.util.List; +import javax.annotation.concurrent.Immutable; + +/** + * A {@link Metric} with one or more {@link TimeSeries}. + * + * @since 0.16 + */ +@ExperimentalApi +@Immutable +@AutoValue +public abstract class Metric { + + Metric() {} + + /** + * Creates a {@link Metric}. + * + * @param metricDescriptor the {@link MetricDescriptor}. + * @param timeSeriesList the {@link TimeSeries} list for this metric. + * @return a {@code Metric}. + * @since 0.16 + */ + public static Metric create(MetricDescriptor metricDescriptor, List timeSeriesList) { + checkTypeMatch(metricDescriptor.getType(), timeSeriesList); + return new AutoValue_Metric(metricDescriptor, timeSeriesList); + } + + /** + * Returns the {@link MetricDescriptor} of this metric. + * + * @return the {@code MetricDescriptor} of this metric. + * @since 0.16 + */ + public abstract MetricDescriptor getMetricDescriptor(); + + /** + * Returns the {@link TimeSeries} list for this metric. + * + *

    The type of the {@link TimeSeries#getPoints()} must match {@link MetricDescriptor.Type}. + * + * @return the {@code TimeSeriesList} for this metric. + * @since 0.16 + */ + public abstract List getTimeSeriesList(); + + private static void checkTypeMatch(MetricDescriptor.Type type, List timeSeriesList) { + for (TimeSeries timeSeries : timeSeriesList) { + for (Point point : timeSeries.getPoints()) { + Value value = point.getValue(); + String valueClassName = ""; + if (value.getClass().getSuperclass() != null) { // work around nullness check + // AutoValue classes should always have a super class. + valueClassName = value.getClass().getSuperclass().getSimpleName(); + } + switch (type) { + case GAUGE_INT64: + case CUMULATIVE_INT64: + Utils.checkArgument( + value instanceof ValueLong, "Type mismatch: %s, %s.", type, valueClassName); + break; + case CUMULATIVE_DOUBLE: + case GAUGE_DOUBLE: + Utils.checkArgument( + value instanceof ValueDouble, "Type mismatch: %s, %s.", type, valueClassName); + break; + case CUMULATIVE_DISTRIBUTION: + Utils.checkArgument( + value instanceof ValueDistribution, "Type mismatch: %s, %s.", type, valueClassName); + } + } + } + } +} diff --git a/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java b/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java new file mode 100644 index 00000000..4558446a --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java @@ -0,0 +1,150 @@ +/* + * Copyright 2018, 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.metrics; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.internal.Utils; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.annotation.concurrent.Immutable; + +/** + * {@link MetricDescriptor} defines a {@code Metric} type and its schema. + * + * @since 0.16 + */ +@ExperimentalApi +@Immutable +@AutoValue +public abstract class MetricDescriptor { + + MetricDescriptor() {} + + /** + * Creates a {@link MetricDescriptor}. + * + * @param name name of {@code MetricDescriptor}. + * @param description description of {@code MetricDescriptor}. + * @param unit the metric unit. + * @param type type of {@code MetricDescriptor}. + * @param labelKeys the label keys associated with the {@code MetricDescriptor}. + * @return a {@code MetricDescriptor}. + * @since 0.16 + */ + public static MetricDescriptor create( + String name, String description, String unit, Type type, List labelKeys) { + Utils.checkNotNull(labelKeys, "labelKeys"); + Utils.checkListElementNotNull(labelKeys, "labelKey"); + return new AutoValue_MetricDescriptor( + name, + description, + unit, + type, + Collections.unmodifiableList(new ArrayList(labelKeys))); + } + + /** + * Returns the metric descriptor name. + * + * @return the metric descriptor name. + * @since 0.16 + */ + public abstract String getName(); + + /** + * Returns the description of this metric descriptor. + * + * @return the description of this metric descriptor. + * @since 0.16 + */ + public abstract String getDescription(); + + /** + * Returns the unit of this metric descriptor. + * + * @return the unit of this metric descriptor. + * @since 0.16 + */ + public abstract String getUnit(); + + /** + * Returns the type of this metric descriptor. + * + * @return the type of this metric descriptor. + * @since 0.16 + */ + public abstract Type getType(); + + /** + * Returns the label keys associated with this metric descriptor. + * + * @return the label keys associated with this metric descriptor. + * @since 0.16 + */ + public abstract List getLabelKeys(); + + /** + * The kind of metric. It describes how the data is reported. + * + *

    A gauge is an instantaneous measurement of a value. + * + *

    A cumulative measurement is a value accumulated over a time interval. In a time series, + * cumulative measurements should have the same start time and increasing end times, until an + * event resets the cumulative value to zero and sets a new start time for the following points. + * + * @since 0.16 + */ + public enum Type { + + /** + * An instantaneous measurement of an int64 value. + * + * @since 0.16 + */ + GAUGE_INT64, + + /** + * An instantaneous measurement of a double value. + * + * @since 0.16 + */ + GAUGE_DOUBLE, + + /** + * An cumulative measurement of an int64 value. + * + * @since 0.16 + */ + CUMULATIVE_INT64, + + /** + * An cumulative measurement of a double value. + * + * @since 0.16 + */ + CUMULATIVE_DOUBLE, + + /** + * An cumulative measurement of a distribution value. + * + * @since 0.16 + */ + CUMULATIVE_DISTRIBUTION, + } +} diff --git a/api/src/main/java/io/opencensus/metrics/MetricProducer.java b/api/src/main/java/io/opencensus/metrics/MetricProducer.java new file mode 100644 index 00000000..38b5d571 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/MetricProducer.java @@ -0,0 +1,38 @@ +/* + * Copyright 2018, 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.metrics; + +import io.opencensus.common.ExperimentalApi; +import io.opencensus.metrics.export.MetricProducerManager; +import java.util.Collection; + +/** + * A {@link io.opencensus.metrics.Metric} producer that can be registered for exporting using {@link + * MetricProducerManager}. + * + *

    All implementation MUST be thread-safe. + */ +@ExperimentalApi +public abstract class MetricProducer { + + /** + * Returns a collection of produced {@link io.opencensus.metrics.Metric}s to be exported. + * + * @return a collection of produced {@link io.opencensus.metrics.Metric}s to be exported. + */ + public abstract Collection getMetrics(); +} diff --git a/api/src/main/java/io/opencensus/metrics/MetricRegistry.java b/api/src/main/java/io/opencensus/metrics/MetricRegistry.java new file mode 100644 index 00000000..ae4d90b0 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/MetricRegistry.java @@ -0,0 +1,117 @@ +/* + * Copyright 2018, 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.metrics; + +import io.opencensus.common.ExperimentalApi; +import io.opencensus.common.ToDoubleFunction; +import io.opencensus.common.ToLongFunction; +import io.opencensus.internal.Utils; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; + +/** + * Creates and manages your application's set of metrics. Exporters use the metric registry to + * iterate over the set of metrics instrumenting your application, and then further export each + * metric to the backend of choice. + * + * @since 0.16 + */ +@ExperimentalApi +public abstract class MetricRegistry extends MetricProducer { + /** + * Build a new long gauge to be added to the registry. + * + *

    Must be called only once. + * + * @param name the name of the metric. + * @param description the description of the metric. + * @param unit the unit of the metric. + * @param obj the function argument. + * @param function the function to be called. + * @since 0.16 @ExperimentalApi + */ + public abstract void addLongGauge( + String name, + String description, + String unit, + LinkedHashMap labels, + T obj, + ToLongFunction function); + + /** + * Build a new double gauge to be added to the registry. + * + *

    Must be called only once. + * + * @param name the name of the metric. + * @param description the description of the metric. + * @param unit the unit of the metric. + * @param obj the function argument. + * @param function the function to be called. + * @since 0.16 @ExperimentalApi + */ + public abstract void addDoubleGauge( + String name, + String description, + String unit, + LinkedHashMap labels, + T obj, + ToDoubleFunction function); + + static MetricRegistry newNoopMetricRegistry() { + return new NoopMetricRegistry(); + } + + private static final class NoopMetricRegistry extends MetricRegistry { + + @Override + public void addLongGauge( + String name, + String description, + String unit, + LinkedHashMap labels, + T obj, + ToLongFunction function) { + Utils.checkNotNull(name, "name"); + Utils.checkNotNull(description, "description"); + Utils.checkNotNull(unit, "unit"); + Utils.checkNotNull(labels, "labels"); + Utils.checkNotNull(function, "function"); + } + + @Override + public void addDoubleGauge( + String name, + String description, + String unit, + LinkedHashMap labels, + T obj, + ToDoubleFunction function) { + Utils.checkNotNull(name, "name"); + Utils.checkNotNull(description, "description"); + Utils.checkNotNull(unit, "unit"); + Utils.checkNotNull(labels, "labels"); + Utils.checkNotNull(function, "function"); + } + + @Override + public Collection getMetrics() { + return Collections.emptyList(); + } + } +} diff --git a/api/src/main/java/io/opencensus/metrics/Metrics.java b/api/src/main/java/io/opencensus/metrics/Metrics.java new file mode 100644 index 00000000..521fbd08 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/Metrics.java @@ -0,0 +1,96 @@ +/* + * Copyright 2018, 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.metrics; + +import io.opencensus.common.ExperimentalApi; +import io.opencensus.internal.DefaultVisibilityForTesting; +import io.opencensus.internal.Provider; +import io.opencensus.metrics.export.ExportComponent; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; + +/** + * Class for accessing the default {@link MetricsComponent}. + * + * @since 0.16 + */ +@ExperimentalApi +public final class Metrics { + private static final Logger logger = Logger.getLogger(Metrics.class.getName()); + private static final MetricsComponent metricsComponent = + loadMetricsComponent(MetricsComponent.class.getClassLoader()); + + /** + * Returns the global {@link ExportComponent}. + * + * @return the global {@code ExportComponent}. + * @since 0.16 + */ + public static ExportComponent getExportComponent() { + return metricsComponent.getExportComponent(); + } + + /** + * Returns the global {@link MetricRegistry}. + * + *

    This {@code MetricRegistry} is already added to the global {@link + * io.opencensus.metrics.export.MetricProducerManager}. + * + * @return the global {@code MetricRegistry}. + * @since 0.16 + */ + public static MetricRegistry getMetricRegistry() { + return metricsComponent.getMetricRegistry(); + } + + // Any provider that may be used for MetricsComponent can be added here. + @DefaultVisibilityForTesting + static MetricsComponent loadMetricsComponent(@Nullable ClassLoader classLoader) { + try { + // Call Class.forName with literal string name of the class to help shading tools. + return Provider.createInstance( + Class.forName( + "io.opencensus.impl.metrics.MetricsComponentImpl", /*initialize=*/ true, classLoader), + MetricsComponent.class); + } catch (ClassNotFoundException e) { + logger.log( + Level.FINE, + "Couldn't load full implementation for MetricsComponent, now trying to load lite " + + "implementation.", + e); + } + try { + // Call Class.forName with literal string name of the class to help shading tools. + return Provider.createInstance( + Class.forName( + "io.opencensus.impllite.metrics.MetricsComponentImplLite", + /*initialize=*/ true, + classLoader), + MetricsComponent.class); + } catch (ClassNotFoundException e) { + logger.log( + Level.FINE, + "Couldn't load lite implementation for MetricsComponent, now using default " + + "implementation for MetricsComponent.", + e); + } + return MetricsComponent.newNoopMetricsComponent(); + } + + private Metrics() {} +} diff --git a/api/src/main/java/io/opencensus/metrics/MetricsComponent.java b/api/src/main/java/io/opencensus/metrics/MetricsComponent.java new file mode 100644 index 00000000..08d954ef --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/MetricsComponent.java @@ -0,0 +1,71 @@ +/* + * Copyright 2018, 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.metrics; + +import io.opencensus.common.ExperimentalApi; +import io.opencensus.metrics.export.ExportComponent; + +/** + * Class that holds the implementation instance for {@link ExportComponent}. + * + * @since 0.16 + */ +@ExperimentalApi +public abstract class MetricsComponent { + + /** + * Returns the {@link ExportComponent} with the provided implementation. If no implementation is + * provided then no-op implementations will be used. + * + * @return the {@link ExportComponent} implementation. + * @since 0.16 + */ + public abstract ExportComponent getExportComponent(); + + /** + * Returns the {@link MetricRegistry} with the provided implementation. + * + * @return the {@link MetricRegistry} implementation. + * @since 0.16 + */ + public abstract MetricRegistry getMetricRegistry(); + + /** + * Returns an instance that contains no-op implementations for all the instances. + * + * @return an instance that contains no-op implementations for all the instances. + */ + static MetricsComponent newNoopMetricsComponent() { + return new NoopMetricsComponent(); + } + + private static final class NoopMetricsComponent extends MetricsComponent { + private static final ExportComponent EXPORT_COMPONENT = + ExportComponent.newNoopExportComponent(); + private static final MetricRegistry METRIC_REGISTRY = MetricRegistry.newNoopMetricRegistry(); + + @Override + public ExportComponent getExportComponent() { + return EXPORT_COMPONENT; + } + + @Override + public MetricRegistry getMetricRegistry() { + return METRIC_REGISTRY; + } + } +} diff --git a/api/src/main/java/io/opencensus/metrics/Point.java b/api/src/main/java/io/opencensus/metrics/Point.java new file mode 100644 index 00000000..e66b273d --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/Point.java @@ -0,0 +1,63 @@ +/* + * Copyright 2018, 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.metrics; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.common.Timestamp; +import javax.annotation.concurrent.Immutable; + +/** + * A timestamped measurement of a {@code TimeSeries}. + * + * @since 0.16 + */ +@ExperimentalApi +@AutoValue +@Immutable +public abstract class Point { + + Point() {} + + /** + * Creates a {@link Point}. + * + * @param value the {@link Value} of this {@link Point}. + * @param timestamp the {@link Timestamp} when this {@link Point} was recorded. + * @return a {@code Point}. + * @since 0.16 + */ + public static Point create(Value value, Timestamp timestamp) { + return new AutoValue_Point(value, timestamp); + } + + /** + * Returns the {@link Value}. + * + * @return the {@code Value}. + * @since 0.16 + */ + public abstract Value getValue(); + + /** + * Returns the {@link Timestamp} when this {@link Point} was recorded. + * + * @return the {@code Timestamp}. + * @since 0.16 + */ + public abstract Timestamp getTimestamp(); +} diff --git a/api/src/main/java/io/opencensus/metrics/TimeSeries.java b/api/src/main/java/io/opencensus/metrics/TimeSeries.java new file mode 100644 index 00000000..c62b6b72 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/TimeSeries.java @@ -0,0 +1,94 @@ +/* + * Copyright 2018, 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.metrics; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.common.Timestamp; +import io.opencensus.internal.Utils; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * A collection of data points that describes the time-varying values of a {@code Metric}. + * + * @since 0.16 + */ +@ExperimentalApi +@Immutable +@AutoValue +public abstract class TimeSeries { + + TimeSeries() {} + + /** + * Creates a {@link TimeSeries}. + * + * @param labelValues the {@code LabelValue}s that uniquely identify this {@code TimeSeries}. + * @param points the data {@code Point}s of this {@code TimeSeries}. + * @param startTimestamp the start {@code Timestamp} of this {@code TimeSeries}. Must be non-null + * for cumulative {@code Point}s. + * @return a {@code TimeSeries}. + * @since 0.16 + */ + public static TimeSeries create( + List labelValues, List points, @Nullable Timestamp startTimestamp) { + // Fail fast on null lists to prevent NullPointerException when copying the lists. + Utils.checkNotNull(labelValues, "labelValues"); + Utils.checkNotNull(points, "points"); + Utils.checkListElementNotNull(labelValues, "labelValue"); + Utils.checkListElementNotNull(points, "point"); + return new AutoValue_TimeSeries( + Collections.unmodifiableList(new ArrayList(labelValues)), + Collections.unmodifiableList(new ArrayList(points)), + startTimestamp); + } + + /** + * Returns the set of {@link LabelValue}s that uniquely identify this {@link TimeSeries}. + * + *

    Apply to all {@link Point}s. + * + *

    The order of {@link LabelValue}s must match that of {@link LabelKey}s in the {@code + * MetricDescriptor}. + * + * @return the {@code LabelValue}s. + * @since 0.16 + */ + public abstract List getLabelValues(); + + /** + * Returns the data {@link Point}s of this {@link TimeSeries}. + * + * @return the data {@code Point}s. + * @since 0.16 + */ + public abstract List getPoints(); + + /** + * Returns the start {@link Timestamp} of this {@link TimeSeries} if the {@link Point}s are + * cumulative, or {@code null} if the {@link Point}s are gauge. + * + * @return the start {@code Timestamp} or {@code null}. + * @since 0.16 + */ + @Nullable + public abstract Timestamp getStartTimestamp(); +} diff --git a/api/src/main/java/io/opencensus/metrics/Value.java b/api/src/main/java/io/opencensus/metrics/Value.java new file mode 100644 index 00000000..c8fe48f8 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/Value.java @@ -0,0 +1,196 @@ +/* + * Copyright 2018, 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.metrics; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.common.Function; +import javax.annotation.concurrent.Immutable; + +/** + * The actual point value for a {@link Point}. + * + *

    Currently there are three types of {@link Value}: + * + *

      + *
    • {@code double} + *
    • {@code long} + *
    • {@link Distribution} + *
    + * + *

    Each {@link Point} contains exactly one of the three {@link Value} types. + * + * @since 0.16 + */ +@ExperimentalApi +@Immutable +public abstract class Value { + + Value() {} + + /** + * Returns a double {@link Value}. + * + * @param value value in double. + * @return a double {@code Value}. + * @since 0.16 + */ + public static Value doubleValue(double value) { + return ValueDouble.create(value); + } + + /** + * Returns a long {@link Value}. + * + * @param value value in long. + * @return a long {@code Value}. + * @since 0.16 + */ + public static Value longValue(long value) { + return ValueLong.create(value); + } + + /** + * Returns a {@link Distribution} {@link Value}. + * + * @param value value in {@link Distribution}. + * @return a {@code Distribution} {@code Value}. + * @since 0.16 + */ + public static Value distributionValue(Distribution value) { + return ValueDistribution.create(value); + } + + /** + * Applies the given match function to the underlying data type. + * + * @since 0.16 + */ + public abstract T match( + Function doubleFunction, + Function longFunction, + Function distributionFunction, + Function defaultFunction); + + /** A 64-bit double-precision floating-point {@link Value}. */ + @AutoValue + @Immutable + abstract static class ValueDouble extends Value { + + ValueDouble() {} + + @Override + public final T match( + Function doubleFunction, + Function longFunction, + Function distributionFunction, + Function defaultFunction) { + return doubleFunction.apply(getValue()); + } + + /** + * Creates a {@link ValueDouble}. + * + * @param value the value in double. + * @return a {@code ValueDouble}. + */ + static ValueDouble create(double value) { + return new AutoValue_Value_ValueDouble(value); + } + + /** + * Returns the double value. + * + * @return the double value. + */ + abstract double getValue(); + } + + /** A 64-bit integer {@link Value}. */ + @AutoValue + @Immutable + abstract static class ValueLong extends Value { + + ValueLong() {} + + @Override + public final T match( + Function doubleFunction, + Function longFunction, + Function distributionFunction, + Function defaultFunction) { + return longFunction.apply(getValue()); + } + + /** + * Creates a {@link ValueLong}. + * + * @param value the value in long. + * @return a {@code ValueLong}. + */ + static ValueLong create(long value) { + return new AutoValue_Value_ValueLong(value); + } + + /** + * Returns the long value. + * + * @return the long value. + */ + abstract long getValue(); + } + + /** + * {@link ValueDistribution} contains summary statistics for a population of values. It optionally + * contains a histogram representing the distribution of those values across a set of buckets. + */ + @AutoValue + @Immutable + abstract static class ValueDistribution extends Value { + + ValueDistribution() {} + + @Override + public final T match( + Function doubleFunction, + Function longFunction, + Function distributionFunction, + Function defaultFunction) { + return distributionFunction.apply(getValue()); + } + + /** + * Creates a {@link ValueDistribution}. + * + * @param value the {@link Distribution} value. + * @return a {@code ValueDistribution}. + */ + static ValueDistribution create(Distribution value) { + return new AutoValue_Value_ValueDistribution(value); + } + + /** + * Returns the {@link Distribution} value. + * + * @return the {@code Distribution} value. + */ + abstract Distribution getValue(); + } + + // TODO(songya): Add support for Summary type. + // This is an aggregation that produces percentiles directly. +} diff --git a/api/src/main/java/io/opencensus/metrics/export/ExportComponent.java b/api/src/main/java/io/opencensus/metrics/export/ExportComponent.java new file mode 100644 index 00000000..bab65d13 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/export/ExportComponent.java @@ -0,0 +1,60 @@ +/* + * Copyright 2018, 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.metrics.export; + +import io.opencensus.common.ExperimentalApi; + +/** + * Class that holds the implementation instance for {@link MetricProducerManager}. + * + *

    Unless otherwise noted all methods (on component) results are cacheable. + * + * @since 0.16 + */ +@ExperimentalApi +public abstract class ExportComponent { + /** + * Returns the no-op implementation of the {@code ExportComponent}. + * + * @return the no-op implementation of the {@code ExportComponent}. + * @since 0.16 + */ + public static ExportComponent newNoopExportComponent() { + return new NoopExportComponent(); + } + + /** + * Returns the global {@link MetricProducerManager} which can be used to register handlers to + * export all the recorded metrics. + * + * @return the implementation of the {@code MetricExporter} or no-op if no implementation linked + * in the binary. + * @since 0.16 + */ + public abstract MetricProducerManager getMetricProducerManager(); + + private static final class NoopExportComponent extends ExportComponent { + + private static final MetricProducerManager METRIC_PRODUCER_MANAGER = + MetricProducerManager.newNoopMetricProducerManager(); + + @Override + public MetricProducerManager getMetricProducerManager() { + return METRIC_PRODUCER_MANAGER; + } + } +} diff --git a/api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java b/api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java new file mode 100644 index 00000000..c5acf174 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java @@ -0,0 +1,89 @@ +/* + * Copyright 2018, 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.metrics.export; + +import io.opencensus.common.ExperimentalApi; +import io.opencensus.internal.Utils; +import io.opencensus.metrics.MetricProducer; +import java.util.Collections; +import java.util.Set; +import javax.annotation.concurrent.ThreadSafe; + +/** + * Keeps a set of {@link MetricProducer} that is used by exporters to determine the metrics that + * need to be exported. + * + * @since 0.16 + */ +@ExperimentalApi +@ThreadSafe +public abstract class MetricProducerManager { + + /** + * Adds the {@link MetricProducer} to the manager if it is not already present. + * + * @param metricProducer the {@code MetricProducer} to be added to the manager. + * @since 0.16 + */ + public abstract void add(MetricProducer metricProducer); + + /** + * Removes the {@link MetricProducer} to the manager if it is present. + * + * @param metricProducer the {@code MetricProducer} to be removed from the manager. + * @since 0.16 + */ + public abstract void remove(MetricProducer metricProducer); + + /** + * Returns all registered {@link MetricProducer}s that should be exported. + * + *

    This method should be used by any metrics exporter that automatically exports data for + * {@code MetricProducer} registered with the {@code MetricProducerManager}. + * + * @return all registered {@code MetricProducer}s that should be exported. + * @since 0.16 + */ + public abstract Set getAllMetricProducer(); + + /** + * Returns a no-op implementation for {@link MetricProducerManager}. + * + * @return a no-op implementation for {@code MetricProducerManager}. + */ + static MetricProducerManager newNoopMetricProducerManager() { + return new NoopMetricProducerManager(); + } + + private static final class NoopMetricProducerManager extends MetricProducerManager { + + @Override + public void add(MetricProducer metricProducer) { + Utils.checkNotNull(metricProducer, "metricProducer"); + } + + @Override + public void remove(MetricProducer metricProducer) { + Utils.checkNotNull(metricProducer, "metricProducer"); + } + + @Override + public Set getAllMetricProducer() { + return Collections.emptySet(); + } + } +} diff --git a/api/src/main/java/io/opencensus/metrics/package-info.java b/api/src/main/java/io/opencensus/metrics/package-info.java new file mode 100644 index 00000000..33eadf0c --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/package-info.java @@ -0,0 +1,32 @@ +/* + * Copyright 2018, 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. + */ + +/** + * This package describes the Metrics data model. Metrics are a data model for what stats exporters + * take as input. This data model may eventually become the wire format for metrics. + * + *

    WARNING: Currently all the public classes under this package are marked as {@link + * io.opencensus.common.ExperimentalApi}. The classes and APIs under {@link io.opencensus.metrics} + * are likely to get backwards-incompatible updates in the future. DO NOT USE except for + * experimental purposes. + * + *

    Please see + * https://github.com/census-instrumentation/opencensus-specs/blob/master/stats/Metrics.md and + * https://github.com/census-instrumentation/opencensus-proto/blob/master/opencensus/proto/stats/metrics/metrics.proto + * for more details. + */ +@io.opencensus.common.ExperimentalApi +package io.opencensus.metrics; diff --git a/api/src/test/java/io/opencensus/metrics/DistributionTest.java b/api/src/test/java/io/opencensus/metrics/DistributionTest.java new file mode 100644 index 00000000..d511e317 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/DistributionTest.java @@ -0,0 +1,226 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Timestamp; +import io.opencensus.metrics.Distribution.Bucket; +import io.opencensus.metrics.Distribution.Exemplar; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Value}. */ +@RunWith(JUnit4.class) +public class DistributionTest { + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + private static final Timestamp TIMESTAMP = Timestamp.create(1, 0); + private static final Map ATTACHMENTS = Collections.singletonMap("key", "value"); + + @Test + public void createAndGet_Bucket() { + Bucket bucket = Bucket.create(98); + assertThat(bucket.getCount()).isEqualTo(98); + assertThat(bucket.getExemplar()).isNull(); + } + + @Test + public void createAndGet_BucketWithExemplar() { + Exemplar exemplar = Exemplar.create(12.2, TIMESTAMP, ATTACHMENTS); + Bucket bucket = Bucket.create(7, exemplar); + assertThat(bucket.getCount()).isEqualTo(7); + assertThat(bucket.getExemplar()).isEqualTo(exemplar); + } + + @Test + public void createBucket_preventNullExemplar() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("exemplar"); + Bucket.create(1, null); + } + + @Test + public void createAndGet_Exemplar() { + Exemplar exemplar = Exemplar.create(-9.9, TIMESTAMP, ATTACHMENTS); + assertThat(exemplar.getValue()).isEqualTo(-9.9); + assertThat(exemplar.getTimestamp()).isEqualTo(TIMESTAMP); + assertThat(exemplar.getAttachments()).isEqualTo(ATTACHMENTS); + } + + @Test + public void createAndGet_Distribution() { + Exemplar exemplar = Exemplar.create(15.0, TIMESTAMP, ATTACHMENTS); + List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List buckets = + Arrays.asList( + Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4, exemplar)); + Distribution distribution = Distribution.create(6.6, 10, 678.54, bucketBounds, buckets); + assertThat(distribution.getMean()).isEqualTo(6.6); + assertThat(distribution.getCount()).isEqualTo(10); + assertThat(distribution.getSumOfSquaredDeviations()).isEqualTo(678.54); + assertThat(distribution.getBucketBoundaries()) + .containsExactlyElementsIn(bucketBounds) + .inOrder(); + assertThat(distribution.getBuckets()).containsExactlyElementsIn(buckets).inOrder(); + } + + @Test + public void createBucket_NegativeCount() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("bucket count should be non-negative."); + Bucket.create(-5); + } + + @Test + public void createExemplar_PreventNullAttachments() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("attachments"); + Exemplar.create(15, TIMESTAMP, null); + } + + @Test + public void createExemplar_PreventNullAttachmentKey() { + Map attachments = Collections.singletonMap(null, "value"); + thrown.expect(NullPointerException.class); + thrown.expectMessage("key of attachment"); + Exemplar.create(15, TIMESTAMP, attachments); + } + + @Test + public void createExemplar_PreventNullAttachmentValue() { + Map attachments = Collections.singletonMap("key", null); + thrown.expect(NullPointerException.class); + thrown.expectMessage("value of attachment"); + Exemplar.create(15, TIMESTAMP, attachments); + } + + @Test + public void createDistribution_NegativeCount() { + List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List buckets = + Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("count should be non-negative."); + Distribution.create(6.6, -10, 678.54, bucketBounds, buckets); + } + + @Test + public void createDistribution_NegativeSumOfSquaredDeviations() { + List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List buckets = + Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0)); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("sum of squared deviations should be non-negative."); + Distribution.create(6.6, 0, -678.54, bucketBounds, buckets); + } + + @Test + public void createDistribution_ZeroCountAndPositiveMean() { + List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List buckets = + Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0)); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("mean should be 0 if count is 0."); + Distribution.create(6.6, 0, 0, bucketBounds, buckets); + } + + @Test + public void createDistribution_ZeroCountAndSumOfSquaredDeviations() { + List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List buckets = + Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0)); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("sum of squared deviations should be 0 if count is 0."); + Distribution.create(0, 0, 678.54, bucketBounds, buckets); + } + + @Test + public void createDistribution_NullBucketBounds() { + List buckets = + Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); + thrown.expect(NullPointerException.class); + thrown.expectMessage("bucketBoundaries list should not be null."); + Distribution.create(6.6, 10, 678.54, null, buckets); + } + + @Test + public void createDistribution_UnorderedBucketBounds() { + List bucketBounds = Arrays.asList(0.0, -1.0, 1.0); + List buckets = + Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("bucket boundaries not sorted."); + Distribution.create(6.6, 10, 678.54, bucketBounds, buckets); + } + + @Test + public void createDistribution_NullBucketList() { + List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + thrown.expect(NullPointerException.class); + thrown.expectMessage("bucket list should not be null."); + Distribution.create(6.6, 10, 678.54, bucketBounds, null); + } + + @Test + public void createDistribution_NullBucket() { + List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List buckets = + Arrays.asList(Bucket.create(3), Bucket.create(1), null, Bucket.create(4)); + thrown.expect(NullPointerException.class); + thrown.expectMessage("bucket should not be null."); + Distribution.create(6.6, 10, 678.54, bucketBounds, buckets); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + Distribution.create( + 10, + 10, + 1, + Arrays.asList(-5.0, 0.0, 5.0), + Arrays.asList( + Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))), + Distribution.create( + 10, + 10, + 1, + Arrays.asList(-5.0, 0.0, 5.0), + Arrays.asList( + Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)))) + .addEqualityGroup( + Distribution.create( + -7, + 10, + 23.456, + Arrays.asList(-5.0, 0.0, 5.0), + Arrays.asList( + Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)))) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/LabelKeyTest.java b/api/src/test/java/io/opencensus/metrics/LabelKeyTest.java new file mode 100644 index 00000000..83f2b59a --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/LabelKeyTest.java @@ -0,0 +1,86 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import java.util.Arrays; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link LabelKey}. */ +@RunWith(JUnit4.class) +public class LabelKeyTest { + + private static final LabelKey KEY = LabelKey.create("key", "description"); + + @Test + public void testGetKey() { + assertThat(KEY.getKey()).isEqualTo("key"); + } + + @Test + public void testGetDescription() { + assertThat(KEY.getDescription()).isEqualTo("description"); + } + + @Test + public void create_NoLengthConstraint() { + // We have a length constraint of 256-characters for TagKey. That constraint doesn't apply to + // LabelKey. + char[] chars = new char[300]; + Arrays.fill(chars, 'k'); + String key = new String(chars); + assertThat(LabelKey.create(key, "").getKey()).isEqualTo(key); + } + + @Test + public void create_WithUnprintableChars() { + String key = "\2ab\3cd"; + String description = "\4ef\5gh"; + LabelKey labelKey = LabelKey.create(key, description); + assertThat(labelKey.getKey()).isEqualTo(key); + assertThat(labelKey.getDescription()).isEqualTo(description); + } + + @Test + public void create_WithNonAsciiChars() { + String key = "键"; + String description = "测试用键"; + LabelKey nonAsciiKey = LabelKey.create(key, description); + assertThat(nonAsciiKey.getKey()).isEqualTo(key); + assertThat(nonAsciiKey.getDescription()).isEqualTo(description); + } + + @Test + public void create_Empty() { + LabelKey emptyKey = LabelKey.create("", ""); + assertThat(emptyKey.getKey()).isEmpty(); + assertThat(emptyKey.getDescription()).isEmpty(); + } + + @Test + public void testLabelKeyEquals() { + new EqualsTester() + .addEqualityGroup(LabelKey.create("foo", ""), LabelKey.create("foo", "")) + .addEqualityGroup(LabelKey.create("foo", "description")) + .addEqualityGroup(LabelKey.create("bar", "")) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/LabelValueTest.java b/api/src/test/java/io/opencensus/metrics/LabelValueTest.java new file mode 100644 index 00000000..e5526b2f --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/LabelValueTest.java @@ -0,0 +1,74 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import java.util.Arrays; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link LabelValue}. */ +@RunWith(JUnit4.class) +public class LabelValueTest { + + private static final LabelValue VALUE = LabelValue.create("value"); + private static final LabelValue UNSET = LabelValue.create(null); + private static final LabelValue EMPTY = LabelValue.create(""); + + @Test + public void testGetValue() { + assertThat(VALUE.getValue()).isEqualTo("value"); + assertThat(UNSET.getValue()).isNull(); + assertThat(EMPTY.getValue()).isEmpty(); + } + + @Test + public void create_NoLengthConstraint() { + // We have a length constraint of 256-characters for TagValue. That constraint doesn't apply to + // LabelValue. + char[] chars = new char[300]; + Arrays.fill(chars, 'v'); + String value = new String(chars); + assertThat(LabelValue.create(value).getValue()).isEqualTo(value); + } + + @Test + public void create_WithUnprintableChars() { + String value = "\2ab\3cd"; + assertThat(LabelValue.create(value).getValue()).isEqualTo(value); + } + + @Test + public void create_WithNonAsciiChars() { + String value = "值"; + LabelValue nonAsciiValue = LabelValue.create(value); + assertThat(nonAsciiValue.getValue()).isEqualTo(value); + } + + @Test + public void testLabelValueEquals() { + new EqualsTester() + .addEqualityGroup(LabelValue.create("foo"), LabelValue.create("foo")) + .addEqualityGroup(UNSET) + .addEqualityGroup(EMPTY) + .addEqualityGroup(LabelValue.create("bar")) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/MetricDescriptorTest.java b/api/src/test/java/io/opencensus/metrics/MetricDescriptorTest.java new file mode 100644 index 00000000..9c0a42fc --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/MetricDescriptorTest.java @@ -0,0 +1,102 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.metrics.MetricDescriptor.Type; +import java.util.Arrays; +import java.util.List; +import org.hamcrest.CoreMatchers; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link MetricDescriptor}. */ +@RunWith(JUnit4.class) +public class MetricDescriptorTest { + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + private static final String METRIC_NAME_1 = "metric1"; + private static final String METRIC_NAME_2 = "metric2"; + private static final String DESCRIPTION = "Metric description."; + private static final String UNIT = "kb/s"; + private static final LabelKey KEY_1 = LabelKey.create("key1", "some key"); + private static final LabelKey KEY_2 = LabelKey.create("key2", "some other key"); + + @Test + public void testGet() { + MetricDescriptor metricDescriptor = + MetricDescriptor.create( + METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2)); + assertThat(metricDescriptor.getName()).isEqualTo(METRIC_NAME_1); + assertThat(metricDescriptor.getDescription()).isEqualTo(DESCRIPTION); + assertThat(metricDescriptor.getUnit()).isEqualTo(UNIT); + assertThat(metricDescriptor.getType()).isEqualTo(Type.GAUGE_DOUBLE); + assertThat(metricDescriptor.getLabelKeys()).containsExactly(KEY_1, KEY_2).inOrder(); + } + + @Test + public void preventNullLabelKeyList() { + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("labelKeys")); + MetricDescriptor.create(METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, null); + } + + @Test + public void preventNullLabelKey() { + List keys = Arrays.asList(KEY_1, null); + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("labelKey")); + MetricDescriptor.create(METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, keys); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + MetricDescriptor.create( + METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2)), + MetricDescriptor.create( + METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2))) + .addEqualityGroup( + MetricDescriptor.create( + METRIC_NAME_2, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2))) + .addEqualityGroup( + MetricDescriptor.create( + METRIC_NAME_2, DESCRIPTION, UNIT, Type.GAUGE_INT64, Arrays.asList(KEY_1, KEY_2))) + .addEqualityGroup( + MetricDescriptor.create( + METRIC_NAME_1, + DESCRIPTION, + UNIT, + Type.CUMULATIVE_DISTRIBUTION, + Arrays.asList(KEY_1, KEY_2))) + .addEqualityGroup( + MetricDescriptor.create( + METRIC_NAME_1, + DESCRIPTION, + UNIT, + Type.CUMULATIVE_DISTRIBUTION, + Arrays.asList(KEY_1))) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java b/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java new file mode 100644 index 00000000..49e8ce02 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java @@ -0,0 +1,185 @@ +/* + * Copyright 2018, 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.metrics; + +import io.opencensus.common.ToDoubleFunction; +import io.opencensus.common.ToLongFunction; +import java.util.LinkedHashMap; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link MetricRegistry}. */ +@RunWith(JUnit4.class) +public class MetricRegistryTest { + @Rule public ExpectedException thrown = ExpectedException.none(); + + private final MetricRegistry metricRegistry = + MetricsComponent.newNoopMetricsComponent().getMetricRegistry(); + + @Test + public void addDoubleGauge_NullName() { + thrown.expect(NullPointerException.class); + metricRegistry.addDoubleGauge( + null, + "description", + "1", + new LinkedHashMap(), + null, + new ToDoubleFunction() { + @Override + public double applyAsDouble(Object value) { + return 5.0; + } + }); + } + + @Test + public void addDoubleGauge_NullDescription() { + thrown.expect(NullPointerException.class); + metricRegistry.addDoubleGauge( + "name", + null, + "1", + new LinkedHashMap(), + null, + new ToDoubleFunction() { + @Override + public double applyAsDouble(Object value) { + return 5.0; + } + }); + } + + @Test + public void addDoubleGauge_NullUnit() { + thrown.expect(NullPointerException.class); + metricRegistry.addDoubleGauge( + "name", + "description", + null, + new LinkedHashMap(), + null, + new ToDoubleFunction() { + @Override + public double applyAsDouble(Object value) { + return 5.0; + } + }); + } + + @Test + public void addDoubleGauge_NullLabels() { + thrown.expect(NullPointerException.class); + metricRegistry.addDoubleGauge( + "name", + "description", + "1", + null, + null, + new ToDoubleFunction() { + @Override + public double applyAsDouble(Object value) { + return 5.0; + } + }); + } + + @Test + public void addDoubleGauge_NullFunction() { + thrown.expect(NullPointerException.class); + metricRegistry.addDoubleGauge( + "name", "description", "1", new LinkedHashMap(), null, null); + } + + @Test + public void addLongGauge_NullName() { + thrown.expect(NullPointerException.class); + metricRegistry.addLongGauge( + null, + "description", + "1", + new LinkedHashMap(), + null, + new ToLongFunction() { + @Override + public long applyAsLong(Object value) { + return 5; + } + }); + } + + @Test + public void addLongGauge_NullDescription() { + thrown.expect(NullPointerException.class); + metricRegistry.addLongGauge( + "name", + null, + "1", + new LinkedHashMap(), + null, + new ToLongFunction() { + @Override + public long applyAsLong(Object value) { + return 5; + } + }); + } + + @Test + public void addLongGauge_NullUnit() { + thrown.expect(NullPointerException.class); + metricRegistry.addLongGauge( + "name", + "description", + null, + new LinkedHashMap(), + null, + new ToLongFunction() { + @Override + public long applyAsLong(Object value) { + return 5; + } + }); + } + + @Test + public void addLongGauge_NullLabels() { + thrown.expect(NullPointerException.class); + metricRegistry.addLongGauge( + "name", + "description", + "1", + null, + null, + new ToLongFunction() { + @Override + public long applyAsLong(Object value) { + return 5; + } + }); + } + + @Test + public void addLongGauge_NullFunction() { + thrown.expect(NullPointerException.class); + metricRegistry.addLongGauge( + "name", "description", "1", new LinkedHashMap(), null, null); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/MetricTest.java b/api/src/test/java/io/opencensus/metrics/MetricTest.java new file mode 100644 index 00000000..37deed4b --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/MetricTest.java @@ -0,0 +1,116 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Timestamp; +import io.opencensus.metrics.MetricDescriptor.Type; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Metric}. */ +@RunWith(JUnit4.class) +public class MetricTest { + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + private static final String METRIC_NAME_1 = "metric1"; + private static final String METRIC_NAME_2 = "metric2"; + private static final String DESCRIPTION = "Metric description."; + private static final String UNIT = "kb/s"; + private static final LabelKey KEY_1 = LabelKey.create("key1", "some key"); + private static final LabelKey KEY_2 = LabelKey.create("key1", "some other key"); + private static final MetricDescriptor METRIC_DESCRIPTOR_1 = + MetricDescriptor.create( + METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2)); + private static final MetricDescriptor METRIC_DESCRIPTOR_2 = + MetricDescriptor.create( + METRIC_NAME_2, DESCRIPTION, UNIT, Type.CUMULATIVE_INT64, Arrays.asList(KEY_1)); + private static final LabelValue LABEL_VALUE_1 = LabelValue.create("value1"); + private static final LabelValue LABEL_VALUE_2 = LabelValue.create("value1"); + private static final LabelValue LABEL_VALUE_EMPTY = LabelValue.create(""); + private static final Value VALUE_LONG = Value.longValue(12345678); + private static final Value VALUE_DOUBLE_1 = Value.doubleValue(-345.77); + private static final Value VALUE_DOUBLE_2 = Value.doubleValue(133.79); + private static final Timestamp TIMESTAMP_1 = Timestamp.fromMillis(1000); + private static final Timestamp TIMESTAMP_2 = Timestamp.fromMillis(2000); + private static final Timestamp TIMESTAMP_3 = Timestamp.fromMillis(3000); + private static final Point POINT_1 = Point.create(VALUE_DOUBLE_1, TIMESTAMP_2); + private static final Point POINT_2 = Point.create(VALUE_DOUBLE_2, TIMESTAMP_3); + private static final Point POINT_3 = Point.create(VALUE_LONG, TIMESTAMP_3); + private static final TimeSeries GAUGE_TIME_SERIES_1 = + TimeSeries.create(Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), null); + private static final TimeSeries GAUGE_TIME_SERIES_2 = + TimeSeries.create(Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_2), null); + private static final TimeSeries CUMULATIVE_TIME_SERIES = + TimeSeries.create(Arrays.asList(LABEL_VALUE_EMPTY), Arrays.asList(POINT_3), TIMESTAMP_1); + + @Test + public void testGet() { + Metric metric = + Metric.create(METRIC_DESCRIPTOR_1, Arrays.asList(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2)); + assertThat(metric.getMetricDescriptor()).isEqualTo(METRIC_DESCRIPTOR_1); + assertThat(metric.getTimeSeriesList()) + .containsExactly(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2) + .inOrder(); + } + + @Test + public void typeMismatch_GaugeDouble_Long() { + typeMismatch( + METRIC_DESCRIPTOR_1, + Arrays.asList(CUMULATIVE_TIME_SERIES), + String.format("Type mismatch: %s, %s.", Type.GAUGE_DOUBLE, "ValueLong")); + } + + @Test + public void typeMismatch_CumulativeInt64_Double() { + typeMismatch( + METRIC_DESCRIPTOR_2, + Arrays.asList(GAUGE_TIME_SERIES_1), + String.format("Type mismatch: %s, %s.", Type.CUMULATIVE_INT64, "ValueDouble")); + } + + private void typeMismatch( + MetricDescriptor metricDescriptor, List timeSeriesList, String errorMessage) { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage(errorMessage); + Metric.create(metricDescriptor, timeSeriesList); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + Metric.create( + METRIC_DESCRIPTOR_1, Arrays.asList(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2)), + Metric.create( + METRIC_DESCRIPTOR_1, Arrays.asList(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2))) + .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_1, Collections.emptyList())) + .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_2, Arrays.asList(CUMULATIVE_TIME_SERIES))) + .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_2, Collections.emptyList())) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/MetricsComponentTest.java b/api/src/test/java/io/opencensus/metrics/MetricsComponentTest.java new file mode 100644 index 00000000..1c4e70f7 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/MetricsComponentTest.java @@ -0,0 +1,40 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.metrics.export.ExportComponent; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link MetricsComponent}. */ +@RunWith(JUnit4.class) +public class MetricsComponentTest { + @Test + public void defaultExportComponent() { + assertThat(MetricsComponent.newNoopMetricsComponent().getExportComponent()) + .isInstanceOf(ExportComponent.newNoopExportComponent().getClass()); + } + + @Test + public void defaultMetricRegistry() { + assertThat(MetricsComponent.newNoopMetricsComponent().getMetricRegistry()) + .isInstanceOf(MetricRegistry.newNoopMetricRegistry().getClass()); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/MetricsTest.java b/api/src/test/java/io/opencensus/metrics/MetricsTest.java new file mode 100644 index 00000000..9e0eee1f --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/MetricsTest.java @@ -0,0 +1,71 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.metrics.export.ExportComponent; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Metrics}. */ +@RunWith(JUnit4.class) +public class MetricsTest { + @Rule public ExpectedException thrown = ExpectedException.none(); + + @Test + public void loadMetricsComponent_UsesProvidedClassLoader() { + final RuntimeException toThrow = new RuntimeException("UseClassLoader"); + thrown.expect(RuntimeException.class); + thrown.expectMessage("UseClassLoader"); + Metrics.loadMetricsComponent( + new ClassLoader() { + @Override + public Class loadClass(String name) { + throw toThrow; + } + }); + } + + @Test + public void loadMetricsComponent_IgnoresMissingClasses() { + ClassLoader classLoader = + new ClassLoader() { + @Override + public Class loadClass(String name) throws ClassNotFoundException { + throw new ClassNotFoundException(); + } + }; + assertThat(Metrics.loadMetricsComponent(classLoader).getClass().getName()) + .isEqualTo("io.opencensus.metrics.MetricsComponent$NoopMetricsComponent"); + } + + @Test + public void defaultExportComponent() { + assertThat(Metrics.getExportComponent()) + .isInstanceOf(ExportComponent.newNoopExportComponent().getClass()); + } + + @Test + public void defaultMetricRegistry() { + assertThat(Metrics.getMetricRegistry()) + .isInstanceOf(MetricRegistry.newNoopMetricRegistry().getClass()); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/PointTest.java b/api/src/test/java/io/opencensus/metrics/PointTest.java new file mode 100644 index 00000000..cb6175c1 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/PointTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Timestamp; +import io.opencensus.metrics.Distribution.Bucket; +import java.util.Arrays; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Point}. */ +@RunWith(JUnit4.class) +public class PointTest { + + private static final Value DOUBLE_VALUE = Value.doubleValue(55.5); + private static final Value LONG_VALUE = Value.longValue(9876543210L); + private static final Value DISTRIBUTION_VALUE = + Value.distributionValue( + Distribution.create( + 6.6, + 10, + 678.54, + Arrays.asList(-1.0, 0.0, 1.0), + Arrays.asList( + Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)))); + private static final Timestamp TIMESTAMP_1 = Timestamp.create(1, 2); + private static final Timestamp TIMESTAMP_2 = Timestamp.create(3, 4); + private static final Timestamp TIMESTAMP_3 = Timestamp.create(5, 6); + + @Test + public void testGet() { + Point point = Point.create(DOUBLE_VALUE, TIMESTAMP_1); + assertThat(point.getValue()).isEqualTo(DOUBLE_VALUE); + assertThat(point.getTimestamp()).isEqualTo(TIMESTAMP_1); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + Point.create(DOUBLE_VALUE, TIMESTAMP_1), Point.create(DOUBLE_VALUE, TIMESTAMP_1)) + .addEqualityGroup(Point.create(LONG_VALUE, TIMESTAMP_1)) + .addEqualityGroup(Point.create(LONG_VALUE, TIMESTAMP_2)) + .addEqualityGroup( + Point.create(DISTRIBUTION_VALUE, TIMESTAMP_2), + Point.create(DISTRIBUTION_VALUE, TIMESTAMP_2)) + .addEqualityGroup(Point.create(DISTRIBUTION_VALUE, TIMESTAMP_3)) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/TimeSeriesTest.java b/api/src/test/java/io/opencensus/metrics/TimeSeriesTest.java new file mode 100644 index 00000000..07dff97d --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/TimeSeriesTest.java @@ -0,0 +1,116 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Timestamp; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.hamcrest.CoreMatchers; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TimeSeries}. */ +@RunWith(JUnit4.class) +public class TimeSeriesTest { + + @Rule public ExpectedException thrown = ExpectedException.none(); + + private static final LabelValue LABEL_VALUE_1 = LabelValue.create("value1"); + private static final LabelValue LABEL_VALUE_2 = LabelValue.create("value2"); + private static final Value VALUE_LONG = Value.longValue(12345678); + private static final Value VALUE_DOUBLE = Value.doubleValue(-345.77); + private static final Timestamp TIMESTAMP_1 = Timestamp.fromMillis(1000); + private static final Timestamp TIMESTAMP_2 = Timestamp.fromMillis(2000); + private static final Timestamp TIMESTAMP_3 = Timestamp.fromMillis(3000); + private static final Point POINT_1 = Point.create(VALUE_DOUBLE, TIMESTAMP_2); + private static final Point POINT_2 = Point.create(VALUE_LONG, TIMESTAMP_3); + + @Test + public void testGet_TimeSeries() { + TimeSeries cumulativeTimeSeries = + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1); + assertThat(cumulativeTimeSeries.getStartTimestamp()).isEqualTo(TIMESTAMP_1); + assertThat(cumulativeTimeSeries.getLabelValues()) + .containsExactly(LABEL_VALUE_1, LABEL_VALUE_2) + .inOrder(); + assertThat(cumulativeTimeSeries.getPoints()).containsExactly(POINT_1).inOrder(); + } + + @Test + public void create_WithNullLabelValueList() { + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("labelValues")); + TimeSeries.create(null, Collections.emptyList(), TIMESTAMP_1); + } + + @Test + public void create_WithNullLabelValue() { + List labelValues = Arrays.asList(LABEL_VALUE_1, null); + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("labelValue")); + TimeSeries.create(labelValues, Collections.emptyList(), TIMESTAMP_1); + } + + @Test + public void create_WithNullPointList() { + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("points")); + TimeSeries.create(Collections.emptyList(), null, TIMESTAMP_1); + } + + @Test + public void create_WithNullPoint() { + List points = Arrays.asList(POINT_1, null); + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("point")); + TimeSeries.create(Collections.emptyList(), points, TIMESTAMP_1); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1), + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1)) + .addEqualityGroup( + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), null), + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), null)) + .addEqualityGroup( + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_2)) + .addEqualityGroup( + TimeSeries.create(Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_1), TIMESTAMP_2)) + .addEqualityGroup( + TimeSeries.create(Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_2), TIMESTAMP_2)) + .addEqualityGroup( + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_1, POINT_2), TIMESTAMP_2)) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/ValueTest.java b/api/src/test/java/io/opencensus/metrics/ValueTest.java new file mode 100644 index 00000000..63430b28 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/ValueTest.java @@ -0,0 +1,128 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Function; +import io.opencensus.common.Functions; +import io.opencensus.metrics.Distribution.Bucket; +import io.opencensus.metrics.Value.ValueDistribution; +import io.opencensus.metrics.Value.ValueDouble; +import io.opencensus.metrics.Value.ValueLong; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Value}. */ +@RunWith(JUnit4.class) +public class ValueTest { + + private static final Distribution DISTRIBUTION = + Distribution.create( + 10, + 10, + 1, + Arrays.asList(-5.0, 0.0, 5.0), + Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))); + + @Test + public void createAndGet_ValueDouble() { + Value value = Value.doubleValue(-34.56); + assertThat(value).isInstanceOf(ValueDouble.class); + assertThat(((ValueDouble) value).getValue()).isEqualTo(-34.56); + } + + @Test + public void createAndGet_ValueLong() { + Value value = Value.longValue(123456789); + assertThat(value).isInstanceOf(ValueLong.class); + assertThat(((ValueLong) value).getValue()).isEqualTo(123456789); + } + + @Test + public void createAndGet_ValueDistribution() { + Value value = Value.distributionValue(DISTRIBUTION); + assertThat(value).isInstanceOf(ValueDistribution.class); + assertThat(((ValueDistribution) value).getValue()).isEqualTo(DISTRIBUTION); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup(Value.doubleValue(1.0), Value.doubleValue(1.0)) + .addEqualityGroup(Value.doubleValue(2.0)) + .addEqualityGroup(Value.longValue(1L)) + .addEqualityGroup(Value.longValue(2L)) + .addEqualityGroup( + Value.distributionValue( + Distribution.create( + -7, + 10, + 23.456, + Arrays.asList(-5.0, 0.0, 5.0), + Arrays.asList( + Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))))) + .testEquals(); + } + + @Test + public void testMatch() { + List values = + Arrays.asList( + ValueDouble.create(1.0), ValueLong.create(-1), ValueDistribution.create(DISTRIBUTION)); + List expected = + Arrays.asList(1.0, -1L, 10.0, 10L, 1.0, -5.0, 0.0, 5.0, 3L, 1L, 2L, 4L); + final List actual = new ArrayList(); + for (Value value : values) { + value.match( + new Function() { + @Override + public Object apply(Double arg) { + actual.add(arg); + return null; + } + }, + new Function() { + @Override + public Object apply(Long arg) { + actual.add(arg); + return null; + } + }, + new Function() { + @Override + public Object apply(Distribution arg) { + actual.add(arg.getMean()); + actual.add(arg.getCount()); + actual.add(arg.getSumOfSquaredDeviations()); + actual.addAll(arg.getBucketBoundaries()); + for (Bucket bucket : arg.getBuckets()) { + actual.add(bucket.getCount()); + } + return null; + } + }, + Functions.throwAssertionError()); + } + assertThat(actual).containsExactlyElementsIn(expected).inOrder(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/export/ExportComponentTest.java b/api/src/test/java/io/opencensus/metrics/export/ExportComponentTest.java new file mode 100644 index 00000000..15c6e883 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/export/ExportComponentTest.java @@ -0,0 +1,33 @@ +/* + * Copyright 2018, 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.metrics.export; + +import static com.google.common.truth.Truth.assertThat; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link ExportComponent}. */ +@RunWith(JUnit4.class) +public class ExportComponentTest { + @Test + public void defaultMetricExporter() { + assertThat(ExportComponent.newNoopExportComponent().getMetricProducerManager()) + .isInstanceOf(MetricProducerManager.class); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java b/api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java new file mode 100644 index 00000000..07854927 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java @@ -0,0 +1,81 @@ +/* + * Copyright 2018, 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.metrics.export; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.metrics.MetricProducer; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** Unit tests for {@link MetricProducerManager}. */ +@RunWith(JUnit4.class) +public class MetricProducerManagerTest { + private final MetricProducerManager metricProducerManager = + MetricProducerManager.newNoopMetricProducerManager(); + @Mock private MetricProducer metricProducer; + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void add_DisallowsNull() { + thrown.expect(NullPointerException.class); + metricProducerManager.add(null); + } + + @Test + public void add() { + metricProducerManager.add(metricProducer); + assertThat(metricProducerManager.getAllMetricProducer()).isEmpty(); + } + + @Test + public void addAndRemove() { + metricProducerManager.add(metricProducer); + assertThat(metricProducerManager.getAllMetricProducer()).isEmpty(); + metricProducerManager.remove(metricProducer); + assertThat(metricProducerManager.getAllMetricProducer()).isEmpty(); + } + + @Test + public void remove_DisallowsNull() { + thrown.expect(NullPointerException.class); + metricProducerManager.remove(null); + } + + @Test + public void remove_FromEmpty() { + metricProducerManager.remove(metricProducer); + assertThat(metricProducerManager.getAllMetricProducer()).isEmpty(); + } + + @Test + public void getAllMetricProducer_empty() { + assertThat(metricProducerManager.getAllMetricProducer()).isEmpty(); + } +} -- cgit v1.2.3 From 3d98a788798898ca653d3d2ac0aa984410e2a436 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Mon, 17 Sep 2018 10:15:15 -0700 Subject: Tracing: Add AttributeValueDouble. (#1442) Also update Trace exporters and ZPages, and fix a few typos. --- .../java/io/opencensus/trace/AttributeValue.java | 107 ++++++++++++++++++++- .../io/opencensus/trace/AttributeValueTest.java | 82 ++++++++++++++++ 2 files changed, 185 insertions(+), 4 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/trace/AttributeValue.java b/api/src/main/java/io/opencensus/trace/AttributeValue.java index a8d4e1e3..efa9d1df 100644 --- a/api/src/main/java/io/opencensus/trace/AttributeValue.java +++ b/api/src/main/java/io/opencensus/trace/AttributeValue.java @@ -63,6 +63,17 @@ public abstract class AttributeValue { return AttributeValueLong.create(longValue); } + /** + * Returns an {@code AttributeValue} with a double value. + * + * @param doubleValue The new value. + * @return an {@code AttributeValue} with a double value. + * @since 0.17 + */ + public static AttributeValue doubleAttributeValue(double doubleValue) { + return AttributeValueDouble.create(doubleValue); + } + AttributeValue() {} /** @@ -78,13 +89,38 @@ public abstract class AttributeValue { * io.opencensus.common.Functions} for some common functions for handling unknown types. * @return the result of the function applied to the underlying value. * @since 0.5 + * @deprecated in favor of {@link #match(Function, Function, Function, Function, Function)}. */ + @Deprecated public abstract T match( Function stringFunction, Function booleanFunction, Function longFunction, Function defaultFunction); + /** + * Applies a function to the underlying value. The function that is called depends on the value's + * type, which can be {@code String}, {@code Long}, or {@code Boolean}. + * + * @param stringFunction the function that should be applied if the value has type {@code String}. + * @param longFunction the function that should be applied if the value has type {@code Long}. + * @param booleanFunction the function that should be applied if the value has type {@code + * Boolean}. + * @param doubleFunction the function that should be applied if the value has type {@code Double}. + * @param defaultFunction the function that should be applied if the value has a type that was + * added after this {@code match} method was added to the API. See {@link + * io.opencensus.common.Functions} for some common functions for handling unknown types. + * @return the result of the function applied to the underlying value. + * @since 0.17 + */ + @SuppressWarnings("InconsistentOverloads") + public abstract T match( + Function stringFunction, + Function booleanFunction, + Function longFunction, + Function doubleFunction, + Function defaultFunction); + @Immutable @AutoValue abstract static class AttributeValueString extends AttributeValue { @@ -105,6 +141,16 @@ public abstract class AttributeValue { return stringFunction.apply(getStringValue()); } + @Override + public final T match( + Function stringFunction, + Function booleanFunction, + Function longFunction, + Function doubleFunction, + Function defaultFunction) { + return stringFunction.apply(getStringValue()); + } + abstract String getStringValue(); } @@ -114,9 +160,9 @@ public abstract class AttributeValue { AttributeValueBoolean() {} - static AttributeValue create(Boolean stringValue) { + static AttributeValue create(Boolean booleanValue) { return new AutoValue_AttributeValue_AttributeValueBoolean( - Utils.checkNotNull(stringValue, "stringValue")); + Utils.checkNotNull(booleanValue, "booleanValue")); } @Override @@ -128,6 +174,16 @@ public abstract class AttributeValue { return booleanFunction.apply(getBooleanValue()); } + @Override + public final T match( + Function stringFunction, + Function booleanFunction, + Function longFunction, + Function doubleFunction, + Function defaultFunction) { + return booleanFunction.apply(getBooleanValue()); + } + abstract Boolean getBooleanValue(); } @@ -137,9 +193,9 @@ public abstract class AttributeValue { AttributeValueLong() {} - static AttributeValue create(Long stringValue) { + static AttributeValue create(Long longValue) { return new AutoValue_AttributeValue_AttributeValueLong( - Utils.checkNotNull(stringValue, "stringValue")); + Utils.checkNotNull(longValue, "longValue")); } @Override @@ -151,6 +207,49 @@ public abstract class AttributeValue { return longFunction.apply(getLongValue()); } + @Override + public final T match( + Function stringFunction, + Function booleanFunction, + Function longFunction, + Function doubleFunction, + Function defaultFunction) { + return longFunction.apply(getLongValue()); + } + abstract Long getLongValue(); } + + @Immutable + @AutoValue + abstract static class AttributeValueDouble extends AttributeValue { + + AttributeValueDouble() {} + + static AttributeValue create(Double doubleValue) { + return new AutoValue_AttributeValue_AttributeValueDouble( + Utils.checkNotNull(doubleValue, "doubleValue")); + } + + @Override + public final T match( + Function stringFunction, + Function booleanFunction, + Function longFunction, + Function defaultFunction) { + return defaultFunction.apply(getDoubleValue()); + } + + @Override + public final T match( + Function stringFunction, + Function booleanFunction, + Function longFunction, + Function doubleFunction, + Function defaultFunction) { + return doubleFunction.apply(getDoubleValue()); + } + + abstract Double getDoubleValue(); + } } diff --git a/api/src/test/java/io/opencensus/trace/AttributeValueTest.java b/api/src/test/java/io/opencensus/trace/AttributeValueTest.java index e505c59b..05ef43c0 100644 --- a/api/src/test/java/io/opencensus/trace/AttributeValueTest.java +++ b/api/src/test/java/io/opencensus/trace/AttributeValueTest.java @@ -123,6 +123,83 @@ public class AttributeValueTest { Functions.throwIllegalArgumentException()); } + @Test + public void doubleAttributeValue() { + AttributeValue attribute = AttributeValue.doubleAttributeValue(1.23456); + attribute.match( + new Function() { + @Override + @Nullable + public Object apply(String stringValue) { + fail("Expected a Double"); + return null; + } + }, + new Function() { + @Override + @Nullable + public Object apply(Boolean booleanValue) { + fail("Expected a Double"); + return null; + } + }, + new Function() { + @Override + @Nullable + public Object apply(Long longValue) { + fail("Expected a Double"); + return null; + } + }, + new Function() { + @Override + @Nullable + public Object apply(Double doubleValue) { + assertThat(doubleValue).isEqualTo(1.23456); + return null; + } + }, + Functions.throwIllegalArgumentException()); + } + + @Test + public void doubleAttributeValue_DeprecatedMatchFunction() { + AttributeValue attribute = AttributeValue.doubleAttributeValue(1.23456); + attribute.match( + new Function() { + @Override + @Nullable + public Object apply(String stringValue) { + fail("Expected a Double"); + return null; + } + }, + new Function() { + @Override + @Nullable + public Object apply(Boolean booleanValue) { + fail("Expected a Double"); + return null; + } + }, + new Function() { + @Override + @Nullable + public Object apply(Long longValue) { + fail("Expected a Double"); + return null; + } + }, + new Function() { + @Override + @Nullable + public Object apply(Object value) { + assertThat(value).isEqualTo(1.23456); + return null; + } + }); + } + @Test public void attributeValue_EqualsAndHashCode() { EqualsTester tester = new EqualsTester(); @@ -136,6 +213,9 @@ public class AttributeValueTest { tester.addEqualityGroup( AttributeValue.longAttributeValue(123456L), AttributeValue.longAttributeValue(123456L)); tester.addEqualityGroup(AttributeValue.longAttributeValue(1234567L)); + tester.addEqualityGroup( + AttributeValue.doubleAttributeValue(1.23456), AttributeValue.doubleAttributeValue(1.23456)); + tester.addEqualityGroup(AttributeValue.doubleAttributeValue(1.234567)); tester.testEquals(); } @@ -147,5 +227,7 @@ public class AttributeValueTest { assertThat(attribute.toString()).contains("true"); attribute = AttributeValue.longAttributeValue(123456L); assertThat(attribute.toString()).contains("123456"); + attribute = AttributeValue.doubleAttributeValue(1.23456); + assertThat(attribute.toString()).contains("1.23456"); } } -- cgit v1.2.3 From 7da904c4e75d68eaf77ecaca59e82fa932251e0c Mon Sep 17 00:00:00 2001 From: Yang Song Date: Tue, 18 Sep 2018 16:25:14 -0700 Subject: Common: Add an API Functions.returnToString(). (#1443) * Common: Add an API Functions.returnToString(). * Fix comments and add tests. --- api/src/main/java/io/opencensus/common/Functions.java | 18 ++++++++++++++++++ .../test/java/io/opencensus/common/FunctionsTest.java | 8 ++++++++ 2 files changed, 26 insertions(+) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/Functions.java b/api/src/main/java/io/opencensus/common/Functions.java index eb5984af..ea3457ca 100644 --- a/api/src/main/java/io/opencensus/common/Functions.java +++ b/api/src/main/java/io/opencensus/common/Functions.java @@ -53,6 +53,14 @@ public final class Functions { } }; + private static final Function RETURN_TO_STRING = + new Function() { + @Override + public /*@Nullable*/ String apply(Object input) { + return input == null ? null : input.toString(); + } + }; + /** * A {@code Function} that always ignores its argument and returns {@code null}. * @@ -81,6 +89,16 @@ public final class Functions { }; } + /** + * A {@code Function} that always returns the {@link #toString()} value of the input. + * + * @return a {@code Function} that always returns the {@link #toString()} value of the input. + * @since 0.17 + */ + public static Function returnToString() { + return RETURN_TO_STRING; + } + /** * A {@code Function} that always ignores its argument and throws an {@link * IllegalArgumentException}. diff --git a/api/src/test/java/io/opencensus/common/FunctionsTest.java b/api/src/test/java/io/opencensus/common/FunctionsTest.java index e4d37569..55d58d4d 100644 --- a/api/src/test/java/io/opencensus/common/FunctionsTest.java +++ b/api/src/test/java/io/opencensus/common/FunctionsTest.java @@ -39,6 +39,14 @@ public class FunctionsTest { assertThat(Functions.returnConstant(123).apply("ignored")).isEqualTo(123); } + @Test + public void testReturnToString() { + assertThat(Functions.returnToString().apply("input")).isEqualTo("input"); + assertThat(Functions.returnToString().apply(Boolean.FALSE)).isEqualTo("false"); + assertThat(Functions.returnToString().apply(Double.valueOf(123.45))).isEqualTo("123.45"); + assertThat(Functions.returnToString().apply(null)).isEqualTo(null); + } + @Test public void testThrowIllegalArgumentException() { Function f = Functions.throwIllegalArgumentException(); -- cgit v1.2.3 From fb41bec0a6618bef81f5dcc1f249a8ce530ebd3b Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Sun, 30 Sep 2018 19:20:08 -0700 Subject: Split the public metrics API from the data model. (#1477) * Split the public API from the data model. * Small comment added about registration of the MetricProducer. --- .../java/io/opencensus/metrics/MetricProducer.java | 8 +++++--- .../java/io/opencensus/metrics/MetricRegistry.java | 21 +++++++-------------- 2 files changed, 12 insertions(+), 17 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/metrics/MetricProducer.java b/api/src/main/java/io/opencensus/metrics/MetricProducer.java index 38b5d571..2a78b989 100644 --- a/api/src/main/java/io/opencensus/metrics/MetricProducer.java +++ b/api/src/main/java/io/opencensus/metrics/MetricProducer.java @@ -21,18 +21,20 @@ import io.opencensus.metrics.export.MetricProducerManager; import java.util.Collection; /** - * A {@link io.opencensus.metrics.Metric} producer that can be registered for exporting using {@link + * A {@link Metric} producer that can be registered for exporting using {@link * MetricProducerManager}. * *

    All implementation MUST be thread-safe. + * + * @since 0.17 */ @ExperimentalApi public abstract class MetricProducer { /** - * Returns a collection of produced {@link io.opencensus.metrics.Metric}s to be exported. + * Returns a collection of produced {@link Metric}s to be exported. * - * @return a collection of produced {@link io.opencensus.metrics.Metric}s to be exported. + * @return a collection of produced {@link Metric}s to be exported. */ public abstract Collection getMetrics(); } diff --git a/api/src/main/java/io/opencensus/metrics/MetricRegistry.java b/api/src/main/java/io/opencensus/metrics/MetricRegistry.java index ae4d90b0..c249d47b 100644 --- a/api/src/main/java/io/opencensus/metrics/MetricRegistry.java +++ b/api/src/main/java/io/opencensus/metrics/MetricRegistry.java @@ -20,19 +20,17 @@ import io.opencensus.common.ExperimentalApi; import io.opencensus.common.ToDoubleFunction; import io.opencensus.common.ToLongFunction; import io.opencensus.internal.Utils; -import java.util.Collection; -import java.util.Collections; import java.util.LinkedHashMap; /** - * Creates and manages your application's set of metrics. Exporters use the metric registry to - * iterate over the set of metrics instrumenting your application, and then further export each - * metric to the backend of choice. + * Creates and manages your application's set of metrics. The default implementation of this creates + * a {@link MetricProducer} and registers it to the global {@link + * io.opencensus.metrics.export.MetricProducerManager}. * - * @since 0.16 + * @since 0.17 */ @ExperimentalApi -public abstract class MetricRegistry extends MetricProducer { +public abstract class MetricRegistry { /** * Build a new long gauge to be added to the registry. * @@ -43,7 +41,7 @@ public abstract class MetricRegistry extends MetricProducer { * @param unit the unit of the metric. * @param obj the function argument. * @param function the function to be called. - * @since 0.16 @ExperimentalApi + * @since 0.17 */ public abstract void addLongGauge( String name, @@ -63,7 +61,7 @@ public abstract class MetricRegistry extends MetricProducer { * @param unit the unit of the metric. * @param obj the function argument. * @param function the function to be called. - * @since 0.16 @ExperimentalApi + * @since 0.17 */ public abstract void addDoubleGauge( String name, @@ -108,10 +106,5 @@ public abstract class MetricRegistry extends MetricProducer { Utils.checkNotNull(labels, "labels"); Utils.checkNotNull(function, "function"); } - - @Override - public Collection getMetrics() { - return Collections.emptyList(); - } } } -- cgit v1.2.3 From 84630fb6ae3474039cec4977c989b1a30e695906 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Mon, 1 Oct 2018 09:16:23 -0700 Subject: Uptade since tag for the entire metrics package. (#1478) --- .../java/io/opencensus/metrics/Distribution.java | 34 +++++++++++----------- .../main/java/io/opencensus/metrics/LabelKey.java | 6 ++-- .../java/io/opencensus/metrics/LabelValue.java | 4 +-- .../main/java/io/opencensus/metrics/Metric.java | 8 ++--- .../io/opencensus/metrics/MetricDescriptor.java | 26 ++++++++--------- .../java/io/opencensus/metrics/MetricProducer.java | 1 + .../main/java/io/opencensus/metrics/Metrics.java | 6 ++-- .../io/opencensus/metrics/MetricsComponent.java | 6 ++-- api/src/main/java/io/opencensus/metrics/Point.java | 8 ++--- .../java/io/opencensus/metrics/TimeSeries.java | 10 +++---- api/src/main/java/io/opencensus/metrics/Value.java | 10 +++---- .../opencensus/metrics/export/ExportComponent.java | 6 ++-- .../metrics/export/MetricProducerManager.java | 8 ++--- 13 files changed, 67 insertions(+), 66 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/metrics/Distribution.java b/api/src/main/java/io/opencensus/metrics/Distribution.java index bdea7762..87f99635 100644 --- a/api/src/main/java/io/opencensus/metrics/Distribution.java +++ b/api/src/main/java/io/opencensus/metrics/Distribution.java @@ -33,7 +33,7 @@ import javax.annotation.concurrent.Immutable; * {@link Distribution} contains summary statistics for a population of values. It optionally * contains a histogram representing the distribution of those values across a set of buckets. * - * @since 0.16 + * @since 0.17 */ @ExperimentalApi @AutoValue @@ -51,7 +51,7 @@ public abstract class Distribution { * @param bucketBoundaries bucket boundaries of a histogram. * @param buckets {@link Bucket}s of a histogram. * @return a {@code Distribution}. - * @since 0.16 + * @since 0.17 */ public static Distribution create( double mean, @@ -103,7 +103,7 @@ public abstract class Distribution { * Returns the aggregated mean. * * @return the aggregated mean. - * @since 0.16 + * @since 0.17 */ public abstract double getMean(); @@ -111,7 +111,7 @@ public abstract class Distribution { * Returns the aggregated count. * * @return the aggregated count. - * @since 0.16 + * @since 0.17 */ public abstract long getCount(); @@ -126,7 +126,7 @@ public abstract class Distribution { *

    If count is zero then this field must be zero. * * @return the aggregated sum of squared deviations. - * @since 0.16 + * @since 0.17 */ public abstract double getSumOfSquaredDeviations(); @@ -151,7 +151,7 @@ public abstract class Distribution { * monotonically increasing. * * @return the bucket boundaries of this distribution. - * @since 0.16 + * @since 0.17 */ public abstract List getBucketBoundaries(); @@ -159,14 +159,14 @@ public abstract class Distribution { * Returns the aggregated histogram {@link Bucket}s. * * @return the aggregated histogram buckets. - * @since 0.16 + * @since 0.17 */ public abstract List getBuckets(); /** * The histogram bucket of the population values. * - * @since 0.16 + * @since 0.17 */ @AutoValue @Immutable @@ -179,7 +179,7 @@ public abstract class Distribution { * * @param count the number of values in each bucket of the histogram. * @return a {@code Bucket}. - * @since 0.16 + * @since 0.17 */ public static Bucket create(long count) { Utils.checkArgument(count >= 0, "bucket count should be non-negative."); @@ -192,7 +192,7 @@ public abstract class Distribution { * @param count the number of values in each bucket of the histogram. * @param exemplar the {@code Exemplar} of this {@code Bucket}. * @return a {@code Bucket}. - * @since 0.16 + * @since 0.17 */ public static Bucket create(long count, Exemplar exemplar) { Utils.checkArgument(count >= 0, "bucket count should be non-negative."); @@ -204,7 +204,7 @@ public abstract class Distribution { * Returns the number of values in each bucket of the histogram. * * @return the number of values in each bucket of the histogram. - * @since 0.16 + * @since 0.17 */ public abstract long getCount(); @@ -214,7 +214,7 @@ public abstract class Distribution { * * @return the {@code Exemplar} associated with the {@code Bucket}, or {@code null} if there * isn't one. - * @since 0.16 + * @since 0.17 */ @Nullable public abstract Exemplar getExemplar(); @@ -224,7 +224,7 @@ public abstract class Distribution { * An example point that may be used to annotate aggregated distribution values, associated with a * histogram bucket. * - * @since 0.16 + * @since 0.17 */ @Immutable @AutoValue @@ -236,7 +236,7 @@ public abstract class Distribution { * Returns value of the {@link Exemplar} point. * * @return value of the {@code Exemplar} point. - * @since 0.16 + * @since 0.17 */ public abstract double getValue(); @@ -244,7 +244,7 @@ public abstract class Distribution { * Returns the time that this {@link Exemplar}'s value was recorded. * * @return the time that this {@code Exemplar}'s value was recorded. - * @since 0.16 + * @since 0.17 */ public abstract Timestamp getTimestamp(); @@ -252,7 +252,7 @@ public abstract class Distribution { * Returns the contextual information about the example value, represented as a string map. * * @return the contextual information about the example value. - * @since 0.16 + * @since 0.17 */ public abstract Map getAttachments(); @@ -263,7 +263,7 @@ public abstract class Distribution { * @param timestamp the time that this {@code Exemplar}'s value was recorded. * @param attachments the contextual information about the example value. * @return an {@code Exemplar}. - * @since 0.16 + * @since 0.17 */ public static Exemplar create( double value, Timestamp timestamp, Map attachments) { diff --git a/api/src/main/java/io/opencensus/metrics/LabelKey.java b/api/src/main/java/io/opencensus/metrics/LabelKey.java index 01ef0b55..efc51e64 100644 --- a/api/src/main/java/io/opencensus/metrics/LabelKey.java +++ b/api/src/main/java/io/opencensus/metrics/LabelKey.java @@ -38,7 +38,7 @@ public abstract class LabelKey { * @param key the key of a {@code Label}. * @param description a human-readable description of what this label key represents. * @return a {@code LabelKey}. - * @since 0.15 + * @since 0.17 */ public static LabelKey create(String key, String description) { return new AutoValue_LabelKey(key, description); @@ -48,7 +48,7 @@ public abstract class LabelKey { * Returns the key of this {@link LabelKey}. * * @return the key. - * @since 0.15 + * @since 0.17 */ public abstract String getKey(); @@ -56,7 +56,7 @@ public abstract class LabelKey { * Returns the description of this {@link LabelKey}. * * @return the description. - * @since 0.15 + * @since 0.17 */ public abstract String getDescription(); } diff --git a/api/src/main/java/io/opencensus/metrics/LabelValue.java b/api/src/main/java/io/opencensus/metrics/LabelValue.java index e81b63d2..e5708655 100644 --- a/api/src/main/java/io/opencensus/metrics/LabelValue.java +++ b/api/src/main/java/io/opencensus/metrics/LabelValue.java @@ -39,7 +39,7 @@ public abstract class LabelValue { * @param value the value of a {@code Label}. {@code null} value indicates an unset {@code * LabelValue}. * @return a {@code LabelValue}. - * @since 0.15 + * @since 0.17 */ public static LabelValue create(@Nullable String value) { return new AutoValue_LabelValue(value); @@ -50,7 +50,7 @@ public abstract class LabelValue { * supposed to be ignored. * * @return the value. - * @since 0.15 + * @since 0.17 */ @Nullable public abstract String getValue(); diff --git a/api/src/main/java/io/opencensus/metrics/Metric.java b/api/src/main/java/io/opencensus/metrics/Metric.java index fa0018b3..b463420c 100644 --- a/api/src/main/java/io/opencensus/metrics/Metric.java +++ b/api/src/main/java/io/opencensus/metrics/Metric.java @@ -28,7 +28,7 @@ import javax.annotation.concurrent.Immutable; /** * A {@link Metric} with one or more {@link TimeSeries}. * - * @since 0.16 + * @since 0.17 */ @ExperimentalApi @Immutable @@ -43,7 +43,7 @@ public abstract class Metric { * @param metricDescriptor the {@link MetricDescriptor}. * @param timeSeriesList the {@link TimeSeries} list for this metric. * @return a {@code Metric}. - * @since 0.16 + * @since 0.17 */ public static Metric create(MetricDescriptor metricDescriptor, List timeSeriesList) { checkTypeMatch(metricDescriptor.getType(), timeSeriesList); @@ -54,7 +54,7 @@ public abstract class Metric { * Returns the {@link MetricDescriptor} of this metric. * * @return the {@code MetricDescriptor} of this metric. - * @since 0.16 + * @since 0.17 */ public abstract MetricDescriptor getMetricDescriptor(); @@ -64,7 +64,7 @@ public abstract class Metric { *

    The type of the {@link TimeSeries#getPoints()} must match {@link MetricDescriptor.Type}. * * @return the {@code TimeSeriesList} for this metric. - * @since 0.16 + * @since 0.17 */ public abstract List getTimeSeriesList(); diff --git a/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java b/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java index 4558446a..e20730e9 100644 --- a/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java +++ b/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java @@ -27,7 +27,7 @@ import javax.annotation.concurrent.Immutable; /** * {@link MetricDescriptor} defines a {@code Metric} type and its schema. * - * @since 0.16 + * @since 0.17 */ @ExperimentalApi @Immutable @@ -45,7 +45,7 @@ public abstract class MetricDescriptor { * @param type type of {@code MetricDescriptor}. * @param labelKeys the label keys associated with the {@code MetricDescriptor}. * @return a {@code MetricDescriptor}. - * @since 0.16 + * @since 0.17 */ public static MetricDescriptor create( String name, String description, String unit, Type type, List labelKeys) { @@ -63,7 +63,7 @@ public abstract class MetricDescriptor { * Returns the metric descriptor name. * * @return the metric descriptor name. - * @since 0.16 + * @since 0.17 */ public abstract String getName(); @@ -71,7 +71,7 @@ public abstract class MetricDescriptor { * Returns the description of this metric descriptor. * * @return the description of this metric descriptor. - * @since 0.16 + * @since 0.17 */ public abstract String getDescription(); @@ -79,7 +79,7 @@ public abstract class MetricDescriptor { * Returns the unit of this metric descriptor. * * @return the unit of this metric descriptor. - * @since 0.16 + * @since 0.17 */ public abstract String getUnit(); @@ -87,7 +87,7 @@ public abstract class MetricDescriptor { * Returns the type of this metric descriptor. * * @return the type of this metric descriptor. - * @since 0.16 + * @since 0.17 */ public abstract Type getType(); @@ -95,7 +95,7 @@ public abstract class MetricDescriptor { * Returns the label keys associated with this metric descriptor. * * @return the label keys associated with this metric descriptor. - * @since 0.16 + * @since 0.17 */ public abstract List getLabelKeys(); @@ -108,42 +108,42 @@ public abstract class MetricDescriptor { * cumulative measurements should have the same start time and increasing end times, until an * event resets the cumulative value to zero and sets a new start time for the following points. * - * @since 0.16 + * @since 0.17 */ public enum Type { /** * An instantaneous measurement of an int64 value. * - * @since 0.16 + * @since 0.17 */ GAUGE_INT64, /** * An instantaneous measurement of a double value. * - * @since 0.16 + * @since 0.17 */ GAUGE_DOUBLE, /** * An cumulative measurement of an int64 value. * - * @since 0.16 + * @since 0.17 */ CUMULATIVE_INT64, /** * An cumulative measurement of a double value. * - * @since 0.16 + * @since 0.17 */ CUMULATIVE_DOUBLE, /** * An cumulative measurement of a distribution value. * - * @since 0.16 + * @since 0.17 */ CUMULATIVE_DISTRIBUTION, } diff --git a/api/src/main/java/io/opencensus/metrics/MetricProducer.java b/api/src/main/java/io/opencensus/metrics/MetricProducer.java index 2a78b989..86f9732f 100644 --- a/api/src/main/java/io/opencensus/metrics/MetricProducer.java +++ b/api/src/main/java/io/opencensus/metrics/MetricProducer.java @@ -35,6 +35,7 @@ public abstract class MetricProducer { * Returns a collection of produced {@link Metric}s to be exported. * * @return a collection of produced {@link Metric}s to be exported. + * @since 0.17 */ public abstract Collection getMetrics(); } diff --git a/api/src/main/java/io/opencensus/metrics/Metrics.java b/api/src/main/java/io/opencensus/metrics/Metrics.java index 521fbd08..920a4a88 100644 --- a/api/src/main/java/io/opencensus/metrics/Metrics.java +++ b/api/src/main/java/io/opencensus/metrics/Metrics.java @@ -27,7 +27,7 @@ import javax.annotation.Nullable; /** * Class for accessing the default {@link MetricsComponent}. * - * @since 0.16 + * @since 0.17 */ @ExperimentalApi public final class Metrics { @@ -39,7 +39,7 @@ public final class Metrics { * Returns the global {@link ExportComponent}. * * @return the global {@code ExportComponent}. - * @since 0.16 + * @since 0.17 */ public static ExportComponent getExportComponent() { return metricsComponent.getExportComponent(); @@ -52,7 +52,7 @@ public final class Metrics { * io.opencensus.metrics.export.MetricProducerManager}. * * @return the global {@code MetricRegistry}. - * @since 0.16 + * @since 0.17 */ public static MetricRegistry getMetricRegistry() { return metricsComponent.getMetricRegistry(); diff --git a/api/src/main/java/io/opencensus/metrics/MetricsComponent.java b/api/src/main/java/io/opencensus/metrics/MetricsComponent.java index 08d954ef..3a992306 100644 --- a/api/src/main/java/io/opencensus/metrics/MetricsComponent.java +++ b/api/src/main/java/io/opencensus/metrics/MetricsComponent.java @@ -22,7 +22,7 @@ import io.opencensus.metrics.export.ExportComponent; /** * Class that holds the implementation instance for {@link ExportComponent}. * - * @since 0.16 + * @since 0.17 */ @ExperimentalApi public abstract class MetricsComponent { @@ -32,7 +32,7 @@ public abstract class MetricsComponent { * provided then no-op implementations will be used. * * @return the {@link ExportComponent} implementation. - * @since 0.16 + * @since 0.17 */ public abstract ExportComponent getExportComponent(); @@ -40,7 +40,7 @@ public abstract class MetricsComponent { * Returns the {@link MetricRegistry} with the provided implementation. * * @return the {@link MetricRegistry} implementation. - * @since 0.16 + * @since 0.17 */ public abstract MetricRegistry getMetricRegistry(); diff --git a/api/src/main/java/io/opencensus/metrics/Point.java b/api/src/main/java/io/opencensus/metrics/Point.java index e66b273d..9ef7c15b 100644 --- a/api/src/main/java/io/opencensus/metrics/Point.java +++ b/api/src/main/java/io/opencensus/metrics/Point.java @@ -24,7 +24,7 @@ import javax.annotation.concurrent.Immutable; /** * A timestamped measurement of a {@code TimeSeries}. * - * @since 0.16 + * @since 0.17 */ @ExperimentalApi @AutoValue @@ -39,7 +39,7 @@ public abstract class Point { * @param value the {@link Value} of this {@link Point}. * @param timestamp the {@link Timestamp} when this {@link Point} was recorded. * @return a {@code Point}. - * @since 0.16 + * @since 0.17 */ public static Point create(Value value, Timestamp timestamp) { return new AutoValue_Point(value, timestamp); @@ -49,7 +49,7 @@ public abstract class Point { * Returns the {@link Value}. * * @return the {@code Value}. - * @since 0.16 + * @since 0.17 */ public abstract Value getValue(); @@ -57,7 +57,7 @@ public abstract class Point { * Returns the {@link Timestamp} when this {@link Point} was recorded. * * @return the {@code Timestamp}. - * @since 0.16 + * @since 0.17 */ public abstract Timestamp getTimestamp(); } diff --git a/api/src/main/java/io/opencensus/metrics/TimeSeries.java b/api/src/main/java/io/opencensus/metrics/TimeSeries.java index c62b6b72..d504dad9 100644 --- a/api/src/main/java/io/opencensus/metrics/TimeSeries.java +++ b/api/src/main/java/io/opencensus/metrics/TimeSeries.java @@ -29,7 +29,7 @@ import javax.annotation.concurrent.Immutable; /** * A collection of data points that describes the time-varying values of a {@code Metric}. * - * @since 0.16 + * @since 0.17 */ @ExperimentalApi @Immutable @@ -46,7 +46,7 @@ public abstract class TimeSeries { * @param startTimestamp the start {@code Timestamp} of this {@code TimeSeries}. Must be non-null * for cumulative {@code Point}s. * @return a {@code TimeSeries}. - * @since 0.16 + * @since 0.17 */ public static TimeSeries create( List labelValues, List points, @Nullable Timestamp startTimestamp) { @@ -70,7 +70,7 @@ public abstract class TimeSeries { * MetricDescriptor}. * * @return the {@code LabelValue}s. - * @since 0.16 + * @since 0.17 */ public abstract List getLabelValues(); @@ -78,7 +78,7 @@ public abstract class TimeSeries { * Returns the data {@link Point}s of this {@link TimeSeries}. * * @return the data {@code Point}s. - * @since 0.16 + * @since 0.17 */ public abstract List getPoints(); @@ -87,7 +87,7 @@ public abstract class TimeSeries { * cumulative, or {@code null} if the {@link Point}s are gauge. * * @return the start {@code Timestamp} or {@code null}. - * @since 0.16 + * @since 0.17 */ @Nullable public abstract Timestamp getStartTimestamp(); diff --git a/api/src/main/java/io/opencensus/metrics/Value.java b/api/src/main/java/io/opencensus/metrics/Value.java index c8fe48f8..5dd70c8d 100644 --- a/api/src/main/java/io/opencensus/metrics/Value.java +++ b/api/src/main/java/io/opencensus/metrics/Value.java @@ -34,7 +34,7 @@ import javax.annotation.concurrent.Immutable; * *

    Each {@link Point} contains exactly one of the three {@link Value} types. * - * @since 0.16 + * @since 0.17 */ @ExperimentalApi @Immutable @@ -47,7 +47,7 @@ public abstract class Value { * * @param value value in double. * @return a double {@code Value}. - * @since 0.16 + * @since 0.17 */ public static Value doubleValue(double value) { return ValueDouble.create(value); @@ -58,7 +58,7 @@ public abstract class Value { * * @param value value in long. * @return a long {@code Value}. - * @since 0.16 + * @since 0.17 */ public static Value longValue(long value) { return ValueLong.create(value); @@ -69,7 +69,7 @@ public abstract class Value { * * @param value value in {@link Distribution}. * @return a {@code Distribution} {@code Value}. - * @since 0.16 + * @since 0.17 */ public static Value distributionValue(Distribution value) { return ValueDistribution.create(value); @@ -78,7 +78,7 @@ public abstract class Value { /** * Applies the given match function to the underlying data type. * - * @since 0.16 + * @since 0.17 */ public abstract T match( Function doubleFunction, diff --git a/api/src/main/java/io/opencensus/metrics/export/ExportComponent.java b/api/src/main/java/io/opencensus/metrics/export/ExportComponent.java index bab65d13..11e1fdbd 100644 --- a/api/src/main/java/io/opencensus/metrics/export/ExportComponent.java +++ b/api/src/main/java/io/opencensus/metrics/export/ExportComponent.java @@ -23,7 +23,7 @@ import io.opencensus.common.ExperimentalApi; * *

    Unless otherwise noted all methods (on component) results are cacheable. * - * @since 0.16 + * @since 0.17 */ @ExperimentalApi public abstract class ExportComponent { @@ -31,7 +31,7 @@ public abstract class ExportComponent { * Returns the no-op implementation of the {@code ExportComponent}. * * @return the no-op implementation of the {@code ExportComponent}. - * @since 0.16 + * @since 0.17 */ public static ExportComponent newNoopExportComponent() { return new NoopExportComponent(); @@ -43,7 +43,7 @@ public abstract class ExportComponent { * * @return the implementation of the {@code MetricExporter} or no-op if no implementation linked * in the binary. - * @since 0.16 + * @since 0.17 */ public abstract MetricProducerManager getMetricProducerManager(); diff --git a/api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java b/api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java index c5acf174..fc864200 100644 --- a/api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java +++ b/api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java @@ -27,7 +27,7 @@ import javax.annotation.concurrent.ThreadSafe; * Keeps a set of {@link MetricProducer} that is used by exporters to determine the metrics that * need to be exported. * - * @since 0.16 + * @since 0.17 */ @ExperimentalApi @ThreadSafe @@ -37,7 +37,7 @@ public abstract class MetricProducerManager { * Adds the {@link MetricProducer} to the manager if it is not already present. * * @param metricProducer the {@code MetricProducer} to be added to the manager. - * @since 0.16 + * @since 0.17 */ public abstract void add(MetricProducer metricProducer); @@ -45,7 +45,7 @@ public abstract class MetricProducerManager { * Removes the {@link MetricProducer} to the manager if it is present. * * @param metricProducer the {@code MetricProducer} to be removed from the manager. - * @since 0.16 + * @since 0.17 */ public abstract void remove(MetricProducer metricProducer); @@ -56,7 +56,7 @@ public abstract class MetricProducerManager { * {@code MetricProducer} registered with the {@code MetricProducerManager}. * * @return all registered {@code MetricProducer}s that should be exported. - * @since 0.16 + * @since 0.17 */ public abstract Set getAllMetricProducer(); -- cgit v1.2.3 From bcfd159c58e80036bbbe1468bf305154d001982e Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Tue, 2 Oct 2018 16:44:12 -0400 Subject: Make metrics compatible with the current proto definition. (#1479) * Make metrics compatible with the current proto definition. * Fix minor comments from the review. * Fix @Nullable. --- .../java/io/opencensus/metrics/Distribution.java | 24 +-- .../main/java/io/opencensus/metrics/Metric.java | 6 + .../io/opencensus/metrics/MetricDescriptor.java | 24 ++- .../main/java/io/opencensus/metrics/Summary.java | 187 ++++++++++++++++++++ api/src/main/java/io/opencensus/metrics/Value.java | 54 +++++- .../io/opencensus/metrics/DistributionTest.java | 29 ++-- .../test/java/io/opencensus/metrics/PointTest.java | 2 +- .../java/io/opencensus/metrics/SummaryTest.java | 189 +++++++++++++++++++++ .../test/java/io/opencensus/metrics/ValueTest.java | 35 +++- 9 files changed, 516 insertions(+), 34 deletions(-) create mode 100644 api/src/main/java/io/opencensus/metrics/Summary.java create mode 100644 api/src/test/java/io/opencensus/metrics/SummaryTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/metrics/Distribution.java b/api/src/main/java/io/opencensus/metrics/Distribution.java index 87f99635..9294b838 100644 --- a/api/src/main/java/io/opencensus/metrics/Distribution.java +++ b/api/src/main/java/io/opencensus/metrics/Distribution.java @@ -45,17 +45,17 @@ public abstract class Distribution { /** * Creates a {@link Distribution}. * - * @param mean mean of the population values. - * @param count count of the population values. - * @param sumOfSquaredDeviations sum of squared deviations of the population values. + * @param count the count of the population values. + * @param sum the sum of the population values. + * @param sumOfSquaredDeviations the sum of squared deviations of the population values. * @param bucketBoundaries bucket boundaries of a histogram. * @param buckets {@link Bucket}s of a histogram. * @return a {@code Distribution}. * @since 0.17 */ public static Distribution create( - double mean, long count, + double sum, double sumOfSquaredDeviations, List bucketBoundaries, List buckets) { @@ -63,13 +63,13 @@ public abstract class Distribution { Utils.checkArgument( sumOfSquaredDeviations >= 0, "sum of squared deviations should be non-negative."); if (count == 0) { - Utils.checkArgument(mean == 0, "mean should be 0 if count is 0."); + Utils.checkArgument(sum == 0, "sum should be 0 if count is 0."); Utils.checkArgument( sumOfSquaredDeviations == 0, "sum of squared deviations should be 0 if count is 0."); } return new AutoValue_Distribution( - mean, count, + sum, sumOfSquaredDeviations, copyBucketBounds(bucketBoundaries), copyBucketCount(buckets)); @@ -100,20 +100,20 @@ public abstract class Distribution { } /** - * Returns the aggregated mean. + * Returns the aggregated count. * - * @return the aggregated mean. + * @return the aggregated count. * @since 0.17 */ - public abstract double getMean(); + public abstract long getCount(); /** - * Returns the aggregated count. + * Returns the aggregated sum. * - * @return the aggregated count. + * @return the aggregated sum. * @since 0.17 */ - public abstract long getCount(); + public abstract double getSum(); /** * Returns the aggregated sum of squared deviations. diff --git a/api/src/main/java/io/opencensus/metrics/Metric.java b/api/src/main/java/io/opencensus/metrics/Metric.java index b463420c..0c108b56 100644 --- a/api/src/main/java/io/opencensus/metrics/Metric.java +++ b/api/src/main/java/io/opencensus/metrics/Metric.java @@ -22,6 +22,7 @@ import io.opencensus.internal.Utils; import io.opencensus.metrics.Value.ValueDistribution; import io.opencensus.metrics.Value.ValueDouble; import io.opencensus.metrics.Value.ValueLong; +import io.opencensus.metrics.Value.ValueSummary; import java.util.List; import javax.annotation.concurrent.Immutable; @@ -88,9 +89,14 @@ public abstract class Metric { Utils.checkArgument( value instanceof ValueDouble, "Type mismatch: %s, %s.", type, valueClassName); break; + case GAUGE_DISTRIBUTION: case CUMULATIVE_DISTRIBUTION: Utils.checkArgument( value instanceof ValueDistribution, "Type mismatch: %s, %s.", type, valueClassName); + break; + case SUMMARY: + Utils.checkArgument( + value instanceof ValueSummary, "Type mismatch: %s, %s.", type, valueClassName); } } } diff --git a/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java b/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java index e20730e9..5146cd85 100644 --- a/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java +++ b/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java @@ -126,6 +126,15 @@ public abstract class MetricDescriptor { */ GAUGE_DOUBLE, + /** + * An instantaneous measurement of a distribution value. The count and sum can go both up and + * down. Used in scenarios like a snapshot of time the current items in a queue have spent + * there. + * + * @since 0.17 + */ + GAUGE_DISTRIBUTION, + /** * An cumulative measurement of an int64 value. * @@ -141,10 +150,23 @@ public abstract class MetricDescriptor { CUMULATIVE_DOUBLE, /** - * An cumulative measurement of a distribution value. + * An cumulative measurement of a distribution value. The count and sum can only go up, if + * resets then the start_time should also be reset. * * @since 0.17 */ CUMULATIVE_DISTRIBUTION, + + /** + * Some frameworks implemented DISTRIBUTION as a summary of observations (usually things like + * request durations and response sizes). While it also provides a total count of observations + * and a sum of all observed values, it calculates configurable quantiles over a sliding time + * window. + * + *

    This is not recommended, since it cannot be aggregated. + * + * @since 0.17 + */ + SUMMARY, } } diff --git a/api/src/main/java/io/opencensus/metrics/Summary.java b/api/src/main/java/io/opencensus/metrics/Summary.java new file mode 100644 index 00000000..f23667bb --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/Summary.java @@ -0,0 +1,187 @@ +/* + * Copyright 2018, 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.metrics; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.internal.Utils; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * Implementation of the {@link Distribution} as a summary of observations. + * + *

    This is not recommended, since it cannot be aggregated. + * + * @since 0.17 + */ +@ExperimentalApi +@AutoValue +@Immutable +public abstract class Summary { + Summary() {} + + /** + * Creates a {@link Summary}. + * + * @param count the count of the population values. + * @param sum the sum of the population values. + * @param snapshot bucket boundaries of a histogram. + * @return a {@code Summary} with the given values. + * @since 0.17 + */ + public static Summary create(@Nullable Long count, @Nullable Double sum, Snapshot snapshot) { + checkCountAndSum(count, sum); + Utils.checkNotNull(snapshot, "snapshot"); + return new AutoValue_Summary(count, sum, snapshot); + } + + /** + * Returns the aggregated count. If not available returns {@code null}. + * + * @return the aggregated count. + * @since 0.17 + */ + @Nullable + public abstract Long getCount(); + + /** + * Returns the aggregated sum. If not available returns {@code null}. + * + * @return the aggregated sum. + * @since 0.17 + */ + @Nullable + public abstract Double getSum(); + + /** + * Returns the {@link Snapshot}. + * + * @return the {@code Snapshot}. + * @since 0.17 + */ + public abstract Snapshot getSnapshot(); + + /** + * Represents the summary observation of the recorded events over a sliding time window. + * + * @since 0.17 + */ + @Immutable + @AutoValue + public abstract static class Snapshot { + /** + * Returns the number of values in this {@code Snapshot}. If not available returns {@code null}. + * + * @return the number of values in this {@code Snapshot}. + * @since 0.17 + */ + @Nullable + public abstract Long getCount(); + + /** + * Returns the sum of values in this {@code Snapshot}. If not available returns {@code null}. + * + * @return the sum of values in this {@code Snapshot}. + * @since 0.17 + */ + @Nullable + public abstract Double getSum(); + + /** + * Returns the list of {@code ValueAtPercentile}s in this {@code Snapshot}. + * + * @return the list of {@code ValueAtPercentile}s in this {@code Snapshot}. + * @since 0.17 + */ + public abstract List getValueAtPercentiles(); + + /** + * Creates a {@link Snapshot}. + * + * @param count the number of values in this {@code Snapshot}. + * @param sum the number of values in this {@code Snapshot}. + * @param valueAtPercentiles the list of {@code ValueAtPercentile}. + * @return a {@code Snapshot} with the given values. + * @since 0.17 + */ + public static Snapshot create( + @Nullable Long count, @Nullable Double sum, List valueAtPercentiles) { + checkCountAndSum(count, sum); + Utils.checkNotNull(valueAtPercentiles, "valueAtPercentiles"); + Utils.checkListElementNotNull(valueAtPercentiles, "value in valueAtPercentiles"); + return new AutoValue_Summary_Snapshot( + count, + sum, + Collections.unmodifiableList(new ArrayList(valueAtPercentiles))); + } + + /** + * Represents the value at a given percentile of a distribution. + * + * @since 0.17 + */ + @Immutable + @AutoValue + public abstract static class ValueAtPercentile { + /** + * Returns the percentile in this {@code ValueAtPercentile}. + * + *

    Must be in the interval (0.0, 100.0]. + * + * @return the percentile in this {@code ValueAtPercentile}. + * @since 0.17 + */ + public abstract double getPercentile(); + + /** + * Returns the value in this {@code ValueAtPercentile}. + * + * @return the value in this {@code ValueAtPercentile}. + * @since 0.17 + */ + public abstract double getValue(); + + /** + * Creates a {@link ValueAtPercentile}. + * + * @param percentile the percentile in this {@code ValueAtPercentile}. + * @param value the value in this {@code ValueAtPercentile}. + * @return a {@code ValueAtPercentile} with the given values. + * @since 0.17 + */ + public static ValueAtPercentile create(double percentile, double value) { + Utils.checkArgument( + 0 < percentile && percentile <= 100.0, + "percentile must be in the interval (0.0, 100.0]"); + Utils.checkArgument(value >= 0, "value must be non-negative"); + return new AutoValue_Summary_Snapshot_ValueAtPercentile(percentile, value); + } + } + } + + private static void checkCountAndSum(@Nullable Long count, @Nullable Double sum) { + Utils.checkArgument(count == null || count >= 0, "count must be non-negative."); + Utils.checkArgument(sum == null || sum >= 0, "sum must be non-negative."); + if (count != null && count == 0) { + Utils.checkArgument(sum == null || sum == 0, "sum must be 0 if count is 0."); + } + } +} diff --git a/api/src/main/java/io/opencensus/metrics/Value.java b/api/src/main/java/io/opencensus/metrics/Value.java index 5dd70c8d..1bc63b79 100644 --- a/api/src/main/java/io/opencensus/metrics/Value.java +++ b/api/src/main/java/io/opencensus/metrics/Value.java @@ -75,6 +75,17 @@ public abstract class Value { return ValueDistribution.create(value); } + /** + * Returns a {@link Summary} {@link Value}. + * + * @param value value in {@link Summary}. + * @return a {@code Summary} {@code Value}. + * @since 0.17 + */ + public static Value summaryValue(Summary value) { + return ValueSummary.create(value); + } + /** * Applies the given match function to the underlying data type. * @@ -84,6 +95,7 @@ public abstract class Value { Function doubleFunction, Function longFunction, Function distributionFunction, + Function summaryFunction, Function defaultFunction); /** A 64-bit double-precision floating-point {@link Value}. */ @@ -98,6 +110,7 @@ public abstract class Value { Function doubleFunction, Function longFunction, Function distributionFunction, + Function summaryFunction, Function defaultFunction) { return doubleFunction.apply(getValue()); } @@ -132,6 +145,7 @@ public abstract class Value { Function doubleFunction, Function longFunction, Function distributionFunction, + Function summaryFunction, Function defaultFunction) { return longFunction.apply(getValue()); } @@ -169,6 +183,7 @@ public abstract class Value { Function doubleFunction, Function longFunction, Function distributionFunction, + Function summaryFunction, Function defaultFunction) { return distributionFunction.apply(getValue()); } @@ -191,6 +206,41 @@ public abstract class Value { abstract Distribution getValue(); } - // TODO(songya): Add support for Summary type. - // This is an aggregation that produces percentiles directly. + /** + * {@link ValueSummary} contains a snapshot representing values calculated over an arbitrary time + * window. + */ + @AutoValue + @Immutable + abstract static class ValueSummary extends Value { + + ValueSummary() {} + + @Override + public final T match( + Function doubleFunction, + Function longFunction, + Function distributionFunction, + Function summaryFunction, + Function defaultFunction) { + return summaryFunction.apply(getValue()); + } + + /** + * Creates a {@link ValueSummary}. + * + * @param value the {@link Summary} value. + * @return a {@code ValueSummary}. + */ + static ValueSummary create(Summary value) { + return new AutoValue_Value_ValueSummary(value); + } + + /** + * Returns the {@link Summary} value. + * + * @return the {@code Summary} value. + */ + abstract Summary getValue(); + } } diff --git a/api/src/test/java/io/opencensus/metrics/DistributionTest.java b/api/src/test/java/io/opencensus/metrics/DistributionTest.java index d511e317..5ee88dd6 100644 --- a/api/src/test/java/io/opencensus/metrics/DistributionTest.java +++ b/api/src/test/java/io/opencensus/metrics/DistributionTest.java @@ -32,7 +32,7 @@ import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** Unit tests for {@link Value}. */ +/** Unit tests for {@link Distribution}. */ @RunWith(JUnit4.class) public class DistributionTest { @@ -40,6 +40,7 @@ public class DistributionTest { private static final Timestamp TIMESTAMP = Timestamp.create(1, 0); private static final Map ATTACHMENTS = Collections.singletonMap("key", "value"); + private static final double TOLERANCE = 1e-6; @Test public void createAndGet_Bucket() { @@ -66,7 +67,7 @@ public class DistributionTest { @Test public void createAndGet_Exemplar() { Exemplar exemplar = Exemplar.create(-9.9, TIMESTAMP, ATTACHMENTS); - assertThat(exemplar.getValue()).isEqualTo(-9.9); + assertThat(exemplar.getValue()).isWithin(TOLERANCE).of(-9.9); assertThat(exemplar.getTimestamp()).isEqualTo(TIMESTAMP); assertThat(exemplar.getAttachments()).isEqualTo(ATTACHMENTS); } @@ -78,10 +79,10 @@ public class DistributionTest { List buckets = Arrays.asList( Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4, exemplar)); - Distribution distribution = Distribution.create(6.6, 10, 678.54, bucketBounds, buckets); - assertThat(distribution.getMean()).isEqualTo(6.6); + Distribution distribution = Distribution.create(10, 6.6, 678.54, bucketBounds, buckets); assertThat(distribution.getCount()).isEqualTo(10); - assertThat(distribution.getSumOfSquaredDeviations()).isEqualTo(678.54); + assertThat(distribution.getSum()).isWithin(TOLERANCE).of(6.6); + assertThat(distribution.getSumOfSquaredDeviations()).isWithin(TOLERANCE).of(678.54); assertThat(distribution.getBucketBoundaries()) .containsExactlyElementsIn(bucketBounds) .inOrder(); @@ -125,7 +126,7 @@ public class DistributionTest { Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); thrown.expect(IllegalArgumentException.class); thrown.expectMessage("count should be non-negative."); - Distribution.create(6.6, -10, 678.54, bucketBounds, buckets); + Distribution.create(-10, 6.6, 678.54, bucketBounds, buckets); } @Test @@ -135,7 +136,7 @@ public class DistributionTest { Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0)); thrown.expect(IllegalArgumentException.class); thrown.expectMessage("sum of squared deviations should be non-negative."); - Distribution.create(6.6, 0, -678.54, bucketBounds, buckets); + Distribution.create(0, 6.6, -678.54, bucketBounds, buckets); } @Test @@ -144,8 +145,8 @@ public class DistributionTest { List buckets = Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0)); thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("mean should be 0 if count is 0."); - Distribution.create(6.6, 0, 0, bucketBounds, buckets); + thrown.expectMessage("sum should be 0 if count is 0."); + Distribution.create(0, 6.6, 0, bucketBounds, buckets); } @Test @@ -164,7 +165,7 @@ public class DistributionTest { Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); thrown.expect(NullPointerException.class); thrown.expectMessage("bucketBoundaries list should not be null."); - Distribution.create(6.6, 10, 678.54, null, buckets); + Distribution.create(10, 6.6, 678.54, null, buckets); } @Test @@ -174,7 +175,7 @@ public class DistributionTest { Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); thrown.expect(IllegalArgumentException.class); thrown.expectMessage("bucket boundaries not sorted."); - Distribution.create(6.6, 10, 678.54, bucketBounds, buckets); + Distribution.create(10, 6.6, 678.54, bucketBounds, buckets); } @Test @@ -182,7 +183,7 @@ public class DistributionTest { List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); thrown.expect(NullPointerException.class); thrown.expectMessage("bucket list should not be null."); - Distribution.create(6.6, 10, 678.54, bucketBounds, null); + Distribution.create(10, 6.6, 678.54, bucketBounds, null); } @Test @@ -192,7 +193,7 @@ public class DistributionTest { Arrays.asList(Bucket.create(3), Bucket.create(1), null, Bucket.create(4)); thrown.expect(NullPointerException.class); thrown.expectMessage("bucket should not be null."); - Distribution.create(6.6, 10, 678.54, bucketBounds, buckets); + Distribution.create(10, 6.6, 678.54, bucketBounds, buckets); } @Test @@ -215,7 +216,7 @@ public class DistributionTest { Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)))) .addEqualityGroup( Distribution.create( - -7, + 7, 10, 23.456, Arrays.asList(-5.0, 0.0, 5.0), diff --git a/api/src/test/java/io/opencensus/metrics/PointTest.java b/api/src/test/java/io/opencensus/metrics/PointTest.java index cb6175c1..708814c5 100644 --- a/api/src/test/java/io/opencensus/metrics/PointTest.java +++ b/api/src/test/java/io/opencensus/metrics/PointTest.java @@ -35,8 +35,8 @@ public class PointTest { private static final Value DISTRIBUTION_VALUE = Value.distributionValue( Distribution.create( - 6.6, 10, + 6.6, 678.54, Arrays.asList(-1.0, 0.0, 1.0), Arrays.asList( diff --git a/api/src/test/java/io/opencensus/metrics/SummaryTest.java b/api/src/test/java/io/opencensus/metrics/SummaryTest.java new file mode 100644 index 00000000..0b70d94e --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/SummaryTest.java @@ -0,0 +1,189 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.metrics.Summary.Snapshot; +import io.opencensus.metrics.Summary.Snapshot.ValueAtPercentile; +import java.util.Collections; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Summary}. */ +@RunWith(JUnit4.class) +public class SummaryTest { + + @Rule public final ExpectedException thrown = ExpectedException.none(); + private static final double TOLERANCE = 1e-6; + + @Test + public void createAndGet_ValueAtPercentile() { + ValueAtPercentile valueAtPercentile = ValueAtPercentile.create(99.5, 10.2); + assertThat(valueAtPercentile.getPercentile()).isWithin(TOLERANCE).of(99.5); + assertThat(valueAtPercentile.getValue()).isWithin(TOLERANCE).of(10.2); + } + + @Test + public void createValueAtPercentile_InvalidValueAtPercentileInterval() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("percentile must be in the interval (0.0, 100.0]"); + ValueAtPercentile.create(100.1, 10.2); + } + + @Test + public void createValueAtPercentile_NegativeValue() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("value must be non-negative"); + ValueAtPercentile.create(99.5, -10.2); + } + + @Test + public void createAndGet_Snapshot() { + Snapshot snapshot = + Snapshot.create( + 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))); + assertThat(snapshot.getCount()).isEqualTo(10); + assertThat(snapshot.getSum()).isWithin(TOLERANCE).of(87.07); + assertThat(snapshot.getValueAtPercentiles()) + .containsExactly(ValueAtPercentile.create(99.5, 10.2)); + } + + @Test + public void createAndGet_Snapshot_WithNullCountAndSum() { + Snapshot snapshot = + Snapshot.create( + null, null, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))); + assertThat(snapshot.getCount()).isNull(); + assertThat(snapshot.getSum()).isNull(); + assertThat(snapshot.getValueAtPercentiles()) + .containsExactly(ValueAtPercentile.create(99.5, 10.2)); + } + + @Test + public void createSnapshot_NegativeCount() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("count must be non-negative"); + Snapshot.create(-10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))); + } + + @Test + public void createSnapshot_NegativeSum() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("sum must be non-negative"); + Snapshot.create(10L, -87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))); + } + + @Test + public void createSnapshot_ZeroCountAndNonZeroSum() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("sum must be 0 if count is 0"); + Snapshot.create(0L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))); + } + + @Test + public void createSnapshot_NullValueAtPercentilesList() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("valueAtPercentiles"); + Snapshot.create(10L, 87.07, null); + } + + @Test + public void createSnapshot_OneNullValueAtPercentile() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("value in valueAtPercentiles"); + Snapshot.create(10L, 87.07, Collections.singletonList(null)); + } + + @Test + public void createAndGet_Summary() { + Snapshot snapshot = + Snapshot.create( + 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))); + Summary summary = Summary.create(10L, 6.6, snapshot); + assertThat(summary.getCount()).isEqualTo(10); + assertThat(summary.getSum()).isWithin(TOLERANCE).of(6.6); + assertThat(summary.getSnapshot()).isEqualTo(snapshot); + } + + @Test + public void createSummary_NegativeCount() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("count must be non-negative"); + Summary.create( + -10L, 6.6, Snapshot.create(null, null, Collections.emptyList())); + } + + @Test + public void createSummary_NegativeSum() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("sum must be non-negative"); + Summary.create( + 10L, -6.6, Snapshot.create(null, null, Collections.emptyList())); + } + + @Test + public void createSummary_ZeroCountAndNonZeroSum() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("sum must be 0 if count is 0"); + Summary.create( + 0L, 6.6, Snapshot.create(null, null, Collections.emptyList())); + } + + @Test + public void createSummary_NullSnapshot() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("snapshot"); + Summary.create(10L, 6.6, null); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + Summary.create( + 10L, + 10.0, + Snapshot.create( + 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)))), + Summary.create( + 10L, + 10.0, + Snapshot.create( + 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))))) + .addEqualityGroup( + Summary.create( + 7L, + 10.0, + Snapshot.create( + 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))))) + .addEqualityGroup( + Summary.create( + 10L, + 7.0, + Snapshot.create( + 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))))) + .addEqualityGroup( + Summary.create( + 10L, 10.0, Snapshot.create(null, null, Collections.emptyList()))) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/ValueTest.java b/api/src/test/java/io/opencensus/metrics/ValueTest.java index 63430b28..a65202a8 100644 --- a/api/src/test/java/io/opencensus/metrics/ValueTest.java +++ b/api/src/test/java/io/opencensus/metrics/ValueTest.java @@ -22,11 +22,15 @@ import com.google.common.testing.EqualsTester; import io.opencensus.common.Function; import io.opencensus.common.Functions; import io.opencensus.metrics.Distribution.Bucket; +import io.opencensus.metrics.Summary.Snapshot; +import io.opencensus.metrics.Summary.Snapshot.ValueAtPercentile; import io.opencensus.metrics.Value.ValueDistribution; import io.opencensus.metrics.Value.ValueDouble; import io.opencensus.metrics.Value.ValueLong; +import io.opencensus.metrics.Value.ValueSummary; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; @@ -35,6 +39,7 @@ import org.junit.runners.JUnit4; /** Unit tests for {@link Value}. */ @RunWith(JUnit4.class) public class ValueTest { + private static final double TOLERANCE = 1e-6; private static final Distribution DISTRIBUTION = Distribution.create( @@ -43,12 +48,18 @@ public class ValueTest { 1, Arrays.asList(-5.0, 0.0, 5.0), Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))); + private static final Summary SUMMARY = + Summary.create( + 10L, + 10.0, + Snapshot.create( + 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(0.98, 10.2)))); @Test public void createAndGet_ValueDouble() { Value value = Value.doubleValue(-34.56); assertThat(value).isInstanceOf(ValueDouble.class); - assertThat(((ValueDouble) value).getValue()).isEqualTo(-34.56); + assertThat(((ValueDouble) value).getValue()).isWithin(TOLERANCE).of(-34.56); } @Test @@ -65,6 +76,13 @@ public class ValueTest { assertThat(((ValueDistribution) value).getValue()).isEqualTo(DISTRIBUTION); } + @Test + public void createAndGet_ValueSummary() { + Value value = Value.summaryValue(SUMMARY); + assertThat(value).isInstanceOf(ValueSummary.class); + assertThat(((ValueSummary) value).getValue()).isEqualTo(SUMMARY); + } + @Test public void testEquals() { new EqualsTester() @@ -75,7 +93,7 @@ public class ValueTest { .addEqualityGroup( Value.distributionValue( Distribution.create( - -7, + 7, 10, 23.456, Arrays.asList(-5.0, 0.0, 5.0), @@ -88,7 +106,10 @@ public class ValueTest { public void testMatch() { List values = Arrays.asList( - ValueDouble.create(1.0), ValueLong.create(-1), ValueDistribution.create(DISTRIBUTION)); + ValueDouble.create(1.0), + ValueLong.create(-1), + ValueDistribution.create(DISTRIBUTION), + ValueSummary.create(SUMMARY)); List expected = Arrays.asList(1.0, -1L, 10.0, 10L, 1.0, -5.0, 0.0, 5.0, 3L, 1L, 2L, 4L); final List actual = new ArrayList(); @@ -111,7 +132,7 @@ public class ValueTest { new Function() { @Override public Object apply(Distribution arg) { - actual.add(arg.getMean()); + actual.add(arg.getSum()); actual.add(arg.getCount()); actual.add(arg.getSumOfSquaredDeviations()); actual.addAll(arg.getBucketBoundaries()); @@ -121,6 +142,12 @@ public class ValueTest { return null; } }, + new Function() { + @Override + public Object apply(Summary arg) { + return null; + } + }, Functions.throwAssertionError()); } assertThat(actual).containsExactlyElementsIn(expected).inOrder(); -- cgit v1.2.3 From 90edbd5a8a0ff10d7658bd78beae9434aee8cdbe Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Tue, 2 Oct 2018 17:48:35 -0400 Subject: Mode classes for metrics data model in the exporter package. (#1480) * Mode classes for metrics data model in the exporter package. Consistent with trace. * Fix test class coments. --- .../java/io/opencensus/metrics/Distribution.java | 280 --------------------- .../main/java/io/opencensus/metrics/Metric.java | 104 -------- .../io/opencensus/metrics/MetricDescriptor.java | 172 ------------- .../java/io/opencensus/metrics/MetricProducer.java | 41 --- .../java/io/opencensus/metrics/MetricRegistry.java | 2 +- api/src/main/java/io/opencensus/metrics/Point.java | 63 ----- .../main/java/io/opencensus/metrics/Summary.java | 187 -------------- .../java/io/opencensus/metrics/TimeSeries.java | 94 ------- api/src/main/java/io/opencensus/metrics/Value.java | 246 ------------------ .../io/opencensus/metrics/export/Distribution.java | 280 +++++++++++++++++++++ .../java/io/opencensus/metrics/export/Metric.java | 104 ++++++++ .../metrics/export/MetricDescriptor.java | 173 +++++++++++++ .../opencensus/metrics/export/MetricProducer.java | 40 +++ .../metrics/export/MetricProducerManager.java | 1 - .../java/io/opencensus/metrics/export/Point.java | 63 +++++ .../java/io/opencensus/metrics/export/Summary.java | 187 ++++++++++++++ .../io/opencensus/metrics/export/TimeSeries.java | 96 +++++++ .../java/io/opencensus/metrics/export/Value.java | 246 ++++++++++++++++++ .../io/opencensus/metrics/DistributionTest.java | 227 ----------------- .../opencensus/metrics/MetricDescriptorTest.java | 102 -------- .../java/io/opencensus/metrics/MetricTest.java | 116 --------- .../test/java/io/opencensus/metrics/PointTest.java | 68 ----- .../java/io/opencensus/metrics/SummaryTest.java | 189 -------------- .../java/io/opencensus/metrics/TimeSeriesTest.java | 116 --------- .../test/java/io/opencensus/metrics/ValueTest.java | 155 ------------ .../metrics/export/DistributionTest.java | 227 +++++++++++++++++ .../metrics/export/MetricDescriptorTest.java | 103 ++++++++ .../metrics/export/MetricProducerManagerTest.java | 1 - .../io/opencensus/metrics/export/MetricTest.java | 118 +++++++++ .../io/opencensus/metrics/export/PointTest.java | 68 +++++ .../io/opencensus/metrics/export/SummaryTest.java | 189 ++++++++++++++ .../opencensus/metrics/export/TimeSeriesTest.java | 117 +++++++++ .../io/opencensus/metrics/export/ValueTest.java | 155 ++++++++++++ 33 files changed, 2167 insertions(+), 2163 deletions(-) delete mode 100644 api/src/main/java/io/opencensus/metrics/Distribution.java delete mode 100644 api/src/main/java/io/opencensus/metrics/Metric.java delete mode 100644 api/src/main/java/io/opencensus/metrics/MetricDescriptor.java delete mode 100644 api/src/main/java/io/opencensus/metrics/MetricProducer.java delete mode 100644 api/src/main/java/io/opencensus/metrics/Point.java delete mode 100644 api/src/main/java/io/opencensus/metrics/Summary.java delete mode 100644 api/src/main/java/io/opencensus/metrics/TimeSeries.java delete mode 100644 api/src/main/java/io/opencensus/metrics/Value.java create mode 100644 api/src/main/java/io/opencensus/metrics/export/Distribution.java create mode 100644 api/src/main/java/io/opencensus/metrics/export/Metric.java create mode 100644 api/src/main/java/io/opencensus/metrics/export/MetricDescriptor.java create mode 100644 api/src/main/java/io/opencensus/metrics/export/MetricProducer.java create mode 100644 api/src/main/java/io/opencensus/metrics/export/Point.java create mode 100644 api/src/main/java/io/opencensus/metrics/export/Summary.java create mode 100644 api/src/main/java/io/opencensus/metrics/export/TimeSeries.java create mode 100644 api/src/main/java/io/opencensus/metrics/export/Value.java delete mode 100644 api/src/test/java/io/opencensus/metrics/DistributionTest.java delete mode 100644 api/src/test/java/io/opencensus/metrics/MetricDescriptorTest.java delete mode 100644 api/src/test/java/io/opencensus/metrics/MetricTest.java delete mode 100644 api/src/test/java/io/opencensus/metrics/PointTest.java delete mode 100644 api/src/test/java/io/opencensus/metrics/SummaryTest.java delete mode 100644 api/src/test/java/io/opencensus/metrics/TimeSeriesTest.java delete mode 100644 api/src/test/java/io/opencensus/metrics/ValueTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/export/DistributionTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/export/MetricDescriptorTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/export/MetricTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/export/PointTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/export/SummaryTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/export/TimeSeriesTest.java create mode 100644 api/src/test/java/io/opencensus/metrics/export/ValueTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/metrics/Distribution.java b/api/src/main/java/io/opencensus/metrics/Distribution.java deleted file mode 100644 index 9294b838..00000000 --- a/api/src/main/java/io/opencensus/metrics/Distribution.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import com.google.auto.value.AutoValue; -import io.opencensus.common.ExperimentalApi; -import io.opencensus.common.Timestamp; -import io.opencensus.internal.Utils; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; - -/** - * {@link Distribution} contains summary statistics for a population of values. It optionally - * contains a histogram representing the distribution of those values across a set of buckets. - * - * @since 0.17 - */ -@ExperimentalApi -@AutoValue -@Immutable -public abstract class Distribution { - - Distribution() {} - - /** - * Creates a {@link Distribution}. - * - * @param count the count of the population values. - * @param sum the sum of the population values. - * @param sumOfSquaredDeviations the sum of squared deviations of the population values. - * @param bucketBoundaries bucket boundaries of a histogram. - * @param buckets {@link Bucket}s of a histogram. - * @return a {@code Distribution}. - * @since 0.17 - */ - public static Distribution create( - long count, - double sum, - double sumOfSquaredDeviations, - List bucketBoundaries, - List buckets) { - Utils.checkArgument(count >= 0, "count should be non-negative."); - Utils.checkArgument( - sumOfSquaredDeviations >= 0, "sum of squared deviations should be non-negative."); - if (count == 0) { - Utils.checkArgument(sum == 0, "sum should be 0 if count is 0."); - Utils.checkArgument( - sumOfSquaredDeviations == 0, "sum of squared deviations should be 0 if count is 0."); - } - return new AutoValue_Distribution( - count, - sum, - sumOfSquaredDeviations, - copyBucketBounds(bucketBoundaries), - copyBucketCount(buckets)); - } - - private static List copyBucketBounds(List bucketBoundaries) { - Utils.checkNotNull(bucketBoundaries, "bucketBoundaries list should not be null."); - List bucketBoundariesCopy = new ArrayList(bucketBoundaries); // Deep copy. - // Check if sorted. - if (bucketBoundariesCopy.size() > 1) { - double lower = bucketBoundariesCopy.get(0); - for (int i = 1; i < bucketBoundariesCopy.size(); i++) { - double next = bucketBoundariesCopy.get(i); - Utils.checkArgument(lower < next, "bucket boundaries not sorted."); - lower = next; - } - } - return Collections.unmodifiableList(bucketBoundariesCopy); - } - - private static List copyBucketCount(List buckets) { - Utils.checkNotNull(buckets, "bucket list should not be null."); - List bucketsCopy = new ArrayList(buckets); - for (Bucket bucket : bucketsCopy) { - Utils.checkNotNull(bucket, "bucket should not be null."); - } - return Collections.unmodifiableList(bucketsCopy); - } - - /** - * Returns the aggregated count. - * - * @return the aggregated count. - * @since 0.17 - */ - public abstract long getCount(); - - /** - * Returns the aggregated sum. - * - * @return the aggregated sum. - * @since 0.17 - */ - public abstract double getSum(); - - /** - * Returns the aggregated sum of squared deviations. - * - *

    The sum of squared deviations from the mean of the values in the population. For values x_i - * this is: - * - *

    Sum[i=1..n]((x_i - mean)^2) - * - *

    If count is zero then this field must be zero. - * - * @return the aggregated sum of squared deviations. - * @since 0.17 - */ - public abstract double getSumOfSquaredDeviations(); - - /** - * Returns the bucket boundaries of this distribution. - * - *

    The bucket boundaries for that histogram are described by bucket_bounds. This defines - * size(bucket_bounds) + 1 (= N) buckets. The boundaries for bucket index i are: - * - *

      - *
    • {@code (-infinity, bucket_bounds[i]) for i == 0} - *
    • {@code [bucket_bounds[i-1], bucket_bounds[i]) for 0 < i < N-2} - *
    • {@code [bucket_bounds[i-1], +infinity) for i == N-1} - *
    - * - *

    i.e. an underflow bucket (number 0), zero or more finite buckets (1 through N - 2, and an - * overflow bucket (N - 1), with inclusive lower bounds and exclusive upper bounds. - * - *

    If bucket_bounds has no elements (zero size), then there is no histogram associated with the - * Distribution. If bucket_bounds has only one element, there are no finite buckets, and that - * single element is the common boundary of the overflow and underflow buckets. The values must be - * monotonically increasing. - * - * @return the bucket boundaries of this distribution. - * @since 0.17 - */ - public abstract List getBucketBoundaries(); - - /** - * Returns the aggregated histogram {@link Bucket}s. - * - * @return the aggregated histogram buckets. - * @since 0.17 - */ - public abstract List getBuckets(); - - /** - * The histogram bucket of the population values. - * - * @since 0.17 - */ - @AutoValue - @Immutable - public abstract static class Bucket { - - Bucket() {} - - /** - * Creates a {@link Bucket}. - * - * @param count the number of values in each bucket of the histogram. - * @return a {@code Bucket}. - * @since 0.17 - */ - public static Bucket create(long count) { - Utils.checkArgument(count >= 0, "bucket count should be non-negative."); - return new AutoValue_Distribution_Bucket(count, null); - } - - /** - * Creates a {@link Bucket} with an {@link Exemplar}. - * - * @param count the number of values in each bucket of the histogram. - * @param exemplar the {@code Exemplar} of this {@code Bucket}. - * @return a {@code Bucket}. - * @since 0.17 - */ - public static Bucket create(long count, Exemplar exemplar) { - Utils.checkArgument(count >= 0, "bucket count should be non-negative."); - Utils.checkNotNull(exemplar, "exemplar"); - return new AutoValue_Distribution_Bucket(count, exemplar); - } - - /** - * Returns the number of values in each bucket of the histogram. - * - * @return the number of values in each bucket of the histogram. - * @since 0.17 - */ - public abstract long getCount(); - - /** - * Returns the {@link Exemplar} associated with the {@link Bucket}, or {@code null} if there - * isn't one. - * - * @return the {@code Exemplar} associated with the {@code Bucket}, or {@code null} if there - * isn't one. - * @since 0.17 - */ - @Nullable - public abstract Exemplar getExemplar(); - } - - /** - * An example point that may be used to annotate aggregated distribution values, associated with a - * histogram bucket. - * - * @since 0.17 - */ - @Immutable - @AutoValue - public abstract static class Exemplar { - - Exemplar() {} - - /** - * Returns value of the {@link Exemplar} point. - * - * @return value of the {@code Exemplar} point. - * @since 0.17 - */ - public abstract double getValue(); - - /** - * Returns the time that this {@link Exemplar}'s value was recorded. - * - * @return the time that this {@code Exemplar}'s value was recorded. - * @since 0.17 - */ - public abstract Timestamp getTimestamp(); - - /** - * Returns the contextual information about the example value, represented as a string map. - * - * @return the contextual information about the example value. - * @since 0.17 - */ - public abstract Map getAttachments(); - - /** - * Creates an {@link Exemplar}. - * - * @param value value of the {@link Exemplar} point. - * @param timestamp the time that this {@code Exemplar}'s value was recorded. - * @param attachments the contextual information about the example value. - * @return an {@code Exemplar}. - * @since 0.17 - */ - public static Exemplar create( - double value, Timestamp timestamp, Map attachments) { - Utils.checkNotNull(attachments, "attachments"); - Map attachmentsCopy = - Collections.unmodifiableMap(new HashMap(attachments)); - for (Entry entry : attachmentsCopy.entrySet()) { - Utils.checkNotNull(entry.getKey(), "key of attachments"); - Utils.checkNotNull(entry.getValue(), "value of attachments"); - } - return new AutoValue_Distribution_Exemplar(value, timestamp, attachmentsCopy); - } - } -} diff --git a/api/src/main/java/io/opencensus/metrics/Metric.java b/api/src/main/java/io/opencensus/metrics/Metric.java deleted file mode 100644 index 0c108b56..00000000 --- a/api/src/main/java/io/opencensus/metrics/Metric.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import com.google.auto.value.AutoValue; -import io.opencensus.common.ExperimentalApi; -import io.opencensus.internal.Utils; -import io.opencensus.metrics.Value.ValueDistribution; -import io.opencensus.metrics.Value.ValueDouble; -import io.opencensus.metrics.Value.ValueLong; -import io.opencensus.metrics.Value.ValueSummary; -import java.util.List; -import javax.annotation.concurrent.Immutable; - -/** - * A {@link Metric} with one or more {@link TimeSeries}. - * - * @since 0.17 - */ -@ExperimentalApi -@Immutable -@AutoValue -public abstract class Metric { - - Metric() {} - - /** - * Creates a {@link Metric}. - * - * @param metricDescriptor the {@link MetricDescriptor}. - * @param timeSeriesList the {@link TimeSeries} list for this metric. - * @return a {@code Metric}. - * @since 0.17 - */ - public static Metric create(MetricDescriptor metricDescriptor, List timeSeriesList) { - checkTypeMatch(metricDescriptor.getType(), timeSeriesList); - return new AutoValue_Metric(metricDescriptor, timeSeriesList); - } - - /** - * Returns the {@link MetricDescriptor} of this metric. - * - * @return the {@code MetricDescriptor} of this metric. - * @since 0.17 - */ - public abstract MetricDescriptor getMetricDescriptor(); - - /** - * Returns the {@link TimeSeries} list for this metric. - * - *

    The type of the {@link TimeSeries#getPoints()} must match {@link MetricDescriptor.Type}. - * - * @return the {@code TimeSeriesList} for this metric. - * @since 0.17 - */ - public abstract List getTimeSeriesList(); - - private static void checkTypeMatch(MetricDescriptor.Type type, List timeSeriesList) { - for (TimeSeries timeSeries : timeSeriesList) { - for (Point point : timeSeries.getPoints()) { - Value value = point.getValue(); - String valueClassName = ""; - if (value.getClass().getSuperclass() != null) { // work around nullness check - // AutoValue classes should always have a super class. - valueClassName = value.getClass().getSuperclass().getSimpleName(); - } - switch (type) { - case GAUGE_INT64: - case CUMULATIVE_INT64: - Utils.checkArgument( - value instanceof ValueLong, "Type mismatch: %s, %s.", type, valueClassName); - break; - case CUMULATIVE_DOUBLE: - case GAUGE_DOUBLE: - Utils.checkArgument( - value instanceof ValueDouble, "Type mismatch: %s, %s.", type, valueClassName); - break; - case GAUGE_DISTRIBUTION: - case CUMULATIVE_DISTRIBUTION: - Utils.checkArgument( - value instanceof ValueDistribution, "Type mismatch: %s, %s.", type, valueClassName); - break; - case SUMMARY: - Utils.checkArgument( - value instanceof ValueSummary, "Type mismatch: %s, %s.", type, valueClassName); - } - } - } - } -} diff --git a/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java b/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java deleted file mode 100644 index 5146cd85..00000000 --- a/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import com.google.auto.value.AutoValue; -import io.opencensus.common.ExperimentalApi; -import io.opencensus.internal.Utils; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.annotation.concurrent.Immutable; - -/** - * {@link MetricDescriptor} defines a {@code Metric} type and its schema. - * - * @since 0.17 - */ -@ExperimentalApi -@Immutable -@AutoValue -public abstract class MetricDescriptor { - - MetricDescriptor() {} - - /** - * Creates a {@link MetricDescriptor}. - * - * @param name name of {@code MetricDescriptor}. - * @param description description of {@code MetricDescriptor}. - * @param unit the metric unit. - * @param type type of {@code MetricDescriptor}. - * @param labelKeys the label keys associated with the {@code MetricDescriptor}. - * @return a {@code MetricDescriptor}. - * @since 0.17 - */ - public static MetricDescriptor create( - String name, String description, String unit, Type type, List labelKeys) { - Utils.checkNotNull(labelKeys, "labelKeys"); - Utils.checkListElementNotNull(labelKeys, "labelKey"); - return new AutoValue_MetricDescriptor( - name, - description, - unit, - type, - Collections.unmodifiableList(new ArrayList(labelKeys))); - } - - /** - * Returns the metric descriptor name. - * - * @return the metric descriptor name. - * @since 0.17 - */ - public abstract String getName(); - - /** - * Returns the description of this metric descriptor. - * - * @return the description of this metric descriptor. - * @since 0.17 - */ - public abstract String getDescription(); - - /** - * Returns the unit of this metric descriptor. - * - * @return the unit of this metric descriptor. - * @since 0.17 - */ - public abstract String getUnit(); - - /** - * Returns the type of this metric descriptor. - * - * @return the type of this metric descriptor. - * @since 0.17 - */ - public abstract Type getType(); - - /** - * Returns the label keys associated with this metric descriptor. - * - * @return the label keys associated with this metric descriptor. - * @since 0.17 - */ - public abstract List getLabelKeys(); - - /** - * The kind of metric. It describes how the data is reported. - * - *

    A gauge is an instantaneous measurement of a value. - * - *

    A cumulative measurement is a value accumulated over a time interval. In a time series, - * cumulative measurements should have the same start time and increasing end times, until an - * event resets the cumulative value to zero and sets a new start time for the following points. - * - * @since 0.17 - */ - public enum Type { - - /** - * An instantaneous measurement of an int64 value. - * - * @since 0.17 - */ - GAUGE_INT64, - - /** - * An instantaneous measurement of a double value. - * - * @since 0.17 - */ - GAUGE_DOUBLE, - - /** - * An instantaneous measurement of a distribution value. The count and sum can go both up and - * down. Used in scenarios like a snapshot of time the current items in a queue have spent - * there. - * - * @since 0.17 - */ - GAUGE_DISTRIBUTION, - - /** - * An cumulative measurement of an int64 value. - * - * @since 0.17 - */ - CUMULATIVE_INT64, - - /** - * An cumulative measurement of a double value. - * - * @since 0.17 - */ - CUMULATIVE_DOUBLE, - - /** - * An cumulative measurement of a distribution value. The count and sum can only go up, if - * resets then the start_time should also be reset. - * - * @since 0.17 - */ - CUMULATIVE_DISTRIBUTION, - - /** - * Some frameworks implemented DISTRIBUTION as a summary of observations (usually things like - * request durations and response sizes). While it also provides a total count of observations - * and a sum of all observed values, it calculates configurable quantiles over a sliding time - * window. - * - *

    This is not recommended, since it cannot be aggregated. - * - * @since 0.17 - */ - SUMMARY, - } -} diff --git a/api/src/main/java/io/opencensus/metrics/MetricProducer.java b/api/src/main/java/io/opencensus/metrics/MetricProducer.java deleted file mode 100644 index 86f9732f..00000000 --- a/api/src/main/java/io/opencensus/metrics/MetricProducer.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import io.opencensus.common.ExperimentalApi; -import io.opencensus.metrics.export.MetricProducerManager; -import java.util.Collection; - -/** - * A {@link Metric} producer that can be registered for exporting using {@link - * MetricProducerManager}. - * - *

    All implementation MUST be thread-safe. - * - * @since 0.17 - */ -@ExperimentalApi -public abstract class MetricProducer { - - /** - * Returns a collection of produced {@link Metric}s to be exported. - * - * @return a collection of produced {@link Metric}s to be exported. - * @since 0.17 - */ - public abstract Collection getMetrics(); -} diff --git a/api/src/main/java/io/opencensus/metrics/MetricRegistry.java b/api/src/main/java/io/opencensus/metrics/MetricRegistry.java index c249d47b..a9987b75 100644 --- a/api/src/main/java/io/opencensus/metrics/MetricRegistry.java +++ b/api/src/main/java/io/opencensus/metrics/MetricRegistry.java @@ -24,7 +24,7 @@ import java.util.LinkedHashMap; /** * Creates and manages your application's set of metrics. The default implementation of this creates - * a {@link MetricProducer} and registers it to the global {@link + * a {@link io.opencensus.metrics.export.MetricProducer} and registers it to the global {@link * io.opencensus.metrics.export.MetricProducerManager}. * * @since 0.17 diff --git a/api/src/main/java/io/opencensus/metrics/Point.java b/api/src/main/java/io/opencensus/metrics/Point.java deleted file mode 100644 index 9ef7c15b..00000000 --- a/api/src/main/java/io/opencensus/metrics/Point.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import com.google.auto.value.AutoValue; -import io.opencensus.common.ExperimentalApi; -import io.opencensus.common.Timestamp; -import javax.annotation.concurrent.Immutable; - -/** - * A timestamped measurement of a {@code TimeSeries}. - * - * @since 0.17 - */ -@ExperimentalApi -@AutoValue -@Immutable -public abstract class Point { - - Point() {} - - /** - * Creates a {@link Point}. - * - * @param value the {@link Value} of this {@link Point}. - * @param timestamp the {@link Timestamp} when this {@link Point} was recorded. - * @return a {@code Point}. - * @since 0.17 - */ - public static Point create(Value value, Timestamp timestamp) { - return new AutoValue_Point(value, timestamp); - } - - /** - * Returns the {@link Value}. - * - * @return the {@code Value}. - * @since 0.17 - */ - public abstract Value getValue(); - - /** - * Returns the {@link Timestamp} when this {@link Point} was recorded. - * - * @return the {@code Timestamp}. - * @since 0.17 - */ - public abstract Timestamp getTimestamp(); -} diff --git a/api/src/main/java/io/opencensus/metrics/Summary.java b/api/src/main/java/io/opencensus/metrics/Summary.java deleted file mode 100644 index f23667bb..00000000 --- a/api/src/main/java/io/opencensus/metrics/Summary.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import com.google.auto.value.AutoValue; -import io.opencensus.common.ExperimentalApi; -import io.opencensus.internal.Utils; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; - -/** - * Implementation of the {@link Distribution} as a summary of observations. - * - *

    This is not recommended, since it cannot be aggregated. - * - * @since 0.17 - */ -@ExperimentalApi -@AutoValue -@Immutable -public abstract class Summary { - Summary() {} - - /** - * Creates a {@link Summary}. - * - * @param count the count of the population values. - * @param sum the sum of the population values. - * @param snapshot bucket boundaries of a histogram. - * @return a {@code Summary} with the given values. - * @since 0.17 - */ - public static Summary create(@Nullable Long count, @Nullable Double sum, Snapshot snapshot) { - checkCountAndSum(count, sum); - Utils.checkNotNull(snapshot, "snapshot"); - return new AutoValue_Summary(count, sum, snapshot); - } - - /** - * Returns the aggregated count. If not available returns {@code null}. - * - * @return the aggregated count. - * @since 0.17 - */ - @Nullable - public abstract Long getCount(); - - /** - * Returns the aggregated sum. If not available returns {@code null}. - * - * @return the aggregated sum. - * @since 0.17 - */ - @Nullable - public abstract Double getSum(); - - /** - * Returns the {@link Snapshot}. - * - * @return the {@code Snapshot}. - * @since 0.17 - */ - public abstract Snapshot getSnapshot(); - - /** - * Represents the summary observation of the recorded events over a sliding time window. - * - * @since 0.17 - */ - @Immutable - @AutoValue - public abstract static class Snapshot { - /** - * Returns the number of values in this {@code Snapshot}. If not available returns {@code null}. - * - * @return the number of values in this {@code Snapshot}. - * @since 0.17 - */ - @Nullable - public abstract Long getCount(); - - /** - * Returns the sum of values in this {@code Snapshot}. If not available returns {@code null}. - * - * @return the sum of values in this {@code Snapshot}. - * @since 0.17 - */ - @Nullable - public abstract Double getSum(); - - /** - * Returns the list of {@code ValueAtPercentile}s in this {@code Snapshot}. - * - * @return the list of {@code ValueAtPercentile}s in this {@code Snapshot}. - * @since 0.17 - */ - public abstract List getValueAtPercentiles(); - - /** - * Creates a {@link Snapshot}. - * - * @param count the number of values in this {@code Snapshot}. - * @param sum the number of values in this {@code Snapshot}. - * @param valueAtPercentiles the list of {@code ValueAtPercentile}. - * @return a {@code Snapshot} with the given values. - * @since 0.17 - */ - public static Snapshot create( - @Nullable Long count, @Nullable Double sum, List valueAtPercentiles) { - checkCountAndSum(count, sum); - Utils.checkNotNull(valueAtPercentiles, "valueAtPercentiles"); - Utils.checkListElementNotNull(valueAtPercentiles, "value in valueAtPercentiles"); - return new AutoValue_Summary_Snapshot( - count, - sum, - Collections.unmodifiableList(new ArrayList(valueAtPercentiles))); - } - - /** - * Represents the value at a given percentile of a distribution. - * - * @since 0.17 - */ - @Immutable - @AutoValue - public abstract static class ValueAtPercentile { - /** - * Returns the percentile in this {@code ValueAtPercentile}. - * - *

    Must be in the interval (0.0, 100.0]. - * - * @return the percentile in this {@code ValueAtPercentile}. - * @since 0.17 - */ - public abstract double getPercentile(); - - /** - * Returns the value in this {@code ValueAtPercentile}. - * - * @return the value in this {@code ValueAtPercentile}. - * @since 0.17 - */ - public abstract double getValue(); - - /** - * Creates a {@link ValueAtPercentile}. - * - * @param percentile the percentile in this {@code ValueAtPercentile}. - * @param value the value in this {@code ValueAtPercentile}. - * @return a {@code ValueAtPercentile} with the given values. - * @since 0.17 - */ - public static ValueAtPercentile create(double percentile, double value) { - Utils.checkArgument( - 0 < percentile && percentile <= 100.0, - "percentile must be in the interval (0.0, 100.0]"); - Utils.checkArgument(value >= 0, "value must be non-negative"); - return new AutoValue_Summary_Snapshot_ValueAtPercentile(percentile, value); - } - } - } - - private static void checkCountAndSum(@Nullable Long count, @Nullable Double sum) { - Utils.checkArgument(count == null || count >= 0, "count must be non-negative."); - Utils.checkArgument(sum == null || sum >= 0, "sum must be non-negative."); - if (count != null && count == 0) { - Utils.checkArgument(sum == null || sum == 0, "sum must be 0 if count is 0."); - } - } -} diff --git a/api/src/main/java/io/opencensus/metrics/TimeSeries.java b/api/src/main/java/io/opencensus/metrics/TimeSeries.java deleted file mode 100644 index d504dad9..00000000 --- a/api/src/main/java/io/opencensus/metrics/TimeSeries.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import com.google.auto.value.AutoValue; -import io.opencensus.common.ExperimentalApi; -import io.opencensus.common.Timestamp; -import io.opencensus.internal.Utils; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; - -/** - * A collection of data points that describes the time-varying values of a {@code Metric}. - * - * @since 0.17 - */ -@ExperimentalApi -@Immutable -@AutoValue -public abstract class TimeSeries { - - TimeSeries() {} - - /** - * Creates a {@link TimeSeries}. - * - * @param labelValues the {@code LabelValue}s that uniquely identify this {@code TimeSeries}. - * @param points the data {@code Point}s of this {@code TimeSeries}. - * @param startTimestamp the start {@code Timestamp} of this {@code TimeSeries}. Must be non-null - * for cumulative {@code Point}s. - * @return a {@code TimeSeries}. - * @since 0.17 - */ - public static TimeSeries create( - List labelValues, List points, @Nullable Timestamp startTimestamp) { - // Fail fast on null lists to prevent NullPointerException when copying the lists. - Utils.checkNotNull(labelValues, "labelValues"); - Utils.checkNotNull(points, "points"); - Utils.checkListElementNotNull(labelValues, "labelValue"); - Utils.checkListElementNotNull(points, "point"); - return new AutoValue_TimeSeries( - Collections.unmodifiableList(new ArrayList(labelValues)), - Collections.unmodifiableList(new ArrayList(points)), - startTimestamp); - } - - /** - * Returns the set of {@link LabelValue}s that uniquely identify this {@link TimeSeries}. - * - *

    Apply to all {@link Point}s. - * - *

    The order of {@link LabelValue}s must match that of {@link LabelKey}s in the {@code - * MetricDescriptor}. - * - * @return the {@code LabelValue}s. - * @since 0.17 - */ - public abstract List getLabelValues(); - - /** - * Returns the data {@link Point}s of this {@link TimeSeries}. - * - * @return the data {@code Point}s. - * @since 0.17 - */ - public abstract List getPoints(); - - /** - * Returns the start {@link Timestamp} of this {@link TimeSeries} if the {@link Point}s are - * cumulative, or {@code null} if the {@link Point}s are gauge. - * - * @return the start {@code Timestamp} or {@code null}. - * @since 0.17 - */ - @Nullable - public abstract Timestamp getStartTimestamp(); -} diff --git a/api/src/main/java/io/opencensus/metrics/Value.java b/api/src/main/java/io/opencensus/metrics/Value.java deleted file mode 100644 index 1bc63b79..00000000 --- a/api/src/main/java/io/opencensus/metrics/Value.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import com.google.auto.value.AutoValue; -import io.opencensus.common.ExperimentalApi; -import io.opencensus.common.Function; -import javax.annotation.concurrent.Immutable; - -/** - * The actual point value for a {@link Point}. - * - *

    Currently there are three types of {@link Value}: - * - *

      - *
    • {@code double} - *
    • {@code long} - *
    • {@link Distribution} - *
    - * - *

    Each {@link Point} contains exactly one of the three {@link Value} types. - * - * @since 0.17 - */ -@ExperimentalApi -@Immutable -public abstract class Value { - - Value() {} - - /** - * Returns a double {@link Value}. - * - * @param value value in double. - * @return a double {@code Value}. - * @since 0.17 - */ - public static Value doubleValue(double value) { - return ValueDouble.create(value); - } - - /** - * Returns a long {@link Value}. - * - * @param value value in long. - * @return a long {@code Value}. - * @since 0.17 - */ - public static Value longValue(long value) { - return ValueLong.create(value); - } - - /** - * Returns a {@link Distribution} {@link Value}. - * - * @param value value in {@link Distribution}. - * @return a {@code Distribution} {@code Value}. - * @since 0.17 - */ - public static Value distributionValue(Distribution value) { - return ValueDistribution.create(value); - } - - /** - * Returns a {@link Summary} {@link Value}. - * - * @param value value in {@link Summary}. - * @return a {@code Summary} {@code Value}. - * @since 0.17 - */ - public static Value summaryValue(Summary value) { - return ValueSummary.create(value); - } - - /** - * Applies the given match function to the underlying data type. - * - * @since 0.17 - */ - public abstract T match( - Function doubleFunction, - Function longFunction, - Function distributionFunction, - Function summaryFunction, - Function defaultFunction); - - /** A 64-bit double-precision floating-point {@link Value}. */ - @AutoValue - @Immutable - abstract static class ValueDouble extends Value { - - ValueDouble() {} - - @Override - public final T match( - Function doubleFunction, - Function longFunction, - Function distributionFunction, - Function summaryFunction, - Function defaultFunction) { - return doubleFunction.apply(getValue()); - } - - /** - * Creates a {@link ValueDouble}. - * - * @param value the value in double. - * @return a {@code ValueDouble}. - */ - static ValueDouble create(double value) { - return new AutoValue_Value_ValueDouble(value); - } - - /** - * Returns the double value. - * - * @return the double value. - */ - abstract double getValue(); - } - - /** A 64-bit integer {@link Value}. */ - @AutoValue - @Immutable - abstract static class ValueLong extends Value { - - ValueLong() {} - - @Override - public final T match( - Function doubleFunction, - Function longFunction, - Function distributionFunction, - Function summaryFunction, - Function defaultFunction) { - return longFunction.apply(getValue()); - } - - /** - * Creates a {@link ValueLong}. - * - * @param value the value in long. - * @return a {@code ValueLong}. - */ - static ValueLong create(long value) { - return new AutoValue_Value_ValueLong(value); - } - - /** - * Returns the long value. - * - * @return the long value. - */ - abstract long getValue(); - } - - /** - * {@link ValueDistribution} contains summary statistics for a population of values. It optionally - * contains a histogram representing the distribution of those values across a set of buckets. - */ - @AutoValue - @Immutable - abstract static class ValueDistribution extends Value { - - ValueDistribution() {} - - @Override - public final T match( - Function doubleFunction, - Function longFunction, - Function distributionFunction, - Function summaryFunction, - Function defaultFunction) { - return distributionFunction.apply(getValue()); - } - - /** - * Creates a {@link ValueDistribution}. - * - * @param value the {@link Distribution} value. - * @return a {@code ValueDistribution}. - */ - static ValueDistribution create(Distribution value) { - return new AutoValue_Value_ValueDistribution(value); - } - - /** - * Returns the {@link Distribution} value. - * - * @return the {@code Distribution} value. - */ - abstract Distribution getValue(); - } - - /** - * {@link ValueSummary} contains a snapshot representing values calculated over an arbitrary time - * window. - */ - @AutoValue - @Immutable - abstract static class ValueSummary extends Value { - - ValueSummary() {} - - @Override - public final T match( - Function doubleFunction, - Function longFunction, - Function distributionFunction, - Function summaryFunction, - Function defaultFunction) { - return summaryFunction.apply(getValue()); - } - - /** - * Creates a {@link ValueSummary}. - * - * @param value the {@link Summary} value. - * @return a {@code ValueSummary}. - */ - static ValueSummary create(Summary value) { - return new AutoValue_Value_ValueSummary(value); - } - - /** - * Returns the {@link Summary} value. - * - * @return the {@code Summary} value. - */ - abstract Summary getValue(); - } -} diff --git a/api/src/main/java/io/opencensus/metrics/export/Distribution.java b/api/src/main/java/io/opencensus/metrics/export/Distribution.java new file mode 100644 index 00000000..dc9fa9e9 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/export/Distribution.java @@ -0,0 +1,280 @@ +/* + * Copyright 2018, 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.metrics.export; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.common.Timestamp; +import io.opencensus.internal.Utils; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * {@link Distribution} contains summary statistics for a population of values. It optionally + * contains a histogram representing the distribution of those values across a set of buckets. + * + * @since 0.17 + */ +@ExperimentalApi +@AutoValue +@Immutable +public abstract class Distribution { + + Distribution() {} + + /** + * Creates a {@link Distribution}. + * + * @param count the count of the population values. + * @param sum the sum of the population values. + * @param sumOfSquaredDeviations the sum of squared deviations of the population values. + * @param bucketBoundaries bucket boundaries of a histogram. + * @param buckets {@link Bucket}s of a histogram. + * @return a {@code Distribution}. + * @since 0.17 + */ + public static Distribution create( + long count, + double sum, + double sumOfSquaredDeviations, + List bucketBoundaries, + List buckets) { + Utils.checkArgument(count >= 0, "count should be non-negative."); + Utils.checkArgument( + sumOfSquaredDeviations >= 0, "sum of squared deviations should be non-negative."); + if (count == 0) { + Utils.checkArgument(sum == 0, "sum should be 0 if count is 0."); + Utils.checkArgument( + sumOfSquaredDeviations == 0, "sum of squared deviations should be 0 if count is 0."); + } + return new AutoValue_Distribution( + count, + sum, + sumOfSquaredDeviations, + copyBucketBounds(bucketBoundaries), + copyBucketCount(buckets)); + } + + private static List copyBucketBounds(List bucketBoundaries) { + Utils.checkNotNull(bucketBoundaries, "bucketBoundaries list should not be null."); + List bucketBoundariesCopy = new ArrayList(bucketBoundaries); // Deep copy. + // Check if sorted. + if (bucketBoundariesCopy.size() > 1) { + double lower = bucketBoundariesCopy.get(0); + for (int i = 1; i < bucketBoundariesCopy.size(); i++) { + double next = bucketBoundariesCopy.get(i); + Utils.checkArgument(lower < next, "bucket boundaries not sorted."); + lower = next; + } + } + return Collections.unmodifiableList(bucketBoundariesCopy); + } + + private static List copyBucketCount(List buckets) { + Utils.checkNotNull(buckets, "bucket list should not be null."); + List bucketsCopy = new ArrayList(buckets); + for (Bucket bucket : bucketsCopy) { + Utils.checkNotNull(bucket, "bucket should not be null."); + } + return Collections.unmodifiableList(bucketsCopy); + } + + /** + * Returns the aggregated count. + * + * @return the aggregated count. + * @since 0.17 + */ + public abstract long getCount(); + + /** + * Returns the aggregated sum. + * + * @return the aggregated sum. + * @since 0.17 + */ + public abstract double getSum(); + + /** + * Returns the aggregated sum of squared deviations. + * + *

    The sum of squared deviations from the mean of the values in the population. For values x_i + * this is: + * + *

    Sum[i=1..n]((x_i - mean)^2) + * + *

    If count is zero then this field must be zero. + * + * @return the aggregated sum of squared deviations. + * @since 0.17 + */ + public abstract double getSumOfSquaredDeviations(); + + /** + * Returns the bucket boundaries of this distribution. + * + *

    The bucket boundaries for that histogram are described by bucket_bounds. This defines + * size(bucket_bounds) + 1 (= N) buckets. The boundaries for bucket index i are: + * + *

      + *
    • {@code (-infinity, bucket_bounds[i]) for i == 0} + *
    • {@code [bucket_bounds[i-1], bucket_bounds[i]) for 0 < i < N-2} + *
    • {@code [bucket_bounds[i-1], +infinity) for i == N-1} + *
    + * + *

    i.e. an underflow bucket (number 0), zero or more finite buckets (1 through N - 2, and an + * overflow bucket (N - 1), with inclusive lower bounds and exclusive upper bounds. + * + *

    If bucket_bounds has no elements (zero size), then there is no histogram associated with the + * Distribution. If bucket_bounds has only one element, there are no finite buckets, and that + * single element is the common boundary of the overflow and underflow buckets. The values must be + * monotonically increasing. + * + * @return the bucket boundaries of this distribution. + * @since 0.17 + */ + public abstract List getBucketBoundaries(); + + /** + * Returns the aggregated histogram {@link Bucket}s. + * + * @return the aggregated histogram buckets. + * @since 0.17 + */ + public abstract List getBuckets(); + + /** + * The histogram bucket of the population values. + * + * @since 0.17 + */ + @AutoValue + @Immutable + public abstract static class Bucket { + + Bucket() {} + + /** + * Creates a {@link Bucket}. + * + * @param count the number of values in each bucket of the histogram. + * @return a {@code Bucket}. + * @since 0.17 + */ + public static Bucket create(long count) { + Utils.checkArgument(count >= 0, "bucket count should be non-negative."); + return new AutoValue_Distribution_Bucket(count, null); + } + + /** + * Creates a {@link Bucket} with an {@link Exemplar}. + * + * @param count the number of values in each bucket of the histogram. + * @param exemplar the {@code Exemplar} of this {@code Bucket}. + * @return a {@code Bucket}. + * @since 0.17 + */ + public static Bucket create(long count, Exemplar exemplar) { + Utils.checkArgument(count >= 0, "bucket count should be non-negative."); + Utils.checkNotNull(exemplar, "exemplar"); + return new AutoValue_Distribution_Bucket(count, exemplar); + } + + /** + * Returns the number of values in each bucket of the histogram. + * + * @return the number of values in each bucket of the histogram. + * @since 0.17 + */ + public abstract long getCount(); + + /** + * Returns the {@link Exemplar} associated with the {@link Bucket}, or {@code null} if there + * isn't one. + * + * @return the {@code Exemplar} associated with the {@code Bucket}, or {@code null} if there + * isn't one. + * @since 0.17 + */ + @Nullable + public abstract Exemplar getExemplar(); + } + + /** + * An example point that may be used to annotate aggregated distribution values, associated with a + * histogram bucket. + * + * @since 0.17 + */ + @Immutable + @AutoValue + public abstract static class Exemplar { + + Exemplar() {} + + /** + * Returns value of the {@link Exemplar} point. + * + * @return value of the {@code Exemplar} point. + * @since 0.17 + */ + public abstract double getValue(); + + /** + * Returns the time that this {@link Exemplar}'s value was recorded. + * + * @return the time that this {@code Exemplar}'s value was recorded. + * @since 0.17 + */ + public abstract Timestamp getTimestamp(); + + /** + * Returns the contextual information about the example value, represented as a string map. + * + * @return the contextual information about the example value. + * @since 0.17 + */ + public abstract Map getAttachments(); + + /** + * Creates an {@link Exemplar}. + * + * @param value value of the {@link Exemplar} point. + * @param timestamp the time that this {@code Exemplar}'s value was recorded. + * @param attachments the contextual information about the example value. + * @return an {@code Exemplar}. + * @since 0.17 + */ + public static Exemplar create( + double value, Timestamp timestamp, Map attachments) { + Utils.checkNotNull(attachments, "attachments"); + Map attachmentsCopy = + Collections.unmodifiableMap(new HashMap(attachments)); + for (Entry entry : attachmentsCopy.entrySet()) { + Utils.checkNotNull(entry.getKey(), "key of attachments"); + Utils.checkNotNull(entry.getValue(), "value of attachments"); + } + return new AutoValue_Distribution_Exemplar(value, timestamp, attachmentsCopy); + } + } +} diff --git a/api/src/main/java/io/opencensus/metrics/export/Metric.java b/api/src/main/java/io/opencensus/metrics/export/Metric.java new file mode 100644 index 00000000..07fe356a --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/export/Metric.java @@ -0,0 +1,104 @@ +/* + * Copyright 2018, 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.metrics.export; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.internal.Utils; +import io.opencensus.metrics.export.Value.ValueDistribution; +import io.opencensus.metrics.export.Value.ValueDouble; +import io.opencensus.metrics.export.Value.ValueLong; +import io.opencensus.metrics.export.Value.ValueSummary; +import java.util.List; +import javax.annotation.concurrent.Immutable; + +/** + * A {@link Metric} with one or more {@link TimeSeries}. + * + * @since 0.17 + */ +@ExperimentalApi +@Immutable +@AutoValue +public abstract class Metric { + + Metric() {} + + /** + * Creates a {@link Metric}. + * + * @param metricDescriptor the {@link MetricDescriptor}. + * @param timeSeriesList the {@link TimeSeries} list for this metric. + * @return a {@code Metric}. + * @since 0.17 + */ + public static Metric create(MetricDescriptor metricDescriptor, List timeSeriesList) { + checkTypeMatch(metricDescriptor.getType(), timeSeriesList); + return new AutoValue_Metric(metricDescriptor, timeSeriesList); + } + + /** + * Returns the {@link MetricDescriptor} of this metric. + * + * @return the {@code MetricDescriptor} of this metric. + * @since 0.17 + */ + public abstract MetricDescriptor getMetricDescriptor(); + + /** + * Returns the {@link TimeSeries} list for this metric. + * + *

    The type of the {@link TimeSeries#getPoints()} must match {@link MetricDescriptor.Type}. + * + * @return the {@code TimeSeriesList} for this metric. + * @since 0.17 + */ + public abstract List getTimeSeriesList(); + + private static void checkTypeMatch(MetricDescriptor.Type type, List timeSeriesList) { + for (TimeSeries timeSeries : timeSeriesList) { + for (Point point : timeSeries.getPoints()) { + Value value = point.getValue(); + String valueClassName = ""; + if (value.getClass().getSuperclass() != null) { // work around nullness check + // AutoValue classes should always have a super class. + valueClassName = value.getClass().getSuperclass().getSimpleName(); + } + switch (type) { + case GAUGE_INT64: + case CUMULATIVE_INT64: + Utils.checkArgument( + value instanceof ValueLong, "Type mismatch: %s, %s.", type, valueClassName); + break; + case CUMULATIVE_DOUBLE: + case GAUGE_DOUBLE: + Utils.checkArgument( + value instanceof ValueDouble, "Type mismatch: %s, %s.", type, valueClassName); + break; + case GAUGE_DISTRIBUTION: + case CUMULATIVE_DISTRIBUTION: + Utils.checkArgument( + value instanceof ValueDistribution, "Type mismatch: %s, %s.", type, valueClassName); + break; + case SUMMARY: + Utils.checkArgument( + value instanceof ValueSummary, "Type mismatch: %s, %s.", type, valueClassName); + } + } + } + } +} diff --git a/api/src/main/java/io/opencensus/metrics/export/MetricDescriptor.java b/api/src/main/java/io/opencensus/metrics/export/MetricDescriptor.java new file mode 100644 index 00000000..a4629f8e --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/export/MetricDescriptor.java @@ -0,0 +1,173 @@ +/* + * Copyright 2018, 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.metrics.export; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.internal.Utils; +import io.opencensus.metrics.LabelKey; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.annotation.concurrent.Immutable; + +/** + * {@link MetricDescriptor} defines a {@code Metric} type and its schema. + * + * @since 0.17 + */ +@ExperimentalApi +@Immutable +@AutoValue +public abstract class MetricDescriptor { + + MetricDescriptor() {} + + /** + * Creates a {@link MetricDescriptor}. + * + * @param name name of {@code MetricDescriptor}. + * @param description description of {@code MetricDescriptor}. + * @param unit the metric unit. + * @param type type of {@code MetricDescriptor}. + * @param labelKeys the label keys associated with the {@code MetricDescriptor}. + * @return a {@code MetricDescriptor}. + * @since 0.17 + */ + public static MetricDescriptor create( + String name, String description, String unit, Type type, List labelKeys) { + Utils.checkNotNull(labelKeys, "labelKeys"); + Utils.checkListElementNotNull(labelKeys, "labelKey"); + return new AutoValue_MetricDescriptor( + name, + description, + unit, + type, + Collections.unmodifiableList(new ArrayList(labelKeys))); + } + + /** + * Returns the metric descriptor name. + * + * @return the metric descriptor name. + * @since 0.17 + */ + public abstract String getName(); + + /** + * Returns the description of this metric descriptor. + * + * @return the description of this metric descriptor. + * @since 0.17 + */ + public abstract String getDescription(); + + /** + * Returns the unit of this metric descriptor. + * + * @return the unit of this metric descriptor. + * @since 0.17 + */ + public abstract String getUnit(); + + /** + * Returns the type of this metric descriptor. + * + * @return the type of this metric descriptor. + * @since 0.17 + */ + public abstract Type getType(); + + /** + * Returns the label keys associated with this metric descriptor. + * + * @return the label keys associated with this metric descriptor. + * @since 0.17 + */ + public abstract List getLabelKeys(); + + /** + * The kind of metric. It describes how the data is reported. + * + *

    A gauge is an instantaneous measurement of a value. + * + *

    A cumulative measurement is a value accumulated over a time interval. In a time series, + * cumulative measurements should have the same start time and increasing end times, until an + * event resets the cumulative value to zero and sets a new start time for the following points. + * + * @since 0.17 + */ + public enum Type { + + /** + * An instantaneous measurement of an int64 value. + * + * @since 0.17 + */ + GAUGE_INT64, + + /** + * An instantaneous measurement of a double value. + * + * @since 0.17 + */ + GAUGE_DOUBLE, + + /** + * An instantaneous measurement of a distribution value. The count and sum can go both up and + * down. Used in scenarios like a snapshot of time the current items in a queue have spent + * there. + * + * @since 0.17 + */ + GAUGE_DISTRIBUTION, + + /** + * An cumulative measurement of an int64 value. + * + * @since 0.17 + */ + CUMULATIVE_INT64, + + /** + * An cumulative measurement of a double value. + * + * @since 0.17 + */ + CUMULATIVE_DOUBLE, + + /** + * An cumulative measurement of a distribution value. The count and sum can only go up, if + * resets then the start_time should also be reset. + * + * @since 0.17 + */ + CUMULATIVE_DISTRIBUTION, + + /** + * Some frameworks implemented DISTRIBUTION as a summary of observations (usually things like + * request durations and response sizes). While it also provides a total count of observations + * and a sum of all observed values, it calculates configurable quantiles over a sliding time + * window. + * + *

    This is not recommended, since it cannot be aggregated. + * + * @since 0.17 + */ + SUMMARY, + } +} diff --git a/api/src/main/java/io/opencensus/metrics/export/MetricProducer.java b/api/src/main/java/io/opencensus/metrics/export/MetricProducer.java new file mode 100644 index 00000000..739a0a9f --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/export/MetricProducer.java @@ -0,0 +1,40 @@ +/* + * Copyright 2018, 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.metrics.export; + +import io.opencensus.common.ExperimentalApi; +import java.util.Collection; + +/** + * A {@link Metric} producer that can be registered for exporting using {@link + * MetricProducerManager}. + * + *

    All implementation MUST be thread-safe. + * + * @since 0.17 + */ +@ExperimentalApi +public abstract class MetricProducer { + + /** + * Returns a collection of produced {@link Metric}s to be exported. + * + * @return a collection of produced {@link Metric}s to be exported. + * @since 0.17 + */ + public abstract Collection getMetrics(); +} diff --git a/api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java b/api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java index fc864200..304d9294 100644 --- a/api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java +++ b/api/src/main/java/io/opencensus/metrics/export/MetricProducerManager.java @@ -18,7 +18,6 @@ package io.opencensus.metrics.export; import io.opencensus.common.ExperimentalApi; import io.opencensus.internal.Utils; -import io.opencensus.metrics.MetricProducer; import java.util.Collections; import java.util.Set; import javax.annotation.concurrent.ThreadSafe; diff --git a/api/src/main/java/io/opencensus/metrics/export/Point.java b/api/src/main/java/io/opencensus/metrics/export/Point.java new file mode 100644 index 00000000..1f382f9b --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/export/Point.java @@ -0,0 +1,63 @@ +/* + * Copyright 2018, 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.metrics.export; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.common.Timestamp; +import javax.annotation.concurrent.Immutable; + +/** + * A timestamped measurement of a {@code TimeSeries}. + * + * @since 0.17 + */ +@ExperimentalApi +@AutoValue +@Immutable +public abstract class Point { + + Point() {} + + /** + * Creates a {@link Point}. + * + * @param value the {@link Value} of this {@link Point}. + * @param timestamp the {@link Timestamp} when this {@link Point} was recorded. + * @return a {@code Point}. + * @since 0.17 + */ + public static Point create(Value value, Timestamp timestamp) { + return new AutoValue_Point(value, timestamp); + } + + /** + * Returns the {@link Value}. + * + * @return the {@code Value}. + * @since 0.17 + */ + public abstract Value getValue(); + + /** + * Returns the {@link Timestamp} when this {@link Point} was recorded. + * + * @return the {@code Timestamp}. + * @since 0.17 + */ + public abstract Timestamp getTimestamp(); +} diff --git a/api/src/main/java/io/opencensus/metrics/export/Summary.java b/api/src/main/java/io/opencensus/metrics/export/Summary.java new file mode 100644 index 00000000..c82ca961 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/export/Summary.java @@ -0,0 +1,187 @@ +/* + * Copyright 2018, 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.metrics.export; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.internal.Utils; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * Implementation of the {@link Distribution} as a summary of observations. + * + *

    This is not recommended, since it cannot be aggregated. + * + * @since 0.17 + */ +@ExperimentalApi +@AutoValue +@Immutable +public abstract class Summary { + Summary() {} + + /** + * Creates a {@link Summary}. + * + * @param count the count of the population values. + * @param sum the sum of the population values. + * @param snapshot bucket boundaries of a histogram. + * @return a {@code Summary} with the given values. + * @since 0.17 + */ + public static Summary create(@Nullable Long count, @Nullable Double sum, Snapshot snapshot) { + checkCountAndSum(count, sum); + Utils.checkNotNull(snapshot, "snapshot"); + return new AutoValue_Summary(count, sum, snapshot); + } + + /** + * Returns the aggregated count. If not available returns {@code null}. + * + * @return the aggregated count. + * @since 0.17 + */ + @Nullable + public abstract Long getCount(); + + /** + * Returns the aggregated sum. If not available returns {@code null}. + * + * @return the aggregated sum. + * @since 0.17 + */ + @Nullable + public abstract Double getSum(); + + /** + * Returns the {@link Snapshot}. + * + * @return the {@code Snapshot}. + * @since 0.17 + */ + public abstract Snapshot getSnapshot(); + + /** + * Represents the summary observation of the recorded events over a sliding time window. + * + * @since 0.17 + */ + @Immutable + @AutoValue + public abstract static class Snapshot { + /** + * Returns the number of values in this {@code Snapshot}. If not available returns {@code null}. + * + * @return the number of values in this {@code Snapshot}. + * @since 0.17 + */ + @Nullable + public abstract Long getCount(); + + /** + * Returns the sum of values in this {@code Snapshot}. If not available returns {@code null}. + * + * @return the sum of values in this {@code Snapshot}. + * @since 0.17 + */ + @Nullable + public abstract Double getSum(); + + /** + * Returns the list of {@code ValueAtPercentile}s in this {@code Snapshot}. + * + * @return the list of {@code ValueAtPercentile}s in this {@code Snapshot}. + * @since 0.17 + */ + public abstract List getValueAtPercentiles(); + + /** + * Creates a {@link Snapshot}. + * + * @param count the number of values in this {@code Snapshot}. + * @param sum the number of values in this {@code Snapshot}. + * @param valueAtPercentiles the list of {@code ValueAtPercentile}. + * @return a {@code Snapshot} with the given values. + * @since 0.17 + */ + public static Snapshot create( + @Nullable Long count, @Nullable Double sum, List valueAtPercentiles) { + checkCountAndSum(count, sum); + Utils.checkNotNull(valueAtPercentiles, "valueAtPercentiles"); + Utils.checkListElementNotNull(valueAtPercentiles, "value in valueAtPercentiles"); + return new AutoValue_Summary_Snapshot( + count, + sum, + Collections.unmodifiableList(new ArrayList(valueAtPercentiles))); + } + + /** + * Represents the value at a given percentile of a distribution. + * + * @since 0.17 + */ + @Immutable + @AutoValue + public abstract static class ValueAtPercentile { + /** + * Returns the percentile in this {@code ValueAtPercentile}. + * + *

    Must be in the interval (0.0, 100.0]. + * + * @return the percentile in this {@code ValueAtPercentile}. + * @since 0.17 + */ + public abstract double getPercentile(); + + /** + * Returns the value in this {@code ValueAtPercentile}. + * + * @return the value in this {@code ValueAtPercentile}. + * @since 0.17 + */ + public abstract double getValue(); + + /** + * Creates a {@link ValueAtPercentile}. + * + * @param percentile the percentile in this {@code ValueAtPercentile}. + * @param value the value in this {@code ValueAtPercentile}. + * @return a {@code ValueAtPercentile} with the given values. + * @since 0.17 + */ + public static ValueAtPercentile create(double percentile, double value) { + Utils.checkArgument( + 0 < percentile && percentile <= 100.0, + "percentile must be in the interval (0.0, 100.0]"); + Utils.checkArgument(value >= 0, "value must be non-negative"); + return new AutoValue_Summary_Snapshot_ValueAtPercentile(percentile, value); + } + } + } + + private static void checkCountAndSum(@Nullable Long count, @Nullable Double sum) { + Utils.checkArgument(count == null || count >= 0, "count must be non-negative."); + Utils.checkArgument(sum == null || sum >= 0, "sum must be non-negative."); + if (count != null && count == 0) { + Utils.checkArgument(sum == null || sum == 0, "sum must be 0 if count is 0."); + } + } +} diff --git a/api/src/main/java/io/opencensus/metrics/export/TimeSeries.java b/api/src/main/java/io/opencensus/metrics/export/TimeSeries.java new file mode 100644 index 00000000..959f55ba --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/export/TimeSeries.java @@ -0,0 +1,96 @@ +/* + * Copyright 2018, 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.metrics.export; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.common.Timestamp; +import io.opencensus.internal.Utils; +import io.opencensus.metrics.LabelKey; +import io.opencensus.metrics.LabelValue; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * A collection of data points that describes the time-varying values of a {@code Metric}. + * + * @since 0.17 + */ +@ExperimentalApi +@Immutable +@AutoValue +public abstract class TimeSeries { + + TimeSeries() {} + + /** + * Creates a {@link TimeSeries}. + * + * @param labelValues the {@code LabelValue}s that uniquely identify this {@code TimeSeries}. + * @param points the data {@code Point}s of this {@code TimeSeries}. + * @param startTimestamp the start {@code Timestamp} of this {@code TimeSeries}. Must be non-null + * for cumulative {@code Point}s. + * @return a {@code TimeSeries}. + * @since 0.17 + */ + public static TimeSeries create( + List labelValues, List points, @Nullable Timestamp startTimestamp) { + // Fail fast on null lists to prevent NullPointerException when copying the lists. + Utils.checkNotNull(labelValues, "labelValues"); + Utils.checkNotNull(points, "points"); + Utils.checkListElementNotNull(labelValues, "labelValue"); + Utils.checkListElementNotNull(points, "point"); + return new AutoValue_TimeSeries( + Collections.unmodifiableList(new ArrayList(labelValues)), + Collections.unmodifiableList(new ArrayList(points)), + startTimestamp); + } + + /** + * Returns the set of {@link LabelValue}s that uniquely identify this {@link TimeSeries}. + * + *

    Apply to all {@link Point}s. + * + *

    The order of {@link LabelValue}s must match that of {@link LabelKey}s in the {@code + * MetricDescriptor}. + * + * @return the {@code LabelValue}s. + * @since 0.17 + */ + public abstract List getLabelValues(); + + /** + * Returns the data {@link Point}s of this {@link TimeSeries}. + * + * @return the data {@code Point}s. + * @since 0.17 + */ + public abstract List getPoints(); + + /** + * Returns the start {@link Timestamp} of this {@link TimeSeries} if the {@link Point}s are + * cumulative, or {@code null} if the {@link Point}s are gauge. + * + * @return the start {@code Timestamp} or {@code null}. + * @since 0.17 + */ + @Nullable + public abstract Timestamp getStartTimestamp(); +} diff --git a/api/src/main/java/io/opencensus/metrics/export/Value.java b/api/src/main/java/io/opencensus/metrics/export/Value.java new file mode 100644 index 00000000..00a939c0 --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/export/Value.java @@ -0,0 +1,246 @@ +/* + * Copyright 2018, 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.metrics.export; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.common.Function; +import javax.annotation.concurrent.Immutable; + +/** + * The actual point value for a {@link Point}. + * + *

    Currently there are three types of {@link Value}: + * + *

      + *
    • {@code double} + *
    • {@code long} + *
    • {@link Distribution} + *
    + * + *

    Each {@link Point} contains exactly one of the three {@link Value} types. + * + * @since 0.17 + */ +@ExperimentalApi +@Immutable +public abstract class Value { + + Value() {} + + /** + * Returns a double {@link Value}. + * + * @param value value in double. + * @return a double {@code Value}. + * @since 0.17 + */ + public static Value doubleValue(double value) { + return ValueDouble.create(value); + } + + /** + * Returns a long {@link Value}. + * + * @param value value in long. + * @return a long {@code Value}. + * @since 0.17 + */ + public static Value longValue(long value) { + return ValueLong.create(value); + } + + /** + * Returns a {@link Distribution} {@link Value}. + * + * @param value value in {@link Distribution}. + * @return a {@code Distribution} {@code Value}. + * @since 0.17 + */ + public static Value distributionValue(Distribution value) { + return ValueDistribution.create(value); + } + + /** + * Returns a {@link Summary} {@link Value}. + * + * @param value value in {@link Summary}. + * @return a {@code Summary} {@code Value}. + * @since 0.17 + */ + public static Value summaryValue(Summary value) { + return ValueSummary.create(value); + } + + /** + * Applies the given match function to the underlying data type. + * + * @since 0.17 + */ + public abstract T match( + Function doubleFunction, + Function longFunction, + Function distributionFunction, + Function summaryFunction, + Function defaultFunction); + + /** A 64-bit double-precision floating-point {@link Value}. */ + @AutoValue + @Immutable + abstract static class ValueDouble extends Value { + + ValueDouble() {} + + @Override + public final T match( + Function doubleFunction, + Function longFunction, + Function distributionFunction, + Function summaryFunction, + Function defaultFunction) { + return doubleFunction.apply(getValue()); + } + + /** + * Creates a {@link ValueDouble}. + * + * @param value the value in double. + * @return a {@code ValueDouble}. + */ + static ValueDouble create(double value) { + return new AutoValue_Value_ValueDouble(value); + } + + /** + * Returns the double value. + * + * @return the double value. + */ + abstract double getValue(); + } + + /** A 64-bit integer {@link Value}. */ + @AutoValue + @Immutable + abstract static class ValueLong extends Value { + + ValueLong() {} + + @Override + public final T match( + Function doubleFunction, + Function longFunction, + Function distributionFunction, + Function summaryFunction, + Function defaultFunction) { + return longFunction.apply(getValue()); + } + + /** + * Creates a {@link ValueLong}. + * + * @param value the value in long. + * @return a {@code ValueLong}. + */ + static ValueLong create(long value) { + return new AutoValue_Value_ValueLong(value); + } + + /** + * Returns the long value. + * + * @return the long value. + */ + abstract long getValue(); + } + + /** + * {@link ValueDistribution} contains summary statistics for a population of values. It optionally + * contains a histogram representing the distribution of those values across a set of buckets. + */ + @AutoValue + @Immutable + abstract static class ValueDistribution extends Value { + + ValueDistribution() {} + + @Override + public final T match( + Function doubleFunction, + Function longFunction, + Function distributionFunction, + Function summaryFunction, + Function defaultFunction) { + return distributionFunction.apply(getValue()); + } + + /** + * Creates a {@link ValueDistribution}. + * + * @param value the {@link Distribution} value. + * @return a {@code ValueDistribution}. + */ + static ValueDistribution create(Distribution value) { + return new AutoValue_Value_ValueDistribution(value); + } + + /** + * Returns the {@link Distribution} value. + * + * @return the {@code Distribution} value. + */ + abstract Distribution getValue(); + } + + /** + * {@link ValueSummary} contains a snapshot representing values calculated over an arbitrary time + * window. + */ + @AutoValue + @Immutable + abstract static class ValueSummary extends Value { + + ValueSummary() {} + + @Override + public final T match( + Function doubleFunction, + Function longFunction, + Function distributionFunction, + Function summaryFunction, + Function defaultFunction) { + return summaryFunction.apply(getValue()); + } + + /** + * Creates a {@link ValueSummary}. + * + * @param value the {@link Summary} value. + * @return a {@code ValueSummary}. + */ + static ValueSummary create(Summary value) { + return new AutoValue_Value_ValueSummary(value); + } + + /** + * Returns the {@link Summary} value. + * + * @return the {@code Summary} value. + */ + abstract Summary getValue(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/DistributionTest.java b/api/src/test/java/io/opencensus/metrics/DistributionTest.java deleted file mode 100644 index 5ee88dd6..00000000 --- a/api/src/test/java/io/opencensus/metrics/DistributionTest.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import io.opencensus.common.Timestamp; -import io.opencensus.metrics.Distribution.Bucket; -import io.opencensus.metrics.Distribution.Exemplar; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link Distribution}. */ -@RunWith(JUnit4.class) -public class DistributionTest { - - @Rule public final ExpectedException thrown = ExpectedException.none(); - - private static final Timestamp TIMESTAMP = Timestamp.create(1, 0); - private static final Map ATTACHMENTS = Collections.singletonMap("key", "value"); - private static final double TOLERANCE = 1e-6; - - @Test - public void createAndGet_Bucket() { - Bucket bucket = Bucket.create(98); - assertThat(bucket.getCount()).isEqualTo(98); - assertThat(bucket.getExemplar()).isNull(); - } - - @Test - public void createAndGet_BucketWithExemplar() { - Exemplar exemplar = Exemplar.create(12.2, TIMESTAMP, ATTACHMENTS); - Bucket bucket = Bucket.create(7, exemplar); - assertThat(bucket.getCount()).isEqualTo(7); - assertThat(bucket.getExemplar()).isEqualTo(exemplar); - } - - @Test - public void createBucket_preventNullExemplar() { - thrown.expect(NullPointerException.class); - thrown.expectMessage("exemplar"); - Bucket.create(1, null); - } - - @Test - public void createAndGet_Exemplar() { - Exemplar exemplar = Exemplar.create(-9.9, TIMESTAMP, ATTACHMENTS); - assertThat(exemplar.getValue()).isWithin(TOLERANCE).of(-9.9); - assertThat(exemplar.getTimestamp()).isEqualTo(TIMESTAMP); - assertThat(exemplar.getAttachments()).isEqualTo(ATTACHMENTS); - } - - @Test - public void createAndGet_Distribution() { - Exemplar exemplar = Exemplar.create(15.0, TIMESTAMP, ATTACHMENTS); - List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); - List buckets = - Arrays.asList( - Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4, exemplar)); - Distribution distribution = Distribution.create(10, 6.6, 678.54, bucketBounds, buckets); - assertThat(distribution.getCount()).isEqualTo(10); - assertThat(distribution.getSum()).isWithin(TOLERANCE).of(6.6); - assertThat(distribution.getSumOfSquaredDeviations()).isWithin(TOLERANCE).of(678.54); - assertThat(distribution.getBucketBoundaries()) - .containsExactlyElementsIn(bucketBounds) - .inOrder(); - assertThat(distribution.getBuckets()).containsExactlyElementsIn(buckets).inOrder(); - } - - @Test - public void createBucket_NegativeCount() { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("bucket count should be non-negative."); - Bucket.create(-5); - } - - @Test - public void createExemplar_PreventNullAttachments() { - thrown.expect(NullPointerException.class); - thrown.expectMessage("attachments"); - Exemplar.create(15, TIMESTAMP, null); - } - - @Test - public void createExemplar_PreventNullAttachmentKey() { - Map attachments = Collections.singletonMap(null, "value"); - thrown.expect(NullPointerException.class); - thrown.expectMessage("key of attachment"); - Exemplar.create(15, TIMESTAMP, attachments); - } - - @Test - public void createExemplar_PreventNullAttachmentValue() { - Map attachments = Collections.singletonMap("key", null); - thrown.expect(NullPointerException.class); - thrown.expectMessage("value of attachment"); - Exemplar.create(15, TIMESTAMP, attachments); - } - - @Test - public void createDistribution_NegativeCount() { - List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); - List buckets = - Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("count should be non-negative."); - Distribution.create(-10, 6.6, 678.54, bucketBounds, buckets); - } - - @Test - public void createDistribution_NegativeSumOfSquaredDeviations() { - List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); - List buckets = - Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0)); - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("sum of squared deviations should be non-negative."); - Distribution.create(0, 6.6, -678.54, bucketBounds, buckets); - } - - @Test - public void createDistribution_ZeroCountAndPositiveMean() { - List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); - List buckets = - Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0)); - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("sum should be 0 if count is 0."); - Distribution.create(0, 6.6, 0, bucketBounds, buckets); - } - - @Test - public void createDistribution_ZeroCountAndSumOfSquaredDeviations() { - List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); - List buckets = - Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0)); - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("sum of squared deviations should be 0 if count is 0."); - Distribution.create(0, 0, 678.54, bucketBounds, buckets); - } - - @Test - public void createDistribution_NullBucketBounds() { - List buckets = - Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); - thrown.expect(NullPointerException.class); - thrown.expectMessage("bucketBoundaries list should not be null."); - Distribution.create(10, 6.6, 678.54, null, buckets); - } - - @Test - public void createDistribution_UnorderedBucketBounds() { - List bucketBounds = Arrays.asList(0.0, -1.0, 1.0); - List buckets = - Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("bucket boundaries not sorted."); - Distribution.create(10, 6.6, 678.54, bucketBounds, buckets); - } - - @Test - public void createDistribution_NullBucketList() { - List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); - thrown.expect(NullPointerException.class); - thrown.expectMessage("bucket list should not be null."); - Distribution.create(10, 6.6, 678.54, bucketBounds, null); - } - - @Test - public void createDistribution_NullBucket() { - List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); - List buckets = - Arrays.asList(Bucket.create(3), Bucket.create(1), null, Bucket.create(4)); - thrown.expect(NullPointerException.class); - thrown.expectMessage("bucket should not be null."); - Distribution.create(10, 6.6, 678.54, bucketBounds, buckets); - } - - @Test - public void testEquals() { - new EqualsTester() - .addEqualityGroup( - Distribution.create( - 10, - 10, - 1, - Arrays.asList(-5.0, 0.0, 5.0), - Arrays.asList( - Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))), - Distribution.create( - 10, - 10, - 1, - Arrays.asList(-5.0, 0.0, 5.0), - Arrays.asList( - Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)))) - .addEqualityGroup( - Distribution.create( - 7, - 10, - 23.456, - Arrays.asList(-5.0, 0.0, 5.0), - Arrays.asList( - Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)))) - .testEquals(); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/MetricDescriptorTest.java b/api/src/test/java/io/opencensus/metrics/MetricDescriptorTest.java deleted file mode 100644 index 9c0a42fc..00000000 --- a/api/src/test/java/io/opencensus/metrics/MetricDescriptorTest.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import io.opencensus.metrics.MetricDescriptor.Type; -import java.util.Arrays; -import java.util.List; -import org.hamcrest.CoreMatchers; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link MetricDescriptor}. */ -@RunWith(JUnit4.class) -public class MetricDescriptorTest { - - @Rule public final ExpectedException thrown = ExpectedException.none(); - - private static final String METRIC_NAME_1 = "metric1"; - private static final String METRIC_NAME_2 = "metric2"; - private static final String DESCRIPTION = "Metric description."; - private static final String UNIT = "kb/s"; - private static final LabelKey KEY_1 = LabelKey.create("key1", "some key"); - private static final LabelKey KEY_2 = LabelKey.create("key2", "some other key"); - - @Test - public void testGet() { - MetricDescriptor metricDescriptor = - MetricDescriptor.create( - METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2)); - assertThat(metricDescriptor.getName()).isEqualTo(METRIC_NAME_1); - assertThat(metricDescriptor.getDescription()).isEqualTo(DESCRIPTION); - assertThat(metricDescriptor.getUnit()).isEqualTo(UNIT); - assertThat(metricDescriptor.getType()).isEqualTo(Type.GAUGE_DOUBLE); - assertThat(metricDescriptor.getLabelKeys()).containsExactly(KEY_1, KEY_2).inOrder(); - } - - @Test - public void preventNullLabelKeyList() { - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("labelKeys")); - MetricDescriptor.create(METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, null); - } - - @Test - public void preventNullLabelKey() { - List keys = Arrays.asList(KEY_1, null); - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("labelKey")); - MetricDescriptor.create(METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, keys); - } - - @Test - public void testEquals() { - new EqualsTester() - .addEqualityGroup( - MetricDescriptor.create( - METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2)), - MetricDescriptor.create( - METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2))) - .addEqualityGroup( - MetricDescriptor.create( - METRIC_NAME_2, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2))) - .addEqualityGroup( - MetricDescriptor.create( - METRIC_NAME_2, DESCRIPTION, UNIT, Type.GAUGE_INT64, Arrays.asList(KEY_1, KEY_2))) - .addEqualityGroup( - MetricDescriptor.create( - METRIC_NAME_1, - DESCRIPTION, - UNIT, - Type.CUMULATIVE_DISTRIBUTION, - Arrays.asList(KEY_1, KEY_2))) - .addEqualityGroup( - MetricDescriptor.create( - METRIC_NAME_1, - DESCRIPTION, - UNIT, - Type.CUMULATIVE_DISTRIBUTION, - Arrays.asList(KEY_1))) - .testEquals(); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/MetricTest.java b/api/src/test/java/io/opencensus/metrics/MetricTest.java deleted file mode 100644 index 37deed4b..00000000 --- a/api/src/test/java/io/opencensus/metrics/MetricTest.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import io.opencensus.common.Timestamp; -import io.opencensus.metrics.MetricDescriptor.Type; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link Metric}. */ -@RunWith(JUnit4.class) -public class MetricTest { - - @Rule public final ExpectedException thrown = ExpectedException.none(); - - private static final String METRIC_NAME_1 = "metric1"; - private static final String METRIC_NAME_2 = "metric2"; - private static final String DESCRIPTION = "Metric description."; - private static final String UNIT = "kb/s"; - private static final LabelKey KEY_1 = LabelKey.create("key1", "some key"); - private static final LabelKey KEY_2 = LabelKey.create("key1", "some other key"); - private static final MetricDescriptor METRIC_DESCRIPTOR_1 = - MetricDescriptor.create( - METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2)); - private static final MetricDescriptor METRIC_DESCRIPTOR_2 = - MetricDescriptor.create( - METRIC_NAME_2, DESCRIPTION, UNIT, Type.CUMULATIVE_INT64, Arrays.asList(KEY_1)); - private static final LabelValue LABEL_VALUE_1 = LabelValue.create("value1"); - private static final LabelValue LABEL_VALUE_2 = LabelValue.create("value1"); - private static final LabelValue LABEL_VALUE_EMPTY = LabelValue.create(""); - private static final Value VALUE_LONG = Value.longValue(12345678); - private static final Value VALUE_DOUBLE_1 = Value.doubleValue(-345.77); - private static final Value VALUE_DOUBLE_2 = Value.doubleValue(133.79); - private static final Timestamp TIMESTAMP_1 = Timestamp.fromMillis(1000); - private static final Timestamp TIMESTAMP_2 = Timestamp.fromMillis(2000); - private static final Timestamp TIMESTAMP_3 = Timestamp.fromMillis(3000); - private static final Point POINT_1 = Point.create(VALUE_DOUBLE_1, TIMESTAMP_2); - private static final Point POINT_2 = Point.create(VALUE_DOUBLE_2, TIMESTAMP_3); - private static final Point POINT_3 = Point.create(VALUE_LONG, TIMESTAMP_3); - private static final TimeSeries GAUGE_TIME_SERIES_1 = - TimeSeries.create(Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), null); - private static final TimeSeries GAUGE_TIME_SERIES_2 = - TimeSeries.create(Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_2), null); - private static final TimeSeries CUMULATIVE_TIME_SERIES = - TimeSeries.create(Arrays.asList(LABEL_VALUE_EMPTY), Arrays.asList(POINT_3), TIMESTAMP_1); - - @Test - public void testGet() { - Metric metric = - Metric.create(METRIC_DESCRIPTOR_1, Arrays.asList(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2)); - assertThat(metric.getMetricDescriptor()).isEqualTo(METRIC_DESCRIPTOR_1); - assertThat(metric.getTimeSeriesList()) - .containsExactly(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2) - .inOrder(); - } - - @Test - public void typeMismatch_GaugeDouble_Long() { - typeMismatch( - METRIC_DESCRIPTOR_1, - Arrays.asList(CUMULATIVE_TIME_SERIES), - String.format("Type mismatch: %s, %s.", Type.GAUGE_DOUBLE, "ValueLong")); - } - - @Test - public void typeMismatch_CumulativeInt64_Double() { - typeMismatch( - METRIC_DESCRIPTOR_2, - Arrays.asList(GAUGE_TIME_SERIES_1), - String.format("Type mismatch: %s, %s.", Type.CUMULATIVE_INT64, "ValueDouble")); - } - - private void typeMismatch( - MetricDescriptor metricDescriptor, List timeSeriesList, String errorMessage) { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage(errorMessage); - Metric.create(metricDescriptor, timeSeriesList); - } - - @Test - public void testEquals() { - new EqualsTester() - .addEqualityGroup( - Metric.create( - METRIC_DESCRIPTOR_1, Arrays.asList(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2)), - Metric.create( - METRIC_DESCRIPTOR_1, Arrays.asList(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2))) - .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_1, Collections.emptyList())) - .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_2, Arrays.asList(CUMULATIVE_TIME_SERIES))) - .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_2, Collections.emptyList())) - .testEquals(); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/PointTest.java b/api/src/test/java/io/opencensus/metrics/PointTest.java deleted file mode 100644 index 708814c5..00000000 --- a/api/src/test/java/io/opencensus/metrics/PointTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import io.opencensus.common.Timestamp; -import io.opencensus.metrics.Distribution.Bucket; -import java.util.Arrays; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link Point}. */ -@RunWith(JUnit4.class) -public class PointTest { - - private static final Value DOUBLE_VALUE = Value.doubleValue(55.5); - private static final Value LONG_VALUE = Value.longValue(9876543210L); - private static final Value DISTRIBUTION_VALUE = - Value.distributionValue( - Distribution.create( - 10, - 6.6, - 678.54, - Arrays.asList(-1.0, 0.0, 1.0), - Arrays.asList( - Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)))); - private static final Timestamp TIMESTAMP_1 = Timestamp.create(1, 2); - private static final Timestamp TIMESTAMP_2 = Timestamp.create(3, 4); - private static final Timestamp TIMESTAMP_3 = Timestamp.create(5, 6); - - @Test - public void testGet() { - Point point = Point.create(DOUBLE_VALUE, TIMESTAMP_1); - assertThat(point.getValue()).isEqualTo(DOUBLE_VALUE); - assertThat(point.getTimestamp()).isEqualTo(TIMESTAMP_1); - } - - @Test - public void testEquals() { - new EqualsTester() - .addEqualityGroup( - Point.create(DOUBLE_VALUE, TIMESTAMP_1), Point.create(DOUBLE_VALUE, TIMESTAMP_1)) - .addEqualityGroup(Point.create(LONG_VALUE, TIMESTAMP_1)) - .addEqualityGroup(Point.create(LONG_VALUE, TIMESTAMP_2)) - .addEqualityGroup( - Point.create(DISTRIBUTION_VALUE, TIMESTAMP_2), - Point.create(DISTRIBUTION_VALUE, TIMESTAMP_2)) - .addEqualityGroup(Point.create(DISTRIBUTION_VALUE, TIMESTAMP_3)) - .testEquals(); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/SummaryTest.java b/api/src/test/java/io/opencensus/metrics/SummaryTest.java deleted file mode 100644 index 0b70d94e..00000000 --- a/api/src/test/java/io/opencensus/metrics/SummaryTest.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import io.opencensus.metrics.Summary.Snapshot; -import io.opencensus.metrics.Summary.Snapshot.ValueAtPercentile; -import java.util.Collections; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link Summary}. */ -@RunWith(JUnit4.class) -public class SummaryTest { - - @Rule public final ExpectedException thrown = ExpectedException.none(); - private static final double TOLERANCE = 1e-6; - - @Test - public void createAndGet_ValueAtPercentile() { - ValueAtPercentile valueAtPercentile = ValueAtPercentile.create(99.5, 10.2); - assertThat(valueAtPercentile.getPercentile()).isWithin(TOLERANCE).of(99.5); - assertThat(valueAtPercentile.getValue()).isWithin(TOLERANCE).of(10.2); - } - - @Test - public void createValueAtPercentile_InvalidValueAtPercentileInterval() { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("percentile must be in the interval (0.0, 100.0]"); - ValueAtPercentile.create(100.1, 10.2); - } - - @Test - public void createValueAtPercentile_NegativeValue() { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("value must be non-negative"); - ValueAtPercentile.create(99.5, -10.2); - } - - @Test - public void createAndGet_Snapshot() { - Snapshot snapshot = - Snapshot.create( - 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))); - assertThat(snapshot.getCount()).isEqualTo(10); - assertThat(snapshot.getSum()).isWithin(TOLERANCE).of(87.07); - assertThat(snapshot.getValueAtPercentiles()) - .containsExactly(ValueAtPercentile.create(99.5, 10.2)); - } - - @Test - public void createAndGet_Snapshot_WithNullCountAndSum() { - Snapshot snapshot = - Snapshot.create( - null, null, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))); - assertThat(snapshot.getCount()).isNull(); - assertThat(snapshot.getSum()).isNull(); - assertThat(snapshot.getValueAtPercentiles()) - .containsExactly(ValueAtPercentile.create(99.5, 10.2)); - } - - @Test - public void createSnapshot_NegativeCount() { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("count must be non-negative"); - Snapshot.create(-10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))); - } - - @Test - public void createSnapshot_NegativeSum() { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("sum must be non-negative"); - Snapshot.create(10L, -87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))); - } - - @Test - public void createSnapshot_ZeroCountAndNonZeroSum() { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("sum must be 0 if count is 0"); - Snapshot.create(0L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))); - } - - @Test - public void createSnapshot_NullValueAtPercentilesList() { - thrown.expect(NullPointerException.class); - thrown.expectMessage("valueAtPercentiles"); - Snapshot.create(10L, 87.07, null); - } - - @Test - public void createSnapshot_OneNullValueAtPercentile() { - thrown.expect(NullPointerException.class); - thrown.expectMessage("value in valueAtPercentiles"); - Snapshot.create(10L, 87.07, Collections.singletonList(null)); - } - - @Test - public void createAndGet_Summary() { - Snapshot snapshot = - Snapshot.create( - 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))); - Summary summary = Summary.create(10L, 6.6, snapshot); - assertThat(summary.getCount()).isEqualTo(10); - assertThat(summary.getSum()).isWithin(TOLERANCE).of(6.6); - assertThat(summary.getSnapshot()).isEqualTo(snapshot); - } - - @Test - public void createSummary_NegativeCount() { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("count must be non-negative"); - Summary.create( - -10L, 6.6, Snapshot.create(null, null, Collections.emptyList())); - } - - @Test - public void createSummary_NegativeSum() { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("sum must be non-negative"); - Summary.create( - 10L, -6.6, Snapshot.create(null, null, Collections.emptyList())); - } - - @Test - public void createSummary_ZeroCountAndNonZeroSum() { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("sum must be 0 if count is 0"); - Summary.create( - 0L, 6.6, Snapshot.create(null, null, Collections.emptyList())); - } - - @Test - public void createSummary_NullSnapshot() { - thrown.expect(NullPointerException.class); - thrown.expectMessage("snapshot"); - Summary.create(10L, 6.6, null); - } - - @Test - public void testEquals() { - new EqualsTester() - .addEqualityGroup( - Summary.create( - 10L, - 10.0, - Snapshot.create( - 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)))), - Summary.create( - 10L, - 10.0, - Snapshot.create( - 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))))) - .addEqualityGroup( - Summary.create( - 7L, - 10.0, - Snapshot.create( - 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))))) - .addEqualityGroup( - Summary.create( - 10L, - 7.0, - Snapshot.create( - 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))))) - .addEqualityGroup( - Summary.create( - 10L, 10.0, Snapshot.create(null, null, Collections.emptyList()))) - .testEquals(); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/TimeSeriesTest.java b/api/src/test/java/io/opencensus/metrics/TimeSeriesTest.java deleted file mode 100644 index 07dff97d..00000000 --- a/api/src/test/java/io/opencensus/metrics/TimeSeriesTest.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import io.opencensus.common.Timestamp; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import org.hamcrest.CoreMatchers; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link TimeSeries}. */ -@RunWith(JUnit4.class) -public class TimeSeriesTest { - - @Rule public ExpectedException thrown = ExpectedException.none(); - - private static final LabelValue LABEL_VALUE_1 = LabelValue.create("value1"); - private static final LabelValue LABEL_VALUE_2 = LabelValue.create("value2"); - private static final Value VALUE_LONG = Value.longValue(12345678); - private static final Value VALUE_DOUBLE = Value.doubleValue(-345.77); - private static final Timestamp TIMESTAMP_1 = Timestamp.fromMillis(1000); - private static final Timestamp TIMESTAMP_2 = Timestamp.fromMillis(2000); - private static final Timestamp TIMESTAMP_3 = Timestamp.fromMillis(3000); - private static final Point POINT_1 = Point.create(VALUE_DOUBLE, TIMESTAMP_2); - private static final Point POINT_2 = Point.create(VALUE_LONG, TIMESTAMP_3); - - @Test - public void testGet_TimeSeries() { - TimeSeries cumulativeTimeSeries = - TimeSeries.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1); - assertThat(cumulativeTimeSeries.getStartTimestamp()).isEqualTo(TIMESTAMP_1); - assertThat(cumulativeTimeSeries.getLabelValues()) - .containsExactly(LABEL_VALUE_1, LABEL_VALUE_2) - .inOrder(); - assertThat(cumulativeTimeSeries.getPoints()).containsExactly(POINT_1).inOrder(); - } - - @Test - public void create_WithNullLabelValueList() { - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("labelValues")); - TimeSeries.create(null, Collections.emptyList(), TIMESTAMP_1); - } - - @Test - public void create_WithNullLabelValue() { - List labelValues = Arrays.asList(LABEL_VALUE_1, null); - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("labelValue")); - TimeSeries.create(labelValues, Collections.emptyList(), TIMESTAMP_1); - } - - @Test - public void create_WithNullPointList() { - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("points")); - TimeSeries.create(Collections.emptyList(), null, TIMESTAMP_1); - } - - @Test - public void create_WithNullPoint() { - List points = Arrays.asList(POINT_1, null); - thrown.expect(NullPointerException.class); - thrown.expectMessage(CoreMatchers.equalTo("point")); - TimeSeries.create(Collections.emptyList(), points, TIMESTAMP_1); - } - - @Test - public void testEquals() { - new EqualsTester() - .addEqualityGroup( - TimeSeries.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1), - TimeSeries.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1)) - .addEqualityGroup( - TimeSeries.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), null), - TimeSeries.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), null)) - .addEqualityGroup( - TimeSeries.create( - Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_2)) - .addEqualityGroup( - TimeSeries.create(Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_1), TIMESTAMP_2)) - .addEqualityGroup( - TimeSeries.create(Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_2), TIMESTAMP_2)) - .addEqualityGroup( - TimeSeries.create( - Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_1, POINT_2), TIMESTAMP_2)) - .testEquals(); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/ValueTest.java b/api/src/test/java/io/opencensus/metrics/ValueTest.java deleted file mode 100644 index a65202a8..00000000 --- a/api/src/test/java/io/opencensus/metrics/ValueTest.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2018, 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.metrics; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.common.testing.EqualsTester; -import io.opencensus.common.Function; -import io.opencensus.common.Functions; -import io.opencensus.metrics.Distribution.Bucket; -import io.opencensus.metrics.Summary.Snapshot; -import io.opencensus.metrics.Summary.Snapshot.ValueAtPercentile; -import io.opencensus.metrics.Value.ValueDistribution; -import io.opencensus.metrics.Value.ValueDouble; -import io.opencensus.metrics.Value.ValueLong; -import io.opencensus.metrics.Value.ValueSummary; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link Value}. */ -@RunWith(JUnit4.class) -public class ValueTest { - private static final double TOLERANCE = 1e-6; - - private static final Distribution DISTRIBUTION = - Distribution.create( - 10, - 10, - 1, - Arrays.asList(-5.0, 0.0, 5.0), - Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))); - private static final Summary SUMMARY = - Summary.create( - 10L, - 10.0, - Snapshot.create( - 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(0.98, 10.2)))); - - @Test - public void createAndGet_ValueDouble() { - Value value = Value.doubleValue(-34.56); - assertThat(value).isInstanceOf(ValueDouble.class); - assertThat(((ValueDouble) value).getValue()).isWithin(TOLERANCE).of(-34.56); - } - - @Test - public void createAndGet_ValueLong() { - Value value = Value.longValue(123456789); - assertThat(value).isInstanceOf(ValueLong.class); - assertThat(((ValueLong) value).getValue()).isEqualTo(123456789); - } - - @Test - public void createAndGet_ValueDistribution() { - Value value = Value.distributionValue(DISTRIBUTION); - assertThat(value).isInstanceOf(ValueDistribution.class); - assertThat(((ValueDistribution) value).getValue()).isEqualTo(DISTRIBUTION); - } - - @Test - public void createAndGet_ValueSummary() { - Value value = Value.summaryValue(SUMMARY); - assertThat(value).isInstanceOf(ValueSummary.class); - assertThat(((ValueSummary) value).getValue()).isEqualTo(SUMMARY); - } - - @Test - public void testEquals() { - new EqualsTester() - .addEqualityGroup(Value.doubleValue(1.0), Value.doubleValue(1.0)) - .addEqualityGroup(Value.doubleValue(2.0)) - .addEqualityGroup(Value.longValue(1L)) - .addEqualityGroup(Value.longValue(2L)) - .addEqualityGroup( - Value.distributionValue( - Distribution.create( - 7, - 10, - 23.456, - Arrays.asList(-5.0, 0.0, 5.0), - Arrays.asList( - Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))))) - .testEquals(); - } - - @Test - public void testMatch() { - List values = - Arrays.asList( - ValueDouble.create(1.0), - ValueLong.create(-1), - ValueDistribution.create(DISTRIBUTION), - ValueSummary.create(SUMMARY)); - List expected = - Arrays.asList(1.0, -1L, 10.0, 10L, 1.0, -5.0, 0.0, 5.0, 3L, 1L, 2L, 4L); - final List actual = new ArrayList(); - for (Value value : values) { - value.match( - new Function() { - @Override - public Object apply(Double arg) { - actual.add(arg); - return null; - } - }, - new Function() { - @Override - public Object apply(Long arg) { - actual.add(arg); - return null; - } - }, - new Function() { - @Override - public Object apply(Distribution arg) { - actual.add(arg.getSum()); - actual.add(arg.getCount()); - actual.add(arg.getSumOfSquaredDeviations()); - actual.addAll(arg.getBucketBoundaries()); - for (Bucket bucket : arg.getBuckets()) { - actual.add(bucket.getCount()); - } - return null; - } - }, - new Function() { - @Override - public Object apply(Summary arg) { - return null; - } - }, - Functions.throwAssertionError()); - } - assertThat(actual).containsExactlyElementsIn(expected).inOrder(); - } -} diff --git a/api/src/test/java/io/opencensus/metrics/export/DistributionTest.java b/api/src/test/java/io/opencensus/metrics/export/DistributionTest.java new file mode 100644 index 00000000..0be4b5d1 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/export/DistributionTest.java @@ -0,0 +1,227 @@ +/* + * Copyright 2018, 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.metrics.export; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Timestamp; +import io.opencensus.metrics.export.Distribution.Bucket; +import io.opencensus.metrics.export.Distribution.Exemplar; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Distribution}. */ +@RunWith(JUnit4.class) +public class DistributionTest { + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + private static final Timestamp TIMESTAMP = Timestamp.create(1, 0); + private static final Map ATTACHMENTS = Collections.singletonMap("key", "value"); + private static final double TOLERANCE = 1e-6; + + @Test + public void createAndGet_Bucket() { + Bucket bucket = Bucket.create(98); + assertThat(bucket.getCount()).isEqualTo(98); + assertThat(bucket.getExemplar()).isNull(); + } + + @Test + public void createAndGet_BucketWithExemplar() { + Exemplar exemplar = Exemplar.create(12.2, TIMESTAMP, ATTACHMENTS); + Bucket bucket = Bucket.create(7, exemplar); + assertThat(bucket.getCount()).isEqualTo(7); + assertThat(bucket.getExemplar()).isEqualTo(exemplar); + } + + @Test + public void createBucket_preventNullExemplar() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("exemplar"); + Bucket.create(1, null); + } + + @Test + public void createAndGet_Exemplar() { + Exemplar exemplar = Exemplar.create(-9.9, TIMESTAMP, ATTACHMENTS); + assertThat(exemplar.getValue()).isWithin(TOLERANCE).of(-9.9); + assertThat(exemplar.getTimestamp()).isEqualTo(TIMESTAMP); + assertThat(exemplar.getAttachments()).isEqualTo(ATTACHMENTS); + } + + @Test + public void createAndGet_Distribution() { + Exemplar exemplar = Exemplar.create(15.0, TIMESTAMP, ATTACHMENTS); + List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List buckets = + Arrays.asList( + Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4, exemplar)); + Distribution distribution = Distribution.create(10, 6.6, 678.54, bucketBounds, buckets); + assertThat(distribution.getCount()).isEqualTo(10); + assertThat(distribution.getSum()).isWithin(TOLERANCE).of(6.6); + assertThat(distribution.getSumOfSquaredDeviations()).isWithin(TOLERANCE).of(678.54); + assertThat(distribution.getBucketBoundaries()) + .containsExactlyElementsIn(bucketBounds) + .inOrder(); + assertThat(distribution.getBuckets()).containsExactlyElementsIn(buckets).inOrder(); + } + + @Test + public void createBucket_NegativeCount() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("bucket count should be non-negative."); + Bucket.create(-5); + } + + @Test + public void createExemplar_PreventNullAttachments() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("attachments"); + Exemplar.create(15, TIMESTAMP, null); + } + + @Test + public void createExemplar_PreventNullAttachmentKey() { + Map attachments = Collections.singletonMap(null, "value"); + thrown.expect(NullPointerException.class); + thrown.expectMessage("key of attachment"); + Exemplar.create(15, TIMESTAMP, attachments); + } + + @Test + public void createExemplar_PreventNullAttachmentValue() { + Map attachments = Collections.singletonMap("key", null); + thrown.expect(NullPointerException.class); + thrown.expectMessage("value of attachment"); + Exemplar.create(15, TIMESTAMP, attachments); + } + + @Test + public void createDistribution_NegativeCount() { + List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List buckets = + Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("count should be non-negative."); + Distribution.create(-10, 6.6, 678.54, bucketBounds, buckets); + } + + @Test + public void createDistribution_NegativeSumOfSquaredDeviations() { + List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List buckets = + Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0)); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("sum of squared deviations should be non-negative."); + Distribution.create(0, 6.6, -678.54, bucketBounds, buckets); + } + + @Test + public void createDistribution_ZeroCountAndPositiveMean() { + List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List buckets = + Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0)); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("sum should be 0 if count is 0."); + Distribution.create(0, 6.6, 0, bucketBounds, buckets); + } + + @Test + public void createDistribution_ZeroCountAndSumOfSquaredDeviations() { + List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List buckets = + Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0)); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("sum of squared deviations should be 0 if count is 0."); + Distribution.create(0, 0, 678.54, bucketBounds, buckets); + } + + @Test + public void createDistribution_NullBucketBounds() { + List buckets = + Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); + thrown.expect(NullPointerException.class); + thrown.expectMessage("bucketBoundaries list should not be null."); + Distribution.create(10, 6.6, 678.54, null, buckets); + } + + @Test + public void createDistribution_UnorderedBucketBounds() { + List bucketBounds = Arrays.asList(0.0, -1.0, 1.0); + List buckets = + Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("bucket boundaries not sorted."); + Distribution.create(10, 6.6, 678.54, bucketBounds, buckets); + } + + @Test + public void createDistribution_NullBucketList() { + List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + thrown.expect(NullPointerException.class); + thrown.expectMessage("bucket list should not be null."); + Distribution.create(10, 6.6, 678.54, bucketBounds, null); + } + + @Test + public void createDistribution_NullBucket() { + List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List buckets = + Arrays.asList(Bucket.create(3), Bucket.create(1), null, Bucket.create(4)); + thrown.expect(NullPointerException.class); + thrown.expectMessage("bucket should not be null."); + Distribution.create(10, 6.6, 678.54, bucketBounds, buckets); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + Distribution.create( + 10, + 10, + 1, + Arrays.asList(-5.0, 0.0, 5.0), + Arrays.asList( + Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))), + Distribution.create( + 10, + 10, + 1, + Arrays.asList(-5.0, 0.0, 5.0), + Arrays.asList( + Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)))) + .addEqualityGroup( + Distribution.create( + 7, + 10, + 23.456, + Arrays.asList(-5.0, 0.0, 5.0), + Arrays.asList( + Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)))) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/export/MetricDescriptorTest.java b/api/src/test/java/io/opencensus/metrics/export/MetricDescriptorTest.java new file mode 100644 index 00000000..502170c6 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/export/MetricDescriptorTest.java @@ -0,0 +1,103 @@ +/* + * Copyright 2018, 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.metrics.export; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.metrics.LabelKey; +import io.opencensus.metrics.export.MetricDescriptor.Type; +import java.util.Arrays; +import java.util.List; +import org.hamcrest.CoreMatchers; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link MetricDescriptor}. */ +@RunWith(JUnit4.class) +public class MetricDescriptorTest { + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + private static final String METRIC_NAME_1 = "metric1"; + private static final String METRIC_NAME_2 = "metric2"; + private static final String DESCRIPTION = "Metric description."; + private static final String UNIT = "kb/s"; + private static final LabelKey KEY_1 = LabelKey.create("key1", "some key"); + private static final LabelKey KEY_2 = LabelKey.create("key2", "some other key"); + + @Test + public void testGet() { + MetricDescriptor metricDescriptor = + MetricDescriptor.create( + METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2)); + assertThat(metricDescriptor.getName()).isEqualTo(METRIC_NAME_1); + assertThat(metricDescriptor.getDescription()).isEqualTo(DESCRIPTION); + assertThat(metricDescriptor.getUnit()).isEqualTo(UNIT); + assertThat(metricDescriptor.getType()).isEqualTo(Type.GAUGE_DOUBLE); + assertThat(metricDescriptor.getLabelKeys()).containsExactly(KEY_1, KEY_2).inOrder(); + } + + @Test + public void preventNullLabelKeyList() { + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("labelKeys")); + MetricDescriptor.create(METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, null); + } + + @Test + public void preventNullLabelKey() { + List keys = Arrays.asList(KEY_1, null); + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("labelKey")); + MetricDescriptor.create(METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, keys); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + MetricDescriptor.create( + METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2)), + MetricDescriptor.create( + METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2))) + .addEqualityGroup( + MetricDescriptor.create( + METRIC_NAME_2, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2))) + .addEqualityGroup( + MetricDescriptor.create( + METRIC_NAME_2, DESCRIPTION, UNIT, Type.GAUGE_INT64, Arrays.asList(KEY_1, KEY_2))) + .addEqualityGroup( + MetricDescriptor.create( + METRIC_NAME_1, + DESCRIPTION, + UNIT, + Type.CUMULATIVE_DISTRIBUTION, + Arrays.asList(KEY_1, KEY_2))) + .addEqualityGroup( + MetricDescriptor.create( + METRIC_NAME_1, + DESCRIPTION, + UNIT, + Type.CUMULATIVE_DISTRIBUTION, + Arrays.asList(KEY_1))) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java b/api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java index 07854927..1025427f 100644 --- a/api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java +++ b/api/src/test/java/io/opencensus/metrics/export/MetricProducerManagerTest.java @@ -18,7 +18,6 @@ package io.opencensus.metrics.export; import static com.google.common.truth.Truth.assertThat; -import io.opencensus.metrics.MetricProducer; import org.junit.Before; import org.junit.Rule; import org.junit.Test; diff --git a/api/src/test/java/io/opencensus/metrics/export/MetricTest.java b/api/src/test/java/io/opencensus/metrics/export/MetricTest.java new file mode 100644 index 00000000..0b1ecf65 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/export/MetricTest.java @@ -0,0 +1,118 @@ +/* + * Copyright 2018, 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.metrics.export; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Timestamp; +import io.opencensus.metrics.LabelKey; +import io.opencensus.metrics.LabelValue; +import io.opencensus.metrics.export.MetricDescriptor.Type; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Metric}. */ +@RunWith(JUnit4.class) +public class MetricTest { + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + private static final String METRIC_NAME_1 = "metric1"; + private static final String METRIC_NAME_2 = "metric2"; + private static final String DESCRIPTION = "Metric description."; + private static final String UNIT = "kb/s"; + private static final LabelKey KEY_1 = LabelKey.create("key1", "some key"); + private static final LabelKey KEY_2 = LabelKey.create("key1", "some other key"); + private static final MetricDescriptor METRIC_DESCRIPTOR_1 = + MetricDescriptor.create( + METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2)); + private static final MetricDescriptor METRIC_DESCRIPTOR_2 = + MetricDescriptor.create( + METRIC_NAME_2, DESCRIPTION, UNIT, Type.CUMULATIVE_INT64, Arrays.asList(KEY_1)); + private static final LabelValue LABEL_VALUE_1 = LabelValue.create("value1"); + private static final LabelValue LABEL_VALUE_2 = LabelValue.create("value1"); + private static final LabelValue LABEL_VALUE_EMPTY = LabelValue.create(""); + private static final Value VALUE_LONG = Value.longValue(12345678); + private static final Value VALUE_DOUBLE_1 = Value.doubleValue(-345.77); + private static final Value VALUE_DOUBLE_2 = Value.doubleValue(133.79); + private static final Timestamp TIMESTAMP_1 = Timestamp.fromMillis(1000); + private static final Timestamp TIMESTAMP_2 = Timestamp.fromMillis(2000); + private static final Timestamp TIMESTAMP_3 = Timestamp.fromMillis(3000); + private static final Point POINT_1 = Point.create(VALUE_DOUBLE_1, TIMESTAMP_2); + private static final Point POINT_2 = Point.create(VALUE_DOUBLE_2, TIMESTAMP_3); + private static final Point POINT_3 = Point.create(VALUE_LONG, TIMESTAMP_3); + private static final TimeSeries GAUGE_TIME_SERIES_1 = + TimeSeries.create(Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), null); + private static final TimeSeries GAUGE_TIME_SERIES_2 = + TimeSeries.create(Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_2), null); + private static final TimeSeries CUMULATIVE_TIME_SERIES = + TimeSeries.create(Arrays.asList(LABEL_VALUE_EMPTY), Arrays.asList(POINT_3), TIMESTAMP_1); + + @Test + public void testGet() { + Metric metric = + Metric.create(METRIC_DESCRIPTOR_1, Arrays.asList(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2)); + assertThat(metric.getMetricDescriptor()).isEqualTo(METRIC_DESCRIPTOR_1); + assertThat(metric.getTimeSeriesList()) + .containsExactly(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2) + .inOrder(); + } + + @Test + public void typeMismatch_GaugeDouble_Long() { + typeMismatch( + METRIC_DESCRIPTOR_1, + Arrays.asList(CUMULATIVE_TIME_SERIES), + String.format("Type mismatch: %s, %s.", Type.GAUGE_DOUBLE, "ValueLong")); + } + + @Test + public void typeMismatch_CumulativeInt64_Double() { + typeMismatch( + METRIC_DESCRIPTOR_2, + Arrays.asList(GAUGE_TIME_SERIES_1), + String.format("Type mismatch: %s, %s.", Type.CUMULATIVE_INT64, "ValueDouble")); + } + + private void typeMismatch( + MetricDescriptor metricDescriptor, List timeSeriesList, String errorMessage) { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage(errorMessage); + Metric.create(metricDescriptor, timeSeriesList); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + Metric.create( + METRIC_DESCRIPTOR_1, Arrays.asList(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2)), + Metric.create( + METRIC_DESCRIPTOR_1, Arrays.asList(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2))) + .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_1, Collections.emptyList())) + .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_2, Arrays.asList(CUMULATIVE_TIME_SERIES))) + .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_2, Collections.emptyList())) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/export/PointTest.java b/api/src/test/java/io/opencensus/metrics/export/PointTest.java new file mode 100644 index 00000000..da5b83dc --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/export/PointTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 2018, 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.metrics.export; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Timestamp; +import io.opencensus.metrics.export.Distribution.Bucket; +import java.util.Arrays; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Point}. */ +@RunWith(JUnit4.class) +public class PointTest { + + private static final Value DOUBLE_VALUE = Value.doubleValue(55.5); + private static final Value LONG_VALUE = Value.longValue(9876543210L); + private static final Value DISTRIBUTION_VALUE = + Value.distributionValue( + Distribution.create( + 10, + 6.6, + 678.54, + Arrays.asList(-1.0, 0.0, 1.0), + Arrays.asList( + Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)))); + private static final Timestamp TIMESTAMP_1 = Timestamp.create(1, 2); + private static final Timestamp TIMESTAMP_2 = Timestamp.create(3, 4); + private static final Timestamp TIMESTAMP_3 = Timestamp.create(5, 6); + + @Test + public void testGet() { + Point point = Point.create(DOUBLE_VALUE, TIMESTAMP_1); + assertThat(point.getValue()).isEqualTo(DOUBLE_VALUE); + assertThat(point.getTimestamp()).isEqualTo(TIMESTAMP_1); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + Point.create(DOUBLE_VALUE, TIMESTAMP_1), Point.create(DOUBLE_VALUE, TIMESTAMP_1)) + .addEqualityGroup(Point.create(LONG_VALUE, TIMESTAMP_1)) + .addEqualityGroup(Point.create(LONG_VALUE, TIMESTAMP_2)) + .addEqualityGroup( + Point.create(DISTRIBUTION_VALUE, TIMESTAMP_2), + Point.create(DISTRIBUTION_VALUE, TIMESTAMP_2)) + .addEqualityGroup(Point.create(DISTRIBUTION_VALUE, TIMESTAMP_3)) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/export/SummaryTest.java b/api/src/test/java/io/opencensus/metrics/export/SummaryTest.java new file mode 100644 index 00000000..c10df043 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/export/SummaryTest.java @@ -0,0 +1,189 @@ +/* + * Copyright 2018, 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.metrics.export; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.metrics.export.Summary.Snapshot; +import io.opencensus.metrics.export.Summary.Snapshot.ValueAtPercentile; +import java.util.Collections; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Summary}. */ +@RunWith(JUnit4.class) +public class SummaryTest { + + @Rule public final ExpectedException thrown = ExpectedException.none(); + private static final double TOLERANCE = 1e-6; + + @Test + public void createAndGet_ValueAtPercentile() { + ValueAtPercentile valueAtPercentile = ValueAtPercentile.create(99.5, 10.2); + assertThat(valueAtPercentile.getPercentile()).isWithin(TOLERANCE).of(99.5); + assertThat(valueAtPercentile.getValue()).isWithin(TOLERANCE).of(10.2); + } + + @Test + public void createValueAtPercentile_InvalidValueAtPercentileInterval() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("percentile must be in the interval (0.0, 100.0]"); + ValueAtPercentile.create(100.1, 10.2); + } + + @Test + public void createValueAtPercentile_NegativeValue() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("value must be non-negative"); + ValueAtPercentile.create(99.5, -10.2); + } + + @Test + public void createAndGet_Snapshot() { + Snapshot snapshot = + Snapshot.create( + 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))); + assertThat(snapshot.getCount()).isEqualTo(10); + assertThat(snapshot.getSum()).isWithin(TOLERANCE).of(87.07); + assertThat(snapshot.getValueAtPercentiles()) + .containsExactly(ValueAtPercentile.create(99.5, 10.2)); + } + + @Test + public void createAndGet_Snapshot_WithNullCountAndSum() { + Snapshot snapshot = + Snapshot.create( + null, null, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))); + assertThat(snapshot.getCount()).isNull(); + assertThat(snapshot.getSum()).isNull(); + assertThat(snapshot.getValueAtPercentiles()) + .containsExactly(ValueAtPercentile.create(99.5, 10.2)); + } + + @Test + public void createSnapshot_NegativeCount() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("count must be non-negative"); + Snapshot.create(-10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))); + } + + @Test + public void createSnapshot_NegativeSum() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("sum must be non-negative"); + Snapshot.create(10L, -87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))); + } + + @Test + public void createSnapshot_ZeroCountAndNonZeroSum() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("sum must be 0 if count is 0"); + Snapshot.create(0L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))); + } + + @Test + public void createSnapshot_NullValueAtPercentilesList() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("valueAtPercentiles"); + Snapshot.create(10L, 87.07, null); + } + + @Test + public void createSnapshot_OneNullValueAtPercentile() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("value in valueAtPercentiles"); + Snapshot.create(10L, 87.07, Collections.singletonList(null)); + } + + @Test + public void createAndGet_Summary() { + Snapshot snapshot = + Snapshot.create( + 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))); + Summary summary = Summary.create(10L, 6.6, snapshot); + assertThat(summary.getCount()).isEqualTo(10); + assertThat(summary.getSum()).isWithin(TOLERANCE).of(6.6); + assertThat(summary.getSnapshot()).isEqualTo(snapshot); + } + + @Test + public void createSummary_NegativeCount() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("count must be non-negative"); + Summary.create( + -10L, 6.6, Snapshot.create(null, null, Collections.emptyList())); + } + + @Test + public void createSummary_NegativeSum() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("sum must be non-negative"); + Summary.create( + 10L, -6.6, Snapshot.create(null, null, Collections.emptyList())); + } + + @Test + public void createSummary_ZeroCountAndNonZeroSum() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("sum must be 0 if count is 0"); + Summary.create( + 0L, 6.6, Snapshot.create(null, null, Collections.emptyList())); + } + + @Test + public void createSummary_NullSnapshot() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("snapshot"); + Summary.create(10L, 6.6, null); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + Summary.create( + 10L, + 10.0, + Snapshot.create( + 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)))), + Summary.create( + 10L, + 10.0, + Snapshot.create( + 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))))) + .addEqualityGroup( + Summary.create( + 7L, + 10.0, + Snapshot.create( + 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))))) + .addEqualityGroup( + Summary.create( + 10L, + 7.0, + Snapshot.create( + 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2))))) + .addEqualityGroup( + Summary.create( + 10L, 10.0, Snapshot.create(null, null, Collections.emptyList()))) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/export/TimeSeriesTest.java b/api/src/test/java/io/opencensus/metrics/export/TimeSeriesTest.java new file mode 100644 index 00000000..31812549 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/export/TimeSeriesTest.java @@ -0,0 +1,117 @@ +/* + * Copyright 2018, 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.metrics.export; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Timestamp; +import io.opencensus.metrics.LabelValue; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.hamcrest.CoreMatchers; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link TimeSeries}. */ +@RunWith(JUnit4.class) +public class TimeSeriesTest { + + @Rule public ExpectedException thrown = ExpectedException.none(); + + private static final LabelValue LABEL_VALUE_1 = LabelValue.create("value1"); + private static final LabelValue LABEL_VALUE_2 = LabelValue.create("value2"); + private static final Value VALUE_LONG = Value.longValue(12345678); + private static final Value VALUE_DOUBLE = Value.doubleValue(-345.77); + private static final Timestamp TIMESTAMP_1 = Timestamp.fromMillis(1000); + private static final Timestamp TIMESTAMP_2 = Timestamp.fromMillis(2000); + private static final Timestamp TIMESTAMP_3 = Timestamp.fromMillis(3000); + private static final Point POINT_1 = Point.create(VALUE_DOUBLE, TIMESTAMP_2); + private static final Point POINT_2 = Point.create(VALUE_LONG, TIMESTAMP_3); + + @Test + public void testGet_TimeSeries() { + TimeSeries cumulativeTimeSeries = + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1); + assertThat(cumulativeTimeSeries.getStartTimestamp()).isEqualTo(TIMESTAMP_1); + assertThat(cumulativeTimeSeries.getLabelValues()) + .containsExactly(LABEL_VALUE_1, LABEL_VALUE_2) + .inOrder(); + assertThat(cumulativeTimeSeries.getPoints()).containsExactly(POINT_1).inOrder(); + } + + @Test + public void create_WithNullLabelValueList() { + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("labelValues")); + TimeSeries.create(null, Collections.emptyList(), TIMESTAMP_1); + } + + @Test + public void create_WithNullLabelValue() { + List labelValues = Arrays.asList(LABEL_VALUE_1, null); + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("labelValue")); + TimeSeries.create(labelValues, Collections.emptyList(), TIMESTAMP_1); + } + + @Test + public void create_WithNullPointList() { + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("points")); + TimeSeries.create(Collections.emptyList(), null, TIMESTAMP_1); + } + + @Test + public void create_WithNullPoint() { + List points = Arrays.asList(POINT_1, null); + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("point")); + TimeSeries.create(Collections.emptyList(), points, TIMESTAMP_1); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup( + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1), + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_1)) + .addEqualityGroup( + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), null), + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), null)) + .addEqualityGroup( + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), TIMESTAMP_2)) + .addEqualityGroup( + TimeSeries.create(Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_1), TIMESTAMP_2)) + .addEqualityGroup( + TimeSeries.create(Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_2), TIMESTAMP_2)) + .addEqualityGroup( + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1), Arrays.asList(POINT_1, POINT_2), TIMESTAMP_2)) + .testEquals(); + } +} diff --git a/api/src/test/java/io/opencensus/metrics/export/ValueTest.java b/api/src/test/java/io/opencensus/metrics/export/ValueTest.java new file mode 100644 index 00000000..3758ed2d --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/export/ValueTest.java @@ -0,0 +1,155 @@ +/* + * Copyright 2018, 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.metrics.export; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.testing.EqualsTester; +import io.opencensus.common.Function; +import io.opencensus.common.Functions; +import io.opencensus.metrics.export.Distribution.Bucket; +import io.opencensus.metrics.export.Summary.Snapshot; +import io.opencensus.metrics.export.Summary.Snapshot.ValueAtPercentile; +import io.opencensus.metrics.export.Value.ValueDistribution; +import io.opencensus.metrics.export.Value.ValueDouble; +import io.opencensus.metrics.export.Value.ValueLong; +import io.opencensus.metrics.export.Value.ValueSummary; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Value}. */ +@RunWith(JUnit4.class) +public class ValueTest { + private static final double TOLERANCE = 1e-6; + + private static final Distribution DISTRIBUTION = + Distribution.create( + 10, + 10, + 1, + Arrays.asList(-5.0, 0.0, 5.0), + Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))); + private static final Summary SUMMARY = + Summary.create( + 10L, + 10.0, + Snapshot.create( + 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(0.98, 10.2)))); + + @Test + public void createAndGet_ValueDouble() { + Value value = Value.doubleValue(-34.56); + assertThat(value).isInstanceOf(ValueDouble.class); + assertThat(((ValueDouble) value).getValue()).isWithin(TOLERANCE).of(-34.56); + } + + @Test + public void createAndGet_ValueLong() { + Value value = Value.longValue(123456789); + assertThat(value).isInstanceOf(ValueLong.class); + assertThat(((ValueLong) value).getValue()).isEqualTo(123456789); + } + + @Test + public void createAndGet_ValueDistribution() { + Value value = Value.distributionValue(DISTRIBUTION); + assertThat(value).isInstanceOf(ValueDistribution.class); + assertThat(((ValueDistribution) value).getValue()).isEqualTo(DISTRIBUTION); + } + + @Test + public void createAndGet_ValueSummary() { + Value value = Value.summaryValue(SUMMARY); + assertThat(value).isInstanceOf(ValueSummary.class); + assertThat(((ValueSummary) value).getValue()).isEqualTo(SUMMARY); + } + + @Test + public void testEquals() { + new EqualsTester() + .addEqualityGroup(Value.doubleValue(1.0), Value.doubleValue(1.0)) + .addEqualityGroup(Value.doubleValue(2.0)) + .addEqualityGroup(Value.longValue(1L)) + .addEqualityGroup(Value.longValue(2L)) + .addEqualityGroup( + Value.distributionValue( + Distribution.create( + 7, + 10, + 23.456, + Arrays.asList(-5.0, 0.0, 5.0), + Arrays.asList( + Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))))) + .testEquals(); + } + + @Test + public void testMatch() { + List values = + Arrays.asList( + ValueDouble.create(1.0), + ValueLong.create(-1), + ValueDistribution.create(DISTRIBUTION), + ValueSummary.create(SUMMARY)); + List expected = + Arrays.asList(1.0, -1L, 10.0, 10L, 1.0, -5.0, 0.0, 5.0, 3L, 1L, 2L, 4L); + final List actual = new ArrayList(); + for (Value value : values) { + value.match( + new Function() { + @Override + public Object apply(Double arg) { + actual.add(arg); + return null; + } + }, + new Function() { + @Override + public Object apply(Long arg) { + actual.add(arg); + return null; + } + }, + new Function() { + @Override + public Object apply(Distribution arg) { + actual.add(arg.getSum()); + actual.add(arg.getCount()); + actual.add(arg.getSumOfSquaredDeviations()); + actual.addAll(arg.getBucketBoundaries()); + for (Bucket bucket : arg.getBuckets()) { + actual.add(bucket.getCount()); + } + return null; + } + }, + new Function() { + @Override + public Object apply(Summary arg) { + return null; + } + }, + Functions.throwAssertionError()); + } + assertThat(actual).containsExactlyElementsIn(expected).inOrder(); + } +} -- cgit v1.2.3 From e3b2074a090836985307123517fd2d361c4b503c Mon Sep 17 00:00:00 2001 From: Yang Song Date: Tue, 9 Oct 2018 18:32:38 -0700 Subject: Metrics: Copy TimeSeries list when creating a Metric. (#1485) * Metrics: Copy TimeSeries list when creating a Metric. * Check for null and add more tests. --- .../java/io/opencensus/metrics/export/Metric.java | 8 +++++- .../io/opencensus/metrics/export/MetricTest.java | 31 ++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/metrics/export/Metric.java b/api/src/main/java/io/opencensus/metrics/export/Metric.java index 07fe356a..5e2fa5e8 100644 --- a/api/src/main/java/io/opencensus/metrics/export/Metric.java +++ b/api/src/main/java/io/opencensus/metrics/export/Metric.java @@ -23,6 +23,8 @@ import io.opencensus.metrics.export.Value.ValueDistribution; import io.opencensus.metrics.export.Value.ValueDouble; import io.opencensus.metrics.export.Value.ValueLong; import io.opencensus.metrics.export.Value.ValueSummary; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import javax.annotation.concurrent.Immutable; @@ -47,8 +49,12 @@ public abstract class Metric { * @since 0.17 */ public static Metric create(MetricDescriptor metricDescriptor, List timeSeriesList) { + Utils.checkNotNull(metricDescriptor, "metricDescriptor"); + Utils.checkNotNull(timeSeriesList, "timeSeriesList"); + Utils.checkListElementNotNull(timeSeriesList, "timeSeries"); checkTypeMatch(metricDescriptor.getType(), timeSeriesList); - return new AutoValue_Metric(metricDescriptor, timeSeriesList); + return new AutoValue_Metric( + metricDescriptor, Collections.unmodifiableList(new ArrayList(timeSeriesList))); } /** diff --git a/api/src/test/java/io/opencensus/metrics/export/MetricTest.java b/api/src/test/java/io/opencensus/metrics/export/MetricTest.java index 0b1ecf65..52fa2c47 100644 --- a/api/src/test/java/io/opencensus/metrics/export/MetricTest.java +++ b/api/src/test/java/io/opencensus/metrics/export/MetricTest.java @@ -23,6 +23,7 @@ import io.opencensus.common.Timestamp; import io.opencensus.metrics.LabelKey; import io.opencensus.metrics.LabelValue; import io.opencensus.metrics.export.MetricDescriptor.Type; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -102,6 +103,36 @@ public class MetricTest { Metric.create(metricDescriptor, timeSeriesList); } + @Test + public void create_WithNullMetricDescriptor() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("metricDescriptor"); + Metric.create(null, Collections.emptyList()); + } + + @Test + public void create_WithNullTimeSeriesList() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("timeSeriesList"); + Metric.create(METRIC_DESCRIPTOR_1, null); + } + + @Test + public void create_WithNullTimeSeries() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("timeSeries"); + Metric.create(METRIC_DESCRIPTOR_1, Arrays.asList(GAUGE_TIME_SERIES_1, null)); + } + + @Test + public void immutableTimeSeriesList() { + List timeSeriesList = new ArrayList(); + timeSeriesList.add(GAUGE_TIME_SERIES_1); + Metric metric = Metric.create(METRIC_DESCRIPTOR_1, timeSeriesList); + timeSeriesList.add(GAUGE_TIME_SERIES_2); + assertThat(metric.getTimeSeriesList()).containsExactly(GAUGE_TIME_SERIES_1); + } + @Test public void testEquals() { new EqualsTester() -- cgit v1.2.3 From 9c4df3dbe085a70850cc466849d33d90ffa846f4 Mon Sep 17 00:00:00 2001 From: Mayur Kale Date: Wed, 10 Oct 2018 12:31:51 -0700 Subject: =?UTF-8?q?Metrics/TimeSeries:=20Add=20createWithOnePoint=20method?= =?UTF-8?q?=20to=20accept=20only=20one=20=E2=80=A6=20(#1486)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Metrics/TimeSeries: Add createWithOnePoint method to accept only one point * Fix reviews * Minor Fix --- .../io/opencensus/metrics/export/TimeSeries.java | 37 ++++++++++++++++++++-- .../opencensus/metrics/export/TimeSeriesTest.java | 34 ++++++++++++++++++++ 2 files changed, 68 insertions(+), 3 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/metrics/export/TimeSeries.java b/api/src/main/java/io/opencensus/metrics/export/TimeSeries.java index 959f55ba..bfaeae98 100644 --- a/api/src/main/java/io/opencensus/metrics/export/TimeSeries.java +++ b/api/src/main/java/io/opencensus/metrics/export/TimeSeries.java @@ -52,14 +52,45 @@ public abstract class TimeSeries { */ public static TimeSeries create( List labelValues, List points, @Nullable Timestamp startTimestamp) { + Utils.checkNotNull(points, "points"); + Utils.checkListElementNotNull(points, "point"); + return createInternal( + labelValues, Collections.unmodifiableList(new ArrayList(points)), startTimestamp); + } + + /** + * Creates a {@link TimeSeries}. + * + * @param labelValues the {@code LabelValue}s that uniquely identify this {@code TimeSeries}. + * @param point the single data {@code Point} of this {@code TimeSeries}. + * @param startTimestamp the start {@code Timestamp} of this {@code TimeSeries}. Must be non-null + * for cumulative {@code Point}s. + * @return a {@code TimeSeries}. + * @since 0.17 + */ + public static TimeSeries createWithOnePoint( + List labelValues, Point point, @Nullable Timestamp startTimestamp) { + Utils.checkNotNull(point, "point"); + return createInternal(labelValues, Collections.singletonList(point), startTimestamp); + } + + /** + * Creates a {@link TimeSeries}. + * + * @param labelValues the {@code LabelValue}s that uniquely identify this {@code TimeSeries}. + * @param points the data {@code Point}s of this {@code TimeSeries}. + * @param startTimestamp the start {@code Timestamp} of this {@code TimeSeries}. Must be non-null + * for cumulative {@code Point}s. + * @return a {@code TimeSeries}. + */ + private static TimeSeries createInternal( + List labelValues, List points, @Nullable Timestamp startTimestamp) { // Fail fast on null lists to prevent NullPointerException when copying the lists. Utils.checkNotNull(labelValues, "labelValues"); - Utils.checkNotNull(points, "points"); Utils.checkListElementNotNull(labelValues, "labelValue"); - Utils.checkListElementNotNull(points, "point"); return new AutoValue_TimeSeries( Collections.unmodifiableList(new ArrayList(labelValues)), - Collections.unmodifiableList(new ArrayList(points)), + points, startTimestamp); } diff --git a/api/src/test/java/io/opencensus/metrics/export/TimeSeriesTest.java b/api/src/test/java/io/opencensus/metrics/export/TimeSeriesTest.java index 31812549..92a2c8cf 100644 --- a/api/src/test/java/io/opencensus/metrics/export/TimeSeriesTest.java +++ b/api/src/test/java/io/opencensus/metrics/export/TimeSeriesTest.java @@ -89,6 +89,40 @@ public class TimeSeriesTest { TimeSeries.create(Collections.emptyList(), points, TIMESTAMP_1); } + @Test + public void testGet_WithOnePointTimeSeries() { + TimeSeries cumulativeTimeSeries = + TimeSeries.createWithOnePoint( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), POINT_1, TIMESTAMP_1); + assertThat(cumulativeTimeSeries.getStartTimestamp()).isEqualTo(TIMESTAMP_1); + assertThat(cumulativeTimeSeries.getLabelValues()) + .containsExactly(LABEL_VALUE_1, LABEL_VALUE_2) + .inOrder(); + assertThat(cumulativeTimeSeries.getPoints()).containsExactly(POINT_1).inOrder(); + } + + @Test + public void createWithOnePoint_WithNullLabelValueList() { + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("labelValues")); + TimeSeries.createWithOnePoint(null, POINT_1, TIMESTAMP_1); + } + + @Test + public void createWithOnePoint_WithNullLabelValue() { + List labelValues = Arrays.asList(LABEL_VALUE_1, null); + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("labelValue")); + TimeSeries.createWithOnePoint(labelValues, POINT_1, TIMESTAMP_1); + } + + @Test + public void createWithOnePoint_WithNullPointList() { + thrown.expect(NullPointerException.class); + thrown.expectMessage(CoreMatchers.equalTo("point")); + TimeSeries.createWithOnePoint(Collections.emptyList(), null, TIMESTAMP_1); + } + @Test public void testEquals() { new EqualsTester() -- cgit v1.2.3 From 4aa3f0c4a17a183c43b793eb5e946c34fdefd4bf Mon Sep 17 00:00:00 2001 From: Mayur Kale Date: Sat, 13 Oct 2018 12:14:59 -0700 Subject: Add BucketOptions for DistributionValue (#1484) * Add BucketOptions for DistributionValue * Fix reviews --- .../io/opencensus/metrics/export/Distribution.java | 161 +++++++++++++++------ .../metrics/export/DistributionTest.java | 146 +++++++++++++++---- .../io/opencensus/metrics/export/PointTest.java | 3 +- .../io/opencensus/metrics/export/ValueTest.java | 21 ++- 4 files changed, 255 insertions(+), 76 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/metrics/export/Distribution.java b/api/src/main/java/io/opencensus/metrics/export/Distribution.java index dc9fa9e9..eb0add86 100644 --- a/api/src/main/java/io/opencensus/metrics/export/Distribution.java +++ b/api/src/main/java/io/opencensus/metrics/export/Distribution.java @@ -18,6 +18,7 @@ package io.opencensus.metrics.export; import com.google.auto.value.AutoValue; import io.opencensus.common.ExperimentalApi; +import io.opencensus.common.Function; import io.opencensus.common.Timestamp; import io.opencensus.internal.Utils; import java.util.ArrayList; @@ -48,7 +49,7 @@ public abstract class Distribution { * @param count the count of the population values. * @param sum the sum of the population values. * @param sumOfSquaredDeviations the sum of squared deviations of the population values. - * @param bucketBoundaries bucket boundaries of a histogram. + * @param bucketOptions the bucket options used to create a histogram for the distribution. * @param buckets {@link Bucket}s of a histogram. * @return a {@code Distribution}. * @since 0.17 @@ -57,7 +58,7 @@ public abstract class Distribution { long count, double sum, double sumOfSquaredDeviations, - List bucketBoundaries, + BucketOptions bucketOptions, List buckets) { Utils.checkArgument(count >= 0, "count should be non-negative."); Utils.checkArgument( @@ -67,35 +68,16 @@ public abstract class Distribution { Utils.checkArgument( sumOfSquaredDeviations == 0, "sum of squared deviations should be 0 if count is 0."); } - return new AutoValue_Distribution( - count, - sum, - sumOfSquaredDeviations, - copyBucketBounds(bucketBoundaries), - copyBucketCount(buckets)); - } + Utils.checkNotNull(bucketOptions, "bucketOptions"); - private static List copyBucketBounds(List bucketBoundaries) { - Utils.checkNotNull(bucketBoundaries, "bucketBoundaries list should not be null."); - List bucketBoundariesCopy = new ArrayList(bucketBoundaries); // Deep copy. - // Check if sorted. - if (bucketBoundariesCopy.size() > 1) { - double lower = bucketBoundariesCopy.get(0); - for (int i = 1; i < bucketBoundariesCopy.size(); i++) { - double next = bucketBoundariesCopy.get(i); - Utils.checkArgument(lower < next, "bucket boundaries not sorted."); - lower = next; - } - } - return Collections.unmodifiableList(bucketBoundariesCopy); + return new AutoValue_Distribution( + count, sum, sumOfSquaredDeviations, bucketOptions, copyBucketCount(buckets)); } private static List copyBucketCount(List buckets) { Utils.checkNotNull(buckets, "bucket list should not be null."); List bucketsCopy = new ArrayList(buckets); - for (Bucket bucket : bucketsCopy) { - Utils.checkNotNull(bucket, "bucket should not be null."); - } + Utils.checkListElementNotNull(bucketsCopy, "bucket should not be null."); return Collections.unmodifiableList(bucketsCopy); } @@ -131,29 +113,14 @@ public abstract class Distribution { public abstract double getSumOfSquaredDeviations(); /** - * Returns the bucket boundaries of this distribution. + * Returns bucket options used to create a histogram for the distribution. * - *

    The bucket boundaries for that histogram are described by bucket_bounds. This defines - * size(bucket_bounds) + 1 (= N) buckets. The boundaries for bucket index i are: - * - *

      - *
    • {@code (-infinity, bucket_bounds[i]) for i == 0} - *
    • {@code [bucket_bounds[i-1], bucket_bounds[i]) for 0 < i < N-2} - *
    • {@code [bucket_bounds[i-1], +infinity) for i == N-1} - *
    - * - *

    i.e. an underflow bucket (number 0), zero or more finite buckets (1 through N - 2, and an - * overflow bucket (N - 1), with inclusive lower bounds and exclusive upper bounds. - * - *

    If bucket_bounds has no elements (zero size), then there is no histogram associated with the - * Distribution. If bucket_bounds has only one element, there are no finite buckets, and that - * single element is the common boundary of the overflow and underflow buckets. The values must be - * monotonically increasing. - * - * @return the bucket boundaries of this distribution. + * @return the {@code BucketOptions} associated with the {@code Distribution}, or {@code null} if + * there isn't one. * @since 0.17 */ - public abstract List getBucketBoundaries(); + @Nullable + public abstract BucketOptions getBucketOptions(); /** * Returns the aggregated histogram {@link Bucket}s. @@ -163,6 +130,110 @@ public abstract class Distribution { */ public abstract List getBuckets(); + /** + * The bucket options used to create a histogram for the distribution. + * + * @since 0.17 + */ + @Immutable + public abstract static class BucketOptions { + + private BucketOptions() {} + + /** + * Returns a {@link ExplicitOptions}. + * + *

    The bucket boundaries for that histogram are described by bucket_bounds. This defines + * size(bucket_bounds) + 1 (= N) buckets. The boundaries for bucket index i are: + * + *

      + *
    • {@code [0, bucket_bounds[i]) for i == 0} + *
    • {@code [bucket_bounds[i-1], bucket_bounds[i]) for 0 < i < N-1} + *
    • {@code [bucket_bounds[i-1], +infinity) for i == N-1} + *
    + * + *

    If bucket_bounds has no elements (zero size), then there is no histogram associated with + * the Distribution. If bucket_bounds has only one element, there are no finite buckets, and + * that single element is the common boundary of the overflow and underflow buckets. The values + * must be monotonically increasing. + * + * @param bucketBoundaries the bucket boundaries of a distribution (given explicitly). The + * values must be strictly increasing and should be positive values. + * @return a {@code ExplicitOptions} {@code BucketOptions}. + * @since 0.17 + */ + public static BucketOptions explicitOptions(List bucketBoundaries) { + return ExplicitOptions.create(bucketBoundaries); + } + + /** + * Applies the given match function to the underlying BucketOptions. + * + * @param explicitFunction the function that should be applied if the BucketOptions has type + * {@code ExplicitOptions}. + * @param defaultFunction the function that should be applied if the BucketOptions has a type + * that was added after this {@code match} method was added to the API. See {@link + * io.opencensus.common.Functions} for some common functions for handling unknown types. + * @return the result of the function applied to the underlying BucketOptions. + * @since 0.17 + */ + public abstract T match( + Function explicitFunction, + Function defaultFunction); + + /** A Bucket with explicit bounds {@link BucketOptions}. */ + @AutoValue + @Immutable + public abstract static class ExplicitOptions extends BucketOptions { + + ExplicitOptions() {} + + @Override + public final T match( + Function explicitFunction, + Function defaultFunction) { + return explicitFunction.apply(this); + } + + /** + * Creates a {@link ExplicitOptions}. + * + * @param bucketBoundaries the bucket boundaries of a distribution (given explicitly). The + * values must be strictly increasing and should be positive. + * @return a {@code ExplicitOptions}. + * @since 0.17 + */ + private static ExplicitOptions create(List bucketBoundaries) { + Utils.checkNotNull(bucketBoundaries, "bucketBoundaries list should not be null."); + return new AutoValue_Distribution_BucketOptions_ExplicitOptions( + checkBucketBoundsAreSorted(bucketBoundaries)); + } + + private static List checkBucketBoundsAreSorted(List bucketBoundaries) { + List bucketBoundariesCopy = new ArrayList(bucketBoundaries); // Deep copy. + // Check if sorted. + if (bucketBoundariesCopy.size() >= 1) { + double previous = bucketBoundariesCopy.get(0); + Utils.checkArgument(previous > 0, "bucket boundaries should be > 0"); + for (int i = 1; i < bucketBoundariesCopy.size(); i++) { + double next = bucketBoundariesCopy.get(i); + Utils.checkArgument(previous < next, "bucket boundaries not sorted."); + previous = next; + } + } + return Collections.unmodifiableList(bucketBoundariesCopy); + } + + /** + * Returns the bucket boundaries of this distribution. + * + * @return the bucket boundaries of this distribution. + * @since 0.17 + */ + public abstract List getBucketBoundaries(); + } + } + /** * The histogram bucket of the population values. * diff --git a/api/src/test/java/io/opencensus/metrics/export/DistributionTest.java b/api/src/test/java/io/opencensus/metrics/export/DistributionTest.java index 0be4b5d1..ad89d338 100644 --- a/api/src/test/java/io/opencensus/metrics/export/DistributionTest.java +++ b/api/src/test/java/io/opencensus/metrics/export/DistributionTest.java @@ -19,9 +19,14 @@ package io.opencensus.metrics.export; import static com.google.common.truth.Truth.assertThat; import com.google.common.testing.EqualsTester; +import io.opencensus.common.Function; +import io.opencensus.common.Functions; import io.opencensus.common.Timestamp; import io.opencensus.metrics.export.Distribution.Bucket; +import io.opencensus.metrics.export.Distribution.BucketOptions; +import io.opencensus.metrics.export.Distribution.BucketOptions.ExplicitOptions; import io.opencensus.metrics.export.Distribution.Exemplar; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -72,20 +77,100 @@ public class DistributionTest { assertThat(exemplar.getAttachments()).isEqualTo(ATTACHMENTS); } + @Test + public void createAndGet_ExplicitBuckets() { + List bucketBounds = Arrays.asList(1.0, 2.0, 3.0); + + BucketOptions bucketOptions = BucketOptions.explicitOptions(bucketBounds); + final List actual = new ArrayList(); + bucketOptions.match( + new Function() { + @Override + public Object apply(ExplicitOptions arg) { + actual.addAll(arg.getBucketBoundaries()); + return null; + } + }, + Functions.throwAssertionError()); + + assertThat(actual).containsExactlyElementsIn(bucketBounds).inOrder(); + } + + @Test + public void createAndGet_ExplicitBucketsNegativeBounds() { + List bucketBounds = Arrays.asList(-1.0); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("bucket boundaries should be > 0"); + BucketOptions.explicitOptions(bucketBounds); + } + + @Test + public void createAndGet_PreventNullExplicitBuckets() { + thrown.expect(NullPointerException.class); + BucketOptions.explicitOptions(Arrays.asList(1.0, null, 3.0)); + } + + @Test + public void createAndGet_ExplicitBucketsEmptyBounds() { + List bucketBounds = new ArrayList(); + BucketOptions bucketOptions = BucketOptions.explicitOptions(bucketBounds); + + final List actual = new ArrayList(); + bucketOptions.match( + new Function() { + @Override + public Object apply(ExplicitOptions arg) { + actual.addAll(arg.getBucketBoundaries()); + return null; + } + }, + Functions.throwAssertionError()); + + assertThat(actual).isEmpty(); + } + + @Test + public void createBucketOptions_UnorderedBucketBounds() { + List bucketBounds = Arrays.asList(1.0, 5.0, 2.0); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("bucket boundaries not sorted."); + BucketOptions.explicitOptions(bucketBounds); + } + + @Test + public void createAndGet_PreventNullBucketOptions() { + thrown.expect(NullPointerException.class); + BucketOptions.explicitOptions(null); + } + @Test public void createAndGet_Distribution() { Exemplar exemplar = Exemplar.create(15.0, TIMESTAMP, ATTACHMENTS); - List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List bucketBounds = Arrays.asList(1.0, 2.0, 5.0); + BucketOptions bucketOptions = BucketOptions.explicitOptions(bucketBounds); List buckets = Arrays.asList( Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4, exemplar)); - Distribution distribution = Distribution.create(10, 6.6, 678.54, bucketBounds, buckets); + Distribution distribution = Distribution.create(10, 6.6, 678.54, bucketOptions, buckets); assertThat(distribution.getCount()).isEqualTo(10); assertThat(distribution.getSum()).isWithin(TOLERANCE).of(6.6); assertThat(distribution.getSumOfSquaredDeviations()).isWithin(TOLERANCE).of(678.54); - assertThat(distribution.getBucketBoundaries()) - .containsExactlyElementsIn(bucketBounds) - .inOrder(); + + final List actual = new ArrayList(); + distribution + .getBucketOptions() + .match( + new Function() { + @Override + public Object apply(ExplicitOptions arg) { + actual.addAll(arg.getBucketBoundaries()); + return null; + } + }, + Functions.throwAssertionError()); + + assertThat(actual).containsExactlyElementsIn(bucketBounds).inOrder(); + assertThat(distribution.getBuckets()).containsExactlyElementsIn(buckets).inOrder(); } @@ -121,42 +206,49 @@ public class DistributionTest { @Test public void createDistribution_NegativeCount() { - List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List bucketBounds = Arrays.asList(1.0, 2.0, 5.0); + BucketOptions bucketOptions = BucketOptions.explicitOptions(bucketBounds); + List buckets = Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); thrown.expect(IllegalArgumentException.class); thrown.expectMessage("count should be non-negative."); - Distribution.create(-10, 6.6, 678.54, bucketBounds, buckets); + Distribution.create(-10, 6.6, 678.54, bucketOptions, buckets); } @Test public void createDistribution_NegativeSumOfSquaredDeviations() { - List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List bucketBounds = Arrays.asList(1.0, 2.0, 5.0); + BucketOptions bucketOptions = BucketOptions.explicitOptions(bucketBounds); + List buckets = Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0)); thrown.expect(IllegalArgumentException.class); thrown.expectMessage("sum of squared deviations should be non-negative."); - Distribution.create(0, 6.6, -678.54, bucketBounds, buckets); + Distribution.create(0, 6.6, -678.54, bucketOptions, buckets); } @Test public void createDistribution_ZeroCountAndPositiveMean() { - List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List bucketBounds = Arrays.asList(1.0, 2.0, 5.0); + BucketOptions bucketOptions = BucketOptions.explicitOptions(bucketBounds); + List buckets = Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0)); thrown.expect(IllegalArgumentException.class); thrown.expectMessage("sum should be 0 if count is 0."); - Distribution.create(0, 6.6, 0, bucketBounds, buckets); + Distribution.create(0, 6.6, 0, bucketOptions, buckets); } @Test public void createDistribution_ZeroCountAndSumOfSquaredDeviations() { - List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List bucketBounds = Arrays.asList(1.0, 2.0, 5.0); + BucketOptions bucketOptions = BucketOptions.explicitOptions(bucketBounds); List buckets = Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0)); thrown.expect(IllegalArgumentException.class); thrown.expectMessage("sum of squared deviations should be 0 if count is 0."); - Distribution.create(0, 0, 678.54, bucketBounds, buckets); + Distribution.create(0, 0, 678.54, bucketOptions, buckets); } @Test @@ -165,53 +257,55 @@ public class DistributionTest { Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); thrown.expect(NullPointerException.class); thrown.expectMessage("bucketBoundaries list should not be null."); - Distribution.create(10, 6.6, 678.54, null, buckets); + Distribution.create(10, 6.6, 678.54, BucketOptions.explicitOptions(null), buckets); } @Test - public void createDistribution_UnorderedBucketBounds() { - List bucketBounds = Arrays.asList(0.0, -1.0, 1.0); + public void createDistribution_NullBucketOptions() { List buckets = Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("bucket boundaries not sorted."); - Distribution.create(10, 6.6, 678.54, bucketBounds, buckets); + thrown.expect(NullPointerException.class); + thrown.expectMessage("bucketOptions"); + Distribution.create(10, 6.6, 678.54, null, buckets); } @Test public void createDistribution_NullBucketList() { - List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List bucketBounds = Arrays.asList(1.0, 2.0, 5.0); + BucketOptions bucketOptions = BucketOptions.explicitOptions(bucketBounds); thrown.expect(NullPointerException.class); thrown.expectMessage("bucket list should not be null."); - Distribution.create(10, 6.6, 678.54, bucketBounds, null); + Distribution.create(10, 6.6, 678.54, bucketOptions, null); } @Test public void createDistribution_NullBucket() { - List bucketBounds = Arrays.asList(-1.0, 0.0, 1.0); + List bucketBounds = Arrays.asList(1.0, 2.0, 5.0); + BucketOptions bucketOptions = BucketOptions.explicitOptions(bucketBounds); List buckets = Arrays.asList(Bucket.create(3), Bucket.create(1), null, Bucket.create(4)); thrown.expect(NullPointerException.class); thrown.expectMessage("bucket should not be null."); - Distribution.create(10, 6.6, 678.54, bucketBounds, buckets); + Distribution.create(10, 6.6, 678.54, bucketOptions, buckets); } @Test public void testEquals() { + List bucketBounds = Arrays.asList(1.0, 2.0, 2.5); new EqualsTester() .addEqualityGroup( Distribution.create( 10, 10, 1, - Arrays.asList(-5.0, 0.0, 5.0), + BucketOptions.explicitOptions(bucketBounds), Arrays.asList( Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))), Distribution.create( 10, 10, 1, - Arrays.asList(-5.0, 0.0, 5.0), + BucketOptions.explicitOptions(bucketBounds), Arrays.asList( Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)))) .addEqualityGroup( @@ -219,7 +313,7 @@ public class DistributionTest { 7, 10, 23.456, - Arrays.asList(-5.0, 0.0, 5.0), + BucketOptions.explicitOptions(bucketBounds), Arrays.asList( Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)))) .testEquals(); diff --git a/api/src/test/java/io/opencensus/metrics/export/PointTest.java b/api/src/test/java/io/opencensus/metrics/export/PointTest.java index da5b83dc..cdfc7792 100644 --- a/api/src/test/java/io/opencensus/metrics/export/PointTest.java +++ b/api/src/test/java/io/opencensus/metrics/export/PointTest.java @@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat; import com.google.common.testing.EqualsTester; import io.opencensus.common.Timestamp; import io.opencensus.metrics.export.Distribution.Bucket; +import io.opencensus.metrics.export.Distribution.BucketOptions; import java.util.Arrays; import org.junit.Test; import org.junit.runner.RunWith; @@ -38,7 +39,7 @@ public class PointTest { 10, 6.6, 678.54, - Arrays.asList(-1.0, 0.0, 1.0), + BucketOptions.explicitOptions(Arrays.asList(1.0, 2.0, 5.0)), Arrays.asList( Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)))); private static final Timestamp TIMESTAMP_1 = Timestamp.create(1, 2); diff --git a/api/src/test/java/io/opencensus/metrics/export/ValueTest.java b/api/src/test/java/io/opencensus/metrics/export/ValueTest.java index 3758ed2d..bf947692 100644 --- a/api/src/test/java/io/opencensus/metrics/export/ValueTest.java +++ b/api/src/test/java/io/opencensus/metrics/export/ValueTest.java @@ -22,6 +22,8 @@ import com.google.common.testing.EqualsTester; import io.opencensus.common.Function; import io.opencensus.common.Functions; import io.opencensus.metrics.export.Distribution.Bucket; +import io.opencensus.metrics.export.Distribution.BucketOptions; +import io.opencensus.metrics.export.Distribution.BucketOptions.ExplicitOptions; import io.opencensus.metrics.export.Summary.Snapshot; import io.opencensus.metrics.export.Summary.Snapshot.ValueAtPercentile; import io.opencensus.metrics.export.Value.ValueDistribution; @@ -46,7 +48,7 @@ public class ValueTest { 10, 10, 1, - Arrays.asList(-5.0, 0.0, 5.0), + BucketOptions.explicitOptions(Arrays.asList(1.0, 2.0, 5.0)), Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))); private static final Summary SUMMARY = Summary.create( @@ -96,7 +98,7 @@ public class ValueTest { 7, 10, 23.456, - Arrays.asList(-5.0, 0.0, 5.0), + BucketOptions.explicitOptions(Arrays.asList(1.0, 2.0, 5.0)), Arrays.asList( Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))))) .testEquals(); @@ -111,7 +113,7 @@ public class ValueTest { ValueDistribution.create(DISTRIBUTION), ValueSummary.create(SUMMARY)); List expected = - Arrays.asList(1.0, -1L, 10.0, 10L, 1.0, -5.0, 0.0, 5.0, 3L, 1L, 2L, 4L); + Arrays.asList(1.0, -1L, 10.0, 10L, 1.0, 1.0, 2.0, 5.0, 3L, 1L, 2L, 4L); final List actual = new ArrayList(); for (Value value : values) { value.match( @@ -135,7 +137,18 @@ public class ValueTest { actual.add(arg.getSum()); actual.add(arg.getCount()); actual.add(arg.getSumOfSquaredDeviations()); - actual.addAll(arg.getBucketBoundaries()); + + arg.getBucketOptions() + .match( + new Function() { + @Override + public Object apply(ExplicitOptions arg) { + actual.addAll(arg.getBucketBoundaries()); + return null; + } + }, + Functions.throwAssertionError()); + for (Bucket bucket : arg.getBuckets()) { actual.add(bucket.getCount()); } -- cgit v1.2.3 From 7c6a1e66dd8ff52aaf99fb086df656db149b58d5 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Sat, 13 Oct 2018 14:21:09 -0700 Subject: Cleanup metrics API exception messages. (#1494) * Cleanup metrics API exception messages. * Fix MutableAggregationTest.java --- .../io/opencensus/metrics/export/Distribution.java | 36 +++++++++------------- .../metrics/export/DistributionTest.java | 22 +++++++++---- 2 files changed, 31 insertions(+), 27 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/metrics/export/Distribution.java b/api/src/main/java/io/opencensus/metrics/export/Distribution.java index eb0add86..d55f101c 100644 --- a/api/src/main/java/io/opencensus/metrics/export/Distribution.java +++ b/api/src/main/java/io/opencensus/metrics/export/Distribution.java @@ -69,16 +69,11 @@ public abstract class Distribution { sumOfSquaredDeviations == 0, "sum of squared deviations should be 0 if count is 0."); } Utils.checkNotNull(bucketOptions, "bucketOptions"); - + List bucketsCopy = + Collections.unmodifiableList(new ArrayList(Utils.checkNotNull(buckets, "buckets"))); + Utils.checkListElementNotNull(bucketsCopy, "bucket"); return new AutoValue_Distribution( - count, sum, sumOfSquaredDeviations, bucketOptions, copyBucketCount(buckets)); - } - - private static List copyBucketCount(List buckets) { - Utils.checkNotNull(buckets, "bucket list should not be null."); - List bucketsCopy = new ArrayList(buckets); - Utils.checkListElementNotNull(bucketsCopy, "bucket should not be null."); - return Collections.unmodifiableList(bucketsCopy); + count, sum, sumOfSquaredDeviations, bucketOptions, bucketsCopy); } /** @@ -204,24 +199,23 @@ public abstract class Distribution { * @since 0.17 */ private static ExplicitOptions create(List bucketBoundaries) { - Utils.checkNotNull(bucketBoundaries, "bucketBoundaries list should not be null."); - return new AutoValue_Distribution_BucketOptions_ExplicitOptions( - checkBucketBoundsAreSorted(bucketBoundaries)); + Utils.checkNotNull(bucketBoundaries, "bucketBoundaries"); + List bucketBoundariesCopy = + Collections.unmodifiableList(new ArrayList(bucketBoundaries)); + checkBucketBoundsAreSorted(bucketBoundariesCopy); + return new AutoValue_Distribution_BucketOptions_ExplicitOptions(bucketBoundariesCopy); } - private static List checkBucketBoundsAreSorted(List bucketBoundaries) { - List bucketBoundariesCopy = new ArrayList(bucketBoundaries); // Deep copy. - // Check if sorted. - if (bucketBoundariesCopy.size() >= 1) { - double previous = bucketBoundariesCopy.get(0); - Utils.checkArgument(previous > 0, "bucket boundaries should be > 0"); - for (int i = 1; i < bucketBoundariesCopy.size(); i++) { - double next = bucketBoundariesCopy.get(i); + private static void checkBucketBoundsAreSorted(List bucketBoundaries) { + if (bucketBoundaries.size() >= 1) { + double previous = Utils.checkNotNull(bucketBoundaries.get(0), "bucketBoundary"); + Utils.checkArgument(previous > 0, "bucket boundary should be > 0"); + for (int i = 1; i < bucketBoundaries.size(); i++) { + double next = Utils.checkNotNull(bucketBoundaries.get(i), "bucketBoundary"); Utils.checkArgument(previous < next, "bucket boundaries not sorted."); previous = next; } } - return Collections.unmodifiableList(bucketBoundariesCopy); } /** diff --git a/api/src/test/java/io/opencensus/metrics/export/DistributionTest.java b/api/src/test/java/io/opencensus/metrics/export/DistributionTest.java index ad89d338..85b31498 100644 --- a/api/src/test/java/io/opencensus/metrics/export/DistributionTest.java +++ b/api/src/test/java/io/opencensus/metrics/export/DistributionTest.java @@ -98,9 +98,9 @@ public class DistributionTest { @Test public void createAndGet_ExplicitBucketsNegativeBounds() { - List bucketBounds = Arrays.asList(-1.0); + List bucketBounds = Collections.singletonList(-1.0); thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("bucket boundaries should be > 0"); + thrown.expectMessage("bucket boundary should be > 0"); BucketOptions.explicitOptions(bucketBounds); } @@ -252,14 +252,24 @@ public class DistributionTest { } @Test - public void createDistribution_NullBucketBounds() { + public void createDistribution_NullBucketBoundaries() { List buckets = Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); thrown.expect(NullPointerException.class); - thrown.expectMessage("bucketBoundaries list should not be null."); + thrown.expectMessage("bucketBoundaries"); Distribution.create(10, 6.6, 678.54, BucketOptions.explicitOptions(null), buckets); } + @Test + public void createDistribution_NullBucketBoundary() { + List buckets = + Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)); + thrown.expect(NullPointerException.class); + thrown.expectMessage("bucketBoundary"); + Distribution.create( + 10, 6.6, 678.54, BucketOptions.explicitOptions(Arrays.asList(2.5, null)), buckets); + } + @Test public void createDistribution_NullBucketOptions() { List buckets = @@ -274,7 +284,7 @@ public class DistributionTest { List bucketBounds = Arrays.asList(1.0, 2.0, 5.0); BucketOptions bucketOptions = BucketOptions.explicitOptions(bucketBounds); thrown.expect(NullPointerException.class); - thrown.expectMessage("bucket list should not be null."); + thrown.expectMessage("buckets"); Distribution.create(10, 6.6, 678.54, bucketOptions, null); } @@ -285,7 +295,7 @@ public class DistributionTest { List buckets = Arrays.asList(Bucket.create(3), Bucket.create(1), null, Bucket.create(4)); thrown.expect(NullPointerException.class); - thrown.expectMessage("bucket should not be null."); + thrown.expectMessage("bucket"); Distribution.create(10, 6.6, 678.54, bucketOptions, buckets); } -- cgit v1.2.3 From 53b1b60633cc3704bdaf0bd84efb3d2503578b20 Mon Sep 17 00:00:00 2001 From: Mayur Kale Date: Sat, 13 Oct 2018 22:28:41 -0700 Subject: Gauge API : Add LongGauge Support (Part1) (#1489) * Gauge API : Add LongGauge Support (Part1) * Fix review comments * Fix review comments, removed LongGauge from registry * Add TODO and remove unnecessary check on removeTimeSeries --- .../main/java/io/opencensus/metrics/LongGauge.java | 211 +++++++++++++++++++++ .../java/io/opencensus/metrics/LongGaugeTest.java | 87 +++++++++ 2 files changed, 298 insertions(+) create mode 100644 api/src/main/java/io/opencensus/metrics/LongGauge.java create mode 100644 api/src/test/java/io/opencensus/metrics/LongGaugeTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/metrics/LongGauge.java b/api/src/main/java/io/opencensus/metrics/LongGauge.java new file mode 100644 index 00000000..2294f0cf --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/LongGauge.java @@ -0,0 +1,211 @@ +/* + * Copyright 2018, 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.metrics; + +import io.opencensus.internal.Utils; +import java.util.List; +import javax.annotation.concurrent.ThreadSafe; + +/** + * Long Gauge metric, to report instantaneous measurement of an int64 value. Gauges can go both up + * and down. The gauges values can be negative. + * + *

    Example 1: Create a Gauge with default labels. + * + *

    {@code
    + * class YourClass {
    + *
    + *   private static final MetricRegistry metricRegistry = Metrics.getMetricRegistry();
    + *
    + *   List labelKeys = Arrays.asList(LabelKey.create("Name", "desc"));
    + *   // TODO(mayurkale): Plugs-in the LongGauge into the registry.
    + *   LongGauge gauge = metricRegistry.addLongGauge("queue_size", "Pending jobs", "1", labelKeys);
    + *
    + *   // It is recommended to keep a reference of a point for manual operations.
    + *   LongPoint defaultPoint = gauge.getDefaultTimeSeries();
    + *
    + *   void doWork() {
    + *      // Your code here.
    + *      defaultPoint.add(10);
    + *   }
    + *
    + * }
    + * }
    + * + *

    Example 2: You can also use labels(keys and values) to track different types of metric. + * + *

    {@code
    + * class YourClass {
    + *
    + *   private static final MetricRegistry metricRegistry = Metrics.getMetricRegistry();
    + *
    + *   List labelKeys = Arrays.asList(LabelKey.create("Name", "desc"));
    + *   List labelValues = Arrays.asList(LabelValue.create("Inbound"));
    + *
    + *   // TODO(mayurkale): Plugs-in the LongGauge into the registry.
    + *   LongGauge gauge = metricRegistry.addLongGauge("queue_size", "Pending jobs", "1", labelKeys);
    + *
    + *   // It is recommended to keep a reference of a point for manual operations.
    + *   LongPoint inboundPoint = gauge.getOrCreateTimeSeries(labelValues);
    + *
    + *   void doSomeWork() {
    + *      // Your code here.
    + *      inboundPoint.set(15);
    + *   }
    + *
    + * }
    + * }
    + * + * @since 0.17 + */ +@ThreadSafe +public abstract class LongGauge { + + /** + * Creates a {@code TimeSeries} and returns a {@code LongPoint} if the specified {@code + * labelValues} is not already associated with this gauge, else returns a existing {@code + * LongPoint}. + * + *

    It is recommended to keep a reference to the LongPoint instead of always calling this method + * for manual operations. + * + * @param labelValues the list of label values. The number of label values must be the same to + * that of the label keys passed to {@link MetricRegistry#addLongGauge}. + * @return a {@code LongPoint} the value of single gauge. + * @throws NullPointerException if {@code labelValues} is null OR any element of {@code + * labelValues} is null. + * @throws IllegalArgumentException if number of {@code labelValues}s are not equal to the label + * keys passed to {@link MetricRegistry#addLongGauge}. + * @since 0.17 + */ + public abstract LongPoint getOrCreateTimeSeries(List labelValues); + + /** + * Returns a {@code LongPoint} for a gauge with all labels not set, or default labels. + * + * @return a {@code LongPoint} the value of default gauge. + * @since 0.17 + */ + public abstract LongPoint getDefaultTimeSeries(); + + /** + * Removes the {@code TimeSeries} from the gauge metric, if it is present. i.e. references to + * previous {@code LongPoint} objects are invalid (not part of the metric). + * + * @param labelValues the list of label values. + * @throws NullPointerException if {@code labelValues} is null or any element of {@code + * labelValues} is null. + * @since 0.17 + */ + public abstract void removeTimeSeries(List labelValues); + + /** + * References to all previous {@code LongPoint} objects are invalid (not part of the metric). + * + * @since 0.17 + */ + public abstract void clear(); + + /** + * Returns the no-op implementation of the {@code LongGauge}. + * + * @return the no-op implementation of the {@code LongGauge}. + * @since 0.17 + */ + static LongGauge newNoopLongGauge( + String name, String description, String unit, List labelKeys) { + return NoopLongGauge.create(name, description, unit, labelKeys); + } + + /** + * The value of a single point in the Gauge.TimeSeries. + * + * @since 0.17 + */ + public abstract static class LongPoint { + + /** + * Adds the given value to the current value. The values can be negative. + * + * @param amt the value to add + * @since 0.17 + */ + public abstract void add(long amt); + + /** + * Sets the given value. + * + * @param val the new value. + * @since 0.17 + */ + public abstract void set(long val); + } + + /** No-op implementations of LongGauge class. */ + private static final class NoopLongGauge extends LongGauge { + private final int labelKeysSize; + + static NoopLongGauge create( + String name, String description, String unit, List labelKeys) { + return new NoopLongGauge(name, description, unit, labelKeys); + } + + /** Creates a new {@code NoopLongPoint}. */ + NoopLongGauge(String name, String description, String unit, List labelKeys) { + Utils.checkNotNull(name, "name"); + Utils.checkNotNull(description, "description"); + Utils.checkNotNull(unit, "unit"); + Utils.checkNotNull(labelKeys, "labelKeys should not be null."); + Utils.checkListElementNotNull(labelKeys, "labelKeys element should not be null."); + labelKeysSize = labelKeys.size(); + } + + @Override + public NoopLongPoint getOrCreateTimeSeries(List labelValues) { + Utils.checkNotNull(labelValues, "labelValues should not be null."); + Utils.checkListElementNotNull(labelValues, "labelValues element should not be null."); + Utils.checkArgument(labelKeysSize == labelValues.size(), "Incorrect number of labels."); + return NoopLongPoint.INSTANCE; + } + + @Override + public NoopLongPoint getDefaultTimeSeries() { + return NoopLongPoint.INSTANCE; + } + + @Override + public void removeTimeSeries(List labelValues) { + Utils.checkNotNull(labelValues, "labelValues should not be null."); + } + + @Override + public void clear() {} + + /** No-op implementations of LongPoint class. */ + private static final class NoopLongPoint extends LongPoint { + private static final NoopLongPoint INSTANCE = new NoopLongPoint(); + + private NoopLongPoint() {} + + @Override + public void add(long amt) {} + + @Override + public void set(long val) {} + } + } +} diff --git a/api/src/test/java/io/opencensus/metrics/LongGaugeTest.java b/api/src/test/java/io/opencensus/metrics/LongGaugeTest.java new file mode 100644 index 00000000..768abe06 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/LongGaugeTest.java @@ -0,0 +1,87 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link LongGauge}. */ +@RunWith(JUnit4.class) +public class LongGaugeTest { + @Rule public ExpectedException thrown = ExpectedException.none(); + + private static final String NAME = "name"; + private static final String DESCRIPTION = "description"; + private static final String UNIT = "1"; + private static final List LABEL_KEY = + Collections.singletonList(LabelKey.create("key", "key description")); + private static final List LABEL_VALUES = + Collections.singletonList(LabelValue.create("value")); + private static final List EMPTY_LABEL_KEYS = new ArrayList(); + private static final List EMPTY_LABEL_VALUES = new ArrayList(); + + // TODO(mayurkale): Add more tests, once LongGauge plugs-in into the registry. + + @Test + public void noopGetOrCreateTimeSeries_WithNullLabelValues() { + LongGauge longGauge = LongGauge.newNoopLongGauge(NAME, DESCRIPTION, UNIT, EMPTY_LABEL_KEYS); + thrown.expect(NullPointerException.class); + thrown.expectMessage("labelValues should not be null."); + longGauge.getOrCreateTimeSeries(null); + } + + @Test + public void noopGetOrCreateTimeSeries_WithNullElement() { + List labelValues = Collections.singletonList(null); + LongGauge longGauge = LongGauge.newNoopLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY); + thrown.expect(NullPointerException.class); + thrown.expectMessage("labelValues element should not be null."); + longGauge.getOrCreateTimeSeries(labelValues); + } + + @Test + public void noopGetOrCreateTimeSeries_WithInvalidLabelSize() { + LongGauge longGauge = LongGauge.newNoopLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Incorrect number of labels."); + longGauge.getOrCreateTimeSeries(EMPTY_LABEL_VALUES); + } + + @Test + public void noopRemoveTimeSeries_WithNullLabelValues() { + LongGauge longGauge = LongGauge.newNoopLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY); + thrown.expect(NullPointerException.class); + thrown.expectMessage("labelValues should not be null."); + longGauge.removeTimeSeries(null); + } + + @Test + public void noopSameAs() { + LongGauge longGauge = LongGauge.newNoopLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY); + assertThat(longGauge.getDefaultTimeSeries()).isSameAs(longGauge.getDefaultTimeSeries()); + assertThat(longGauge.getDefaultTimeSeries()) + .isSameAs(longGauge.getOrCreateTimeSeries(LABEL_VALUES)); + } +} -- cgit v1.2.3 From 418e675ee250299b77370620229bf7d3cd6c6830 Mon Sep 17 00:00:00 2001 From: Mayur Kale Date: Sun, 14 Oct 2018 17:36:19 -0700 Subject: Metrics/Metric: Add a version of create that accepts only one timeseries. (#1495) * Metrics/Metric: Add createWithOneTimeSeries method * Fix review comments --- .../java/io/opencensus/metrics/export/Metric.java | 35 +++++++++++++++-- .../io/opencensus/metrics/export/MetricTest.java | 45 ++++++++++++++++++---- 2 files changed, 69 insertions(+), 11 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/metrics/export/Metric.java b/api/src/main/java/io/opencensus/metrics/export/Metric.java index 5e2fa5e8..7b93fc86 100644 --- a/api/src/main/java/io/opencensus/metrics/export/Metric.java +++ b/api/src/main/java/io/opencensus/metrics/export/Metric.java @@ -49,12 +49,39 @@ public abstract class Metric { * @since 0.17 */ public static Metric create(MetricDescriptor metricDescriptor, List timeSeriesList) { + Utils.checkListElementNotNull( + Utils.checkNotNull(timeSeriesList, "timeSeriesList"), "timeSeries"); + return createInternal( + metricDescriptor, Collections.unmodifiableList(new ArrayList(timeSeriesList))); + } + + /** + * Creates a {@link Metric}. + * + * @param metricDescriptor the {@link MetricDescriptor}. + * @param timeSeries the single {@link TimeSeries} for this metric. + * @return a {@code Metric}. + * @since 0.17 + */ + public static Metric createWithOneTimeSeries( + MetricDescriptor metricDescriptor, TimeSeries timeSeries) { + return createInternal( + metricDescriptor, Collections.singletonList(Utils.checkNotNull(timeSeries, "timeSeries"))); + } + + /** + * Creates a {@link Metric}. + * + * @param metricDescriptor the {@link MetricDescriptor}. + * @param timeSeriesList the {@link TimeSeries} list for this metric. + * @return a {@code Metric}. + * @since 0.17 + */ + private static Metric createInternal( + MetricDescriptor metricDescriptor, List timeSeriesList) { Utils.checkNotNull(metricDescriptor, "metricDescriptor"); - Utils.checkNotNull(timeSeriesList, "timeSeriesList"); - Utils.checkListElementNotNull(timeSeriesList, "timeSeries"); checkTypeMatch(metricDescriptor.getType(), timeSeriesList); - return new AutoValue_Metric( - metricDescriptor, Collections.unmodifiableList(new ArrayList(timeSeriesList))); + return new AutoValue_Metric(metricDescriptor, timeSeriesList); } /** diff --git a/api/src/test/java/io/opencensus/metrics/export/MetricTest.java b/api/src/test/java/io/opencensus/metrics/export/MetricTest.java index 52fa2c47..ed205289 100644 --- a/api/src/test/java/io/opencensus/metrics/export/MetricTest.java +++ b/api/src/test/java/io/opencensus/metrics/export/MetricTest.java @@ -50,7 +50,11 @@ public class MetricTest { METRIC_NAME_1, DESCRIPTION, UNIT, Type.GAUGE_DOUBLE, Arrays.asList(KEY_1, KEY_2)); private static final MetricDescriptor METRIC_DESCRIPTOR_2 = MetricDescriptor.create( - METRIC_NAME_2, DESCRIPTION, UNIT, Type.CUMULATIVE_INT64, Arrays.asList(KEY_1)); + METRIC_NAME_2, + DESCRIPTION, + UNIT, + Type.CUMULATIVE_INT64, + Collections.singletonList(KEY_1)); private static final LabelValue LABEL_VALUE_1 = LabelValue.create("value1"); private static final LabelValue LABEL_VALUE_2 = LabelValue.create("value1"); private static final LabelValue LABEL_VALUE_EMPTY = LabelValue.create(""); @@ -64,11 +68,16 @@ public class MetricTest { private static final Point POINT_2 = Point.create(VALUE_DOUBLE_2, TIMESTAMP_3); private static final Point POINT_3 = Point.create(VALUE_LONG, TIMESTAMP_3); private static final TimeSeries GAUGE_TIME_SERIES_1 = - TimeSeries.create(Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_1), null); + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Collections.singletonList(POINT_1), null); private static final TimeSeries GAUGE_TIME_SERIES_2 = - TimeSeries.create(Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Arrays.asList(POINT_2), null); + TimeSeries.create( + Arrays.asList(LABEL_VALUE_1, LABEL_VALUE_2), Collections.singletonList(POINT_2), null); private static final TimeSeries CUMULATIVE_TIME_SERIES = - TimeSeries.create(Arrays.asList(LABEL_VALUE_EMPTY), Arrays.asList(POINT_3), TIMESTAMP_1); + TimeSeries.create( + Collections.singletonList(LABEL_VALUE_EMPTY), + Collections.singletonList(POINT_3), + TIMESTAMP_1); @Test public void testGet() { @@ -84,7 +93,7 @@ public class MetricTest { public void typeMismatch_GaugeDouble_Long() { typeMismatch( METRIC_DESCRIPTOR_1, - Arrays.asList(CUMULATIVE_TIME_SERIES), + Collections.singletonList(CUMULATIVE_TIME_SERIES), String.format("Type mismatch: %s, %s.", Type.GAUGE_DOUBLE, "ValueLong")); } @@ -92,7 +101,7 @@ public class MetricTest { public void typeMismatch_CumulativeInt64_Double() { typeMismatch( METRIC_DESCRIPTOR_2, - Arrays.asList(GAUGE_TIME_SERIES_1), + Collections.singletonList(GAUGE_TIME_SERIES_1), String.format("Type mismatch: %s, %s.", Type.CUMULATIVE_INT64, "ValueDouble")); } @@ -133,6 +142,27 @@ public class MetricTest { assertThat(metric.getTimeSeriesList()).containsExactly(GAUGE_TIME_SERIES_1); } + @Test + public void createWithOneTimeSeries_WithNullTimeSeries() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("timeSeries"); + Metric.createWithOneTimeSeries(METRIC_DESCRIPTOR_1, null); + } + + @Test + public void createWithOneTimeSeries_WithNullMetricDescriptor() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("metricDescriptor"); + Metric.createWithOneTimeSeries(null, GAUGE_TIME_SERIES_1); + } + + @Test + public void testGet_WithOneTimeSeries() { + Metric metric = Metric.createWithOneTimeSeries(METRIC_DESCRIPTOR_1, GAUGE_TIME_SERIES_1); + assertThat(metric.getMetricDescriptor()).isEqualTo(METRIC_DESCRIPTOR_1); + assertThat(metric.getTimeSeriesList()).containsExactly(GAUGE_TIME_SERIES_1); + } + @Test public void testEquals() { new EqualsTester() @@ -142,7 +172,8 @@ public class MetricTest { Metric.create( METRIC_DESCRIPTOR_1, Arrays.asList(GAUGE_TIME_SERIES_1, GAUGE_TIME_SERIES_2))) .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_1, Collections.emptyList())) - .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_2, Arrays.asList(CUMULATIVE_TIME_SERIES))) + .addEqualityGroup( + Metric.createWithOneTimeSeries(METRIC_DESCRIPTOR_2, CUMULATIVE_TIME_SERIES)) .addEqualityGroup(Metric.create(METRIC_DESCRIPTOR_2, Collections.emptyList())) .testEquals(); } -- cgit v1.2.3 From e56a976d242d34b65e224f74d91fbafec83f96ad Mon Sep 17 00:00:00 2001 From: Mayur Kale Date: Mon, 15 Oct 2018 15:08:51 -0700 Subject: Gauge API : Add DoubleGauge Support (Part2) (#1496) * Gauge API : Add DoubleGauge Support (Part2) * Fix review comments --- .../java/io/opencensus/metrics/DoubleGauge.java | 214 +++++++++++++++++++++ .../main/java/io/opencensus/metrics/LongGauge.java | 7 +- .../io/opencensus/metrics/DoubleGaugeTest.java | 88 +++++++++ 3 files changed, 306 insertions(+), 3 deletions(-) create mode 100644 api/src/main/java/io/opencensus/metrics/DoubleGauge.java create mode 100644 api/src/test/java/io/opencensus/metrics/DoubleGaugeTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/metrics/DoubleGauge.java b/api/src/main/java/io/opencensus/metrics/DoubleGauge.java new file mode 100644 index 00000000..91e131ec --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/DoubleGauge.java @@ -0,0 +1,214 @@ +/* + * Copyright 2018, 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.metrics; + +import io.opencensus.internal.Utils; +import java.util.List; +import javax.annotation.concurrent.ThreadSafe; + +/** + * Double Gauge metric, to report instantaneous measurement of a double value. Gauges can go both up + * and down. The gauges values can be negative. + * + *

    Example 1: Create a Gauge with default labels. + * + *

    {@code
    + * class YourClass {
    + *
    + *   private static final MetricRegistry metricRegistry = Metrics.getMetricRegistry();
    + *
    + *   List labelKeys = Arrays.asList(LabelKey.create("Name", "desc"));
    + *   // TODO(mayurkale): Plugs-in the DoubleGauge into the registry.
    + *   DoubleGauge gauge = metricRegistry.addDoubleGauge("queue_size",
    + *                       "Pending jobs", "1", labelKeys);
    + *
    + *   // It is recommended to keep a reference of a point for manual operations.
    + *   DoublePoint defaultPoint = gauge.getDefaultTimeSeries();
    + *
    + *   void doWork() {
    + *      // Your code here.
    + *      defaultPoint.add(10);
    + *   }
    + *
    + * }
    + * }
    + * + *

    Example 2: You can also use labels(keys and values) to track different types of metric. + * + *

    {@code
    + * class YourClass {
    + *
    + *   private static final MetricRegistry metricRegistry = Metrics.getMetricRegistry();
    + *
    + *   List labelKeys = Arrays.asList(LabelKey.create("Name", "desc"));
    + *   List labelValues = Arrays.asList(LabelValue.create("Inbound"));
    + *
    + *   // TODO(mayurkale): Plugs-in the DoubleGauge into the registry.
    + *   DoubleGauge gauge = metricRegistry.addDoubleGauge("queue_size",
    + *                       "Pending jobs", "1", labelKeys);
    + *
    + *   // It is recommended to keep a reference of a point for manual operations.
    + *   DoublePoint inboundPoint = gauge.getOrCreateTimeSeries(labelValues);
    + *
    + *   void doSomeWork() {
    + *      // Your code here.
    + *      inboundPoint.set(15);
    + *   }
    + *
    + * }
    + * }
    + * + * @since 0.17 + */ +@ThreadSafe +public abstract class DoubleGauge { + + /** + * Creates a {@code TimeSeries} and returns a {@code DoublePoint} if the specified {@code + * labelValues} is not already associated with this gauge, else returns an existing {@code + * DoublePoint}. + * + *

    It is recommended to keep a reference to the DoublePoint instead of always calling this + * method for manual operations. + * + * @param labelValues the list of label values. The number of label values must be the same to + * that of the label keys passed to {@link MetricRegistry#addDoubleGauge}. + * @return a {@code DoublePoint} the value of single gauge. + * @throws NullPointerException if {@code labelValues} is null OR any element of {@code + * labelValues} is null. + * @throws IllegalArgumentException if number of {@code labelValues}s are not equal to the label + * keys passed to {@link MetricRegistry#addDoubleGauge}. + * @since 0.17 + */ + public abstract DoublePoint getOrCreateTimeSeries(List labelValues); + + /** + * Returns a {@code DoublePoint} for a gauge with all labels not set, or default labels. + * + * @return a {@code DoublePoint} for a gauge with all labels not set, or default labels. + * @since 0.17 + */ + public abstract DoublePoint getDefaultTimeSeries(); + + /** + * Removes the {@code TimeSeries} from the gauge metric, if it is present. i.e. references to + * previous {@code DoublePoint} objects are invalid (not part of the metric). + * + * @param labelValues the list of label values. + * @throws NullPointerException if {@code labelValues} is null or any element of {@code + * labelValues} is null. + * @since 0.17 + */ + public abstract void removeTimeSeries(List labelValues); + + /** + * Removes all {@code TimeSeries} from the gauge metric. i.e. references to all previous {@code + * DoublePoint} objects are invalid (not part of the metric). + * + * @since 0.17 + */ + public abstract void clear(); + + /** + * Returns the no-op implementation of the {@code DoubleGauge}. + * + * @return the no-op implementation of the {@code DoubleGauge}. + * @since 0.17 + */ + static DoubleGauge newNoopDoubleGauge( + String name, String description, String unit, List labelKeys) { + return NoopDoubleGauge.create(name, description, unit, labelKeys); + } + + /** + * The value of a single point in the Gauge.TimeSeries. + * + * @since 0.17 + */ + public abstract static class DoublePoint { + + /** + * Adds the given value to the current value. The values can be negative. + * + * @param amt the value to add + * @since 0.17 + */ + public abstract void add(double amt); + + /** + * Sets the given value. + * + * @param val the new value. + * @since 0.17 + */ + public abstract void set(double val); + } + + /** No-op implementations of DoubleGauge class. */ + private static final class NoopDoubleGauge extends DoubleGauge { + private final int labelKeysSize; + + static NoopDoubleGauge create( + String name, String description, String unit, List labelKeys) { + return new NoopDoubleGauge(name, description, unit, labelKeys); + } + + /** Creates a new {@code NoopDoublePoint}. */ + NoopDoubleGauge(String name, String description, String unit, List labelKeys) { + Utils.checkNotNull(name, "name"); + Utils.checkNotNull(description, "description"); + Utils.checkNotNull(unit, "unit"); + Utils.checkNotNull(labelKeys, "labelKeys should not be null."); + Utils.checkListElementNotNull(labelKeys, "labelKeys element should not be null."); + labelKeysSize = labelKeys.size(); + } + + @Override + public NoopDoublePoint getOrCreateTimeSeries(List labelValues) { + Utils.checkNotNull(labelValues, "labelValues should not be null."); + Utils.checkListElementNotNull(labelValues, "labelValues element should not be null."); + Utils.checkArgument(labelKeysSize == labelValues.size(), "Incorrect number of labels."); + return NoopDoublePoint.INSTANCE; + } + + @Override + public NoopDoublePoint getDefaultTimeSeries() { + return NoopDoublePoint.INSTANCE; + } + + @Override + public void removeTimeSeries(List labelValues) { + Utils.checkNotNull(labelValues, "labelValues should not be null."); + } + + @Override + public void clear() {} + + /** No-op implementations of DoublePoint class. */ + private static final class NoopDoublePoint extends DoublePoint { + private static final NoopDoublePoint INSTANCE = new NoopDoublePoint(); + + private NoopDoublePoint() {} + + @Override + public void add(double amt) {} + + @Override + public void set(double val) {} + } + } +} diff --git a/api/src/main/java/io/opencensus/metrics/LongGauge.java b/api/src/main/java/io/opencensus/metrics/LongGauge.java index 2294f0cf..42951d50 100644 --- a/api/src/main/java/io/opencensus/metrics/LongGauge.java +++ b/api/src/main/java/io/opencensus/metrics/LongGauge.java @@ -77,7 +77,7 @@ public abstract class LongGauge { /** * Creates a {@code TimeSeries} and returns a {@code LongPoint} if the specified {@code - * labelValues} is not already associated with this gauge, else returns a existing {@code + * labelValues} is not already associated with this gauge, else returns an existing {@code * LongPoint}. * *

    It is recommended to keep a reference to the LongPoint instead of always calling this method @@ -97,7 +97,7 @@ public abstract class LongGauge { /** * Returns a {@code LongPoint} for a gauge with all labels not set, or default labels. * - * @return a {@code LongPoint} the value of default gauge. + * @return a {@code LongPoint} for a gauge with all labels not set, or default labels. * @since 0.17 */ public abstract LongPoint getDefaultTimeSeries(); @@ -114,7 +114,8 @@ public abstract class LongGauge { public abstract void removeTimeSeries(List labelValues); /** - * References to all previous {@code LongPoint} objects are invalid (not part of the metric). + * Removes all {@code TimeSeries} from the gauge metric. i.e. references to all previous {@code + * LongPoint} objects are invalid (not part of the metric). * * @since 0.17 */ diff --git a/api/src/test/java/io/opencensus/metrics/DoubleGaugeTest.java b/api/src/test/java/io/opencensus/metrics/DoubleGaugeTest.java new file mode 100644 index 00000000..5690bd44 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/DoubleGaugeTest.java @@ -0,0 +1,88 @@ +/* + * Copyright 2018, 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.metrics; + +import static com.google.common.truth.Truth.assertThat; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link DoubleGauge}. */ +@RunWith(JUnit4.class) +public class DoubleGaugeTest { + @Rule public ExpectedException thrown = ExpectedException.none(); + + private static final String NAME = "name"; + private static final String DESCRIPTION = "description"; + private static final String UNIT = "1"; + private static final List LABEL_KEY = + Collections.singletonList(LabelKey.create("key", "key description")); + private static final List LABEL_VALUES = + Collections.singletonList(LabelValue.create("value")); + private static final List EMPTY_LABEL_KEYS = new ArrayList(); + private static final List EMPTY_LABEL_VALUES = new ArrayList(); + + // TODO(mayurkale): Add more tests, once DoubleGauge plugs-in into the registry. + + @Test + public void noopGetOrCreateTimeSeries_WithNullLabelValues() { + DoubleGauge doubleGauge = + DoubleGauge.newNoopDoubleGauge(NAME, DESCRIPTION, UNIT, EMPTY_LABEL_KEYS); + thrown.expect(NullPointerException.class); + thrown.expectMessage("labelValues should not be null."); + doubleGauge.getOrCreateTimeSeries(null); + } + + @Test + public void noopGetOrCreateTimeSeries_WithNullElement() { + List labelValues = Collections.singletonList(null); + DoubleGauge doubleGauge = DoubleGauge.newNoopDoubleGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY); + thrown.expect(NullPointerException.class); + thrown.expectMessage("labelValues element should not be null."); + doubleGauge.getOrCreateTimeSeries(labelValues); + } + + @Test + public void noopGetOrCreateTimeSeries_WithInvalidLabelSize() { + DoubleGauge doubleGauge = DoubleGauge.newNoopDoubleGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Incorrect number of labels."); + doubleGauge.getOrCreateTimeSeries(EMPTY_LABEL_VALUES); + } + + @Test + public void noopRemoveTimeSeries_WithNullLabelValues() { + DoubleGauge doubleGauge = DoubleGauge.newNoopDoubleGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY); + thrown.expect(NullPointerException.class); + thrown.expectMessage("labelValues should not be null."); + doubleGauge.removeTimeSeries(null); + } + + @Test + public void noopSameAs() { + DoubleGauge doubleGauge = DoubleGauge.newNoopDoubleGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY); + assertThat(doubleGauge.getDefaultTimeSeries()).isSameAs(doubleGauge.getDefaultTimeSeries()); + assertThat(doubleGauge.getDefaultTimeSeries()) + .isSameAs(doubleGauge.getOrCreateTimeSeries(LABEL_VALUES)); + } +} -- cgit v1.2.3 From 2b11b167c8d7633acaacc0c6aca6b829e8f4df6d Mon Sep 17 00:00:00 2001 From: Mayur Kale Date: Wed, 17 Oct 2018 14:15:48 -0700 Subject: Plugs-in the LongGauge into the registry (#1498) * plug-in longGauge into MetricRegistry * Minor fix * Add TODO and Fix build * Fix review comments --- .../java/io/opencensus/metrics/DoubleGauge.java | 4 +- .../main/java/io/opencensus/metrics/LongGauge.java | 8 +- .../java/io/opencensus/metrics/MetricRegistry.java | 81 +++------- .../io/opencensus/metrics/MetricRegistryTest.java | 163 +++++---------------- 4 files changed, 58 insertions(+), 198 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/metrics/DoubleGauge.java b/api/src/main/java/io/opencensus/metrics/DoubleGauge.java index 91e131ec..62730a06 100644 --- a/api/src/main/java/io/opencensus/metrics/DoubleGauge.java +++ b/api/src/main/java/io/opencensus/metrics/DoubleGauge.java @@ -86,12 +86,12 @@ public abstract class DoubleGauge { * method for manual operations. * * @param labelValues the list of label values. The number of label values must be the same to - * that of the label keys passed to {@link MetricRegistry#addDoubleGauge}. + * that of the label keys. * @return a {@code DoublePoint} the value of single gauge. * @throws NullPointerException if {@code labelValues} is null OR any element of {@code * labelValues} is null. * @throws IllegalArgumentException if number of {@code labelValues}s are not equal to the label - * keys passed to {@link MetricRegistry#addDoubleGauge}. + * keys. * @since 0.17 */ public abstract DoublePoint getOrCreateTimeSeries(List labelValues); diff --git a/api/src/main/java/io/opencensus/metrics/LongGauge.java b/api/src/main/java/io/opencensus/metrics/LongGauge.java index 42951d50..f473a8ac 100644 --- a/api/src/main/java/io/opencensus/metrics/LongGauge.java +++ b/api/src/main/java/io/opencensus/metrics/LongGauge.java @@ -32,7 +32,7 @@ import javax.annotation.concurrent.ThreadSafe; * private static final MetricRegistry metricRegistry = Metrics.getMetricRegistry(); * * List labelKeys = Arrays.asList(LabelKey.create("Name", "desc")); - * // TODO(mayurkale): Plugs-in the LongGauge into the registry. + * * LongGauge gauge = metricRegistry.addLongGauge("queue_size", "Pending jobs", "1", labelKeys); * * // It is recommended to keep a reference of a point for manual operations. @@ -56,7 +56,6 @@ import javax.annotation.concurrent.ThreadSafe; * List labelKeys = Arrays.asList(LabelKey.create("Name", "desc")); * List labelValues = Arrays.asList(LabelValue.create("Inbound")); * - * // TODO(mayurkale): Plugs-in the LongGauge into the registry. * LongGauge gauge = metricRegistry.addLongGauge("queue_size", "Pending jobs", "1", labelKeys); * * // It is recommended to keep a reference of a point for manual operations. @@ -167,11 +166,6 @@ public abstract class LongGauge { /** Creates a new {@code NoopLongPoint}. */ NoopLongGauge(String name, String description, String unit, List labelKeys) { - Utils.checkNotNull(name, "name"); - Utils.checkNotNull(description, "description"); - Utils.checkNotNull(unit, "unit"); - Utils.checkNotNull(labelKeys, "labelKeys should not be null."); - Utils.checkListElementNotNull(labelKeys, "labelKeys element should not be null."); labelKeysSize = labelKeys.size(); } diff --git a/api/src/main/java/io/opencensus/metrics/MetricRegistry.java b/api/src/main/java/io/opencensus/metrics/MetricRegistry.java index a9987b75..840ad787 100644 --- a/api/src/main/java/io/opencensus/metrics/MetricRegistry.java +++ b/api/src/main/java/io/opencensus/metrics/MetricRegistry.java @@ -17,10 +17,8 @@ package io.opencensus.metrics; import io.opencensus.common.ExperimentalApi; -import io.opencensus.common.ToDoubleFunction; -import io.opencensus.common.ToLongFunction; import io.opencensus.internal.Utils; -import java.util.LinkedHashMap; +import java.util.List; /** * Creates and manages your application's set of metrics. The default implementation of this creates @@ -32,44 +30,21 @@ import java.util.LinkedHashMap; @ExperimentalApi public abstract class MetricRegistry { /** - * Build a new long gauge to be added to the registry. - * - *

    Must be called only once. + * Builds a new long gauge to be added to the registry. This is more convenient form when you want + * to manually increase and decrease values as per your service requirements. * * @param name the name of the metric. * @param description the description of the metric. * @param unit the unit of the metric. - * @param obj the function argument. - * @param function the function to be called. + * @param labelKeys the list of the label keys. + * @throws NullPointerException if {@code labelKeys} is null OR any element of {@code labelKeys} + * is null OR {@code name}, {@code description}, {@code unit} is null. + * @throws IllegalArgumentException if different metric with the same name already registered. * @since 0.17 */ - public abstract void addLongGauge( - String name, - String description, - String unit, - LinkedHashMap labels, - T obj, - ToLongFunction function); - - /** - * Build a new double gauge to be added to the registry. - * - *

    Must be called only once. - * - * @param name the name of the metric. - * @param description the description of the metric. - * @param unit the unit of the metric. - * @param obj the function argument. - * @param function the function to be called. - * @since 0.17 - */ - public abstract void addDoubleGauge( - String name, - String description, - String unit, - LinkedHashMap labels, - T obj, - ToDoubleFunction function); + @ExperimentalApi + public abstract LongGauge addLongGauge( + String name, String description, String unit, List labelKeys); static MetricRegistry newNoopMetricRegistry() { return new NoopMetricRegistry(); @@ -78,33 +53,15 @@ public abstract class MetricRegistry { private static final class NoopMetricRegistry extends MetricRegistry { @Override - public void addLongGauge( - String name, - String description, - String unit, - LinkedHashMap labels, - T obj, - ToLongFunction function) { - Utils.checkNotNull(name, "name"); - Utils.checkNotNull(description, "description"); - Utils.checkNotNull(unit, "unit"); - Utils.checkNotNull(labels, "labels"); - Utils.checkNotNull(function, "function"); - } - - @Override - public void addDoubleGauge( - String name, - String description, - String unit, - LinkedHashMap labels, - T obj, - ToDoubleFunction function) { - Utils.checkNotNull(name, "name"); - Utils.checkNotNull(description, "description"); - Utils.checkNotNull(unit, "unit"); - Utils.checkNotNull(labels, "labels"); - Utils.checkNotNull(function, "function"); + public LongGauge addLongGauge( + String name, String description, String unit, List labelKeys) { + Utils.checkListElementNotNull( + Utils.checkNotNull(labelKeys, "labelKeys"), "labelKey element should not be null."); + return LongGauge.newNoopLongGauge( + Utils.checkNotNull(name, "name"), + Utils.checkNotNull(description, "description"), + Utils.checkNotNull(unit, "unit"), + labelKeys); } } } diff --git a/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java b/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java index 49e8ce02..0d90fa97 100644 --- a/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java +++ b/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java @@ -16,9 +16,10 @@ package io.opencensus.metrics; -import io.opencensus.common.ToDoubleFunction; -import io.opencensus.common.ToLongFunction; -import java.util.LinkedHashMap; +import static com.google.common.truth.Truth.assertThat; + +import java.util.Collections; +import java.util.List; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -30,156 +31,64 @@ import org.junit.runners.JUnit4; public class MetricRegistryTest { @Rule public ExpectedException thrown = ExpectedException.none(); + private static final String NAME = "name"; + private static final String DESCRIPTION = "description"; + private static final String UNIT = "1"; + private static final List LABEL_KEY = + Collections.singletonList(LabelKey.create("key", "key description")); + private static final List LABEL_VALUES = + Collections.singletonList(LabelValue.create("value")); private final MetricRegistry metricRegistry = MetricsComponent.newNoopMetricsComponent().getMetricRegistry(); @Test - public void addDoubleGauge_NullName() { - thrown.expect(NullPointerException.class); - metricRegistry.addDoubleGauge( - null, - "description", - "1", - new LinkedHashMap(), - null, - new ToDoubleFunction() { - @Override - public double applyAsDouble(Object value) { - return 5.0; - } - }); - } - - @Test - public void addDoubleGauge_NullDescription() { + public void noopAddLongGauge_NullName() { thrown.expect(NullPointerException.class); - metricRegistry.addDoubleGauge( - "name", - null, - "1", - new LinkedHashMap(), - null, - new ToDoubleFunction() { - @Override - public double applyAsDouble(Object value) { - return 5.0; - } - }); + thrown.expectMessage("name"); + metricRegistry.addLongGauge(null, DESCRIPTION, UNIT, LABEL_KEY); } @Test - public void addDoubleGauge_NullUnit() { + public void noopAddLongGauge_NullDescription() { thrown.expect(NullPointerException.class); - metricRegistry.addDoubleGauge( - "name", - "description", - null, - new LinkedHashMap(), - null, - new ToDoubleFunction() { - @Override - public double applyAsDouble(Object value) { - return 5.0; - } - }); + thrown.expectMessage("description"); + metricRegistry.addLongGauge(NAME, null, UNIT, LABEL_KEY); } @Test - public void addDoubleGauge_NullLabels() { + public void noopAddLongGauge_NullUnit() { thrown.expect(NullPointerException.class); - metricRegistry.addDoubleGauge( - "name", - "description", - "1", - null, - null, - new ToDoubleFunction() { - @Override - public double applyAsDouble(Object value) { - return 5.0; - } - }); + thrown.expectMessage("unit"); + metricRegistry.addLongGauge(NAME, DESCRIPTION, null, LABEL_KEY); } @Test - public void addDoubleGauge_NullFunction() { + public void noopAddLongGauge_NullLabels() { thrown.expect(NullPointerException.class); - metricRegistry.addDoubleGauge( - "name", "description", "1", new LinkedHashMap(), null, null); + thrown.expectMessage("labelKeys"); + metricRegistry.addLongGauge(NAME, DESCRIPTION, UNIT, null); } @Test - public void addLongGauge_NullName() { + public void noopAddLongGauge_WithNullElement() { + List labelKeys = Collections.singletonList(null); thrown.expect(NullPointerException.class); - metricRegistry.addLongGauge( - null, - "description", - "1", - new LinkedHashMap(), - null, - new ToLongFunction() { - @Override - public long applyAsLong(Object value) { - return 5; - } - }); + thrown.expectMessage("labelKey element should not be null."); + metricRegistry.addLongGauge(NAME, DESCRIPTION, UNIT, labelKeys); } @Test - public void addLongGauge_NullDescription() { - thrown.expect(NullPointerException.class); - metricRegistry.addLongGauge( - "name", - null, - "1", - new LinkedHashMap(), - null, - new ToLongFunction() { - @Override - public long applyAsLong(Object value) { - return 5; - } - }); + public void noopSameAs() { + LongGauge longGauge = metricRegistry.addLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY); + assertThat(longGauge.getDefaultTimeSeries()).isSameAs(longGauge.getDefaultTimeSeries()); + assertThat(longGauge.getDefaultTimeSeries()) + .isSameAs(longGauge.getOrCreateTimeSeries(LABEL_VALUES)); } @Test - public void addLongGauge_NullUnit() { - thrown.expect(NullPointerException.class); - metricRegistry.addLongGauge( - "name", - "description", - null, - new LinkedHashMap(), - null, - new ToLongFunction() { - @Override - public long applyAsLong(Object value) { - return 5; - } - }); - } - - @Test - public void addLongGauge_NullLabels() { - thrown.expect(NullPointerException.class); - metricRegistry.addLongGauge( - "name", - "description", - "1", - null, - null, - new ToLongFunction() { - @Override - public long applyAsLong(Object value) { - return 5; - } - }); - } - - @Test - public void addLongGauge_NullFunction() { - thrown.expect(NullPointerException.class); - metricRegistry.addLongGauge( - "name", "description", "1", new LinkedHashMap(), null, null); + public void noopInstanceOf() { + LongGauge longGauge = metricRegistry.addLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY); + assertThat(longGauge) + .isInstanceOf(LongGauge.newNoopLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY).getClass()); } } -- cgit v1.2.3 From 2f53b977da6b10b7f8e8c29d83f0478d470b229c Mon Sep 17 00:00:00 2001 From: Mayur Kale Date: Wed, 17 Oct 2018 19:25:19 -0700 Subject: Remove Old Gauge and correct exception messages (#1502) --- api/src/main/java/io/opencensus/metrics/DoubleGauge.java | 10 +++++----- api/src/main/java/io/opencensus/metrics/LongGauge.java | 6 +++--- api/src/main/java/io/opencensus/stats/Aggregation.java | 2 +- api/src/main/java/io/opencensus/stats/AggregationData.java | 6 +++--- api/src/main/java/io/opencensus/stats/BucketBoundaries.java | 2 +- api/src/test/java/io/opencensus/metrics/DoubleGaugeTest.java | 6 +++--- api/src/test/java/io/opencensus/metrics/LongGaugeTest.java | 6 +++--- api/src/test/java/io/opencensus/stats/AggregationDataTest.java | 6 +++--- api/src/test/java/io/opencensus/stats/AggregationTest.java | 2 +- 9 files changed, 23 insertions(+), 23 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/metrics/DoubleGauge.java b/api/src/main/java/io/opencensus/metrics/DoubleGauge.java index 62730a06..de2b053b 100644 --- a/api/src/main/java/io/opencensus/metrics/DoubleGauge.java +++ b/api/src/main/java/io/opencensus/metrics/DoubleGauge.java @@ -172,15 +172,15 @@ public abstract class DoubleGauge { Utils.checkNotNull(name, "name"); Utils.checkNotNull(description, "description"); Utils.checkNotNull(unit, "unit"); - Utils.checkNotNull(labelKeys, "labelKeys should not be null."); - Utils.checkListElementNotNull(labelKeys, "labelKeys element should not be null."); + Utils.checkListElementNotNull( + Utils.checkNotNull(labelKeys, "labelKeys"), "labelKey element should not be null."); labelKeysSize = labelKeys.size(); } @Override public NoopDoublePoint getOrCreateTimeSeries(List labelValues) { - Utils.checkNotNull(labelValues, "labelValues should not be null."); - Utils.checkListElementNotNull(labelValues, "labelValues element should not be null."); + Utils.checkListElementNotNull( + Utils.checkNotNull(labelValues, "labelValues"), "labelValue element should not be null."); Utils.checkArgument(labelKeysSize == labelValues.size(), "Incorrect number of labels."); return NoopDoublePoint.INSTANCE; } @@ -192,7 +192,7 @@ public abstract class DoubleGauge { @Override public void removeTimeSeries(List labelValues) { - Utils.checkNotNull(labelValues, "labelValues should not be null."); + Utils.checkNotNull(labelValues, "labelValues"); } @Override diff --git a/api/src/main/java/io/opencensus/metrics/LongGauge.java b/api/src/main/java/io/opencensus/metrics/LongGauge.java index f473a8ac..8ca760be 100644 --- a/api/src/main/java/io/opencensus/metrics/LongGauge.java +++ b/api/src/main/java/io/opencensus/metrics/LongGauge.java @@ -171,8 +171,8 @@ public abstract class LongGauge { @Override public NoopLongPoint getOrCreateTimeSeries(List labelValues) { - Utils.checkNotNull(labelValues, "labelValues should not be null."); - Utils.checkListElementNotNull(labelValues, "labelValues element should not be null."); + Utils.checkListElementNotNull( + Utils.checkNotNull(labelValues, "labelValues"), "labelValue element should not be null."); Utils.checkArgument(labelKeysSize == labelValues.size(), "Incorrect number of labels."); return NoopLongPoint.INSTANCE; } @@ -184,7 +184,7 @@ public abstract class LongGauge { @Override public void removeTimeSeries(List labelValues) { - Utils.checkNotNull(labelValues, "labelValues should not be null."); + Utils.checkNotNull(labelValues, "labelValues"); } @Override diff --git a/api/src/main/java/io/opencensus/stats/Aggregation.java b/api/src/main/java/io/opencensus/stats/Aggregation.java index f5efed9b..9c95e847 100644 --- a/api/src/main/java/io/opencensus/stats/Aggregation.java +++ b/api/src/main/java/io/opencensus/stats/Aggregation.java @@ -180,7 +180,7 @@ public abstract class Aggregation { * @since 0.8 */ public static Distribution create(BucketBoundaries bucketBoundaries) { - Utils.checkNotNull(bucketBoundaries, "bucketBoundaries should not be null."); + Utils.checkNotNull(bucketBoundaries, "bucketBoundaries"); return new AutoValue_Aggregation_Distribution(bucketBoundaries); } diff --git a/api/src/main/java/io/opencensus/stats/AggregationData.java b/api/src/main/java/io/opencensus/stats/AggregationData.java index eb7d40b3..c6e12b67 100644 --- a/api/src/main/java/io/opencensus/stats/AggregationData.java +++ b/api/src/main/java/io/opencensus/stats/AggregationData.java @@ -288,15 +288,15 @@ public abstract class AggregationData { Utils.checkArgument(min <= max, "max should be greater or equal to min."); } - Utils.checkNotNull(bucketCounts, "bucket counts should not be null."); + Utils.checkNotNull(bucketCounts, "bucketCounts"); List bucketCountsCopy = Collections.unmodifiableList(new ArrayList(bucketCounts)); for (Long bucket : bucketCountsCopy) { - Utils.checkNotNull(bucket, "bucket should not be null."); + Utils.checkNotNull(bucket, "bucket"); } Utils.checkNotNull(exemplars, "exemplar list should not be null."); for (Exemplar exemplar : exemplars) { - Utils.checkNotNull(exemplar, "exemplar should not be null."); + Utils.checkNotNull(exemplar, "exemplar"); } return new AutoValue_AggregationData_DistributionData( diff --git a/api/src/main/java/io/opencensus/stats/BucketBoundaries.java b/api/src/main/java/io/opencensus/stats/BucketBoundaries.java index 573a9e10..61e21e6c 100644 --- a/api/src/main/java/io/opencensus/stats/BucketBoundaries.java +++ b/api/src/main/java/io/opencensus/stats/BucketBoundaries.java @@ -42,7 +42,7 @@ public abstract class BucketBoundaries { * @since 0.8 */ public static final BucketBoundaries create(List bucketBoundaries) { - Utils.checkNotNull(bucketBoundaries, "bucketBoundaries list should not be null."); + Utils.checkNotNull(bucketBoundaries, "bucketBoundaries"); List bucketBoundariesCopy = new ArrayList(bucketBoundaries); // Deep copy. // Check if sorted. if (bucketBoundariesCopy.size() > 1) { diff --git a/api/src/test/java/io/opencensus/metrics/DoubleGaugeTest.java b/api/src/test/java/io/opencensus/metrics/DoubleGaugeTest.java index 5690bd44..b0cdea7c 100644 --- a/api/src/test/java/io/opencensus/metrics/DoubleGaugeTest.java +++ b/api/src/test/java/io/opencensus/metrics/DoubleGaugeTest.java @@ -49,7 +49,7 @@ public class DoubleGaugeTest { DoubleGauge doubleGauge = DoubleGauge.newNoopDoubleGauge(NAME, DESCRIPTION, UNIT, EMPTY_LABEL_KEYS); thrown.expect(NullPointerException.class); - thrown.expectMessage("labelValues should not be null."); + thrown.expectMessage("labelValues"); doubleGauge.getOrCreateTimeSeries(null); } @@ -58,7 +58,7 @@ public class DoubleGaugeTest { List labelValues = Collections.singletonList(null); DoubleGauge doubleGauge = DoubleGauge.newNoopDoubleGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY); thrown.expect(NullPointerException.class); - thrown.expectMessage("labelValues element should not be null."); + thrown.expectMessage("labelValue element should not be null."); doubleGauge.getOrCreateTimeSeries(labelValues); } @@ -74,7 +74,7 @@ public class DoubleGaugeTest { public void noopRemoveTimeSeries_WithNullLabelValues() { DoubleGauge doubleGauge = DoubleGauge.newNoopDoubleGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY); thrown.expect(NullPointerException.class); - thrown.expectMessage("labelValues should not be null."); + thrown.expectMessage("labelValues"); doubleGauge.removeTimeSeries(null); } diff --git a/api/src/test/java/io/opencensus/metrics/LongGaugeTest.java b/api/src/test/java/io/opencensus/metrics/LongGaugeTest.java index 768abe06..eedb287c 100644 --- a/api/src/test/java/io/opencensus/metrics/LongGaugeTest.java +++ b/api/src/test/java/io/opencensus/metrics/LongGaugeTest.java @@ -48,7 +48,7 @@ public class LongGaugeTest { public void noopGetOrCreateTimeSeries_WithNullLabelValues() { LongGauge longGauge = LongGauge.newNoopLongGauge(NAME, DESCRIPTION, UNIT, EMPTY_LABEL_KEYS); thrown.expect(NullPointerException.class); - thrown.expectMessage("labelValues should not be null."); + thrown.expectMessage("labelValues"); longGauge.getOrCreateTimeSeries(null); } @@ -57,7 +57,7 @@ public class LongGaugeTest { List labelValues = Collections.singletonList(null); LongGauge longGauge = LongGauge.newNoopLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY); thrown.expect(NullPointerException.class); - thrown.expectMessage("labelValues element should not be null."); + thrown.expectMessage("labelValue element should not be null."); longGauge.getOrCreateTimeSeries(labelValues); } @@ -73,7 +73,7 @@ public class LongGaugeTest { public void noopRemoveTimeSeries_WithNullLabelValues() { LongGauge longGauge = LongGauge.newNoopLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY); thrown.expect(NullPointerException.class); - thrown.expectMessage("labelValues should not be null."); + thrown.expectMessage("labelValues"); longGauge.removeTimeSeries(null); } diff --git a/api/src/test/java/io/opencensus/stats/AggregationDataTest.java b/api/src/test/java/io/opencensus/stats/AggregationDataTest.java index 60551600..a6d6d1de 100644 --- a/api/src/test/java/io/opencensus/stats/AggregationDataTest.java +++ b/api/src/test/java/io/opencensus/stats/AggregationDataTest.java @@ -108,14 +108,14 @@ public class AggregationDataTest { @Test public void preventNullBucketCountList() { thrown.expect(NullPointerException.class); - thrown.expectMessage("bucket counts should not be null."); + thrown.expectMessage("bucketCounts"); DistributionData.create(1, 1, 1, 1, 0, null); } @Test public void preventNullBucket() { thrown.expect(NullPointerException.class); - thrown.expectMessage("bucket should not be null."); + thrown.expectMessage("bucket"); DistributionData.create(1, 1, 1, 1, 0, Arrays.asList(0L, 1L, null)); } @@ -129,7 +129,7 @@ public class AggregationDataTest { @Test public void preventNullExemplar() { thrown.expect(NullPointerException.class); - thrown.expectMessage("exemplar should not be null."); + thrown.expectMessage("exemplar"); DistributionData.create( 1, 1, 1, 1, 0, Arrays.asList(0L, 1L, 1L), Collections.singletonList(null)); } diff --git a/api/src/test/java/io/opencensus/stats/AggregationTest.java b/api/src/test/java/io/opencensus/stats/AggregationTest.java index c2e6a716..cf337030 100644 --- a/api/src/test/java/io/opencensus/stats/AggregationTest.java +++ b/api/src/test/java/io/opencensus/stats/AggregationTest.java @@ -50,7 +50,7 @@ public class AggregationTest { @Test public void testNullBucketBoundaries() { thrown.expect(NullPointerException.class); - thrown.expectMessage("bucketBoundaries should not be null."); + thrown.expectMessage("bucketBoundaries"); Distribution.create(null); } -- cgit v1.2.3 From 30b613fcbf329bf130ae18267b431c4f820bbe28 Mon Sep 17 00:00:00 2001 From: Mayur Kale Date: Wed, 17 Oct 2018 22:09:40 -0700 Subject: Plugs-in the DoubleGauge into the registry (#1503) --- .../java/io/opencensus/metrics/DoubleGauge.java | 5 +-- .../java/io/opencensus/metrics/MetricRegistry.java | 29 +++++++++++++ .../io/opencensus/metrics/MetricRegistryTest.java | 48 +++++++++++++++++++++- 3 files changed, 77 insertions(+), 5 deletions(-) (limited to 'api') diff --git a/api/src/main/java/io/opencensus/metrics/DoubleGauge.java b/api/src/main/java/io/opencensus/metrics/DoubleGauge.java index de2b053b..32759973 100644 --- a/api/src/main/java/io/opencensus/metrics/DoubleGauge.java +++ b/api/src/main/java/io/opencensus/metrics/DoubleGauge.java @@ -32,7 +32,7 @@ import javax.annotation.concurrent.ThreadSafe; * private static final MetricRegistry metricRegistry = Metrics.getMetricRegistry(); * * List labelKeys = Arrays.asList(LabelKey.create("Name", "desc")); - * // TODO(mayurkale): Plugs-in the DoubleGauge into the registry. + * * DoubleGauge gauge = metricRegistry.addDoubleGauge("queue_size", * "Pending jobs", "1", labelKeys); * @@ -57,7 +57,6 @@ import javax.annotation.concurrent.ThreadSafe; * List labelKeys = Arrays.asList(LabelKey.create("Name", "desc")); * List labelValues = Arrays.asList(LabelValue.create("Inbound")); * - * // TODO(mayurkale): Plugs-in the DoubleGauge into the registry. * DoubleGauge gauge = metricRegistry.addDoubleGauge("queue_size", * "Pending jobs", "1", labelKeys); * @@ -86,7 +85,7 @@ public abstract class DoubleGauge { * method for manual operations. * * @param labelValues the list of label values. The number of label values must be the same to - * that of the label keys. + * that of the label keys passed to {@link MetricRegistry#addDoubleGauge}. * @return a {@code DoublePoint} the value of single gauge. * @throws NullPointerException if {@code labelValues} is null OR any element of {@code * labelValues} is null. diff --git a/api/src/main/java/io/opencensus/metrics/MetricRegistry.java b/api/src/main/java/io/opencensus/metrics/MetricRegistry.java index 840ad787..557f886a 100644 --- a/api/src/main/java/io/opencensus/metrics/MetricRegistry.java +++ b/api/src/main/java/io/opencensus/metrics/MetricRegistry.java @@ -46,6 +46,23 @@ public abstract class MetricRegistry { public abstract LongGauge addLongGauge( String name, String description, String unit, List labelKeys); + /** + * Builds a new double gauge to be added to the registry. This is more convenient form when you + * want to manually increase and decrease values as per your service requirements. + * + * @param name the name of the metric. + * @param description the description of the metric. + * @param unit the unit of the metric. + * @param labelKeys the list of the label keys. + * @throws NullPointerException if {@code labelKeys} is null OR any element of {@code labelKeys} + * is null OR {@code name}, {@code description}, {@code unit} is null. + * @throws IllegalArgumentException if different metric with the same name already registered. + * @since 0.17 + */ + @ExperimentalApi + public abstract DoubleGauge addDoubleGauge( + String name, String description, String unit, List labelKeys); + static MetricRegistry newNoopMetricRegistry() { return new NoopMetricRegistry(); } @@ -63,5 +80,17 @@ public abstract class MetricRegistry { Utils.checkNotNull(unit, "unit"), labelKeys); } + + @Override + public DoubleGauge addDoubleGauge( + String name, String description, String unit, List labelKeys) { + Utils.checkListElementNotNull( + Utils.checkNotNull(labelKeys, "labelKeys"), "labelKey element should not be null."); + return DoubleGauge.newNoopDoubleGauge( + Utils.checkNotNull(name, "name"), + Utils.checkNotNull(description, "description"), + Utils.checkNotNull(unit, "unit"), + labelKeys); + } } } diff --git a/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java b/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java index 0d90fa97..2de04096 100644 --- a/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java +++ b/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java @@ -32,6 +32,7 @@ public class MetricRegistryTest { @Rule public ExpectedException thrown = ExpectedException.none(); private static final String NAME = "name"; + private static final String NAME_2 = "name2"; private static final String DESCRIPTION = "description"; private static final String UNIT = "1"; private static final List LABEL_KEY = @@ -77,18 +78,61 @@ public class MetricRegistryTest { metricRegistry.addLongGauge(NAME, DESCRIPTION, UNIT, labelKeys); } + @Test + public void noopAddDoubleGauge_NullName() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("name"); + metricRegistry.addDoubleGauge(null, DESCRIPTION, UNIT, LABEL_KEY); + } + + @Test + public void noopAddDoubleGauge_NullDescription() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("description"); + metricRegistry.addDoubleGauge(NAME_2, null, UNIT, LABEL_KEY); + } + + @Test + public void noopAddDoubleGauge_NullUnit() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("unit"); + metricRegistry.addDoubleGauge(NAME_2, DESCRIPTION, null, LABEL_KEY); + } + + @Test + public void noopAddDoubleGauge_NullLabels() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("labelKeys"); + metricRegistry.addDoubleGauge(NAME_2, DESCRIPTION, UNIT, null); + } + + @Test + public void noopAddDoubleGauge_WithNullElement() { + List labelKeys = Collections.singletonList(null); + thrown.expect(NullPointerException.class); + thrown.expectMessage("labelKey element should not be null."); + metricRegistry.addDoubleGauge(NAME_2, DESCRIPTION, UNIT, labelKeys); + } + @Test public void noopSameAs() { LongGauge longGauge = metricRegistry.addLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY); assertThat(longGauge.getDefaultTimeSeries()).isSameAs(longGauge.getDefaultTimeSeries()); assertThat(longGauge.getDefaultTimeSeries()) .isSameAs(longGauge.getOrCreateTimeSeries(LABEL_VALUES)); + + DoubleGauge doubleGauge = metricRegistry.addDoubleGauge(NAME_2, DESCRIPTION, UNIT, LABEL_KEY); + assertThat(doubleGauge.getDefaultTimeSeries()).isSameAs(doubleGauge.getDefaultTimeSeries()); + assertThat(doubleGauge.getDefaultTimeSeries()) + .isSameAs(doubleGauge.getOrCreateTimeSeries(LABEL_VALUES)); } @Test public void noopInstanceOf() { - LongGauge longGauge = metricRegistry.addLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY); - assertThat(longGauge) + assertThat(metricRegistry.addLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY)) .isInstanceOf(LongGauge.newNoopLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY).getClass()); + assertThat(metricRegistry.addDoubleGauge(NAME_2, DESCRIPTION, UNIT, LABEL_KEY)) + .isInstanceOf( + DoubleGauge.newNoopDoubleGauge(NAME_2, DESCRIPTION, UNIT, LABEL_KEY).getClass()); } } -- cgit v1.2.3 From b98e4b90687833108cb497d0bc61311ff662db7c Mon Sep 17 00:00:00 2001 From: Mayur Kale Date: Wed, 17 Oct 2018 22:19:10 -0700 Subject: Add support for DerivedLongGauge (#1497) * Add support for DerivedLongGauge * Fix minor issues * Fix test * Fix review comments * Add checker annotation * fix checker --- .../java/io/opencensus/common/ToLongFunction.java | 8 +- .../io/opencensus/metrics/DerivedLongGauge.java | 151 +++++++++++++++++++++ .../main/java/io/opencensus/metrics/LongGauge.java | 3 +- .../opencensus/metrics/DerivedLongGaugeTest.java | 89 ++++++++++++ 4 files changed, 247 insertions(+), 4 deletions(-) create mode 100644 api/src/main/java/io/opencensus/metrics/DerivedLongGauge.java create mode 100644 api/src/test/java/io/opencensus/metrics/DerivedLongGaugeTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/ToLongFunction.java b/api/src/main/java/io/opencensus/common/ToLongFunction.java index 26a27b18..cd2b68ed 100644 --- a/api/src/main/java/io/opencensus/common/ToLongFunction.java +++ b/api/src/main/java/io/opencensus/common/ToLongFunction.java @@ -16,6 +16,10 @@ package io.opencensus.common; +/*>>> +import org.checkerframework.checker.nullness.qual.Nullable; +*/ + /** * Represents a function that produces a long-valued result. See {@link * io.opencensus.metrics.MetricRegistry} for an example of its use. @@ -25,12 +29,12 @@ package io.opencensus.common; * * @since 0.16 */ -public interface ToLongFunction { +public interface ToLongFunction { /** * Applies this function to the given argument. * * @param value the function argument. * @return the function result. */ - long applyAsLong(T value); + long applyAsLong(/*@Nullable*/ T value); } diff --git a/api/src/main/java/io/opencensus/metrics/DerivedLongGauge.java b/api/src/main/java/io/opencensus/metrics/DerivedLongGauge.java new file mode 100644 index 00000000..8fdd800d --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/DerivedLongGauge.java @@ -0,0 +1,151 @@ +/* + * Copyright 2018, 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.metrics; + +import io.opencensus.common.ToLongFunction; +import io.opencensus.internal.Utils; +import java.lang.ref.WeakReference; +import java.util.List; +import javax.annotation.concurrent.ThreadSafe; + +/*>>> +import org.checkerframework.checker.nullness.qual.Nullable; +*/ + +/** + * Derived Long Gauge metric, to report instantaneous measurement of an int64 value. Gauges can go + * both up and down. The gauges values can be negative. + * + *

    Example: Create a Gauge with object and function. + * + *

    {@code
    + * class YourClass {
    + *
    + *   private static final MetricRegistry metricRegistry = Metrics.getMetricRegistry();
    + *
    + *   List labelKeys = Arrays.asList(LabelKey.create("Name", "desc"));
    + *   List labelValues = Arrays.asList(LabelValue.create("Inbound"));
    + *
    + *   // TODO(mayurkale): Plugs-in the DerivedLongGauge into the registry.
    + *   DerivedLongGauge gauge = metricRegistry.addDerivedLongGauge(
    + *       "queue_size", "Pending jobs in a queue", "1", labelKeys);
    + *
    + *   QueueManager queueManager = new QueueManager();
    + *   gauge.createTimeSeries(labelValues, queueManager,
    + *         new ToLongFunction() {
    + *           {@literal @}Override
    + *           public long applyAsLong(QueueManager queue) {
    + *             return queue.size();
    + *           }
    + *         });
    + *
    + *   void doWork() {
    + *      // Your code here.
    + *   }
    + * }
    + *
    + * }
    + * + * @since 0.17 + */ +@ThreadSafe +public abstract class DerivedLongGauge { + /** + * Creates a {@code TimeSeries}. The value of a single point in the TimeSeries is observed from a + * callback function. This function is invoked whenever metrics are collected, meaning the + * reported value is up-to-date. It keeps a {@link WeakReference} to the object and it is the + * user's responsibility to manage the lifetime of the object. + * + * @param labelValues the list of label values. + * @param obj the state object from which the function derives a measurement. + * @param function the function to be called. + * @param the type of the object upon which the function derives a measurement. + * @throws NullPointerException if {@code labelValues} is null OR any element of {@code + * labelValues} is null OR {@code function} is null. + * @throws IllegalArgumentException if different time series with the same labels already exists + * OR if number of {@code labelValues}s are not equal to the label keys. + * @since 0.17 + */ + public abstract void createTimeSeries( + List labelValues, /*@Nullable*/ T obj, ToLongFunction function); + + /** + * Removes the {@code TimeSeries} from the gauge metric, if it is present. + * + * @param labelValues the list of label values. + * @throws NullPointerException if {@code labelValues} is null. + * @since 0.17 + */ + public abstract void removeTimeSeries(List labelValues); + + /** + * Removes all {@code TimeSeries} from the gauge metric. + * + * @since 0.17 + */ + public abstract void clear(); + + /** + * Returns the no-op implementation of the {@code DerivedLongGauge}. + * + * @return the no-op implementation of the {@code DerivedLongGauge}. + * @since 0.17 + */ + static DerivedLongGauge newNoopDerivedLongGauge( + String name, String description, String unit, List labelKeys) { + return NoopDerivedLongGauge.create(name, description, unit, labelKeys); + } + + /** No-op implementations of DerivedLongGauge class. */ + private static final class NoopDerivedLongGauge extends DerivedLongGauge { + private final int labelKeysSize; + + static NoopDerivedLongGauge create( + String name, String description, String unit, List labelKeys) { + return new NoopDerivedLongGauge(name, description, unit, labelKeys); + } + + /** Creates a new {@code NoopDerivedLongGauge}. */ + NoopDerivedLongGauge(String name, String description, String unit, List labelKeys) { + Utils.checkNotNull(name, "name"); + Utils.checkNotNull(description, "description"); + Utils.checkNotNull(unit, "unit"); + Utils.checkListElementNotNull( + Utils.checkNotNull(labelKeys, "labelKeys"), "labelKey element should not be null."); + labelKeysSize = labelKeys.size(); + } + + @Override + public void createTimeSeries( + List labelValues, /*@Nullable*/ + T obj, + ToLongFunction function) { + Utils.checkListElementNotNull( + Utils.checkNotNull(labelValues, "labelValues"), "labelValue element should not be null."); + Utils.checkArgument(labelKeysSize == labelValues.size(), "Incorrect number of labels."); + Utils.checkNotNull(function, "function"); + } + + @Override + public void removeTimeSeries(List labelValues) { + Utils.checkNotNull(labelValues, "labelValues"); + } + + @Override + public void clear() {} + } +} diff --git a/api/src/main/java/io/opencensus/metrics/LongGauge.java b/api/src/main/java/io/opencensus/metrics/LongGauge.java index 8ca760be..1d4489c9 100644 --- a/api/src/main/java/io/opencensus/metrics/LongGauge.java +++ b/api/src/main/java/io/opencensus/metrics/LongGauge.java @@ -106,8 +106,7 @@ public abstract class LongGauge { * previous {@code LongPoint} objects are invalid (not part of the metric). * * @param labelValues the list of label values. - * @throws NullPointerException if {@code labelValues} is null or any element of {@code - * labelValues} is null. + * @throws NullPointerException if {@code labelValues} is null. * @since 0.17 */ public abstract void removeTimeSeries(List labelValues); diff --git a/api/src/test/java/io/opencensus/metrics/DerivedLongGaugeTest.java b/api/src/test/java/io/opencensus/metrics/DerivedLongGaugeTest.java new file mode 100644 index 00000000..6a462881 --- /dev/null +++ b/api/src/test/java/io/opencensus/metrics/DerivedLongGaugeTest.java @@ -0,0 +1,89 @@ +/* + * Copyright 2018, 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.metrics; + +import io.opencensus.common.ToLongFunction; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link DerivedLongGauge}. */ +// TODO(mayurkale): Add more tests, once DerivedLongGauge plugs-in into the registry. +@RunWith(JUnit4.class) +public class DerivedLongGaugeTest { + @Rule public ExpectedException thrown = ExpectedException.none(); + + private static final String NAME = "name"; + private static final String DESCRIPTION = "description"; + private static final String UNIT = "1"; + private static final List LABEL_KEY = + Collections.singletonList(LabelKey.create("key", "key description")); + private static final List LABEL_VALUES = + Collections.singletonList(LabelValue.create("value")); + private static final List EMPTY_LABEL_VALUES = new ArrayList(); + + private final DerivedLongGauge derivedLongGauge = + DerivedLongGauge.newNoopDerivedLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY); + private static final ToLongFunction longFunction = + new ToLongFunction() { + @Override + public long applyAsLong(Object value) { + return 5; + } + }; + + @Test + public void noopCreateTimeSeries_WithNullLabelValues() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("labelValues"); + derivedLongGauge.createTimeSeries(null, null, longFunction); + } + + @Test + public void noopCreateTimeSeries_WithNullElement() { + List labelValues = Collections.singletonList(null); + thrown.expect(NullPointerException.class); + thrown.expectMessage("labelValue element should not be null."); + derivedLongGauge.createTimeSeries(labelValues, null, longFunction); + } + + @Test + public void noopCreateTimeSeries_WithInvalidLabelSize() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Incorrect number of labels."); + derivedLongGauge.createTimeSeries(EMPTY_LABEL_VALUES, null, longFunction); + } + + @Test + public void createTimeSeries_WithNullFunction() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("function"); + derivedLongGauge.createTimeSeries(LABEL_VALUES, null, null); + } + + @Test + public void noopRemoveTimeSeries_WithNullLabelValues() { + thrown.expect(NullPointerException.class); + thrown.expectMessage("labelValues"); + derivedLongGauge.removeTimeSeries(null); + } +} -- cgit v1.2.3 From af1358b7e29d15257cff835c25ee3b38382c3c9b Mon Sep 17 00:00:00 2001 From: Mayur Kale Date: Thu, 18 Oct 2018 16:36:55 -0700 Subject: Gauge API : Add support for DerivedDoubleGauge (#1504) * Add support for DerivedDoubleGauge * Fix review comments * Fix reviews --- .../io/opencensus/common/ToDoubleFunction.java | 8 +- .../io/opencensus/metrics/DerivedDoubleGauge.java | 153 +++++++++++++++++++++ .../io/opencensus/metrics/DerivedLongGauge.java | 6 +- .../opencensus/metrics/DerivedDoubleGaugeTest.java | 89 ++++++++++++ 4 files changed, 251 insertions(+), 5 deletions(-) create mode 100644 api/src/main/java/io/opencensus/metrics/DerivedDoubleGauge.java create mode 100644 api/src/test/java/io/opencensus/metrics/DerivedDoubleGaugeTest.java (limited to 'api') diff --git a/api/src/main/java/io/opencensus/common/ToDoubleFunction.java b/api/src/main/java/io/opencensus/common/ToDoubleFunction.java index eac85793..6ace2f7c 100644 --- a/api/src/main/java/io/opencensus/common/ToDoubleFunction.java +++ b/api/src/main/java/io/opencensus/common/ToDoubleFunction.java @@ -16,6 +16,10 @@ package io.opencensus.common; +/*>>> +import org.checkerframework.checker.nullness.qual.Nullable; +*/ + /** * Represents a function that produces a double-valued result. See {@link * io.opencensus.metrics.MetricRegistry} for an example of its use. @@ -25,7 +29,7 @@ package io.opencensus.common; * * @since 0.16 */ -public interface ToDoubleFunction { +public interface ToDoubleFunction { /** * Applies this function to the given argument. @@ -33,5 +37,5 @@ public interface ToDoubleFunction { * @param value the function argument. * @return the function result. */ - double applyAsDouble(T value); + double applyAsDouble(/*@Nullable*/ T value); } diff --git a/api/src/main/java/io/opencensus/metrics/DerivedDoubleGauge.java b/api/src/main/java/io/opencensus/metrics/DerivedDoubleGauge.java new file mode 100644 index 00000000..10119eef --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/DerivedDoubleGauge.java @@ -0,0 +1,153 @@ +/* + * Copyright 2018, 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.metrics; + +import io.opencensus.common.ToDoubleFunction; +import io.opencensus.internal.Utils; +import java.lang.ref.WeakReference; +import java.util.List; +import javax.annotation.concurrent.ThreadSafe; + +/*>>> +import org.checkerframework.checker.nullness.qual.Nullable; +*/ + +/** + * Derived Double Gauge metric, to report instantaneous measurement of a double value. Gauges can go + * both up and down. The gauges values can be negative. + * + *

    Example: Create a Gauge with an object and a callback function. + * + *

    {@code
    + * class YourClass {
    + *
    + *   private static final MetricRegistry metricRegistry = Metrics.getMetricRegistry();
    + *
    + *   List labelKeys = Arrays.asList(LabelKey.create("Name", "desc"));
    + *   List labelValues = Arrays.asList(LabelValue.create("Inbound"));
    + *
    + *   // TODO(mayurkale): Plugs-in the DerivedDoubleGauge into the registry.
    + *   DerivedDoubleGauge gauge = metricRegistry.addDerivedDoubleGauge(
    + *       "queue_size", "Pending jobs in a queue", "1", labelKeys);
    + *
    + *   QueueManager queueManager = new QueueManager();
    + *   gauge.createTimeSeries(labelValues, queueManager,
    + *         new ToDoubleFunction() {
    + *           {@literal @}Override
    + *           public double applyAsDouble(QueueManager queue) {
    + *             return queue.size();
    + *           }
    + *         });
    + *
    + *   void doWork() {
    + *      // Your code here.
    + *   }
    + * }
    + *
    + * }
    + * + * @since 0.17 + */ +@ThreadSafe +public abstract class DerivedDoubleGauge { + /** + * Creates a {@code TimeSeries}. The value of a single point in the TimeSeries is observed from a + * callback function. This function is invoked whenever metrics are collected, meaning the + * reported value is up-to-date. It keeps a {@link WeakReference} to the object and it is the + * user's responsibility to manage the lifetime of the object. + * + * @param labelValues the list of label values. + * @param obj the state object from which the function derives a measurement. + * @param function the function to be called. + * @param the type of the object upon which the function derives a measurement. + * @throws NullPointerException if {@code labelValues} is null OR any element of {@code + * labelValues} is null OR {@code function} is null. + * @throws IllegalArgumentException if different time series with the same labels already exists + * OR if number of {@code labelValues}s are not equal to the label keys. + * @since 0.17 + */ + public abstract void createTimeSeries( + List labelValues, + /*@Nullable*/ T obj, + ToDoubleFunction function); + + /** + * Removes the {@code TimeSeries} from the gauge metric, if it is present. + * + * @param labelValues the list of label values. + * @throws NullPointerException if {@code labelValues} is null. + * @since 0.17 + */ + public abstract void removeTimeSeries(List labelValues); + + /** + * Removes all {@code TimeSeries} from the gauge metric. + * + * @since 0.17 + */ + public abstract void clear(); + + /** + * Returns the no-op implementation of the {@code DerivedDoubleGauge}. + * + * @return the no-op implementation of the {@code DerivedDoubleGauge}. + * @since 0.17 + */ + static DerivedDoubleGauge newNoopDerivedDoubleGauge( + String name, String description, String unit, List labelKeys) { + return NoopDerivedDoubleGauge.create(name, description, unit, labelKeys); + } + + /** No-op implementations of DerivedDoubleGauge class. */ + private static final class NoopDerivedDoubleGauge extends DerivedDoubleGauge { + private final int labelKeysSize; + + static NoopDerivedDoubleGauge create( + String name, String description, String unit, List labelKeys) { + return new NoopDerivedDoubleGauge(name, description, unit, labelKeys); + } + + /** Creates a new {@code NoopDerivedDoubleGauge}. */ + NoopDerivedDoubleGauge(String name, String description, String unit, List labelKeys) { + Utils.checkNotNull(name, "name"); + Utils.checkNotNull(description, "description"); + Utils.checkNotNull(unit, "unit"); + Utils.checkListElementNotNull( + Utils.checkNotNull(labelKeys, "labelKeys"), "labelKey element should not be null."); + labelKeysSize = labelKeys.size(); + } + + @Override + public void createTimeSeries( + List labelValues, + /*@Nullable*/ T obj, + ToDoubleFunction function) { + Utils.checkListElementNotNull( + Utils.checkNotNull(labelValues, "labelValues"), "labelValue element should not be null."); + Utils.checkArgument(labelKeysSize == labelValues.size(), "Incorrect number of labels."); + Utils.checkNotNull(function, "function"); + } + + @Override + public void removeTimeSeries(List labelValues) { + Utils.checkNotNull(labelValues, "labelValues"); + } + + @Override + public void clear() {} + } +} diff --git a/api/src/main/java/io/opencensus/metrics/DerivedLongGauge.java b/api/src/main/java/io/opencensus/metrics/DerivedLongGauge.java index 8fdd800d..43943fa6 100644 --- a/api/src/main/java/io/opencensus/metrics/DerivedLongGauge.java +++ b/api/src/main/java/io/opencensus/metrics/DerivedLongGauge.java @@ -30,7 +30,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; * Derived Long Gauge metric, to report instantaneous measurement of an int64 value. Gauges can go * both up and down. The gauges values can be negative. * - *

    Example: Create a Gauge with object and function. + *

    Example: Create a Gauge with an object and a callback function. * *

    {@code
      * class YourClass {
    @@ -131,8 +131,8 @@ public abstract class DerivedLongGauge {
     
         @Override
         public  void createTimeSeries(
    -        List labelValues, /*@Nullable*/
    -        T obj,
    +        List labelValues,
    +        /*@Nullable*/ T obj,
             ToLongFunction function) {
           Utils.checkListElementNotNull(
               Utils.checkNotNull(labelValues, "labelValues"), "labelValue element should not be null.");
    diff --git a/api/src/test/java/io/opencensus/metrics/DerivedDoubleGaugeTest.java b/api/src/test/java/io/opencensus/metrics/DerivedDoubleGaugeTest.java
    new file mode 100644
    index 00000000..dbae3c49
    --- /dev/null
    +++ b/api/src/test/java/io/opencensus/metrics/DerivedDoubleGaugeTest.java
    @@ -0,0 +1,89 @@
    +/*
    + * Copyright 2018, 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.metrics;
    +
    +import io.opencensus.common.ToDoubleFunction;
    +import java.util.ArrayList;
    +import java.util.Collections;
    +import java.util.List;
    +import org.junit.Rule;
    +import org.junit.Test;
    +import org.junit.rules.ExpectedException;
    +import org.junit.runner.RunWith;
    +import org.junit.runners.JUnit4;
    +
    +/** Unit tests for {@link DerivedDoubleGauge}. */
    +// TODO(mayurkale): Add more tests, once DerivedDoubleGauge plugs-in into the registry.
    +@RunWith(JUnit4.class)
    +public class DerivedDoubleGaugeTest {
    +  @Rule public ExpectedException thrown = ExpectedException.none();
    +
    +  private static final String NAME = "name";
    +  private static final String DESCRIPTION = "description";
    +  private static final String UNIT = "1";
    +  private static final List LABEL_KEY =
    +      Collections.singletonList(LabelKey.create("key", "key description"));
    +  private static final List LABEL_VALUES =
    +      Collections.singletonList(LabelValue.create("value"));
    +  private static final List EMPTY_LABEL_VALUES = new ArrayList();
    +
    +  private final DerivedDoubleGauge derivedDoubleGauge =
    +      DerivedDoubleGauge.newNoopDerivedDoubleGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY);
    +  private static final ToDoubleFunction doubleFunction =
    +      new ToDoubleFunction() {
    +        @Override
    +        public double applyAsDouble(Object value) {
    +          return 5.0;
    +        }
    +      };
    +
    +  @Test
    +  public void noopCreateTimeSeries_WithNullLabelValues() {
    +    thrown.expect(NullPointerException.class);
    +    thrown.expectMessage("labelValues");
    +    derivedDoubleGauge.createTimeSeries(null, null, doubleFunction);
    +  }
    +
    +  @Test
    +  public void noopCreateTimeSeries_WithNullElement() {
    +    List labelValues = Collections.singletonList(null);
    +    thrown.expect(NullPointerException.class);
    +    thrown.expectMessage("labelValue element should not be null.");
    +    derivedDoubleGauge.createTimeSeries(labelValues, null, doubleFunction);
    +  }
    +
    +  @Test
    +  public void noopCreateTimeSeries_WithInvalidLabelSize() {
    +    thrown.expect(IllegalArgumentException.class);
    +    thrown.expectMessage("Incorrect number of labels.");
    +    derivedDoubleGauge.createTimeSeries(EMPTY_LABEL_VALUES, null, doubleFunction);
    +  }
    +
    +  @Test
    +  public void createTimeSeries_WithNullFunction() {
    +    thrown.expect(NullPointerException.class);
    +    thrown.expectMessage("function");
    +    derivedDoubleGauge.createTimeSeries(LABEL_VALUES, null, null);
    +  }
    +
    +  @Test
    +  public void noopRemoveTimeSeries_WithNullLabelValues() {
    +    thrown.expect(NullPointerException.class);
    +    thrown.expectMessage("labelValues");
    +    derivedDoubleGauge.removeTimeSeries(null);
    +  }
    +}
    -- 
    cgit v1.2.3
    
    
    From 633fde4378905bffb967b30857257427cced4228 Mon Sep 17 00:00:00 2001
    From: Mayur Kale 
    Date: Fri, 19 Oct 2018 10:05:26 -0700
    Subject:  Plugs-in the DerivedLongGauge and DerivedDoubleGauge into the
     registry (#1505)
    
    * Plugs-in the DerivedLongGauge into the registry
    
    * Plugs-in the DerivedDoubleGauge into the registry
    ---
     .../io/opencensus/metrics/DerivedDoubleGauge.java  |  1 -
     .../io/opencensus/metrics/DerivedLongGauge.java    |  1 -
     .../java/io/opencensus/metrics/MetricRegistry.java | 60 ++++++++++++++++
     .../io/opencensus/metrics/MetricRegistryTest.java  | 82 ++++++++++++++++++++++
     4 files changed, 142 insertions(+), 2 deletions(-)
    
    (limited to 'api')
    
    diff --git a/api/src/main/java/io/opencensus/metrics/DerivedDoubleGauge.java b/api/src/main/java/io/opencensus/metrics/DerivedDoubleGauge.java
    index 10119eef..3aaca153 100644
    --- a/api/src/main/java/io/opencensus/metrics/DerivedDoubleGauge.java
    +++ b/api/src/main/java/io/opencensus/metrics/DerivedDoubleGauge.java
    @@ -40,7 +40,6 @@ import org.checkerframework.checker.nullness.qual.Nullable;
      *   List labelKeys = Arrays.asList(LabelKey.create("Name", "desc"));
      *   List labelValues = Arrays.asList(LabelValue.create("Inbound"));
      *
    - *   // TODO(mayurkale): Plugs-in the DerivedDoubleGauge into the registry.
      *   DerivedDoubleGauge gauge = metricRegistry.addDerivedDoubleGauge(
      *       "queue_size", "Pending jobs in a queue", "1", labelKeys);
      *
    diff --git a/api/src/main/java/io/opencensus/metrics/DerivedLongGauge.java b/api/src/main/java/io/opencensus/metrics/DerivedLongGauge.java
    index 43943fa6..621873f9 100644
    --- a/api/src/main/java/io/opencensus/metrics/DerivedLongGauge.java
    +++ b/api/src/main/java/io/opencensus/metrics/DerivedLongGauge.java
    @@ -40,7 +40,6 @@ import org.checkerframework.checker.nullness.qual.Nullable;
      *   List labelKeys = Arrays.asList(LabelKey.create("Name", "desc"));
      *   List labelValues = Arrays.asList(LabelValue.create("Inbound"));
      *
    - *   // TODO(mayurkale): Plugs-in the DerivedLongGauge into the registry.
      *   DerivedLongGauge gauge = metricRegistry.addDerivedLongGauge(
      *       "queue_size", "Pending jobs in a queue", "1", labelKeys);
      *
    diff --git a/api/src/main/java/io/opencensus/metrics/MetricRegistry.java b/api/src/main/java/io/opencensus/metrics/MetricRegistry.java
    index 557f886a..5be15594 100644
    --- a/api/src/main/java/io/opencensus/metrics/MetricRegistry.java
    +++ b/api/src/main/java/io/opencensus/metrics/MetricRegistry.java
    @@ -17,6 +17,8 @@
     package io.opencensus.metrics;
     
     import io.opencensus.common.ExperimentalApi;
    +import io.opencensus.common.ToDoubleFunction;
    +import io.opencensus.common.ToLongFunction;
     import io.opencensus.internal.Utils;
     import java.util.List;
     
    @@ -63,6 +65,40 @@ public abstract class MetricRegistry {
       public abstract DoubleGauge addDoubleGauge(
           String name, String description, String unit, List labelKeys);
     
    +  /**
    +   * Builds a new derived long gauge to be added to the registry. This is more convenient form when
    +   * you want to define a gauge by executing a {@link ToLongFunction} on an object.
    +   *
    +   * @param name the name of the metric.
    +   * @param description the description of the metric.
    +   * @param unit the unit of the metric.
    +   * @param labelKeys the list of the label keys.
    +   * @throws NullPointerException if {@code labelKeys} is null OR any element of {@code labelKeys}
    +   *     is null OR {@code name}, {@code description}, {@code unit} is null.
    +   * @throws IllegalArgumentException if different metric with the same name already registered.
    +   * @since 0.17
    +   */
    +  @ExperimentalApi
    +  public abstract DerivedLongGauge addDerivedLongGauge(
    +      String name, String description, String unit, List labelKeys);
    +
    +  /**
    +   * Builds a new derived double gauge to be added to the registry. This is more convenient form
    +   * when you want to define a gauge by executing a {@link ToDoubleFunction} on an object.
    +   *
    +   * @param name the name of the metric.
    +   * @param description the description of the metric.
    +   * @param unit the unit of the metric.
    +   * @param labelKeys the list of the label keys.
    +   * @throws NullPointerException if {@code labelKeys} is null OR any element of {@code labelKeys}
    +   *     is null OR {@code name}, {@code description}, {@code unit} is null.
    +   * @throws IllegalArgumentException if different metric with the same name already registered.
    +   * @since 0.17
    +   */
    +  @ExperimentalApi
    +  public abstract DerivedDoubleGauge addDerivedDoubleGauge(
    +      String name, String description, String unit, List labelKeys);
    +
       static MetricRegistry newNoopMetricRegistry() {
         return new NoopMetricRegistry();
       }
    @@ -92,5 +128,29 @@ public abstract class MetricRegistry {
               Utils.checkNotNull(unit, "unit"),
               labelKeys);
         }
    +
    +    @Override
    +    public DerivedLongGauge addDerivedLongGauge(
    +        String name, String description, String unit, List labelKeys) {
    +      Utils.checkListElementNotNull(
    +          Utils.checkNotNull(labelKeys, "labelKeys"), "labelKey element should not be null.");
    +      return DerivedLongGauge.newNoopDerivedLongGauge(
    +          Utils.checkNotNull(name, "name"),
    +          Utils.checkNotNull(description, "description"),
    +          Utils.checkNotNull(unit, "unit"),
    +          labelKeys);
    +    }
    +
    +    @Override
    +    public DerivedDoubleGauge addDerivedDoubleGauge(
    +        String name, String description, String unit, List labelKeys) {
    +      Utils.checkListElementNotNull(
    +          Utils.checkNotNull(labelKeys, "labelKeys"), "labelKey element should not be null.");
    +      return DerivedDoubleGauge.newNoopDerivedDoubleGauge(
    +          Utils.checkNotNull(name, "name"),
    +          Utils.checkNotNull(description, "description"),
    +          Utils.checkNotNull(unit, "unit"),
    +          labelKeys);
    +    }
       }
     }
    diff --git a/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java b/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java
    index 2de04096..d8a26cc8 100644
    --- a/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java
    +++ b/api/src/test/java/io/opencensus/metrics/MetricRegistryTest.java
    @@ -33,6 +33,8 @@ public class MetricRegistryTest {
     
       private static final String NAME = "name";
       private static final String NAME_2 = "name2";
    +  private static final String NAME_3 = "name3";
    +  private static final String NAME_4 = "name4";
       private static final String DESCRIPTION = "description";
       private static final String UNIT = "1";
       private static final List LABEL_KEY =
    @@ -114,6 +116,78 @@ public class MetricRegistryTest {
         metricRegistry.addDoubleGauge(NAME_2, DESCRIPTION, UNIT, labelKeys);
       }
     
    +  @Test
    +  public void noopAddDerivedLongGauge_NullName() {
    +    thrown.expect(NullPointerException.class);
    +    thrown.expectMessage("name");
    +    metricRegistry.addDerivedLongGauge(null, DESCRIPTION, UNIT, LABEL_KEY);
    +  }
    +
    +  @Test
    +  public void noopAddDerivedLongGauge_NullDescription() {
    +    thrown.expect(NullPointerException.class);
    +    thrown.expectMessage("description");
    +    metricRegistry.addDerivedLongGauge(NAME_3, null, UNIT, LABEL_KEY);
    +  }
    +
    +  @Test
    +  public void noopAddDerivedLongGauge_NullUnit() {
    +    thrown.expect(NullPointerException.class);
    +    thrown.expectMessage("unit");
    +    metricRegistry.addDerivedLongGauge(NAME_3, DESCRIPTION, null, LABEL_KEY);
    +  }
    +
    +  @Test
    +  public void noopAddDerivedLongGauge_NullLabels() {
    +    thrown.expect(NullPointerException.class);
    +    thrown.expectMessage("labelKeys");
    +    metricRegistry.addDerivedLongGauge(NAME_3, DESCRIPTION, UNIT, null);
    +  }
    +
    +  @Test
    +  public void noopAddDerivedLongGauge_WithNullElement() {
    +    List labelKeys = Collections.singletonList(null);
    +    thrown.expect(NullPointerException.class);
    +    thrown.expectMessage("labelKey element should not be null.");
    +    metricRegistry.addDerivedLongGauge(NAME_3, DESCRIPTION, UNIT, labelKeys);
    +  }
    +
    +  @Test
    +  public void noopAddDerivedDoubleGauge_NullName() {
    +    thrown.expect(NullPointerException.class);
    +    thrown.expectMessage("name");
    +    metricRegistry.addDerivedDoubleGauge(null, DESCRIPTION, UNIT, LABEL_KEY);
    +  }
    +
    +  @Test
    +  public void noopAddDerivedDoubleGauge_NullDescription() {
    +    thrown.expect(NullPointerException.class);
    +    thrown.expectMessage("description");
    +    metricRegistry.addDerivedDoubleGauge(NAME_4, null, UNIT, LABEL_KEY);
    +  }
    +
    +  @Test
    +  public void noopAddDerivedDoubleGauge_NullUnit() {
    +    thrown.expect(NullPointerException.class);
    +    thrown.expectMessage("unit");
    +    metricRegistry.addDerivedDoubleGauge(NAME_4, DESCRIPTION, null, LABEL_KEY);
    +  }
    +
    +  @Test
    +  public void noopAddDerivedDoubleGauge_NullLabels() {
    +    thrown.expect(NullPointerException.class);
    +    thrown.expectMessage("labelKeys");
    +    metricRegistry.addDerivedDoubleGauge(NAME_4, DESCRIPTION, UNIT, null);
    +  }
    +
    +  @Test
    +  public void noopAddDerivedDoubleGauge_WithNullElement() {
    +    List labelKeys = Collections.singletonList(null);
    +    thrown.expect(NullPointerException.class);
    +    thrown.expectMessage("labelKey element should not be null.");
    +    metricRegistry.addDerivedDoubleGauge(NAME_4, DESCRIPTION, UNIT, labelKeys);
    +  }
    +
       @Test
       public void noopSameAs() {
         LongGauge longGauge = metricRegistry.addLongGauge(NAME, DESCRIPTION, UNIT, LABEL_KEY);
    @@ -134,5 +208,13 @@ public class MetricRegistryTest {
         assertThat(metricRegistry.addDoubleGauge(NAME_2, DESCRIPTION, UNIT, LABEL_KEY))
             .isInstanceOf(
                 DoubleGauge.newNoopDoubleGauge(NAME_2, DESCRIPTION, UNIT, LABEL_KEY).getClass());
    +    assertThat(metricRegistry.addDerivedLongGauge(NAME_3, DESCRIPTION, UNIT, LABEL_KEY))
    +        .isInstanceOf(
    +            DerivedLongGauge.newNoopDerivedLongGauge(NAME_3, DESCRIPTION, UNIT, LABEL_KEY)
    +                .getClass());
    +    assertThat(metricRegistry.addDerivedDoubleGauge(NAME_4, DESCRIPTION, UNIT, LABEL_KEY))
    +        .isInstanceOf(
    +            DerivedDoubleGauge.newNoopDerivedDoubleGauge(NAME_4, DESCRIPTION, UNIT, LABEL_KEY)
    +                .getClass());
       }
     }
    -- 
    cgit v1.2.3