-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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
Add meaningful tests for OTEL client #13831
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
import static io.opentelemetry.api.common.AttributeKey.stringKey; | ||
import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.SERVICE_NAME; | ||
|
||
import com.google.common.annotations.VisibleForTesting; | ||
import io.opentelemetry.api.OpenTelemetry; | ||
import io.opentelemetry.api.common.Attributes; | ||
import io.opentelemetry.api.common.AttributesBuilder; | ||
|
@@ -20,14 +21,18 @@ | |
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; | ||
import io.opentelemetry.sdk.OpenTelemetrySdk; | ||
import io.opentelemetry.sdk.metrics.SdkMeterProvider; | ||
import io.opentelemetry.sdk.metrics.export.MetricExporter; | ||
import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader; | ||
import io.opentelemetry.sdk.resources.Resource; | ||
import io.opentelemetry.sdk.testing.exporter.InMemoryMetricExporter; | ||
import io.opentelemetry.sdk.trace.SdkTracerProvider; | ||
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; | ||
|
||
public class OpenTelemetryMetricClient implements MetricClient { | ||
|
||
private Meter meter; | ||
private MetricExporter metricExporter; | ||
private SdkMeterProvider meterProvider; | ||
|
||
@Override | ||
public void count(MetricsRegistry metric, long val, String... tags) { | ||
|
@@ -75,9 +80,33 @@ public void initialize(MetricEmittingApp metricEmittingApp, String otelEndpoint) | |
.build()) | ||
.setResource(resource) | ||
.build(); | ||
OtlpGrpcMetricExporter metricExporter = OtlpGrpcMetricExporter.builder() | ||
metricExporter = OtlpGrpcMetricExporter.builder() | ||
.setEndpoint(otelEndpoint).build(); | ||
SdkMeterProvider meterProvider = SdkMeterProvider.builder() | ||
initialize(metricEmittingApp, sdkTracerProvider, resource); | ||
} | ||
|
||
@VisibleForTesting | ||
void initializeWithInMemoryExporter(MetricEmittingApp metricEmittingApp) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if this is only for testing, it is worth moving this out and placing it in the test class? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure - good call. moved |
||
Resource resource = Resource.getDefault().toBuilder().put(SERVICE_NAME, metricEmittingApp.getApplicationName()).build(); | ||
metricExporter = InMemoryMetricExporter.create(); | ||
SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder() | ||
.setResource(resource) | ||
.build(); | ||
initialize(metricEmittingApp, sdkTracerProvider, resource); | ||
} | ||
|
||
@VisibleForTesting | ||
InMemoryMetricExporter getInMemoryMetricExporter() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is there a reason to explicitly return can we make a generic getter function There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure - moved the casting in the test class |
||
return (InMemoryMetricExporter) metricExporter; | ||
} | ||
|
||
@VisibleForTesting | ||
SdkMeterProvider getSdkMeterProvider() { | ||
return meterProvider; | ||
} | ||
|
||
private void initialize(MetricEmittingApp metricEmittingApp, SdkTracerProvider sdkTracerProvider, Resource resource) { | ||
meterProvider = SdkMeterProvider.builder() | ||
.registerMetricReader(PeriodicMetricReader.builder(metricExporter).build()) | ||
.setResource(resource) | ||
.build(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,21 +4,32 @@ | |
|
||
package io.airbyte.metrics.lib; | ||
|
||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat; | ||
|
||
import com.google.common.collect.Iterables; | ||
import io.opentelemetry.api.common.AttributeKey; | ||
import io.opentelemetry.sdk.metrics.SdkMeterProvider; | ||
import io.opentelemetry.sdk.metrics.data.MetricData; | ||
import io.opentelemetry.sdk.testing.exporter.InMemoryMetricExporter; | ||
import java.util.List; | ||
import org.junit.jupiter.api.AfterEach; | ||
import org.junit.jupiter.api.Assertions; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
|
||
class OpenTelemetryMetricClientTest { | ||
|
||
OpenTelemetryMetricClient openTelemetryMetricClient; | ||
private final static String EXPORTER_ENDPOINT = "http://localhost:4322"; | ||
private final static String TAG = "tag1"; | ||
private InMemoryMetricExporter metricExporter; | ||
private SdkMeterProvider metricProvider; | ||
|
||
@BeforeEach | ||
void setUp() { | ||
openTelemetryMetricClient = new OpenTelemetryMetricClient(); | ||
openTelemetryMetricClient.initialize(MetricEmittingApps.WORKER, EXPORTER_ENDPOINT); | ||
openTelemetryMetricClient.initializeWithInMemoryExporter(MetricEmittingApps.WORKER); | ||
metricExporter = openTelemetryMetricClient.getInMemoryMetricExporter(); | ||
metricProvider = openTelemetryMetricClient.getSdkMeterProvider(); | ||
} | ||
|
||
@AfterEach | ||
|
@@ -27,27 +38,63 @@ void tearDown() { | |
} | ||
|
||
@Test | ||
@DisplayName("there should be no exception if we attempt to emit metrics while publish is false") | ||
public void testPublishTrueNoEmitError() { | ||
Assertions.assertDoesNotThrow(() -> { | ||
openTelemetryMetricClient.gauge(OssMetricsRegistry.KUBE_POD_PROCESS_CREATE_TIME_MILLISECS, 1); | ||
}); | ||
@DisplayName("Should send out count metric with correct metric name, description and value") | ||
public void testCountSuccess() { | ||
openTelemetryMetricClient.count(OssMetricsRegistry.KUBE_POD_PROCESS_CREATE_TIME_MILLISECS, 1); | ||
|
||
metricProvider.forceFlush(); | ||
List<MetricData> metricDataList = metricExporter.getFinishedMetricItems(); | ||
MetricData data = Iterables.getOnlyElement(metricDataList); | ||
|
||
assertThat(data.getName()).isEqualTo(OssMetricsRegistry.KUBE_POD_PROCESS_CREATE_TIME_MILLISECS.getMetricName()); | ||
assertThat(data.getDescription()).isEqualTo(OssMetricsRegistry.KUBE_POD_PROCESS_CREATE_TIME_MILLISECS.getMetricDescription()); | ||
assertThat(data.getLongSumData().getPoints().stream().anyMatch(longPointData -> longPointData.getValue() == 1L)); | ||
} | ||
|
||
@Test | ||
@DisplayName("Tags should be passed into metrics") | ||
public void testCountWithTagSuccess() { | ||
openTelemetryMetricClient.count(OssMetricsRegistry.KUBE_POD_PROCESS_CREATE_TIME_MILLISECS, 1, TAG); | ||
|
||
metricProvider.forceFlush(); | ||
List<MetricData> metricDataList = metricExporter.getFinishedMetricItems(); | ||
MetricData data = Iterables.getOnlyElement(metricDataList); | ||
|
||
assertThat(data.getName()).isEqualTo(OssMetricsRegistry.KUBE_POD_PROCESS_CREATE_TIME_MILLISECS.getMetricName()); | ||
assertThat(data.getDescription()).isEqualTo(OssMetricsRegistry.KUBE_POD_PROCESS_CREATE_TIME_MILLISECS.getMetricDescription()); | ||
assertThat(data.getLongSumData().getPoints().stream() | ||
.anyMatch( | ||
longPointData -> longPointData.getValue() == 1L && longPointData.getAttributes().get(AttributeKey.stringKey(TAG)).equals(TAG))); | ||
} | ||
|
||
@Test | ||
@DisplayName("there should be no exception if we attempt to emit metrics while publish is true") | ||
public void testPublishFalseNoEmitError() { | ||
Assertions.assertDoesNotThrow(() -> { | ||
openTelemetryMetricClient.gauge(OssMetricsRegistry.KUBE_POD_PROCESS_CREATE_TIME_MILLISECS, 1); | ||
}); | ||
@DisplayName("Should send out gauge metric with correct metric name, description and value") | ||
public void testGaugeSuccess() throws Exception { | ||
openTelemetryMetricClient.gauge(OssMetricsRegistry.KUBE_POD_PROCESS_CREATE_TIME_MILLISECS, 1); | ||
|
||
metricProvider.forceFlush(); | ||
List<MetricData> metricDataList = metricExporter.getFinishedMetricItems(); | ||
MetricData data = Iterables.getOnlyElement(metricDataList); | ||
|
||
assertThat(data.getName()).isEqualTo(OssMetricsRegistry.KUBE_POD_PROCESS_CREATE_TIME_MILLISECS.getMetricName()); | ||
assertThat(data.getDescription()).isEqualTo(OssMetricsRegistry.KUBE_POD_PROCESS_CREATE_TIME_MILLISECS.getMetricDescription()); | ||
assertThat(data.getDoubleGaugeData().getPoints().stream().anyMatch(doublePointData -> doublePointData.getValue() == 1.0)); | ||
} | ||
|
||
@Test | ||
@DisplayName("there should be no exception if we attempt to emit metrics without initializing") | ||
@DisplayName("Should send out histogram metric with correct metric name, description and value") | ||
public void testNoInitializeNoEmitError() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this function name be changed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oops sure, fixed |
||
Assertions.assertDoesNotThrow(() -> { | ||
openTelemetryMetricClient.gauge(OssMetricsRegistry.KUBE_POD_PROCESS_CREATE_TIME_MILLISECS, 1); | ||
}); | ||
openTelemetryMetricClient.distribution(OssMetricsRegistry.KUBE_POD_PROCESS_CREATE_TIME_MILLISECS, 10); | ||
openTelemetryMetricClient.distribution(OssMetricsRegistry.KUBE_POD_PROCESS_CREATE_TIME_MILLISECS, 30); | ||
|
||
metricProvider.forceFlush(); | ||
List<MetricData> metricDataList = metricExporter.getFinishedMetricItems(); | ||
MetricData data = Iterables.getOnlyElement(metricDataList); | ||
|
||
assertThat(data.getName()).isEqualTo(OssMetricsRegistry.KUBE_POD_PROCESS_CREATE_TIME_MILLISECS.getMetricName()); | ||
assertThat(data.getDescription()).isEqualTo(OssMetricsRegistry.KUBE_POD_PROCESS_CREATE_TIME_MILLISECS.getMetricDescription()); | ||
assertThat(data.getHistogramData().getPoints().stream().anyMatch(histogramPointData -> histogramPointData.getMax() == 30.0)); | ||
assertThat(data.getHistogramData().getPoints().stream().anyMatch(histogramPointData -> histogramPointData.getMin() == 10.0)); | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice rename