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

SmallRye Fault Tolerance: add support for OpenTelemetry Metrics #46636

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,39 @@

public final class OpenTelemetrySdkBuildItem extends SimpleBuildItem {

private final boolean tracingBuildTimeEnabled;
private final boolean metricsBuildTimeEnabled;
private final boolean loggingBuildTimeEnabled;

private final RuntimeValue<Boolean> runtimeEnabled;

public OpenTelemetrySdkBuildItem(RuntimeValue<Boolean> sdkEnabled) {
this.runtimeEnabled = sdkEnabled;
public OpenTelemetrySdkBuildItem(boolean tracingBuildTimeEnabled, boolean metricsBuildTimeEnabled,
boolean loggingBuildTimeEnabled, RuntimeValue<Boolean> runtimeEnabled) {
this.tracingBuildTimeEnabled = tracingBuildTimeEnabled;
this.metricsBuildTimeEnabled = metricsBuildTimeEnabled;
this.loggingBuildTimeEnabled = loggingBuildTimeEnabled;
this.runtimeEnabled = runtimeEnabled;
}

/**
* @return {@code true} if OpenTelemetry Tracing is enabled at build time
*/
public boolean isTracingBuildTimeEnabled() {
return tracingBuildTimeEnabled;
}

/**
* @return {@code true} if OpenTelemetry Metrics is enabled at build time
*/
public boolean isMetricsBuildTimeEnabled() {
return metricsBuildTimeEnabled;
}

/**
* @return {@code true} if OpenTelemetry Logging is enabled at build time
*/
public boolean isLoggingBuildTimeEnabled() {
return loggingBuildTimeEnabled;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ AdditionalBeanBuildItem ensureProducerIsRetained() {
@Record(ExecutionTime.RUNTIME_INIT)
void openTelemetryBean(OpenTelemetryRecorder recorder,
OTelRuntimeConfig oTelRuntimeConfig,
OTelBuildConfig oTelBuildConfig,
BuildProducer<SyntheticBeanBuildItem> syntheticProducer,
BuildProducer<OpenTelemetrySdkBuildItem> openTelemetrySdkBuildItemBuildProducer) {
syntheticProducer.produce(SyntheticBeanBuildItem.configure(OpenTelemetry.class)
Expand All @@ -126,8 +127,21 @@ void openTelemetryBean(OpenTelemetryRecorder recorder,
.destroyer(OpenTelemetryDestroyer.class)
.done());

openTelemetrySdkBuildItemBuildProducer.produce(
new OpenTelemetrySdkBuildItem(recorder.isOtelSdkEnabled(oTelRuntimeConfig)));
// same as `TracerEnabled`
boolean tracingEnabled = oTelBuildConfig.traces().enabled()
.map(it -> it && oTelBuildConfig.enabled())
.orElseGet(oTelBuildConfig::enabled);
// same as `MetricProcessor.MetricEnabled`
boolean metricsEnabled = oTelBuildConfig.metrics().enabled()
.map(it -> it && oTelBuildConfig.enabled())
.orElseGet(oTelBuildConfig::enabled);
// same as `LogHandlerProcessor.LogsEnabled`
boolean loggingEnabled = oTelBuildConfig.logs().enabled()
.map(it -> it && oTelBuildConfig.enabled())
.orElseGet(oTelBuildConfig::enabled);

openTelemetrySdkBuildItemBuildProducer.produce(new OpenTelemetrySdkBuildItem(
tracingEnabled, metricsEnabled, loggingEnabled, recorder.isOtelSdkEnabled(oTelRuntimeConfig)));
}

@BuildStep
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import io.quarkus.arc.deployment.AnnotationsTransformerBuildItem;
import io.quarkus.arc.deployment.BeanArchiveIndexBuildItem;
import io.quarkus.arc.deployment.BeanDefiningAnnotationBuildItem;
import io.quarkus.arc.deployment.OpenTelemetrySdkBuildItem;
import io.quarkus.arc.deployment.ValidationPhaseBuildItem;
import io.quarkus.arc.processor.AnnotationStore;
import io.quarkus.arc.processor.AnnotationsTransformer;
Expand Down Expand Up @@ -85,6 +86,7 @@ public void build(BuildProducer<AnnotationsTransformerBuildItem> annotationsTran
BuildProducer<ServiceProviderBuildItem> serviceProvider,
BuildProducer<BeanDefiningAnnotationBuildItem> additionalBda,
Optional<MetricsCapabilityBuildItem> metricsCapability,
Optional<OpenTelemetrySdkBuildItem> openTelemetrySdk,
BuildProducer<SystemPropertyBuildItem> systemProperty,
CombinedIndexBuildItem combinedIndexBuildItem,
BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
Expand Down Expand Up @@ -177,14 +179,24 @@ public void transform(TransformationContext context) {
SpecCompatibility.class,
Enablement.class);

if (metricsCapability.isEmpty()) {
builder.addBeanClass("io.smallrye.faulttolerance.metrics.NoopProvider");
} else if (metricsCapability.get().metricsSupported(MetricsFactory.MP_METRICS)) {
int metricsProviders = 0;
if (metricsCapability.isPresent() && metricsCapability.get().metricsSupported(MetricsFactory.MP_METRICS)) {
builder.addBeanClass("io.smallrye.faulttolerance.metrics.MicroProfileMetricsProvider");
} else if (metricsCapability.get().metricsSupported(MetricsFactory.MICROMETER)) {
metricsProviders++;
} else if (metricsCapability.isPresent() && metricsCapability.get().metricsSupported(MetricsFactory.MICROMETER)) {
builder.addBeanClass("io.smallrye.faulttolerance.metrics.MicrometerProvider");
metricsProviders++;
}
if (openTelemetrySdk.map(OpenTelemetrySdkBuildItem::isMetricsBuildTimeEnabled).orElse(false)) {
builder.addBeanClass("io.smallrye.faulttolerance.metrics.OpenTelemetryProvider");
Copy link
Contributor

@brunobat brunobat Mar 10, 2025

Choose a reason for hiding this comment

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

This will only be affected by the build time configuration. We are still going to instrument if the OTel SDK is disabled at runtime...
I suggest you skip the processFaultToleranceAnnotations() method (just return or skip all) in case OpenTelemetry is used and if disabled at runtime.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I cannot really do that, because I try to do a lot of things at build time and there's no runtime config at that time.

What I could do is read the runtime config and remove the OTEL metrics provider if runtime-disabled. I'm not yet sure what the best way would be -- clearly the RuntimeValue is a Quarkus-specific concept and so it cannot be in SmallRye Fault Tolerance. On the other hand, SmallRye Fault Tolerance has configuration for disabling the specific metric providers at runtime, so there might be a way to translate the OTEL config to the SRye FT config, somehow. Not yet sure how.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, that build item is only produced at runtime, even if it's published with build time data... Not sure if this will work properly and if we need different build items for OTel build and run times.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Build items are never produced at runtime. I mean, at runtime, the concept of build items and build steps doesn't even exist.

Copy link
Contributor

Choose a reason for hiding this comment

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

Right, the config values the build item holds might come from runtime.

Copy link
Contributor

@brunobat brunobat Mar 10, 2025

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that's the configuration I mentioned above. There might be a way, I just didn't have the time to explore it yet.

metricsProviders++;
}

if (metricsProviders == 0) {
builder.addBeanClass("io.smallrye.faulttolerance.metrics.NoopProvider");
} else if (metricsProviders > 1) {
builder.addBeanClass("io.smallrye.faulttolerance.metrics.CompoundMetricsProvider");
}
// TODO support for OpenTelemetry Metrics -- not present in Quarkus yet

beans.produce(builder.build());

Expand Down
28 changes: 19 additions & 9 deletions tcks/microprofile-fault-tolerance/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<!-- Disable quarkus optimization -->
<quarkus.arc.remove-unused-beans>false</quarkus.arc.remove-unused-beans>
<smallrye.faulttolerance.mp-compatibility>true</smallrye.faulttolerance.mp-compatibility>
<quarkus.otel.metrics.enabled>true</quarkus.otel.metrics.enabled>
</systemPropertyVariables>
<!-- This workaround allows us to run a single test using
the "test" system property -->
Expand All @@ -35,16 +36,8 @@
</dependenciesToScan>
<reuseForks>false</reuseForks>
<excludes>
<!-- Quarkus doesn't implement OpenTelemetry Metrics yet -->
<exclude>org.eclipse.microprofile.fault.tolerance.tck.telemetryMetrics.AllAnnotationTelemetryTest</exclude>
<exclude>org.eclipse.microprofile.fault.tolerance.tck.telemetryMetrics.BulkheadTelemetryTest</exclude>
<!-- https://github.com/microprofile/microprofile-fault-tolerance/pull/655 -->
<exclude>org.eclipse.microprofile.fault.tolerance.tck.telemetryMetrics.CircuitBreakerTelemetryTest</exclude>
<exclude>org.eclipse.microprofile.fault.tolerance.tck.telemetryMetrics.ClashingNameTelemetryTest</exclude>
<exclude>org.eclipse.microprofile.fault.tolerance.tck.telemetryMetrics.ClassLevelTelemetryTest</exclude>
<exclude>org.eclipse.microprofile.fault.tolerance.tck.telemetryMetrics.FallbackTelemetryTest</exclude>
<exclude>org.eclipse.microprofile.fault.tolerance.tck.telemetryMetrics.FaultToleranceDisabledTelemetryTest</exclude>
<exclude>org.eclipse.microprofile.fault.tolerance.tck.telemetryMetrics.RetryTelemetryTest</exclude>
<exclude>org.eclipse.microprofile.fault.tolerance.tck.telemetryMetrics.TimeoutTelemetryTest</exclude>
<!-- We do not support enablement via beans.xml -->
<exclude>org.eclipse.microprofile.fault.tolerance.tck.interceptor.xmlInterceptorEnabling.FaultToleranceInterceptorEnableByXmlTest</exclude>
</excludes>
Expand All @@ -65,6 +58,10 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-metrics</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-opentelemetry</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.microprofile.fault-tolerance</groupId>
<artifactId>microprofile-fault-tolerance-tck</artifactId>
Expand Down Expand Up @@ -98,6 +95,19 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-opentelemetry-deployment</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

</project>
Loading