diff --git a/pom.xml b/pom.xml index 747e09c..76fe103 100644 --- a/pom.xml +++ b/pom.xml @@ -7,12 +7,12 @@ org.fireflyframework fireflyframework-parent - 26.04.01 + 26.05.06 fireflyframework-idp - 26.04.01 + 26.05.06 jar Firefly Framework - Identity Provider @@ -27,6 +27,13 @@ ${project.version} + + + org.fireflyframework + fireflyframework-observability + ${project.version} + + org.springframework diff --git a/src/main/java/org/fireflyframework/idp/observability/IdpMetrics.java b/src/main/java/org/fireflyframework/idp/observability/IdpMetrics.java new file mode 100644 index 0000000..c4312d6 --- /dev/null +++ b/src/main/java/org/fireflyframework/idp/observability/IdpMetrics.java @@ -0,0 +1,68 @@ +/* + * Copyright 2024-2026 Firefly Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.fireflyframework.idp.observability; + +import io.micrometer.core.instrument.MeterRegistry; +import org.fireflyframework.observability.metrics.FireflyMetricsSupport; +import reactor.core.publisher.Mono; + +/** + * Observability instrumentation shared by all Firefly IDP adapter implementations. + *

+ * Records: + *

+ */ +public class IdpMetrics extends FireflyMetricsSupport { + + private static final String TAG_PROVIDER = "provider"; + private static final String TAG_OPERATION = "operation"; + private static final String TAG_TOKEN_TYPE = "token.type"; + + public IdpMetrics(MeterRegistry meterRegistry) { + super(meterRegistry, "idp"); + } + + /** + * Wraps an authentication call (login, validate-token, etc.) with a timer and success/failure counters. + */ + public Mono timedAuthentication(String provider, Mono operation) { + return timed("authentication.duration", operation, TAG_PROVIDER, provider) + .doOnSuccess(v -> recordSuccess("authentications", TAG_PROVIDER, provider)) + .doOnError(e -> { + recordFailure("authentications", e, TAG_PROVIDER, provider); + recordFailure("errors", e, TAG_OPERATION, "authenticate", TAG_PROVIDER, provider); + }); + } + + public void recordTokenIssued(String provider, String tokenType) { + counter("token.issued", TAG_PROVIDER, provider, TAG_TOKEN_TYPE, tokenType).increment(); + } + + public void recordTokenRefreshed(String provider) { + counter("token.refreshed", TAG_PROVIDER, provider).increment(); + } + + public void recordError(String provider, String operation, Throwable error) { + recordFailure("errors", error, TAG_PROVIDER, provider, TAG_OPERATION, operation); + } +} diff --git a/src/main/java/org/fireflyframework/idp/observability/IdpObservabilityAutoConfiguration.java b/src/main/java/org/fireflyframework/idp/observability/IdpObservabilityAutoConfiguration.java new file mode 100644 index 0000000..9d434aa --- /dev/null +++ b/src/main/java/org/fireflyframework/idp/observability/IdpObservabilityAutoConfiguration.java @@ -0,0 +1,43 @@ +/* + * Copyright 2024-2026 Firefly Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.fireflyframework.idp.observability; + +import io.micrometer.core.instrument.MeterRegistry; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; + +/** + * Auto-configures the {@link IdpMetrics} bean used by all IDP adapter implementations + * (AWS Cognito, Azure AD, Keycloak, internal DB). + */ +@AutoConfiguration +@ConditionalOnClass(MeterRegistry.class) +@ConditionalOnProperty(prefix = "firefly.observability.metrics", name = "enabled", + havingValue = "true", matchIfMissing = true) +public class IdpObservabilityAutoConfiguration { + + @Bean + @ConditionalOnMissingBean + @ConditionalOnBean(MeterRegistry.class) + IdpMetrics idpMetrics(MeterRegistry meterRegistry) { + return new IdpMetrics(meterRegistry); + } +} diff --git a/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 379ba2b..6de5313 100644 --- a/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1 +1,2 @@ org.fireflyframework.idp.config.IdpWebAutoConfiguration +org.fireflyframework.idp.observability.IdpObservabilityAutoConfiguration