You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2022/10/26 11:36:08 UTC

[camel] 01/04: CAMEL-18650: camel-micrometer - Add dev console. Reuse created MetricRegistry if none exists.

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 91c68bd69788efc5ad0f660619fbcdb20d193799
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Oct 26 13:17:53 2022 +0200

    CAMEL-18650: camel-micrometer - Add dev console. Reuse created MetricRegistry if none exists.
---
 components/camel-micrometer/pom.xml                |  10 +-
 .../org/apache/camel/dev-console/micrometer        |   2 +
 .../component/micrometer/MicrometerConsole.java    | 188 +++++++++++++++++++++
 .../component/micrometer/MicrometerEndpoint.java   |   2 +-
 .../component/micrometer/MicrometerUtils.java      |  12 +-
 .../micrometer/MicrometerComponentTest.java        |  13 --
 .../messagehistory/ManagedMessageHistoryTest.java  |   1 -
 7 files changed, 206 insertions(+), 22 deletions(-)

diff --git a/components/camel-micrometer/pom.xml b/components/camel-micrometer/pom.xml
index 4f9642a51bd..938c73f76df 100644
--- a/components/camel-micrometer/pom.xml
+++ b/components/camel-micrometer/pom.xml
@@ -38,9 +38,10 @@
             <artifactId>camel-support</artifactId>
         </dependency>
         <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-databind</artifactId>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-console</artifactId>
         </dependency>
+
         <dependency>
             <groupId>io.micrometer</groupId>
             <artifactId>micrometer-core</artifactId>
@@ -53,6 +54,11 @@
             <optional>true</optional>
         </dependency>
 
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+
         <!-- testing -->
         <dependency>
             <groupId>org.apache.camel</groupId>
diff --git a/components/camel-micrometer/src/generated/resources/META-INF/services/org/apache/camel/dev-console/micrometer b/components/camel-micrometer/src/generated/resources/META-INF/services/org/apache/camel/dev-console/micrometer
new file mode 100644
index 00000000000..6d80ff62594
--- /dev/null
+++ b/components/camel-micrometer/src/generated/resources/META-INF/services/org/apache/camel/dev-console/micrometer
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.micrometer.MicrometerConsole
diff --git a/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/MicrometerConsole.java b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/MicrometerConsole.java
new file mode 100644
index 00000000000..021b7073c74
--- /dev/null
+++ b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/MicrometerConsole.java
@@ -0,0 +1,188 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.camel.component.micrometer;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import io.micrometer.core.instrument.Counter;
+import io.micrometer.core.instrument.DistributionSummary;
+import io.micrometer.core.instrument.Gauge;
+import io.micrometer.core.instrument.LongTaskTimer;
+import io.micrometer.core.instrument.Meter;
+import io.micrometer.core.instrument.MeterRegistry;
+import org.apache.camel.impl.console.AbstractDevConsole;
+import org.apache.camel.spi.annotations.DevConsole;
+import org.apache.camel.util.json.JsonObject;
+
+@DevConsole("micrometer")
+public class MicrometerConsole extends AbstractDevConsole {
+
+    public MicrometerConsole() {
+        super("camel", "micrometer", "Micrometer", "Display runtime metrics");
+    }
+
+    @Override
+    protected String doCallText(Map<String, Object> options) {
+        StringBuilder sb = new StringBuilder();
+
+        MeterRegistry mr = lookupMeterRegistry();
+        int i = 0;
+        for (Meter m : mr.getMeters()) {
+            if (m instanceof Counter) {
+                Counter c = (Counter) m;
+                if (i == 0) {
+                    sb.append("Counters:\n");
+                }
+                i++;
+                String name = c.getId().getName();
+                double cnt = c.count();
+                sb.append(String.format("    %s: %s\n", name, cnt));
+            }
+        }
+        i = 0;
+        for (Meter m : mr.getMeters()) {
+            if (m instanceof Gauge) {
+                Gauge g = (Gauge) m;
+                if (i == 0) {
+                    sb.append("\nGauges:\n");
+                }
+                i++;
+                String name = g.getId().getName();
+                double cnt = g.value();
+                sb.append(String.format("    %s: %s\n", name, cnt));
+            }
+        }
+        i = 0;
+        for (Meter m : mr.getMeters()) {
+            if (m instanceof LongTaskTimer) {
+                LongTaskTimer t = (LongTaskTimer) m;
+                if (i == 0) {
+                    sb.append("\nLongTaskTimer:\n");
+                }
+                i++;
+                String name = t.getId().getName();
+                int tasks = t.activeTasks();
+                double mean = t.mean(TimeUnit.MILLISECONDS);
+                double max = t.max(TimeUnit.MILLISECONDS);
+                double duration = t.duration(TimeUnit.MILLISECONDS);
+                sb.append(String.format("    %s: %d (duration: %f mean: %f max: %f)\n", name, tasks, duration, mean, max));
+            }
+        }
+        i = 0;
+        for (Meter m : mr.getMeters()) {
+            if (m instanceof DistributionSummary) {
+                DistributionSummary d = (DistributionSummary) m;
+                if (i == 0) {
+                    sb.append("\nDistributionSummary:\n");
+                }
+                i++;
+                String name = d.getId().getName();
+                long count = d.count();
+                double mean = d.mean();
+                double max = d.max();
+                double total = d.totalAmount();
+                sb.append(String.format("    %s: %d (total: %f mean: %f max: %f)\n", name, count, total, mean, max));
+            }
+        }
+
+        return sb.toString();
+    }
+
+    @Override
+    protected JsonObject doCallJson(Map<String, Object> options) {
+        JsonObject root = new JsonObject();
+
+        MeterRegistry mr = lookupMeterRegistry();
+        int i = 0;
+        for (Meter m : mr.getMeters()) {
+            final List<JsonObject> list = new ArrayList<>();
+            if (m instanceof Counter) {
+                Counter c = (Counter) m;
+                if (i == 0) {
+                    root.put("counters", list);
+                }
+                i++;
+                JsonObject jo = new JsonObject();
+                jo.put("name", c.getId().getName());
+                jo.put("count", c.count());
+                list.add(jo);
+            }
+        }
+        i = 0;
+        for (Meter m : mr.getMeters()) {
+            final List<JsonObject> list = new ArrayList<>();
+            if (m instanceof Gauge) {
+                Gauge g = (Gauge) m;
+                if (i == 0) {
+                    root.put("gauges", list);
+                }
+                i++;
+                JsonObject jo = new JsonObject();
+                jo.put("name", g.getId().getName());
+                jo.put("value", g.value());
+                list.add(jo);
+            }
+        }
+        i = 0;
+        for (Meter m : mr.getMeters()) {
+            if (m instanceof LongTaskTimer) {
+                final List<JsonObject> list = new ArrayList<>();
+                LongTaskTimer t = (LongTaskTimer) m;
+                if (i == 0) {
+                    root.put("timers", list);
+                }
+                i++;
+                JsonObject jo = new JsonObject();
+                jo.put("name", t.getId().getName());
+                jo.put("activeTasks", t.activeTasks());
+                jo.put("mean", t.mean(TimeUnit.MILLISECONDS));
+                jo.put("max", t.max(TimeUnit.MILLISECONDS));
+                jo.put("duration", t.duration(TimeUnit.MILLISECONDS));
+                list.add(jo);
+            }
+        }
+        i = 0;
+        for (Meter m : mr.getMeters()) {
+            if (m instanceof DistributionSummary) {
+                final List<JsonObject> list = new ArrayList<>();
+                DistributionSummary d = (DistributionSummary) m;
+                if (i == 0) {
+                    root.put("distribution", list);
+                }
+                i++;
+                JsonObject jo = new JsonObject();
+                jo.put("name", d.getId().getName());
+                jo.put("count", d.count());
+                jo.put("mean", d.mean());
+                jo.put("max", d.max());
+                jo.put("totalAmount", d.totalAmount());
+                list.add(jo);
+            }
+        }
+
+        return root;
+    }
+
+    private MeterRegistry lookupMeterRegistry() {
+        return MicrometerUtils.getOrCreateMeterRegistry(getCamelContext().getRegistry(),
+                MicrometerConstants.METRICS_REGISTRY_NAME);
+    }
+
+}
diff --git a/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/MicrometerEndpoint.java b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/MicrometerEndpoint.java
index f459a2cfe13..a2ca49af90f 100644
--- a/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/MicrometerEndpoint.java
+++ b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/MicrometerEndpoint.java
@@ -41,7 +41,7 @@ public class MicrometerEndpoint extends DefaultEndpoint {
 
     protected MeterRegistry registry;
 
-    @UriPath(description = "Type of metrics", enums = "counter, distribution_summary, timer")
+    @UriPath(description = "Type of metrics", enums = "counter,distribution_summary,timer")
     @Metadata(required = true)
     protected final Meter.Type metricsType;
     @UriPath(description = "Name of metrics")
diff --git a/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/MicrometerUtils.java b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/MicrometerUtils.java
index 4639a440f7d..3236043a697 100644
--- a/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/MicrometerUtils.java
+++ b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/MicrometerUtils.java
@@ -56,13 +56,15 @@ public abstract class MicrometerUtils {
         }
     }
 
-    public static MeterRegistry getOrCreateMeterRegistry(Registry camelRegistry, String registryName) {
-        LOG.debug("Looking up MeterRegistry from Camel Registry for name \"{}\"", registryName);
-        MeterRegistry result = getMeterRegistryFromCamelRegistry(camelRegistry, registryName);
+    public static MeterRegistry getOrCreateMeterRegistry(Registry camelRegistry, String name) {
+        MeterRegistry result = getMeterRegistryFromCamelRegistry(camelRegistry, name);
         if (result == null) {
-            LOG.debug("MeterRegistry not found from Camel Registry for name \"{}\"", registryName);
-            LOG.info("Creating new default MeterRegistry");
+            LOG.debug("Creating new MeterRegistry: {}", name);
             result = createMeterRegistry();
+            // enlist in registry so it can be reused
+            camelRegistry.bind(name, result);
+        } else {
+            LOG.debug("Using existing MeterRegistry: {}", name);
         }
         return result;
     }
diff --git a/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/MicrometerComponentTest.java b/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/MicrometerComponentTest.java
index 1698b2de9d6..142004e9dfd 100644
--- a/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/MicrometerComponentTest.java
+++ b/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/MicrometerComponentTest.java
@@ -39,7 +39,6 @@ import org.mockito.junit.jupiter.MockitoExtension;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.instanceOf;
 import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.not;
 import static org.hamcrest.Matchers.notNullValue;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.mockito.Mockito.times;
@@ -156,18 +155,6 @@ public class MicrometerComponentTest {
         inOrder.verifyNoMoreInteractions();
     }
 
-    @Test
-    public void testGetOrCreateMetricRegistryNotFoundInCamelRegistry() {
-        when(camelRegistry.lookupByNameAndType("name", MeterRegistry.class)).thenReturn(null);
-        when(camelRegistry.findByType(MeterRegistry.class)).thenReturn(Collections.emptySet());
-        MeterRegistry result = MicrometerUtils.getOrCreateMeterRegistry(camelRegistry, "name");
-        assertThat(result, is(notNullValue()));
-        assertThat(result, is(not(metricRegistry)));
-        inOrder.verify(camelRegistry, times(1)).lookupByNameAndType("name", MeterRegistry.class);
-        inOrder.verify(camelRegistry, times(1)).findByType(MeterRegistry.class);
-        inOrder.verifyNoMoreInteractions();
-    }
-
     @Test
     public void testGetMetricRegistryFromCamelRegistry() {
         when(camelRegistry.lookupByNameAndType("name", MeterRegistry.class)).thenReturn(metricRegistry);
diff --git a/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/messagehistory/ManagedMessageHistoryTest.java b/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/messagehistory/ManagedMessageHistoryTest.java
index 548530e862f..ce1e0bd1993 100644
--- a/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/messagehistory/ManagedMessageHistoryTest.java
+++ b/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/messagehistory/ManagedMessageHistoryTest.java
@@ -99,7 +99,6 @@ public class ManagedMessageHistoryTest extends CamelTestSupport {
         // there should be 3 mbeans
         Set<ObjectName> set
                 = getMBeanServer().queryNames(new ObjectName("org.apache.camel.micrometer:type=timers,name=*"), null);
-        System.out.println(set);
         assertEquals(3, set.size());
 
         ObjectName fooMBean = set.stream().filter(on -> on.getCanonicalName().contains("foo")).findFirst()