This is an automated email from the ASF dual-hosted git repository. jamesnetherton pushed a commit to branch 3.33.x in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
commit cbeaaf5217ea6a4d0d085bfdc4c1fcf9cb108929 Author: James Netherton <[email protected]> AuthorDate: Tue Jun 23 14:08:19 2026 +0100 Ensure Micrometer app.info metric version tag resolves correctly for all Quarkus package types --- .../micrometer/deployment/MicrometerProcessor.java | 54 ++++++++++++++++++++++ .../micrometer/it/MicrometerResource.java | 18 ++++++++ .../component/micrometer/it/MicrometerTest.java | 15 +++++- 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/extensions/micrometer/deployment/src/main/java/org/apache/camel/quarkus/component/micrometer/deployment/MicrometerProcessor.java b/extensions/micrometer/deployment/src/main/java/org/apache/camel/quarkus/component/micrometer/deployment/MicrometerProcessor.java index 1bc904c4ed..ee0755b448 100644 --- a/extensions/micrometer/deployment/src/main/java/org/apache/camel/quarkus/component/micrometer/deployment/MicrometerProcessor.java +++ b/extensions/micrometer/deployment/src/main/java/org/apache/camel/quarkus/component/micrometer/deployment/MicrometerProcessor.java @@ -20,10 +20,13 @@ import java.util.List; import java.util.Optional; import io.micrometer.core.instrument.MeterRegistry; +import io.quarkus.builder.Version; import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.deployment.annotations.ExecutionTime; import io.quarkus.deployment.annotations.Record; +import io.quarkus.deployment.builditem.BytecodeTransformerBuildItem; import io.quarkus.deployment.builditem.FeatureBuildItem; +import io.quarkus.gizmo.Gizmo; import io.quarkus.micrometer.deployment.MicrometerProcessor.MicrometerEnabled; import io.quarkus.micrometer.deployment.MicrometerRegistryProviderBuildItem; import io.quarkus.micrometer.deployment.RootMeterRegistryBuildItem; @@ -33,6 +36,9 @@ import org.apache.camel.quarkus.component.micrometer.CamelMicrometerRecorder; import org.apache.camel.quarkus.core.deployment.spi.CamelBeanBuildItem; import org.apache.camel.quarkus.core.deployment.spi.CamelContextCustomizerBuildItem; import org.apache.camel.quarkus.core.deployment.spi.RuntimeCamelContextCustomizerBuildItem; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; class MicrometerProcessor { @@ -81,4 +87,52 @@ class MicrometerProcessor { recorder.configureDefaultRegistry(registry.get().getValue()); } } + + @BuildStep + BytecodeTransformerBuildItem generateRuntimeInfoMetricVersion() { + // Force the app.info metric version tag value, to avoid runtime usages of reflection + // and other dynamic version lookup strategies that may not work with all Quarkus package + // types. Such as uber-jar and native images + String quarkusVersion = Version.getVersion(); + return new BytecodeTransformerBuildItem.Builder() + .setClassToTransform( + "org.apache.camel.component.micrometer.json.AbstractMicrometerService$RuntimeInfo") + .setCacheable(true) + .setVisitorFunction( + (className, classVisitor) -> new RuntimeInfoClassVisitor(classVisitor, quarkusVersion)) + .build(); + } + + static class RuntimeInfoClassVisitor extends ClassVisitor { + private final String quarkusVersion; + + protected RuntimeInfoClassVisitor(ClassVisitor classVisitor, String quarkusVersion) { + super(Gizmo.ASM_API_VERSION, classVisitor); + this.quarkusVersion = quarkusVersion; + } + + @Override + public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, + String[] exceptions) { + MethodVisitor original = super.visitMethod(access, name, descriptor, signature, exceptions); + if ("scan".equals(name)) { + return new MethodVisitor(Gizmo.ASM_API_VERSION, original) { + @Override + public void visitCode() { + super.visitCode(); + visitLdcInsn(quarkusVersion); + visitMethodInsn(Opcodes.INVOKESTATIC, "java/util/Optional", "of", + "(Ljava/lang/Object;)Ljava/util/Optional;", false); + visitInsn(Opcodes.ARETURN); + } + + @Override + public void visitMaxs(int maxStack, int maxLocals) { + super.visitMaxs(1, 1); + } + }; + } + return original; + } + } } diff --git a/integration-tests/micrometer/src/main/java/org/apache/camel/quarkus/component/micrometer/it/MicrometerResource.java b/integration-tests/micrometer/src/main/java/org/apache/camel/quarkus/component/micrometer/it/MicrometerResource.java index a4dcff44e5..50b24d0bb6 100644 --- a/integration-tests/micrometer/src/main/java/org/apache/camel/quarkus/component/micrometer/it/MicrometerResource.java +++ b/integration-tests/micrometer/src/main/java/org/apache/camel/quarkus/component/micrometer/it/MicrometerResource.java @@ -17,11 +17,14 @@ package org.apache.camel.quarkus.component.micrometer.it; import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.NoSuchElementException; import java.util.concurrent.TimeUnit; +import io.micrometer.core.instrument.Gauge; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Tag; import io.micrometer.core.instrument.Tags; @@ -229,4 +232,19 @@ public class MicrometerResource { producerTemplate.sendBody("direct:dumpAsJson", "hello"); return Response.ok().build(); } + + @Path("/appInfo") + @Produces(MediaType.APPLICATION_JSON) + @GET + public Response appInfo() { + Gauge appInfo = prometheusMeterRegistry.find("app.info").gauge(); + if (appInfo == null) { + return Response.status(500).entity("app.info appInfo not found").build(); + } + Map<String, String> tags = new HashMap<>(); + for (Tag tag : appInfo.getId().getTags()) { + tags.put(tag.getKey(), tag.getValue()); + } + return Response.ok(tags).build(); + } } diff --git a/integration-tests/micrometer/src/test/java/org/apache/camel/quarkus/component/micrometer/it/MicrometerTest.java b/integration-tests/micrometer/src/test/java/org/apache/camel/quarkus/component/micrometer/it/MicrometerTest.java index ec18e5aa14..e456bc3f7e 100644 --- a/integration-tests/micrometer/src/test/java/org/apache/camel/quarkus/component/micrometer/it/MicrometerTest.java +++ b/integration-tests/micrometer/src/test/java/org/apache/camel/quarkus/component/micrometer/it/MicrometerTest.java @@ -38,6 +38,8 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -207,7 +209,7 @@ class MicrometerTest extends AbstractMicrometerTest { return filteredResult.values().stream().map(String::valueOf).collect(Collectors.joining()); }, //1 exchange with completed status should be caught - Matchers.is("1")); + is("1")); } @ParameterizedTest @@ -255,6 +257,17 @@ class MicrometerTest extends AbstractMicrometerTest { } + @Test + void testAppInfo() { + RestAssured.get("/micrometer/appInfo") + .then() + .statusCode(200) + .body("'camel.runtime.provider'", is("Quarkus")) + // Avoid matching against explicit versions as it could change if the Quarkus Platform is updated with a new Quarkus Core + .body("'camel.runtime.version'", not(Matchers.emptyString())) + .body("'camel.context'", is("quarkus-camel-micrometer")); + } + @Test public void micrometerHistoryShouldBeAvailableThroughCamelContext() throws Exception { JsonPath jsonPath = RestAssured.get("/micrometer/history")
