diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-metrics.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-metrics.txt index 406f216642..72a131718a 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-metrics.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-metrics.txt @@ -1,2 +1,61 @@ Comparing source compatibility of opentelemetry-sdk-metrics-1.50.0-SNAPSHOT.jar against opentelemetry-sdk-metrics-1.49.0.jar -No changes. \ No newline at end of file ++++ NEW CLASS: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.metrics.data.DelegatingMetricData (not serializable) + +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a. + +++ NEW INTERFACE: io.opentelemetry.sdk.metrics.data.MetricData + +++ NEW SUPERCLASS: java.lang.Object + +++ NEW METHOD: PUBLIC(+) boolean equals(java.lang.Object) + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.metrics.data.Data getData() + +++ NEW METHOD: PUBLIC(+) java.lang.String getDescription() + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.common.InstrumentationScopeInfo getInstrumentationScopeInfo() + +++ NEW METHOD: PUBLIC(+) java.lang.String getName() + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.resources.Resource getResource() + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.metrics.data.MetricDataType getType() + +++ NEW METHOD: PUBLIC(+) java.lang.String getUnit() + +++ NEW METHOD: PUBLIC(+) int hashCode() + +++ NEW METHOD: PUBLIC(+) java.lang.String toString() +*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.metrics.data.DoubleExemplarData (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + +++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.data.DoubleExemplarData create(io.opentelemetry.api.common.Attributes, long, io.opentelemetry.api.trace.SpanContext, double) +*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.metrics.data.DoublePointData (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + +++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.data.DoublePointData create(long, long, io.opentelemetry.api.common.Attributes, double, java.util.List) +*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.metrics.data.ExponentialHistogramBuckets (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + +++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.data.ExponentialHistogramBuckets create(int, int, java.util.List) +*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.metrics.data.ExponentialHistogramData (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + +++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.data.ExponentialHistogramData create(io.opentelemetry.sdk.metrics.data.AggregationTemporality, java.util.Collection) +*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.metrics.data.ExponentialHistogramPointData (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + +++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.data.ExponentialHistogramPointData create(int, double, long, boolean, double, boolean, double, io.opentelemetry.sdk.metrics.data.ExponentialHistogramBuckets, io.opentelemetry.sdk.metrics.data.ExponentialHistogramBuckets, long, long, io.opentelemetry.api.common.Attributes, java.util.List) +*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.metrics.data.GaugeData (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + GENERIC TEMPLATES: === T:io.opentelemetry.sdk.metrics.data.PointData + +++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.data.GaugeData createDoubleGaugeData(java.util.Collection) + +++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.data.GaugeData createLongGaugeData(java.util.Collection) +*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.metrics.data.HistogramData (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + +++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.data.HistogramData create(io.opentelemetry.sdk.metrics.data.AggregationTemporality, java.util.Collection) +*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.metrics.data.HistogramPointData (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + +++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.data.HistogramPointData create(long, long, io.opentelemetry.api.common.Attributes, double, boolean, double, boolean, double, java.util.List, java.util.List) +*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.metrics.data.LongExemplarData (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + +++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.data.LongExemplarData create(io.opentelemetry.api.common.Attributes, long, io.opentelemetry.api.trace.SpanContext, long) +*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.metrics.data.LongPointData (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + +++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.data.LongPointData create(long, long, io.opentelemetry.api.common.Attributes, long) +*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.metrics.data.SumData (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + GENERIC TEMPLATES: === T:io.opentelemetry.sdk.metrics.data.PointData + +++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.data.SumData createDoubleSumData(boolean, io.opentelemetry.sdk.metrics.data.AggregationTemporality, java.util.Collection) + +++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.data.SumData createLongSumData(boolean, io.opentelemetry.sdk.metrics.data.AggregationTemporality, java.util.Collection) +*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.metrics.data.SummaryData (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + +++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.data.SummaryData create(java.util.Collection) +*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.metrics.data.SummaryPointData (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + +++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.data.SummaryPointData create(long, long, io.opentelemetry.api.common.Attributes, long, double, java.util.List) +*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.metrics.data.ValueAtQuantile (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + +++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.data.ValueAtQuantile create(double, double) diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt index ad0a6b3e4e..cdc87b76ae 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt @@ -1,2 +1,23 @@ Comparing source compatibility of opentelemetry-sdk-testing-1.50.0-SNAPSHOT.jar against opentelemetry-sdk-testing-1.49.0.jar -No changes. \ No newline at end of file ++++ NEW CLASS: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.testing.metrics.TestMetricData (not serializable) + +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a. + +++ NEW SUPERCLASS: java.lang.Object + +++ NEW CONSTRUCTOR: PUBLIC(+) TestMetricData() + +++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.testing.metrics.TestMetricData$Builder builder() ++++ NEW CLASS: PUBLIC(+) ABSTRACT(+) STATIC(+) io.opentelemetry.sdk.testing.metrics.TestMetricData$Builder (not serializable) + +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a. + +++ NEW SUPERCLASS: java.lang.Object + +++ NEW CONSTRUCTOR: PUBLIC(+) TestMetricData$Builder() + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.metrics.TestMetricData build() + +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.testing.metrics.TestMetricData$Builder setDescription(java.lang.String) + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.metrics.TestMetricData$Builder setDoubleGaugeData(io.opentelemetry.sdk.metrics.data.GaugeData) + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.metrics.TestMetricData$Builder setDoubleSumData(io.opentelemetry.sdk.metrics.data.SumData) + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.metrics.TestMetricData$Builder setExponentialHistogramData(io.opentelemetry.sdk.metrics.data.ExponentialHistogramData) + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.metrics.TestMetricData$Builder setHistogramData(io.opentelemetry.sdk.metrics.data.HistogramData) + +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.testing.metrics.TestMetricData$Builder setInstrumentationScopeInfo(io.opentelemetry.sdk.common.InstrumentationScopeInfo) + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.metrics.TestMetricData$Builder setLongGaugeData(io.opentelemetry.sdk.metrics.data.GaugeData) + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.metrics.TestMetricData$Builder setLongSumData(io.opentelemetry.sdk.metrics.data.SumData) + +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.testing.metrics.TestMetricData$Builder setName(java.lang.String) + +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.testing.metrics.TestMetricData$Builder setResource(io.opentelemetry.sdk.resources.Resource) + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.metrics.TestMetricData$Builder setSummaryData(io.opentelemetry.sdk.metrics.data.SummaryData) + +++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.testing.metrics.TestMetricData$Builder setUnit(java.lang.String) diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java new file mode 100644 index 0000000000..9840ec3372 --- /dev/null +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java @@ -0,0 +1,187 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.data; + +import static java.util.Objects.requireNonNull; + +import io.opentelemetry.sdk.common.InstrumentationScopeInfo; +import io.opentelemetry.sdk.resources.Resource; + +/** + * A {@link MetricData} which delegates all methods to another {@link MetricData}. Extend this class + * to modify the {@link MetricData} that will be exported, for example by creating a delegating + * {@link io.opentelemetry.sdk.metrics.export.MetricExporter} which wraps {@link MetricData} with a + * custom implementation. + * + *

Example usage: + * + *

{@code
+ * // class MetricDataWithCustomDescription extends DelegatingMetricData {
+ * //
+ * //   private final String description;
+ * //
+ * //   MetricDataWithCustomDescription(MetricData delegate) {
+ * //     super(delegate);
+ * //     this.description = delegate.getDescription() + " (custom)";
+ * //   }
+ * //
+ * //   @Override
+ * //   public String getDescription() {
+ * //     return description;
+ * //   }
+ * // }
+ * }
+ */ +public abstract class DelegatingMetricData implements MetricData { + + private final MetricData delegate; + + protected DelegatingMetricData(MetricData delegate) { + this.delegate = requireNonNull(delegate, "delegate"); + } + + /** + * Returns the resource associated with this metric data. + * + * @return the {@link Resource} instance. + */ + @Override + public Resource getResource() { + return delegate.getResource(); + } + + /** + * Returns the instrumentation library information associated with this metric data. + * + * @return the {@link InstrumentationScopeInfo} instance. + */ + @Override + public InstrumentationScopeInfo getInstrumentationScopeInfo() { + return delegate.getInstrumentationScopeInfo(); + } + + /** + * Returns the name of the metric. + * + * @return the name of the metric. + */ + @Override + public String getName() { + return delegate.getName(); + } + + /** + * Returns the description of the metric. + * + * @return the description of the metric. + */ + @Override + public String getDescription() { + return delegate.getDescription(); + } + + /** + * Returns the unit of the metric. + * + * @return the unit of the metric. + */ + @Override + public String getUnit() { + return delegate.getUnit(); + } + + /** + * Returns the type of the metric. + * + * @return the type of the metric. + */ + @Override + public MetricDataType getType() { + return delegate.getType(); + } + + /** + * Returns the data of the metric. + * + * @return the data of the metric. + */ + @Override + public Data getData() { + return delegate.getData(); + } + + /** + * Returns a boolean indicating whether the delegate {@link MetricData} is equal to this {@code + * MetricData}. + * + * @param o the object to compare to. + * @return a boolean indicating whether the delegate {@link MetricData} is equal to this {@code + * MetricData}. + */ + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof MetricData) { + MetricData that = (MetricData) o; + return getResource().equals(that.getResource()) + && getInstrumentationScopeInfo().equals(that.getInstrumentationScopeInfo()) + && getName().equals(that.getName()) + && getDescription().equals(that.getDescription()) + && getUnit().equals(that.getUnit()) + && getType().equals(that.getType()) + && getData().equals(that.getData()); + } + return false; + } + + /** + * Returns a hash code value for the delegate {@link MetricData}. + * + * @return a hash code value for the delegate {@link MetricData}. + */ + @Override + public int hashCode() { + int code = 1; + code *= 1000003; + code ^= getResource().hashCode(); + code *= 1000003; + code ^= getInstrumentationScopeInfo().hashCode(); + code *= 1000003; + code ^= getName().hashCode(); + code *= 1000003; + code ^= getDescription().hashCode(); + code *= 1000003; + code ^= getUnit().hashCode(); + code *= 1000003; + code ^= getType().hashCode(); + code *= 1000003; + code ^= getData().hashCode(); + return code; + } + + /** Returns a string representation of the delegate {@link MetricData}. */ + @Override + public String toString() { + return "DelegatingMetricData{" + + "resource=" + + getResource() + + ", instrumentationScopeInfo=" + + getInstrumentationScopeInfo() + + ", name=" + + getName() + + ", description=" + + getDescription() + + ", unit=" + + getUnit() + + ", type=" + + getType() + + ", data=" + + getData() + + "}"; + } +} diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DoubleExemplarData.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DoubleExemplarData.java index 7df07202eb..23cfad21d9 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DoubleExemplarData.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DoubleExemplarData.java @@ -5,6 +5,9 @@ package io.opentelemetry.sdk.metrics.data; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.sdk.metrics.internal.data.ImmutableDoubleExemplarData; import javax.annotation.concurrent.Immutable; /** @@ -14,6 +17,13 @@ import javax.annotation.concurrent.Immutable; */ @Immutable public interface DoubleExemplarData extends ExemplarData { + + static DoubleExemplarData create( + Attributes filteredAttributes, long recordTimeNanos, SpanContext spanContext, double value) { + return ImmutableDoubleExemplarData.create( + filteredAttributes, recordTimeNanos, spanContext, value); + } + /** Numerical value of the measurement that was recorded. */ double getValue(); } diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DoublePointData.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DoublePointData.java index fefbd27f54..e27a19496e 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DoublePointData.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DoublePointData.java @@ -5,6 +5,8 @@ package io.opentelemetry.sdk.metrics.data; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.sdk.metrics.internal.data.ImmutableDoublePointData; import java.util.List; /** @@ -13,6 +15,17 @@ import java.util.List; * @since 1.14.0 */ public interface DoublePointData extends PointData { + + static DoublePointData create( + long startEpochNanos, + long epochNanos, + Attributes attributes, + double value, + List exemplars) { + return ImmutableDoublePointData.create( + startEpochNanos, epochNanos, attributes, value, exemplars); + } + /** Returns the value of the data point. */ double getValue(); diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/ExponentialHistogramBuckets.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/ExponentialHistogramBuckets.java index 71ad13f899..22e2addb0c 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/ExponentialHistogramBuckets.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/ExponentialHistogramBuckets.java @@ -5,6 +5,7 @@ package io.opentelemetry.sdk.metrics.data; +import io.opentelemetry.sdk.metrics.internal.data.ImmutableExponentialHistogramBuckets; import java.util.List; import javax.annotation.concurrent.Immutable; @@ -25,6 +26,10 @@ import javax.annotation.concurrent.Immutable; @Immutable public interface ExponentialHistogramBuckets { + static ExponentialHistogramBuckets create(int scale, int offset, List bucketCounts) { + return ImmutableExponentialHistogramBuckets.create(scale, offset, bucketCounts); + } + /** The scale of the buckets. Must align with {@link ExponentialHistogramPointData#getScale()}. */ int getScale(); diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/ExponentialHistogramData.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/ExponentialHistogramData.java index 68db6f5c6e..8406ef632d 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/ExponentialHistogramData.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/ExponentialHistogramData.java @@ -5,6 +5,7 @@ package io.opentelemetry.sdk.metrics.data; +import io.opentelemetry.sdk.metrics.internal.data.ImmutableExponentialHistogramData; import java.util.Collection; import javax.annotation.concurrent.Immutable; @@ -24,6 +25,11 @@ import javax.annotation.concurrent.Immutable; @Immutable public interface ExponentialHistogramData extends Data { + static ExponentialHistogramData create( + AggregationTemporality temporality, Collection points) { + return ImmutableExponentialHistogramData.create(temporality, points); + } + /** * Returns the {@code AggregationTemporality} of this metric. * diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/ExponentialHistogramPointData.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/ExponentialHistogramPointData.java index 841c2bc62e..8e3d271532 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/ExponentialHistogramPointData.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/ExponentialHistogramPointData.java @@ -5,6 +5,8 @@ package io.opentelemetry.sdk.metrics.data; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.sdk.metrics.internal.data.ImmutableExponentialHistogramPointData; import java.util.List; import javax.annotation.concurrent.Immutable; @@ -24,6 +26,38 @@ import javax.annotation.concurrent.Immutable; @Immutable public interface ExponentialHistogramPointData extends PointData { + @SuppressWarnings("TooManyParameters") + static ExponentialHistogramPointData create( + int scale, + double sum, + long zeroCount, + boolean hasMin, + double min, + boolean hasMax, + double max, + ExponentialHistogramBuckets positiveBuckets, + ExponentialHistogramBuckets negativeBuckets, + long startEpochNanos, + long epochNanos, + Attributes attributes, + List exemplars) { + + return ImmutableExponentialHistogramPointData.create( + scale, + sum, + zeroCount, + hasMin, + min, + hasMax, + max, + positiveBuckets, + negativeBuckets, + startEpochNanos, + epochNanos, + attributes, + exemplars); + } + /** * Scale characterises the resolution of the histogram, with larger values of scale offering * greater precision. Bucket boundaries of the histogram are located at integer powers of the diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/GaugeData.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/GaugeData.java index f08e5bf541..a1c56f51e7 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/GaugeData.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/GaugeData.java @@ -5,6 +5,8 @@ package io.opentelemetry.sdk.metrics.data; +import io.opentelemetry.sdk.metrics.internal.data.ImmutableGaugeData; +import java.util.Collection; import javax.annotation.concurrent.Immutable; /** @@ -13,4 +15,14 @@ import javax.annotation.concurrent.Immutable; * @since 1.14.0 */ @Immutable -public interface GaugeData extends Data {} +public interface GaugeData extends Data { + + // For double gauges + static GaugeData createDoubleGaugeData(Collection points) { + return ImmutableGaugeData.create(points); + } + + static GaugeData createLongGaugeData(Collection points) { + return ImmutableGaugeData.create(points); + } +} diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/HistogramData.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/HistogramData.java index a3952844e6..a315c9c0c3 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/HistogramData.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/HistogramData.java @@ -5,6 +5,7 @@ package io.opentelemetry.sdk.metrics.data; +import io.opentelemetry.sdk.metrics.internal.data.ImmutableHistogramData; import java.util.Collection; import javax.annotation.concurrent.Immutable; @@ -15,6 +16,12 @@ import javax.annotation.concurrent.Immutable; */ @Immutable public interface HistogramData extends Data { + + static HistogramData create( + AggregationTemporality temporality, Collection points) { + return ImmutableHistogramData.create(temporality, points); + } + /** Returns the histogram {@link AggregationTemporality}. */ AggregationTemporality getAggregationTemporality(); diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/HistogramPointData.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/HistogramPointData.java index 36af358200..d6239284dc 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/HistogramPointData.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/HistogramPointData.java @@ -5,6 +5,9 @@ package io.opentelemetry.sdk.metrics.data; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.sdk.metrics.internal.data.ImmutableHistogramPointData; +import java.util.Collections; import java.util.List; import javax.annotation.concurrent.Immutable; @@ -15,6 +18,33 @@ import javax.annotation.concurrent.Immutable; */ @Immutable public interface HistogramPointData extends PointData { + + @SuppressWarnings("TooManyParameters") + static HistogramPointData create( + long startEpochNanos, + long epochNanos, + Attributes attributes, + double sum, + boolean hasMin, + double min, + boolean hasMax, + double max, + List boundaries, + List counts) { + return ImmutableHistogramPointData.create( + startEpochNanos, + epochNanos, + attributes, + sum, + hasMin, + min, + hasMax, + max, + boundaries, + counts, + Collections.emptyList()); + } + /** * The sum of all measurements recorded. * diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/LongExemplarData.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/LongExemplarData.java index 7842241fce..8bf9098258 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/LongExemplarData.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/LongExemplarData.java @@ -5,6 +5,9 @@ package io.opentelemetry.sdk.metrics.data; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.sdk.metrics.internal.data.ImmutableLongExemplarData; import javax.annotation.concurrent.Immutable; /** @@ -14,6 +17,13 @@ import javax.annotation.concurrent.Immutable; */ @Immutable public interface LongExemplarData extends ExemplarData { + + static LongExemplarData create( + Attributes filteredAttributes, long recordTimeNanos, SpanContext spanContext, long value) { + return ImmutableLongExemplarData.create( + filteredAttributes, recordTimeNanos, spanContext, value); + } + /** Numerical value of the measurement that was recorded. */ long getValue(); } diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/LongPointData.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/LongPointData.java index 18b42cb9d0..3aff3ea47b 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/LongPointData.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/LongPointData.java @@ -5,6 +5,9 @@ package io.opentelemetry.sdk.metrics.data; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.sdk.metrics.internal.data.ImmutableLongPointData; +import java.util.Collections; import java.util.List; /** @@ -13,6 +16,13 @@ import java.util.List; * @since 1.14.0 */ public interface LongPointData extends PointData { + + static LongPointData create( + long startEpochNanos, long epochNanos, Attributes attributes, long value) { + return ImmutableLongPointData.create( + startEpochNanos, epochNanos, attributes, value, Collections.emptyList()); + } + /** Returns the value of the data point. */ long getValue(); diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/SumData.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/SumData.java index af74e0338e..914671ee53 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/SumData.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/SumData.java @@ -5,6 +5,8 @@ package io.opentelemetry.sdk.metrics.data; +import io.opentelemetry.sdk.metrics.internal.data.ImmutableSumData; +import java.util.Collection; import javax.annotation.concurrent.Immutable; /** @@ -14,6 +16,17 @@ import javax.annotation.concurrent.Immutable; */ @Immutable public interface SumData extends Data { + + static SumData createLongSumData( + boolean isMonotonic, AggregationTemporality temporality, Collection points) { + return ImmutableSumData.create(isMonotonic, temporality, points); + } + + static SumData createDoubleSumData( + boolean isMonotonic, AggregationTemporality temporality, Collection points) { + return ImmutableSumData.create(isMonotonic, temporality, points); + } + /** Returns "true" if the sum is monotonic. */ boolean isMonotonic(); diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/SummaryData.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/SummaryData.java index 1189a76db1..3ecd0049c1 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/SummaryData.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/SummaryData.java @@ -5,6 +5,8 @@ package io.opentelemetry.sdk.metrics.data; +import io.opentelemetry.sdk.metrics.internal.data.ImmutableSummaryData; +import java.util.Collection; import javax.annotation.concurrent.Immutable; /** @@ -13,4 +15,9 @@ import javax.annotation.concurrent.Immutable; * @since 1.14.0 */ @Immutable -public interface SummaryData extends Data {} +public interface SummaryData extends Data { + + static SummaryData create(Collection points) { + return ImmutableSummaryData.create(points); + } +} diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/SummaryPointData.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/SummaryPointData.java index df9db3d85b..37df18d1c2 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/SummaryPointData.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/SummaryPointData.java @@ -5,6 +5,8 @@ package io.opentelemetry.sdk.metrics.data; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.sdk.metrics.internal.data.ImmutableSummaryPointData; import java.util.List; import javax.annotation.concurrent.Immutable; @@ -15,6 +17,18 @@ import javax.annotation.concurrent.Immutable; */ @Immutable public interface SummaryPointData extends PointData { + + static SummaryPointData create( + long startEpochNanos, + long epochNanos, + Attributes attributes, + long count, + double sum, + List percentileValues) { + return ImmutableSummaryPointData.create( + startEpochNanos, epochNanos, attributes, count, sum, percentileValues); + } + /** Returns the count of measurements. */ long getCount(); diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/ValueAtQuantile.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/ValueAtQuantile.java index 35702e46bb..4df1339d4f 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/ValueAtQuantile.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/ValueAtQuantile.java @@ -5,6 +5,7 @@ package io.opentelemetry.sdk.metrics.data; +import io.opentelemetry.sdk.metrics.internal.data.ImmutableValueAtQuantile; import javax.annotation.concurrent.Immutable; /** @@ -14,6 +15,11 @@ import javax.annotation.concurrent.Immutable; */ @Immutable public interface ValueAtQuantile { + + static ValueAtQuantile create(double quantile, double value) { + return ImmutableValueAtQuantile.create(quantile, value); + } + /** Returns the quantile of a distribution. Must be in the interval [0.0, 1.0]. */ double getQuantile(); diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricDataTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricDataTest.java new file mode 100644 index 0000000000..3b3763ca6f --- /dev/null +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricDataTest.java @@ -0,0 +1,212 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.data; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.sdk.common.InstrumentationScopeInfo; +import io.opentelemetry.sdk.metrics.internal.data.ImmutableHistogramData; +import io.opentelemetry.sdk.metrics.internal.data.ImmutableSummaryData; +import io.opentelemetry.sdk.resources.Resource; +import io.opentelemetry.sdk.testing.metrics.TestMetricData; +import org.assertj.core.api.recursive.comparison.RecursiveComparisonConfiguration; +import org.junit.jupiter.api.Test; + +class DelegatingMetricDataTest { + + @Test + void delegates() { + MetricData metricData = createBasicMetricBuilder().build(); + MetricData noOpWrapper = new NoOpDelegatingMetricData(metricData); + + assertThat(noOpWrapper) + .usingRecursiveComparison( + RecursiveComparisonConfiguration.builder().withIgnoredFields("delegate").build()) + .isEqualTo(metricData); + } + + @Test + void overrideDelegate() { + MetricData metricData = createBasicMetricBuilder().build(); + MetricData withCustomDescription = new MetricDataWithCustomDescription(metricData); + + assertThat(withCustomDescription.getDescription()).isEqualTo("test"); + } + + @Test + void equals() { + MetricData metricData = createBasicMetricBuilder().build(); + MetricData noOpWrapper = new NoOpDelegatingMetricData(metricData); + MetricData withCustomDescription = new MetricDataWithCustomDescription(metricData); + + assertThat(noOpWrapper).isEqualTo(metricData); + assertThat(metricData).isNotEqualTo(withCustomDescription); + } + + @Test + void equals_sameInstance() { + MetricData metricData = createBasicMetricBuilder().build(); + MetricData noOpWrapper = new NoOpDelegatingMetricData(metricData); + + assertThat(noOpWrapper.equals(noOpWrapper)).isTrue(); + } + + @Test + void equals_differentResource() { + MetricData metricData1 = + createBasicMetricBuilder() + .setResource(Resource.create(Attributes.builder().put("key", "value1").build())) + .build(); + MetricData metricData2 = + createBasicMetricBuilder() + .setResource(Resource.create(Attributes.builder().put("key", "value2").build())) + .build(); + MetricData noOpWrapper1 = new NoOpDelegatingMetricData(metricData1); + MetricData noOpWrapper2 = new NoOpDelegatingMetricData(metricData2); + + assertThat(noOpWrapper1).isNotEqualTo(noOpWrapper2); + } + + @Test + void equals_differentInstrumentationScopeInfo() { + MetricData metricData1 = + createBasicMetricBuilder() + .setInstrumentationScopeInfo(InstrumentationScopeInfo.create("scope1")) + .build(); + MetricData metricData2 = + createBasicMetricBuilder() + .setInstrumentationScopeInfo(InstrumentationScopeInfo.create("scope2")) + .build(); + MetricData noOpWrapper1 = new NoOpDelegatingMetricData(metricData1); + MetricData noOpWrapper2 = new NoOpDelegatingMetricData(metricData2); + + assertThat(noOpWrapper1).isNotEqualTo(noOpWrapper2); + } + + @Test + void equals_differentName() { + MetricData metricData1 = createBasicMetricBuilder().setName("name1").build(); + MetricData metricData2 = createBasicMetricBuilder().setName("name2").build(); + MetricData noOpWrapper1 = new NoOpDelegatingMetricData(metricData1); + MetricData noOpWrapper2 = new NoOpDelegatingMetricData(metricData2); + + assertThat(noOpWrapper1).isNotEqualTo(noOpWrapper2); + } + + @Test + void equals_differentUnit() { + MetricData metricData1 = createBasicMetricBuilder().setUnit("unit1").build(); + MetricData metricData2 = createBasicMetricBuilder().setUnit("unit2").build(); + MetricData noOpWrapper1 = new NoOpDelegatingMetricData(metricData1); + MetricData noOpWrapper2 = new NoOpDelegatingMetricData(metricData2); + + assertThat(noOpWrapper1).isNotEqualTo(noOpWrapper2); + } + + @Test + void equals_differentType() { + MetricData metricData1 = + createBasicMetricBuilder().setHistogramData(ImmutableHistogramData.empty()).build(); + MetricData metricData2 = + createBasicMetricBuilder().setSummaryData(ImmutableSummaryData.empty()).build(); + MetricData noOpWrapper1 = new NoOpDelegatingMetricData(metricData1); + MetricData noOpWrapper2 = new NoOpDelegatingMetricData(metricData2); + + assertThat(noOpWrapper1).isNotEqualTo(noOpWrapper2); + } + + @Test + void equals_differentData() { + MetricData metricData1 = + createBasicMetricBuilder().setSummaryData(ImmutableSummaryData.empty()).build(); + MetricData metricData2 = + createBasicMetricBuilder().setSummaryData(ImmutableSummaryData.empty()).build(); + MetricData noOpWrapper1 = new NoOpDelegatingMetricData(metricData1); + MetricData noOpWrapper2 = new NoOpDelegatingMetricData(metricData2); + + assertThat(noOpWrapper1).isEqualTo(noOpWrapper2); + } + + @Test + void equals_nonMetricDataObject_returnsFalse() { + MetricData metricData = createBasicMetricBuilder().build(); + MetricData noOpWrapper = new NoOpDelegatingMetricData(metricData); + + // Compare with a String object (non-MetricData) + Object nonMetricData = "not a metric data"; + + assertThat(noOpWrapper.equals(nonMetricData)).isFalse(); + } + + @Test + void testToString() { + MetricData metricData = createBasicMetricBuilder().build(); + MetricData noOpWrapper = new NoOpDelegatingMetricData(metricData); + + String expectedString = + "DelegatingMetricData{" + + "resource=" + + metricData.getResource() + + ", instrumentationScopeInfo=" + + metricData.getInstrumentationScopeInfo() + + ", name=" + + metricData.getName() + + ", description=" + + metricData.getDescription() + + ", unit=" + + metricData.getUnit() + + ", type=" + + metricData.getType() + + ", data=" + + metricData.getData() + + "}"; + + assertThat(noOpWrapper.toString()).isEqualTo(expectedString); + } + + @Test + void testHashCode() { + MetricData metricData1 = createBasicMetricBuilder().build(); + MetricData metricData2 = createBasicMetricBuilder().build(); + MetricData noOpWrapper1 = new NoOpDelegatingMetricData(metricData1); + MetricData noOpWrapper2 = new NoOpDelegatingMetricData(metricData2); + + assertThat(noOpWrapper1.hashCode()).isEqualTo(metricData1.hashCode()); + assertThat(noOpWrapper2.hashCode()).isEqualTo(metricData2.hashCode()); + assertThat(noOpWrapper1.hashCode()).isEqualTo(noOpWrapper2.hashCode()); + } + + private static TestMetricData.Builder createBasicMetricBuilder() { + return TestMetricData.builder() + .setResource(Resource.empty()) + .setInstrumentationScopeInfo(InstrumentationScopeInfo.empty()) + .setDescription("") + .setUnit("1") + .setName("name") + .setSummaryData(ImmutableSummaryData.empty()); + } + + private static final class NoOpDelegatingMetricData extends DelegatingMetricData { + private NoOpDelegatingMetricData(MetricData delegate) { + super(delegate); + } + } + + private static final class MetricDataWithCustomDescription extends DelegatingMetricData { + private final String description; + + private MetricDataWithCustomDescription(MetricData delegate) { + super(delegate); + this.description = "test"; + } + + @Override + public String getDescription() { + return description; + } + } +} diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/DoubleExemplarDataTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/DoubleExemplarDataTest.java new file mode 100644 index 0000000000..ec3d8d31d0 --- /dev/null +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/DoubleExemplarDataTest.java @@ -0,0 +1,41 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.data; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.internal.ImmutableSpanContext; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.api.trace.TraceFlags; +import io.opentelemetry.api.trace.TraceState; +import org.junit.jupiter.api.Test; + +class DoubleExemplarDataTest { + + private static final String TRACE_ID = "00000000000000000000000000000061"; + private static final String SPAN_ID = "0000000000000061"; + + @Test + void create() { + SpanContext spanContext = + ImmutableSpanContext.create( + TRACE_ID, + SPAN_ID, + TraceFlags.getDefault(), + TraceState.getDefault(), + /* remote= */ false, + /* skipIdValidation= */ false); + DoubleExemplarData exemplarData = + DoubleExemplarData.create( + Attributes.builder().put("key", "value1").build(), // attributes + 1, // epochNanos + /* spanContext= */ spanContext, + /* value= */ 2.0); + assertThat(exemplarData.getValue()).isEqualTo(2.0); + assertThat(exemplarData.getEpochNanos()).isEqualTo(1); + } +} diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/DoublePointDataTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/DoublePointDataTest.java new file mode 100644 index 0000000000..c44c0dde2a --- /dev/null +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/DoublePointDataTest.java @@ -0,0 +1,27 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.data; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.common.Attributes; +import java.util.Collections; +import org.junit.jupiter.api.Test; + +class DoublePointDataTest { + + @Test + void create() { + DoublePointData pointData = + DoublePointData.create( + 1, 2, Attributes.builder().put("key", "value1").build(), 3, Collections.emptyList()); + assertThat(pointData.getStartEpochNanos()).isEqualTo(1); + assertThat(pointData.getEpochNanos()).isEqualTo(2); + assertThat(pointData.getAttributes()) + .isEqualTo(Attributes.builder().put("key", "value1").build()); + assertThat(pointData.getValue()).isEqualTo(3); + } +} diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/ExponentialHistogramBucketsTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/ExponentialHistogramBucketsTest.java new file mode 100644 index 0000000000..f496ec0454 --- /dev/null +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/ExponentialHistogramBucketsTest.java @@ -0,0 +1,23 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.data; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import org.junit.jupiter.api.Test; + +class ExponentialHistogramBucketsTest { + + @Test + void create() { + ExponentialHistogramBuckets buckets = + ExponentialHistogramBuckets.create(1, 2, Arrays.asList(3L, 4L)); + assertThat(buckets.getBucketCounts()).containsExactly(3L, 4L); + assertThat(buckets.getScale()).isEqualTo(1); + assertThat(buckets.getOffset()).isEqualTo(2); + } +} diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/ExponentialHistogramDataTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/ExponentialHistogramDataTest.java new file mode 100644 index 0000000000..28664f07cb --- /dev/null +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/ExponentialHistogramDataTest.java @@ -0,0 +1,23 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.data; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Collections; +import org.junit.jupiter.api.Test; + +class ExponentialHistogramDataTest { + + @Test + void create() { + ExponentialHistogramData histogramData = + ExponentialHistogramData.create(AggregationTemporality.CUMULATIVE, Collections.emptyList()); + assertThat(histogramData.getAggregationTemporality()) + .isEqualTo(AggregationTemporality.CUMULATIVE); + assertThat(histogramData.getPoints()).isEmpty(); + } +} diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/ExponentialHistogramPointDataTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/ExponentialHistogramPointDataTest.java new file mode 100644 index 0000000000..2e066af2e0 --- /dev/null +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/ExponentialHistogramPointDataTest.java @@ -0,0 +1,68 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.data; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.api.trace.TraceFlags; +import io.opentelemetry.api.trace.TraceState; +import io.opentelemetry.sdk.metrics.internal.data.ImmutableDoubleExemplarData; +import io.opentelemetry.sdk.metrics.internal.data.ImmutableExponentialHistogramBuckets; +import java.util.Arrays; +import java.util.Collections; +import org.junit.jupiter.api.Test; + +class ExponentialHistogramPointDataTest { + + @Test + void create() { + DoubleExemplarData doubleExemplarOne = + ImmutableDoubleExemplarData.create( + Attributes.empty(), + 0, + SpanContext.create( + "TraceId", "SpanId", TraceFlags.getDefault(), TraceState.getDefault()), + 1.0); + + DoubleExemplarData doubleExemplarTwo = + ImmutableDoubleExemplarData.create( + Attributes.empty(), + 2, + SpanContext.create( + "TraceId", "SpanId", TraceFlags.getDefault(), TraceState.getDefault()), + 2.0); + ExponentialHistogramPointData pointData = + ExponentialHistogramPointData.create( + 1, + 10.0, + 1, + /* hasMin= */ true, + 2.0, + /* hasMax= */ true, + 4.0, + ImmutableExponentialHistogramBuckets.create(1, 10, Arrays.asList(1L, 2L)), + ImmutableExponentialHistogramBuckets.create(1, 0, Collections.emptyList()), + 1, + 2, + Attributes.empty(), + Arrays.asList(doubleExemplarOne, doubleExemplarTwo)); + assertThat(pointData.getStartEpochNanos()).isEqualTo(1); + assertThat(pointData.getEpochNanos()).isEqualTo(2); + assertThat(pointData.getAttributes()).isEqualTo(Attributes.empty()); + assertThat(pointData.getSum()).isEqualTo(10.0); + assertThat(pointData.getCount()).isEqualTo(4); + assertThat(pointData.hasMin()).isTrue(); + assertThat(pointData.getMin()).isEqualTo(2.0); + assertThat(pointData.hasMax()).isTrue(); + assertThat(pointData.getMax()).isEqualTo(4.0); + assertThat(pointData.getPositiveBuckets().getTotalCount()).isEqualTo(3); + assertThat(pointData.getNegativeBuckets().getTotalCount()).isEqualTo(0); + assertThat(pointData.getPositiveBuckets().getBucketCounts()).containsExactly(1L, 2L); + assertThat(pointData.getNegativeBuckets().getBucketCounts()).isEmpty(); + } +} diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/GaugeDataTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/GaugeDataTest.java new file mode 100644 index 0000000000..85e3c73e3d --- /dev/null +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/GaugeDataTest.java @@ -0,0 +1,32 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.data; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.common.Attributes; +import java.util.Collections; +import org.junit.jupiter.api.Test; + +class GaugeDataTest { + + @Test + void createLongGaugeData() { + LongPointData point = LongPointData.create(0, 0, Attributes.empty(), 1); + GaugeData gaugeData = + GaugeData.createLongGaugeData(Collections.singleton(point)); + assertThat(gaugeData.getPoints()).containsExactly(point); + } + + @Test + void createDoubleGaugeData() { + DoublePointData point = + DoublePointData.create(0, 0, Attributes.empty(), 1.0, Collections.emptyList()); + GaugeData gaugeData = + GaugeData.createDoubleGaugeData(Collections.singleton(point)); + assertThat(gaugeData.getPoints()).containsExactly(point); + } +} diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/HistogramDataTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/HistogramDataTest.java new file mode 100644 index 0000000000..ca131e125b --- /dev/null +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/HistogramDataTest.java @@ -0,0 +1,23 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.data; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Collections; +import org.junit.jupiter.api.Test; + +class HistogramDataTest { + + @Test + void create() { + HistogramData histogramData = + HistogramData.create(AggregationTemporality.CUMULATIVE, Collections.emptyList()); + assertThat(histogramData.getAggregationTemporality()) + .isEqualTo(AggregationTemporality.CUMULATIVE); + assertThat(histogramData.getPoints()).isEmpty(); + } +} diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/HistogramPointDataTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/HistogramPointDataTest.java new file mode 100644 index 0000000000..72b132fbc8 --- /dev/null +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/HistogramPointDataTest.java @@ -0,0 +1,41 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.data; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.google.common.collect.ImmutableList; +import io.opentelemetry.api.common.Attributes; +import java.util.ArrayList; +import org.junit.jupiter.api.Test; + +class HistogramPointDataTest { + + @Test + void create() { + HistogramPointData pointData = + HistogramPointData.create( + 0, + 0, + Attributes.empty(), + 3.0, + /* hasMin= */ false, + 1.0, + /* hasMax= */ false, + 2.0, + new ArrayList<>(), + ImmutableList.of(0L)); + assertThat(pointData.getStartEpochNanos()).isEqualTo(0); + assertThat(pointData.getEpochNanos()).isEqualTo(0); + assertThat(pointData.getAttributes()).isEqualTo(Attributes.empty()); + assertThat(pointData.getSum()).isEqualTo(3.0); + assertThat(pointData.getCount()).isEqualTo(0); + assertThat(pointData.hasMin()).isFalse(); + assertThat(pointData.getMin()).isEqualTo(1.0); + assertThat(pointData.hasMax()).isFalse(); + assertThat(pointData.getMax()).isEqualTo(2.0); + } +} diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/LongExemplarDataTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/LongExemplarDataTest.java new file mode 100644 index 0000000000..25da1c9e24 --- /dev/null +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/LongExemplarDataTest.java @@ -0,0 +1,35 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.data; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.api.trace.TraceFlags; +import io.opentelemetry.api.trace.TraceState; +import org.junit.jupiter.api.Test; + +class LongExemplarDataTest { + + @Test + void create() { + Attributes attributes = Attributes.builder().put("test", "value").build(); + LongExemplarData exemplar = + LongExemplarData.create( + attributes, + 2L, + SpanContext.create( + "00000000000000000000000000000001", + "0000000000000002", + TraceFlags.getDefault(), + TraceState.getDefault()), + 1); + assertThat(exemplar.getFilteredAttributes()).isEqualTo(attributes); + assertThat(exemplar.getValue()).isEqualTo(1L); + assertThat(exemplar.getSpanContext()).isNotNull(); + } +} diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/LongPointDataTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/LongPointDataTest.java new file mode 100644 index 0000000000..7685ff2968 --- /dev/null +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/LongPointDataTest.java @@ -0,0 +1,23 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.data; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.common.Attributes; +import org.junit.jupiter.api.Test; + +class LongPointDataTest { + + @Test + void create() { + LongPointData pointData = LongPointData.create(0, 0, Attributes.empty(), 0); + assertThat(pointData.getStartEpochNanos()).isEqualTo(0); + assertThat(pointData.getEpochNanos()).isEqualTo(0); + assertThat(pointData.getAttributes()).isEqualTo(Attributes.empty()); + assertThat(pointData.getValue()).isEqualTo(0); + } +} diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/SumDataTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/SumDataTest.java new file mode 100644 index 0000000000..96f959d52a --- /dev/null +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/SumDataTest.java @@ -0,0 +1,38 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.data; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.common.Attributes; +import java.util.Collections; +import org.junit.jupiter.api.Test; + +class SumDataTest { + + @Test + void createLongSumData() { + LongPointData point = LongPointData.create(0, 0, Attributes.empty(), 1); + SumData sumData = + SumData.createLongSumData( + /* isMonotonic= */ false, + AggregationTemporality.CUMULATIVE, + Collections.singletonList(point)); + assertThat(sumData.getPoints()).containsExactly(point); + } + + @Test + void createDoubleSumData() { + DoublePointData point = + DoublePointData.create(0, 0, Attributes.empty(), 1.0, Collections.emptyList()); + SumData sumData = + SumData.createDoubleSumData( + /* isMonotonic= */ false, + AggregationTemporality.CUMULATIVE, + Collections.singletonList(point)); + assertThat(sumData.getPoints()).containsExactly(point); + } +} diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/SummaryDataTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/SummaryDataTest.java new file mode 100644 index 0000000000..729b3bf511 --- /dev/null +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/SummaryDataTest.java @@ -0,0 +1,31 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.data; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.sdk.metrics.internal.data.ImmutableSummaryData; +import io.opentelemetry.sdk.metrics.internal.data.ImmutableSummaryPointData; +import io.opentelemetry.sdk.metrics.internal.data.ImmutableValueAtQuantile; +import java.util.Collections; +import java.util.List; +import org.junit.jupiter.api.Test; + +class SummaryDataTest { + + @Test + void create() { + List percentileValues = + Collections.singletonList(ImmutableValueAtQuantile.create(3.0, 4.0)); + List points = + Collections.singletonList( + ImmutableSummaryPointData.create( + 12345, 12346, Attributes.empty(), 1, 2.0, percentileValues)); + SummaryData summary = ImmutableSummaryData.create(points); + assertThat(summary.getPoints()).isEqualTo(points); + } +} diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/SummaryPointDataTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/SummaryPointDataTest.java new file mode 100644 index 0000000000..08ba69bac5 --- /dev/null +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/SummaryPointDataTest.java @@ -0,0 +1,38 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.data; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.common.Attributes; +import java.util.Collections; +import java.util.concurrent.TimeUnit; +import org.junit.jupiter.api.Test; + +class SummaryPointDataTest { + + @Test + void create() { + AttributeKey kvAttr = AttributeKey.stringKey("key"); + long startEpochNanos = TimeUnit.MILLISECONDS.toNanos(1000); + long epochNanos = TimeUnit.MILLISECONDS.toNanos(2000); + double sum = 10.0; + long count = 5; + SummaryPointData summaryPoint = + SummaryPointData.create( + startEpochNanos, + epochNanos, + Attributes.of(kvAttr, "value"), + count, + sum, + Collections.emptyList()); + assertThat(summaryPoint.getStartEpochNanos()).isEqualTo(startEpochNanos); + assertThat(summaryPoint.getEpochNanos()).isEqualTo(epochNanos); + assertThat(summaryPoint.getSum()).isEqualTo(sum); + assertThat(summaryPoint.getCount()).isEqualTo(count); + } +} diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/ValueAtQuantileTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/ValueAtQuantileTest.java new file mode 100644 index 0000000000..ffcd37cc5d --- /dev/null +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/data/ValueAtQuantileTest.java @@ -0,0 +1,20 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.data; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +class ValueAtQuantileTest { + + @Test + void create() { + ValueAtQuantile valueAtQuantile = ValueAtQuantile.create(0.0, 1.1); + assertThat(valueAtQuantile.getQuantile()).isEqualTo(0.0); + assertThat(valueAtQuantile.getValue()).isEqualTo(1.1); + } +} diff --git a/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/metrics/TestMetricData.java b/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/metrics/TestMetricData.java new file mode 100644 index 0000000000..adeb3f783f --- /dev/null +++ b/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/metrics/TestMetricData.java @@ -0,0 +1,91 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.testing.metrics; + +import com.google.auto.value.AutoValue; +import io.opentelemetry.sdk.common.InstrumentationScopeInfo; +import io.opentelemetry.sdk.metrics.data.Data; +import io.opentelemetry.sdk.metrics.data.DoublePointData; +import io.opentelemetry.sdk.metrics.data.ExponentialHistogramData; +import io.opentelemetry.sdk.metrics.data.GaugeData; +import io.opentelemetry.sdk.metrics.data.HistogramData; +import io.opentelemetry.sdk.metrics.data.LongPointData; +import io.opentelemetry.sdk.metrics.data.MetricData; +import io.opentelemetry.sdk.metrics.data.MetricDataType; +import io.opentelemetry.sdk.metrics.data.SumData; +import io.opentelemetry.sdk.metrics.data.SummaryData; +import io.opentelemetry.sdk.resources.Resource; +import javax.annotation.concurrent.Immutable; + +/** + * Immutable representation of all data collected by the {@link + * io.opentelemetry.sdk.metrics.data.MetricData} class. + */ +@Immutable +@AutoValue +public abstract class TestMetricData implements MetricData { + public static Builder builder() { + return new AutoValue_TestMetricData.Builder() + .setResource(Resource.empty()) + .setInstrumentationScopeInfo(InstrumentationScopeInfo.empty()); + } + + /** A builder for {@link TestMetricData}. */ + @AutoValue.Builder + public abstract static class Builder { + abstract TestMetricData autoBuild(); + + public TestMetricData build() { + return autoBuild(); + } + + public abstract Builder setResource(Resource resource); + + public abstract Builder setName(String name); + + public abstract Builder setDescription(String description); + + public abstract Builder setUnit(String unit); + + // Make setType package-private to restrict direct access + abstract Builder setType(MetricDataType type); + + // Keep the generic setData method for internal use + abstract Builder setData(Data data); + + // Add specific setData overloads for each metric data type + public Builder setExponentialHistogramData(ExponentialHistogramData data) { + return setType(MetricDataType.EXPONENTIAL_HISTOGRAM).setData(data); + } + + public Builder setHistogramData(HistogramData data) { + return setType(MetricDataType.HISTOGRAM).setData(data); + } + + public Builder setLongSumData(SumData data) { + return setType(MetricDataType.LONG_SUM).setData(data); + } + + public Builder setDoubleSumData(SumData data) { + return setType(MetricDataType.DOUBLE_SUM).setData(data); + } + + public Builder setDoubleGaugeData(GaugeData data) { + return setType(MetricDataType.DOUBLE_GAUGE).setData(data); + } + + public Builder setLongGaugeData(GaugeData data) { + return setType(MetricDataType.LONG_GAUGE).setData(data); + } + + public Builder setSummaryData(SummaryData data) { + return setType(MetricDataType.SUMMARY).setData(data); + } + + public abstract Builder setInstrumentationScopeInfo( + InstrumentationScopeInfo instrumentationScopeInfo); + } +}