-
Notifications
You must be signed in to change notification settings - Fork 858
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Disable http and rpc metrics when advice can not be applied (#10671)
- Loading branch information
Showing
8 changed files
with
164 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
72 changes: 72 additions & 0 deletions
72
...api/src/main/java/io/opentelemetry/instrumentation/api/internal/OperationMetricsUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.instrumentation.api.internal; | ||
|
||
import io.opentelemetry.api.common.Attributes; | ||
import io.opentelemetry.api.metrics.DoubleHistogramBuilder; | ||
import io.opentelemetry.api.metrics.Meter; | ||
import io.opentelemetry.context.Context; | ||
import io.opentelemetry.extension.incubator.metrics.ExtendedDoubleHistogramBuilder; | ||
import io.opentelemetry.instrumentation.api.instrumenter.OperationListener; | ||
import io.opentelemetry.instrumentation.api.instrumenter.OperationMetrics; | ||
import java.util.function.BiConsumer; | ||
import java.util.function.Function; | ||
import java.util.logging.Level; | ||
import java.util.logging.Logger; | ||
|
||
/** | ||
* This class is internal and is hence not for public use. Its APIs are unstable and can change at | ||
* any time. | ||
*/ | ||
public class OperationMetricsUtil { | ||
private static final Logger logger = Logger.getLogger(OperationMetricsUtil.class.getName()); | ||
private static final OperationListener NOOP_OPERATION_LISTENER = | ||
new OperationListener() { | ||
|
||
@Override | ||
public Context onStart(Context context, Attributes startAttributes, long startNanos) { | ||
return context; | ||
} | ||
|
||
@Override | ||
public void onEnd(Context context, Attributes endAttributes, long endNanos) {} | ||
}; | ||
|
||
public static OperationMetrics create( | ||
String description, Function<Meter, OperationListener> factory) { | ||
return create( | ||
description, | ||
factory, | ||
(s, histogramBuilder) -> | ||
logger.log( | ||
Level.WARNING, | ||
"Disabling {0} metrics because {1} does not implement {2}. This prevents using " | ||
+ "metrics advice, which could result in {0} having high cardinality attributes.", | ||
new Object[] { | ||
description, | ||
histogramBuilder.getClass().getName(), | ||
ExtendedDoubleHistogramBuilder.class.getName() | ||
})); | ||
} | ||
|
||
// visible for testing | ||
static OperationMetrics create( | ||
String description, | ||
Function<Meter, OperationListener> factory, | ||
BiConsumer<String, DoubleHistogramBuilder> warningEmitter) { | ||
return meter -> { | ||
DoubleHistogramBuilder histogramBuilder = meter.histogramBuilder("compatibility-test"); | ||
if (!(histogramBuilder instanceof ExtendedDoubleHistogramBuilder) | ||
&& !histogramBuilder.getClass().getName().contains("NoopDoubleHistogram")) { | ||
warningEmitter.accept(description, histogramBuilder); | ||
return NOOP_OPERATION_LISTENER; | ||
} | ||
return factory.apply(meter); | ||
}; | ||
} | ||
|
||
private OperationMetricsUtil() {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
78 changes: 78 additions & 0 deletions
78
...src/test/java/io/opentelemetry/instrumentation/api/internal/OperationMetricsUtilTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.instrumentation.api.internal; | ||
|
||
import io.opentelemetry.api.metrics.DoubleHistogramBuilder; | ||
import io.opentelemetry.api.metrics.Meter; | ||
import io.opentelemetry.api.metrics.MeterProvider; | ||
import io.opentelemetry.instrumentation.api.instrumenter.OperationMetrics; | ||
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; | ||
import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; | ||
import java.lang.reflect.Proxy; | ||
import java.util.concurrent.atomic.AtomicBoolean; | ||
import org.assertj.core.api.Assertions; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.RegisterExtension; | ||
|
||
class OperationMetricsUtilTest { | ||
@RegisterExtension | ||
static final InstrumentationExtension testing = LibraryInstrumentationExtension.create(); | ||
|
||
@Test | ||
void noWarning() { | ||
AtomicBoolean warning = new AtomicBoolean(false); | ||
OperationMetrics operationMetrics = | ||
OperationMetricsUtil.create( | ||
"test metrics", meter -> null, (s, doubleHistogramBuilder) -> warning.set(true)); | ||
operationMetrics.create(testing.getOpenTelemetry().getMeter("test")); | ||
|
||
Assertions.assertThat(warning).isFalse(); | ||
} | ||
|
||
@Test | ||
void noWarningWithNoopMetrics() { | ||
AtomicBoolean warning = new AtomicBoolean(false); | ||
OperationMetrics operationMetrics = | ||
OperationMetricsUtil.create( | ||
"test metrics", meter -> null, (s, doubleHistogramBuilder) -> warning.set(true)); | ||
operationMetrics.create(MeterProvider.noop().get("test")); | ||
|
||
Assertions.assertThat(warning).isFalse(); | ||
} | ||
|
||
@Test | ||
void warning() { | ||
AtomicBoolean warning = new AtomicBoolean(false); | ||
OperationMetrics operationMetrics = | ||
OperationMetricsUtil.create( | ||
"test metrics", meter -> null, (s, doubleHistogramBuilder) -> warning.set(true)); | ||
Meter defaultMeter = MeterProvider.noop().get("test"); | ||
Meter meter = | ||
(Meter) | ||
Proxy.newProxyInstance( | ||
Meter.class.getClassLoader(), | ||
new Class<?>[] {Meter.class}, | ||
(proxy, method, args) -> { | ||
if ("histogramBuilder".equals(method.getName())) { | ||
// proxy the histogram builder so that the builder instance does not implement | ||
// ExtendedDoubleHistogramBuilder which will trigger the warning | ||
return proxyDoubleHistogramBuilder(defaultMeter); | ||
} | ||
return method.invoke(defaultMeter, args); | ||
}); | ||
operationMetrics.create(meter); | ||
|
||
Assertions.assertThat(warning).isTrue(); | ||
} | ||
|
||
private static DoubleHistogramBuilder proxyDoubleHistogramBuilder(Meter meter) { | ||
return (DoubleHistogramBuilder) | ||
Proxy.newProxyInstance( | ||
DoubleHistogramBuilder.class.getClassLoader(), | ||
new Class<?>[] {DoubleHistogramBuilder.class}, | ||
(proxy1, method1, args1) -> meter.histogramBuilder((String) args1[0])); | ||
} | ||
} |