Add close method to MetricReader (#5109)
This commit is contained in:
parent
b300e72dab
commit
1915f1fb60
|
|
@ -4,9 +4,9 @@ import japicmp.model.JApiCompatibility
|
|||
import japicmp.model.JApiCompatibilityChange
|
||||
import japicmp.model.JApiMethod
|
||||
import me.champeau.gradle.japicmp.JapicmpTask
|
||||
import me.champeau.gradle.japicmp.report.Severity
|
||||
import me.champeau.gradle.japicmp.report.Violation
|
||||
import me.champeau.gradle.japicmp.report.stdrules.AbstractRecordingSeenMembers
|
||||
import me.champeau.gradle.japicmp.report.stdrules.BinaryIncompatibleRule
|
||||
import me.champeau.gradle.japicmp.report.stdrules.RecordSeenMembersSetup
|
||||
import me.champeau.gradle.japicmp.report.stdrules.SourceCompatibleRule
|
||||
import me.champeau.gradle.japicmp.report.stdrules.UnchangedMemberRule
|
||||
|
|
@ -32,32 +32,24 @@ val latestReleasedVersion: String by lazy {
|
|||
moduleVersion
|
||||
}
|
||||
|
||||
class AllowDefaultMethodRule : AbstractRecordingSeenMembers() {
|
||||
class AllowNewAbstractMethodOnAutovalueClasses : AbstractRecordingSeenMembers() {
|
||||
override fun maybeAddViolation(member: JApiCompatibility): Violation? {
|
||||
for (change in member.compatibilityChanges) {
|
||||
if (isAbstractMethodOnAutoValue(member, change)) {
|
||||
continue
|
||||
}
|
||||
if (!change.isSourceCompatible) {
|
||||
return Violation.error(member, "Not source compatible")
|
||||
}
|
||||
if (!change.isBinaryCompatible) {
|
||||
return Violation.notBinaryCompatible(member, Severity.error)
|
||||
}
|
||||
if (member.compatibilityChanges == listOf(JApiCompatibilityChange.METHOD_ABSTRACT_ADDED_TO_CLASS) &&
|
||||
member is JApiMethod &&
|
||||
member.getjApiClass().newClass.get().getAnnotation(AutoValue::class.java) != null
|
||||
) {
|
||||
return Violation.accept(member, "Autovalue will automatically add implementation")
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the change is an abstract method on a class annotated with AutoValue.
|
||||
* AutoValues need to override default interface methods and declare them abstract again.
|
||||
* It causes METHOD_ABSTRACT_ADDED_TO_CLASS - source-incompatible change. It's
|
||||
* false-positive since AutoValue will generate implementation anyway.
|
||||
*/
|
||||
fun isAbstractMethodOnAutoValue(member: JApiCompatibility, change: JApiCompatibilityChange): Boolean {
|
||||
return change == JApiCompatibilityChange.METHOD_ABSTRACT_ADDED_TO_CLASS &&
|
||||
member is JApiMethod &&
|
||||
member.getjApiClass().newClass.get().getAnnotation(AutoValue::class.java) != null
|
||||
class SourceIncompatibleRule : AbstractRecordingSeenMembers() {
|
||||
override fun maybeAddViolation(member: JApiCompatibility): Violation? {
|
||||
if (!member.isSourceCompatible()) {
|
||||
return Violation.error(member, "Not source compatible")
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -114,17 +106,26 @@ if (!project.hasProperty("otel.release") && !project.name.startsWith("bom")) {
|
|||
)
|
||||
|
||||
// Reproduce defaults from https://github.com/melix/japicmp-gradle-plugin/blob/09f52739ef1fccda6b4310cf3f4b19dc97377024/src/main/java/me/champeau/gradle/japicmp/report/ViolationsGenerator.java#L130
|
||||
// but allow new default methods on interfaces, adding default implementations to
|
||||
// interface methods previously abstract, and select additional customizations defined in
|
||||
// AllowDefaultMethodRule.
|
||||
compatibilityChangeExcludes.set(listOf("METHOD_NEW_DEFAULT", "METHOD_ABSTRACT_NOW_DEFAULT"))
|
||||
// with some changes.
|
||||
val exclusions = mutableListOf<String>()
|
||||
// Allow new default methods on interfaces
|
||||
exclusions.add("METHOD_NEW_DEFAULT")
|
||||
// Allow adding default implementations for default methods
|
||||
exclusions.add("METHOD_ABSTRACT_NOW_DEFAULT")
|
||||
// Bug prevents recognizing default methods of superinterface.
|
||||
// Fixed in https://github.com/siom79/japicmp/pull/343 but not yet available in me.champeau.gradle.japicmp
|
||||
exclusions.add("METHOD_ABSTRACT_ADDED_IN_IMPLEMENTED_INTERFACE")
|
||||
compatibilityChangeExcludes.set(exclusions)
|
||||
richReport {
|
||||
addSetupRule(RecordSeenMembersSetup::class.java)
|
||||
addRule(JApiChangeStatus.NEW, SourceCompatibleRule::class.java)
|
||||
addRule(JApiChangeStatus.MODIFIED, SourceCompatibleRule::class.java)
|
||||
addRule(JApiChangeStatus.UNCHANGED, UnchangedMemberRule::class.java)
|
||||
addRule(AllowDefaultMethodRule::class.java)
|
||||
addRule(SourceCompatibleRule::class.java)
|
||||
// Allow new abstract methods on autovalue
|
||||
addRule(AllowNewAbstractMethodOnAutovalueClasses::class.java)
|
||||
addRule(BinaryIncompatibleRule::class.java)
|
||||
// Disallow source incompatible changes, which are allowed by default for some reason
|
||||
addRule(SourceIncompatibleRule::class.java)
|
||||
}
|
||||
|
||||
// this is needed so that we only consider the current artifact, and not dependencies
|
||||
|
|
|
|||
|
|
@ -1,2 +1,11 @@
|
|||
Comparing source compatibility of against
|
||||
No changes.
|
||||
*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.metrics.export.MetricReader (not serializable)
|
||||
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
|
||||
+++ NEW INTERFACE: java.io.Closeable
|
||||
+++ NEW INTERFACE: java.lang.AutoCloseable
|
||||
+++ NEW METHOD: PUBLIC(+) void close()
|
||||
+++ NEW EXCEPTION: java.io.IOException
|
||||
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.sdk.metrics.export.PeriodicMetricReader (not serializable)
|
||||
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
|
||||
+++ NEW INTERFACE: java.io.Closeable
|
||||
+++ NEW INTERFACE: java.lang.AutoCloseable
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import io.opentelemetry.sdk.metrics.data.MetricData;
|
|||
import io.opentelemetry.sdk.metrics.export.CollectionRegistration;
|
||||
import io.opentelemetry.sdk.metrics.export.MetricReader;
|
||||
import io.opentelemetry.sdk.metrics.internal.export.MetricProducer;
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
|
|
@ -53,7 +52,7 @@ import javax.annotation.Nullable;
|
|||
*/
|
||||
// Very similar to
|
||||
// https://github.com/prometheus/client_java/blob/master/simpleclient_httpserver/src/main/java/io/prometheus/client/exporter/HTTPServer.java
|
||||
public final class PrometheusHttpServer implements Closeable, MetricReader {
|
||||
public final class PrometheusHttpServer implements MetricReader {
|
||||
|
||||
private static final DaemonThreadFactory THREAD_FACTORY =
|
||||
new DaemonThreadFactory("prometheus-http");
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ import io.opentelemetry.sdk.common.CompletableResultCode;
|
|||
import io.opentelemetry.sdk.metrics.Aggregation;
|
||||
import io.opentelemetry.sdk.metrics.InstrumentType;
|
||||
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* A metric reader reads metrics from an {@link SdkMeterProvider}.
|
||||
|
|
@ -18,7 +21,8 @@ import io.opentelemetry.sdk.metrics.SdkMeterProvider;
|
|||
*
|
||||
* @since 1.14.0
|
||||
*/
|
||||
public interface MetricReader extends AggregationTemporalitySelector, DefaultAggregationSelector {
|
||||
public interface MetricReader
|
||||
extends AggregationTemporalitySelector, DefaultAggregationSelector, Closeable {
|
||||
|
||||
/**
|
||||
* Called by {@link SdkMeterProvider} and supplies the {@link MetricReader} with a handle to
|
||||
|
|
@ -63,4 +67,10 @@ public interface MetricReader extends AggregationTemporalitySelector, DefaultAgg
|
|||
* @return the result of the shutdown.
|
||||
*/
|
||||
CompletableResultCode shutdown();
|
||||
|
||||
/** Close this {@link MetricReader}, releasing any resources. */
|
||||
@Override
|
||||
default void close() throws IOException {
|
||||
shutdown().join(10, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
|||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
|
@ -27,6 +28,7 @@ import io.opentelemetry.sdk.metrics.internal.data.ImmutableMetricData;
|
|||
import io.opentelemetry.sdk.metrics.internal.data.ImmutableSumData;
|
||||
import io.opentelemetry.sdk.metrics.internal.export.MetricProducer;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
|
@ -172,14 +174,13 @@ class PeriodicMetricReaderTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void oneLastExportAfterShutdown() throws Exception {
|
||||
void shutdown_ExportsOneLastTime() throws Exception {
|
||||
WaitingMetricExporter waitingMetricExporter = new WaitingMetricExporter();
|
||||
PeriodicMetricReader reader =
|
||||
PeriodicMetricReader.builder(waitingMetricExporter)
|
||||
.setInterval(Duration.ofSeconds(100))
|
||||
.setInterval(Duration.ofSeconds(Integer.MAX_VALUE))
|
||||
.build();
|
||||
reader.register(metricProducer);
|
||||
// Assume that this will be called in less than 100 seconds.
|
||||
reader.shutdown();
|
||||
|
||||
// This export was called during shutdown.
|
||||
|
|
@ -189,6 +190,19 @@ class PeriodicMetricReaderTest {
|
|||
assertThat(waitingMetricExporter.hasShutdown.get()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void close_CallsShutdown() throws IOException {
|
||||
PeriodicMetricReader reader =
|
||||
spy(
|
||||
PeriodicMetricReader.builder(new WaitingMetricExporter())
|
||||
.setInterval(Duration.ofSeconds(Integer.MAX_VALUE))
|
||||
.build());
|
||||
reader.register(metricProducer);
|
||||
reader.close();
|
||||
|
||||
verify(reader, times(1)).shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("PreferJavaTimeOverload") // Testing the overload
|
||||
void invalidConfig() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue