diff --git a/microprofile/grpc/metrics/pom.xml b/microprofile/grpc/metrics/pom.xml
index a3d3878525f..dec7b83636d 100644
--- a/microprofile/grpc/metrics/pom.xml
+++ b/microprofile/grpc/metrics/pom.xml
@@ -42,6 +42,10 @@
- * This extension will process annotated types that are gRPC methods and
- * ensure that those methods re properly intercepted with a gRPC metrics
- * {@link io.grpc.ServerInterceptor}.
- *
- * If a method is discovered that is annotated with both a metrics annotation and a gRPC
- * method type annotation they metrics annotation will be effectively removed from the CDI
- * bean so that normal Helidon metrics interceptors do not also intercept that method.
+ * This extension instantiates and enrolls with the metrics CDI extension a metrics annotation discovery observer and a metrics
+ * registration observer. It records them for later use by the {@code MetricsConfigurer}.
*/
-public class GrpcMetricsCdiExtension
- implements Extension {
-
- static final int OBSERVER_PRIORITY = Interceptor.Priority.APPLICATION;
-
- static final EnumMap
+ * The discovery event describes the executable to which the metric annotation applies. + * This is not necessarily where the annotation appears, because a metric annotation which appears on the + * type applies to all methods and constructors on that type. + * In that case, the discovery event describes the discovery of the metric as applied + * to the method or constructor, not to the type itself. + * Further, a metric annotation declared at the type level triggers a separate discovery event for each constructor + * and method on the type. + *
+ */ +public interface MetricAnnotationDiscovery { + + /** + * Returns the configurator for the annotated type containing the site to which the metric annotation applies. + * + * @return the configurator for the annotated type + */ + AnnotatedTypeConfigurator> annotatedTypeConfigurator(); + + /** + * Returns the {@link java.lang.annotation.Annotation} object for the metric annotation discovered. + * + * @return the annotation object for the metrics annotation + */ + Annotation annotation(); + + /** + * Requests that the discovery be deactivated, thereby preventing it from triggering a metric registration. + */ + void deactivate(); + + /** + * Requests that the default metrics interceptor not be used for the metric corresponding to the indicated annotation + * which appears on this method. + */ + void disableDefaultInterceptor(); + + /** + * + * @return if the discovery is active (i.e., has not been deactivated) + */ + boolean isActive(); + + /** + * Discovery of an annotation of interest on a constructor. + */ + interface OfConstructor extends MetricAnnotationDiscovery { + + /** + * @return the configurator for the constructor on which an annotation of interest appears + */ + AnnotatedConstructorConfigurator> configurator(); + } + + /** + * Discovery of an annotation of interest on a method. + */ + interface OfMethod extends MetricAnnotationDiscovery { + + /** + * @return the configurotor for the method on which an annotation of interest appears + */ + AnnotatedMethodConfigurator> configurator(); + } +} diff --git a/microprofile/metrics/src/main/java/io/helidon/microprofile/metrics/MetricAnnotationDiscoveryBase.java b/microprofile/metrics/src/main/java/io/helidon/microprofile/metrics/MetricAnnotationDiscoveryBase.java new file mode 100644 index 00000000000..3c1c6ba0855 --- /dev/null +++ b/microprofile/metrics/src/main/java/io/helidon/microprofile/metrics/MetricAnnotationDiscoveryBase.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2022 Oracle and/or its affiliates. + * + * 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 io.helidon.microprofile.metrics; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Member; +import java.util.StringJoiner; + +import jakarta.enterprise.inject.spi.configurator.AnnotatedConstructorConfigurator; +import jakarta.enterprise.inject.spi.configurator.AnnotatedMethodConfigurator; +import jakarta.enterprise.inject.spi.configurator.AnnotatedTypeConfigurator; + +/** + * Implementation of metrics annotation discovery event. + *+ * The {@link jakarta.enterprise.inject.spi.configurator.AnnotatedConstructorConfigurator} and + * {@link jakarta.enterprise.inject.spi.configurator.AnnotatedMethodConfigurator} interfaces share no common ancestor, so + * we have two subtypes of discovery, one for each: + * {@link MetricAnnotationDiscoveryBase.OfConstructor OfConstructor} and + * {@link MetricAnnotationDiscovery.OfMethod ofMethod}. + *
+ * + */ +abstract class MetricAnnotationDiscoveryBase implements MetricAnnotationDiscovery { + + private final AnnotatedTypeConfigurator> annotatedTypeConfigurator; + private final Annotation annotation; + + private boolean isActive = true; + private boolean useDefaultInterceptor = true; + + private MetricAnnotationDiscoveryBase(AnnotatedTypeConfigurator> annotatedTypeConfigurator, + Annotation annotation) { + this.annotatedTypeConfigurator = annotatedTypeConfigurator; + this.annotation = annotation; + } + + static- * Instead, see {@link MatchingType}. - *
- * - * @param element element - * @param annotClass annotation class - * @param clazz class - * @param
* Earlier versions of this class detected app-provided producer fields and methods and triggered creation and registration
- * of the corresponding metrics upon such detection. As explained in
- * https://github.com/eclipse/microprofile-metrics/issues/456 and https://github.com/eclipse/microprofile-metrics/pull/594
+ * of the corresponding metrics upon such detection. As explained in this
+ * MP metrics issue
+ * and this MP metrics PR,
* this probably was never correct and does not work because {@code @Metric} no longer applies to producers per the
* MP metrics 3.0 spec. The issue and PR discussion explain how developers who provide their own producers should use
* CDI qualifiers on the producers (and, therefore, injection points) to avoid ambiguity between their own producers and
@@ -122,12 +126,16 @@ public class MetricsCdiExtension extends HelidonRestCdiExtension
+ * Implementations make themselves known via the Java service loader mechanism.
+ *
+ * Observers are notified during {@code ProcessAnnotatedType}, for each metric annotation that is
+ * discovered to apply to an executable, via a
+ * {@link io.helidon.microprofile.metrics.MetricAnnotationDiscovery} event.
+ *
+ * Implementations make themselves known via the Java service loader mechanism.
+ *
+ * Once registered, the observer is notified each time a metric required by a metric annotation is registered.
+ *