Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added DelegatingMetricData & TestMetricData Classes #6225

Draft
wants to merge 15 commits into
base: main
Choose a base branch
from
15 changes: 14 additions & 1 deletion docs/apidiffs/current_vs_latest/opentelemetry-sdk-metrics.txt
@@ -1,2 +1,15 @@
Comparing source compatibility of against
No changes.
+++ 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()
18 changes: 17 additions & 1 deletion docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt
@@ -1,2 +1,18 @@
Comparing source compatibility of against
No changes.
+++ 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 setData(io.opentelemetry.sdk.metrics.data.Data<?>)
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.testing.metrics.TestMetricData$Builder setDescription(java.lang.String)
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.testing.metrics.TestMetricData$Builder setInstrumentationScopeInfo(io.opentelemetry.sdk.common.InstrumentationScopeInfo)
+++ 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(+) ABSTRACT(+) io.opentelemetry.sdk.testing.metrics.TestMetricData$Builder setType(io.opentelemetry.sdk.metrics.data.MetricDataType)
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.testing.metrics.TestMetricData$Builder setUnit(java.lang.String)
@@ -0,0 +1,124 @@
/*
* 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;
import javax.annotation.Nullable;

/**
* A {@link MetricData} which delegates all methods to another {@link MetricData}. Extend this class
* to modify the {@link MetricData} that will be exported.
*/
public abstract class DelegatingMetricData implements MetricData {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may want to provide delegating version of the *PointData interfaces as well (or maybe just make the existing immutable implementations public!). This PR will allow you to easily override resource, scope, name, description, unit, but you still need to bring your own implementation of the Data and PointData interfaces.


private final MetricData delegate;

protected DelegatingMetricData(MetricData delegate) {
this.delegate = requireNonNull(delegate, "delegate");
}

@Override
public Resource getResource() {
return delegate.getResource();
}

@Override
public InstrumentationScopeInfo getInstrumentationScopeInfo() {
return delegate.getInstrumentationScopeInfo();
}

@Override
public String getName() {
return delegate.getName();
}

@Override
public String getDescription() {
return delegate.getDescription();
}

@Override
public String getUnit() {
return delegate.getUnit();
}

@Override
public MetricDataType getType() {
return delegate.getType();
}

@Override
public Data<?> getData() {
return delegate.getData();
}

@Override
public boolean equals(@Nullable Object o) {
if (o == this) {
return true;

Check warning on line 64 in sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java

View check run for this annotation

Codecov / codecov/patch

sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java#L64

Added line #L64 was not covered by tests
}
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;

Check warning on line 76 in sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java

View check run for this annotation

Codecov / codecov/patch

sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java#L76

Added line #L76 was not covered by tests
}

@Override
public int hashCode() {
int result = 1;
result *= 1000003;
result ^= this.getResource().hashCode();
result *= 1000003;
result ^= this.getInstrumentationScopeInfo().hashCode();
result *= 1000003;
result ^= this.getName().hashCode();
result *= 1000003;
result ^= this.getDescription().hashCode();
result *= 1000003;
result ^= this.getUnit().hashCode();
result *= 1000003;
result ^= this.getType().hashCode();
result *= 1000003;
result ^= this.getData().hashCode();
return result;

Check warning on line 96 in sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java

View check run for this annotation

Codecov / codecov/patch

sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java#L81-L96

Added lines #L81 - L96 were not covered by tests
}

@Override
public String toString() {
return "DelegatingMetricData{"

Check warning on line 101 in sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java

View check run for this annotation

Codecov / codecov/patch

sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java#L101

Added line #L101 was not covered by tests
+ "resource="
+ getResource()

Check warning on line 103 in sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java

View check run for this annotation

Codecov / codecov/patch

sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java#L103

Added line #L103 was not covered by tests
+ ", "
+ "instrumentationScopeInfo="
+ getInstrumentationScopeInfo()

Check warning on line 106 in sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java

View check run for this annotation

Codecov / codecov/patch

sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java#L106

Added line #L106 was not covered by tests
+ ", "
+ "name="
+ getName()

Check warning on line 109 in sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java

View check run for this annotation

Codecov / codecov/patch

sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java#L109

Added line #L109 was not covered by tests
+ ", "
+ "description="
+ getDescription()

Check warning on line 112 in sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java

View check run for this annotation

Codecov / codecov/patch

sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java#L112

Added line #L112 was not covered by tests
+ ", "
+ "unit="
+ getUnit()

Check warning on line 115 in sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java

View check run for this annotation

Codecov / codecov/patch

sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java#L115

Added line #L115 was not covered by tests
+ ", "
+ "type="
+ getType()

Check warning on line 118 in sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java

View check run for this annotation

Codecov / codecov/patch

sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java#L118

Added line #L118 was not covered by tests
+ ", "
+ "data="
+ getData()

Check warning on line 121 in sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java

View check run for this annotation

Codecov / codecov/patch

sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/data/DelegatingMetricData.java#L121

Added line #L121 was not covered by tests
+ "}";
}
}
@@ -0,0 +1,78 @@
/*
* 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.sdk.common.InstrumentationScopeInfo;
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 {

private static final class NoOpDelegatingMetricData extends DelegatingMetricData {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#nit: Can you move these static classes to the bottom of the file?

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;
}
}

@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);
}

private static TestMetricData.Builder createBasicMetricBuilder() {
return TestMetricData.builder()
.setResource(Resource.empty())
.setInstrumentationScopeInfo(InstrumentationScopeInfo.empty())
.setDescription("")
.setUnit("1")
.setName("name")
.setData(ImmutableSummaryData.empty())
.setType(MetricDataType.SUMMARY); // Not sure what type should be here
}
}
@@ -0,0 +1,107 @@
/*
* 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.MetricData;
import io.opentelemetry.sdk.metrics.data.MetricDataType;
import io.opentelemetry.sdk.metrics.internal.data.ImmutableSummaryData;
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())
.setName("name")
.setInstrumentationScopeInfo(InstrumentationScopeInfo.empty())
.setDescription("description")
.setUnit("1")
.setData(ImmutableSummaryData.empty())
.setType(MetricDataType.SUMMARY);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure setting data and type to arbitrary selections is better than omitting them.

Also, the value of this is limited without usable Data and PointData implementations.

@jkwatson WDYT about adding static create methods to all the interfaces in the io.opentelemetry.sdk.metrics.data? These could return the internal immutable implementations, without requiring that we make all those classes public.

}

/** A builder for {@link TestMetricData}. */
@AutoValue.Builder
public abstract static class Builder {
abstract TestMetricData autoBuild();

/**
* Builds and returns a new {@link MetricData} instance from the data in {@code this}.
*
* @return a new {@link MetricData} instance.
*/
public TestMetricData build() {
return autoBuild();
}

/**
* Sets the resource of the metric.
*
* @param resource the resource of the metric.
* @return this.
*/
public abstract Builder setResource(Resource resource);

/**
* Sets the name of the metric.
*
* @param name the name of the metric.
* @return this.
*/
public abstract Builder setName(String name);

/**
* Sets the description of the metric.
*
* @param description the description of the metric.
* @return this.
*/
public abstract Builder setDescription(String description);

/**
* Sets the unit of the metric.
*
* @param unit the unit of the metric.
* @return this.
*/
public abstract Builder setUnit(String unit);

/**
* Sets the type of the metric.
*
* @param type the type of the metric.
* @return this.
*/
public abstract Builder setType(MetricDataType type);

/**
* Sets the data of the metric.
*
* @param data the data of the metric.
* @return this.
*/
public abstract Builder setData(Data<?> data);

/**
* Sets the Instrumentation scope of the metric.
*
* @param instrumentationScopeInfo the instrumentation scope of the tracer which created this
* metric.
* @return this.
*/
public abstract Builder setInstrumentationScopeInfo(
InstrumentationScopeInfo instrumentationScopeInfo);
}
}