diff --git a/common/src/main/java/org/keycloak/common/Profile.java b/common/src/main/java/org/keycloak/common/Profile.java index 5b42fd067d5..e1601bafed7 100755 --- a/common/src/main/java/org/keycloak/common/Profile.java +++ b/common/src/main/java/org/keycloak/common/Profile.java @@ -137,9 +137,7 @@ public class Profile { OPENTELEMETRY("OpenTelemetry support", Type.DEFAULT), OPENTELEMETRY_LOGS("OpenTelemetry Logs support", Type.PREVIEW, OPENTELEMETRY), - OPENTELEMETRY_METRICS("Micrometer to OpenTelemetry bridge support for metrics", Type.EXPERIMENTAL, 1, false, true, - () -> isClassAvailable("io.quarkus.micrometer.opentelemetry.runtime.MicrometerOtelBridgeRecorder"), - null, OPENTELEMETRY), + OPENTELEMETRY_METRICS("Micrometer to OpenTelemetry bridge support for metrics", Type.EXPERIMENTAL, OPENTELEMETRY), DECLARATIVE_UI("declarative ui spi", Type.EXPERIMENTAL), @@ -189,7 +187,6 @@ public class Profile { private final String unversionedKey; private final String key; private final BooleanSupplier isAvailable; - private final boolean hideWhenUnavailable; private final FeatureUpdatePolicy updatePolicy; private final Set dependencies; private final boolean deprecated; @@ -216,16 +213,11 @@ public class Profile { } Feature(String label, Type type, int version, boolean deprecated, BooleanSupplier isAvailable, FeatureUpdatePolicy updatePolicy, Feature... dependencies) { - this(label, type, version, deprecated, false, isAvailable, updatePolicy, dependencies); - } - - Feature(String label, Type type, int version, boolean deprecated, boolean hideWhenUnavailable, BooleanSupplier isAvailable, FeatureUpdatePolicy updatePolicy, Feature... dependencies) { this.label = label; this.type = type; this.version = version; this.deprecated = type == Type.DEPRECATED || deprecated; this.isAvailable = isAvailable; - this.hideWhenUnavailable = hideWhenUnavailable; this.updatePolicy = updatePolicy == null ? FeatureUpdatePolicy.ROLLING : updatePolicy; this.key = name().toLowerCase().replaceAll("_", "-"); if (this.name().endsWith("_V" + version)) { @@ -291,10 +283,6 @@ public class Profile { return updatePolicy; } - private boolean isVisible() { - return isAvailable() || !hideWhenUnavailable; - } - public enum Type { // in priority order @@ -471,18 +459,11 @@ public class Profile { } public static Set getAllUnversionedFeatureNames() { - return Collections.unmodifiableSet(getOrderedFeatures().entrySet().stream() - .filter(e -> e.getValue().stream().anyMatch(Feature::isVisible)) - .map(Map.Entry::getKey) - .collect(Collectors.toSet())); + return Collections.unmodifiableSet(getOrderedFeatures().keySet()); } public static Set getDisableableUnversionedFeatureNames() { - return getOrderedFeatures().entrySet().stream() - .filter(e -> !ESSENTIAL_FEATURES.contains(e.getKey())) - .filter(e -> e.getValue().stream().anyMatch(Feature::isVisible)) - .map(Map.Entry::getKey) - .collect(Collectors.toSet()); + return getOrderedFeatures().keySet().stream().filter(f -> !ESSENTIAL_FEATURES.contains(f)).collect(Collectors.toSet()); } /** @@ -601,15 +582,6 @@ public class Profile { } } - private static boolean isClassAvailable(String className) { - try { - Class.forName(className); - return true; - } catch (ClassNotFoundException e) { - return false; - } - } - public enum FeatureUpdatePolicy { // Always allow a rolling update when the Feature is enabled/disabled ROLLING, diff --git a/docs/guides/observability/telemetry.adoc b/docs/guides/observability/telemetry.adoc index 778118bd9e5..7c6e5721be7 100644 --- a/docs/guides/observability/telemetry.adoc +++ b/docs/guides/observability/telemetry.adoc @@ -152,8 +152,6 @@ As stated for the general configuration of headers, you can configure custom req <@kc.start parameters="--telemetry-logs-header-Authorization='Bearer logs-token'"/> -<@profile.ifCommunity> - == Metrics WARNING: The OpenTelemetry Metrics feature is currently experimental, and it is not recommended for use in production. @@ -180,6 +178,8 @@ As stated for the general configuration of headers, you can configure custom req <@kc.start parameters="--telemetry-metrics-header-Authorization='Bearer metrics-token'"/> +<@profile.ifCommunity> + == Development setup For development purposes, you can use the https://github.com/grafana/docker-otel-lgtm[Grafana OTel-LGTM service], containing OpenTelemetry Collector and backends for logs (Loki), metrics (Prometheus), and traces (Tempo). @@ -206,10 +206,8 @@ Then, you can navigate to Grafana UI by accessing `+localhost:3000+` and then yo === Logs <@opts.includeOptions includedOptions="telemetry-logs-*"/> -<@profile.ifCommunity> === Metrics <@opts.includeOptions includedOptions="metrics-enabled telemetry-metrics-*"/> - diff --git a/quarkus/deployment/pom.xml b/quarkus/deployment/pom.xml index 35f4306b512..1c8061d8952 100644 --- a/quarkus/deployment/pom.xml +++ b/quarkus/deployment/pom.xml @@ -204,6 +204,11 @@ io.quarkus quarkus-opentelemetry-deployment + + io.quarkus + quarkus-micrometer-opentelemetry-deployment + + io.quarkus quarkus-junit5-internal @@ -261,21 +266,4 @@ - - - community - - - !product - - - - - io.quarkus - quarkus-micrometer-opentelemetry-deployment - - - - - diff --git a/quarkus/runtime/pom.xml b/quarkus/runtime/pom.xml index 36504659e43..3cd1e24a8f3 100644 --- a/quarkus/runtime/pom.xml +++ b/quarkus/runtime/pom.xml @@ -121,6 +121,11 @@ io.opentelemetry.instrumentation opentelemetry-apache-httpclient-4.3 + + io.quarkus + quarkus-micrometer-opentelemetry + + com.apicatalog titanium-json-ld @@ -851,19 +856,5 @@ - - community - - - !product - - - - - io.quarkus - quarkus-micrometer-opentelemetry - - - diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/IgnoredArtifacts.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/IgnoredArtifacts.java index 497186a437b..65e7c3e97a7 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/IgnoredArtifacts.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/IgnoredArtifacts.java @@ -28,7 +28,6 @@ import org.keycloak.config.MetricsOptions; import org.keycloak.config.OpenApiOptions; import org.keycloak.config.TelemetryOptions; import org.keycloak.config.database.Database; -import org.keycloak.quarkus.runtime.cli.PropertyException; import static java.util.Collections.emptySet; @@ -188,9 +187,6 @@ public class IgnoredArtifacts { private static Set otelMetrics() { boolean isOtelMetricsEnabled = Configuration.isTrue(TelemetryOptions.TELEMETRY_METRICS_ENABLED); - if (isOtelMetricsEnabled && !Profile.Feature.OPENTELEMETRY_METRICS.isAvailable()) { - throw new PropertyException("The OpenTelemetry Metrics feature is not available in this distribution."); - } return !isOtelMetricsEnabled ? OTEL_METRICS : emptySet(); } diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/TelemetryPropertyMappers.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/TelemetryPropertyMappers.java index 57e7ebb5ace..737e1e9f72a 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/TelemetryPropertyMappers.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/configuration/mappers/TelemetryPropertyMappers.java @@ -58,7 +58,6 @@ public class TelemetryPropertyMappers implements PropertyMapperGrouping{ @Override public List> getPropertyMappers() { TELEMETRY_HEADERS_CACHE = null; - boolean metricsAvailable = Profile.Feature.OPENTELEMETRY_METRICS.isAvailable(); return List.of( fromFeature(Profile.Feature.OPENTELEMETRY) .transformer(TelemetryPropertyMappers::checkIfDependantsAreEnabled) @@ -128,36 +127,36 @@ public class TelemetryPropertyMappers implements PropertyMapperGrouping{ .isMasked(true) // it may contain sensitive information .build(), // Telemetry Metrics - fromOption(metricsAvailable ? TELEMETRY_METRICS_ENABLED : toHidden(TELEMETRY_METRICS_ENABLED)) + fromOption(TELEMETRY_METRICS_ENABLED) .isEnabled(TelemetryPropertyMappers::isOtelMetricsFeatureEnabled, OTEL_METRICS_FEATURE_ENABLED_MSG) .to("quarkus.otel.metrics.enabled") .build(), - fromOption(metricsAvailable ? TELEMETRY_METRICS_ENDPOINT : toHidden(TELEMETRY_METRICS_ENDPOINT)) + fromOption(TELEMETRY_METRICS_ENDPOINT) .isEnabled(TelemetryPropertyMappers::isTelemetryMetricsEnabled, OTEL_METRICS_ENABLED_MSG) .mapFrom(TelemetryOptions.TELEMETRY_ENDPOINT) .to("quarkus.otel.exporter.otlp.metrics.endpoint") .paramLabel("url") .validator(TelemetryPropertyMappers::validateEndpoint) .build(), - fromOption(metricsAvailable ? TELEMETRY_METRICS_PROTOCOL : toHidden(TELEMETRY_METRICS_PROTOCOL)) + fromOption(TELEMETRY_METRICS_PROTOCOL) .isEnabled(TelemetryPropertyMappers::isTelemetryMetricsEnabled, OTEL_METRICS_ENABLED_MSG) .mapFrom(TelemetryOptions.TELEMETRY_PROTOCOL) .to("quarkus.otel.exporter.otlp.metrics.protocol") .paramLabel("protocol") .build(), - fromOption(metricsAvailable ? TELEMETRY_METRICS_INTERVAL : toHidden(TELEMETRY_METRICS_INTERVAL)) + fromOption(TELEMETRY_METRICS_INTERVAL) .isEnabled(TelemetryPropertyMappers::isTelemetryMetricsEnabled, OTEL_METRICS_ENABLED_MSG) .to("quarkus.otel.metric.export.interval") .paramLabel("duration") .validator(TelemetryPropertyMappers::validateDuration) .build(), - fromOption(metricsAvailable ? TELEMETRY_METRICS_HEADERS : toHidden(TELEMETRY_METRICS_HEADERS)) + fromOption(TELEMETRY_METRICS_HEADERS) .isEnabled(TelemetryPropertyMappers::isTelemetryMetricsEnabled, OTEL_METRICS_ENABLED_MSG) .to("quarkus.otel.exporter.otlp.metrics.headers") .transformer((value, context) -> transformTelemetryHeaders(TELEMETRY_METRICS_HEADER, value)) .isMasked(true) .build(), - fromOption(metricsAvailable ? TELEMETRY_METRICS_HEADER : toHidden(TELEMETRY_METRICS_HEADER)) + fromOption(TELEMETRY_METRICS_HEADER) .isEnabled(TelemetryPropertyMappers::isTelemetryMetricsEnabled, OTEL_METRICS_ENABLED_MSG) .paramLabel("") .isMasked(true) // it may contain sensitive information @@ -165,10 +164,6 @@ public class TelemetryPropertyMappers implements PropertyMapperGrouping{ ); } - private static Option toHidden(Option option) { - return option.toBuilder().hidden().build(); - } - private static String checkIfDependantsAreEnabled(String value, ConfigSourceInterceptorContext context) { if (TelemetryPropertyMappers.isTelemetryLogsEnabled() || TelemetryPropertyMappers.isTelemetryMetricsEnabled() || TracingPropertyMappers.isTracingEnabled()) { return Boolean.TRUE.toString(); diff --git a/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/cli/PicocliTest.java b/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/cli/PicocliTest.java index 1959d3c6227..d818769e2c3 100644 --- a/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/cli/PicocliTest.java +++ b/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/cli/PicocliTest.java @@ -36,7 +36,6 @@ import org.keycloak.quarkus.runtime.configuration.AbstractConfigurationTest; import org.keycloak.quarkus.runtime.configuration.PersistedConfigSource; import org.apache.commons.io.FileUtils; -import org.junit.Assume; import org.junit.Ignore; import org.junit.Test; import picocli.CommandLine; @@ -1073,7 +1072,6 @@ public class PicocliTest extends AbstractConfigurationTest { @Test public void telemetryParentHeaders() { - Assume.assumeTrue(Profile.Feature.OPENTELEMETRY_METRICS.isAvailable()); // tracing enabled var nonRunningPicocli = pseudoLaunch("start-dev", "--tracing-enabled=true", "--telemetry-header-Authorization=Bearer asdlkfjadsflkj"); assertNoError(nonRunningPicocli); @@ -1162,7 +1160,6 @@ public class PicocliTest extends AbstractConfigurationTest { @Test public void otelMetricsHeaders() { - Assume.assumeTrue(Profile.Feature.OPENTELEMETRY_METRICS.isAvailable()); // Otel Metrics is disabled var nonRunningPicocli = pseudoLaunch("start-dev", "--features=opentelemetry-metrics", "--metrics-enabled=true", "--telemetry-metrics-enabled=false", "--telemetry-metrics-header-Authorization=Bearer"); assertError(nonRunningPicocli, "Unknown option:"); //for some reason, the wildcard options does not respect the isEnabled() when disabled @@ -1648,7 +1645,6 @@ public class PicocliTest extends AbstractConfigurationTest { @Test public void otelMetrics() { - Assume.assumeTrue(Profile.Feature.OPENTELEMETRY_METRICS.isAvailable()); // parent feature disabled NonRunningPicocli nonRunningPicocli = pseudoLaunch("start-dev", "--feature-opentelemetry=disabled", "--feature-opentelemetry-metrics=enabled"); assertEquals(CommandLine.ExitCode.USAGE, nonRunningPicocli.exitCode); @@ -1802,7 +1798,6 @@ public class PicocliTest extends AbstractConfigurationTest { @Test public void otelAll() { - Assume.assumeTrue(Profile.Feature.OPENTELEMETRY_METRICS.isAvailable()); // tracing pseudoLaunch("start-dev", "--tracing-enabled=true"); assertConfig("tracing-enabled", "true"); diff --git a/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/configuration/IgnoredArtifactsTest.java b/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/configuration/IgnoredArtifactsTest.java index 8f84d4f7973..f9b722e5471 100644 --- a/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/configuration/IgnoredArtifactsTest.java +++ b/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/configuration/IgnoredArtifactsTest.java @@ -50,7 +50,6 @@ import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.in; import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeTrue; public class IgnoredArtifactsTest extends AbstractConfigurationTest { @@ -160,7 +159,6 @@ public class IgnoredArtifactsTest extends AbstractConfigurationTest { @Test public void otelMetrics(){ - assumeTrue(Profile.Feature.OPENTELEMETRY_METRICS.isAvailable()); assertIgnoredArtifacts(IgnoredArtifacts.OTEL_METRICS, TelemetryOptions.TELEMETRY_METRICS_ENABLED); } diff --git a/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/configuration/TelemetryConfigurationTest.java b/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/configuration/TelemetryConfigurationTest.java index 972bd54dc84..3fcd53db4e2 100644 --- a/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/configuration/TelemetryConfigurationTest.java +++ b/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/configuration/TelemetryConfigurationTest.java @@ -2,9 +2,6 @@ package org.keycloak.quarkus.runtime.configuration; import java.util.Map; -import org.keycloak.common.Profile; - -import org.junit.Assume; import org.junit.Test; public class TelemetryConfigurationTest extends AbstractConfigurationTest { @@ -129,7 +126,6 @@ public class TelemetryConfigurationTest extends AbstractConfigurationTest { @Test public void metricsDefaults() { - Assume.assumeTrue(Profile.Feature.OPENTELEMETRY_METRICS.isAvailable()); initConfig(); assertConfig(Map.of( @@ -150,7 +146,6 @@ public class TelemetryConfigurationTest extends AbstractConfigurationTest { @Test public void metricsPriorities() { - Assume.assumeTrue(Profile.Feature.OPENTELEMETRY_METRICS.isAvailable()); ConfigArgsConfigSource.setCliArgs("--features=opentelemetry-metrics", "--metrics-enabled=true", "--telemetry-metrics-enabled=true", "--telemetry-metrics-endpoint=localhost:2000", "--telemetry-metrics-protocol=http/protobuf"); initConfig(); assertConfig(Map.of( diff --git a/services/pom.xml b/services/pom.xml index 29ab9c651ab..3336ce6bac7 100755 --- a/services/pom.xml +++ b/services/pom.xml @@ -128,12 +128,6 @@ - - - io.quarkus - quarkus-micrometer-opentelemetry - test - org.apache.httpcomponents httpclient