GERONIMO-6653 tomcat extension
authorRomain Manni-Bucau <rmannibucau@gmail.com>
Thu, 25 Oct 2018 16:21:50 +0000 (18:21 +0200)
committerRomain Manni-Bucau <rmannibucau@gmail.com>
Thu, 25 Oct 2018 16:21:50 +0000 (18:21 +0200)
15 files changed:
geronimo-metrics-extensions/geronimo-metrics-extension-common/pom.xml [new file with mode: 0644]
geronimo-metrics-extensions/geronimo-metrics-extension-common/src/main/java/org/apache/geronimo/microprofile/metrics/extension/common/Definition.java [new file with mode: 0644]
geronimo-metrics-extensions/geronimo-metrics-extension-common/src/main/java/org/apache/geronimo/microprofile/metrics/extension/common/MicroprofileMetricsAdapter.java [new file with mode: 0644]
geronimo-metrics-extensions/geronimo-metrics-extension-common/src/main/java/org/apache/geronimo/microprofile/metrics/extension/common/RegistryTypeLiteral.java [new file with mode: 0644]
geronimo-metrics-extensions/geronimo-metrics-extension-common/src/main/java/org/apache/geronimo/microprofile/metrics/extension/common/ThrowingSupplier.java [new file with mode: 0644]
geronimo-metrics-extensions/geronimo-metrics-sigar/pom.xml
geronimo-metrics-extensions/geronimo-metrics-sigar/src/main/java/org/apache/geronimo/microprofile/metrics/extension/sigar/MicroprofileMetricsSigarRegistrar.java
geronimo-metrics-extensions/geronimo-metrics-sigar/src/main/java/org/apache/geronimo/microprofile/metrics/extension/sigar/SigarRegistrar.java
geronimo-metrics-extensions/geronimo-metrics-tomcat/pom.xml [new file with mode: 0644]
geronimo-metrics-extensions/geronimo-metrics-tomcat/src/main/java/org/apache/geronimo/microprofile/metrics/extension/tomcat/ServerRegistration.java [new file with mode: 0644]
geronimo-metrics-extensions/geronimo-metrics-tomcat/src/main/java/org/apache/geronimo/microprofile/metrics/extension/tomcat/TomcatExtension.java [new file with mode: 0644]
geronimo-metrics-extensions/geronimo-metrics-tomcat/src/main/java/org/apache/geronimo/microprofile/metrics/extension/tomcat/TomcatRegistrar.java [new file with mode: 0644]
geronimo-metrics-extensions/geronimo-metrics-tomcat/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension [new file with mode: 0644]
geronimo-metrics-extensions/geronimo-metrics-tomcat/src/test/java/org/apache/geronimo/microprofile/metrics/extension/tomcat/TomcatExtensionTest.java [new file with mode: 0644]
geronimo-metrics-extensions/pom.xml

diff --git a/geronimo-metrics-extensions/geronimo-metrics-extension-common/pom.xml b/geronimo-metrics-extensions/geronimo-metrics-extension-common/pom.xml
new file mode 100644 (file)
index 0000000..5df90b3
--- /dev/null
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="
+            http://maven.apache.org/POM/4.0.0
+            http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <artifactId>geronimo-metrics-extensions</artifactId>
+    <groupId>org.apache.geronimo</groupId>
+    <version>1.0.1-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>geronimo-metrics-extension-common</artifactId>
+  <name>Geronimo Metrics :: Extensions :: Common</name>
+  <packaging>bundle</packaging>
+
+  <properties>
+    <geronimo-metrics.Automatic-Module-Name>org.apache.geronimo.microprofile.metrics.extension.common</geronimo-metrics.Automatic-Module-Name>
+  </properties>
+</project>
diff --git a/geronimo-metrics-extensions/geronimo-metrics-extension-common/src/main/java/org/apache/geronimo/microprofile/metrics/extension/common/Definition.java b/geronimo-metrics-extensions/geronimo-metrics-extension-common/src/main/java/org/apache/geronimo/microprofile/metrics/extension/common/Definition.java
new file mode 100644 (file)
index 0000000..a6a48e4
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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.geronimo.microprofile.metrics.extension.common;
+
+import java.util.Objects;
+import java.util.function.DoubleSupplier;
+
+public class Definition {
+    private final String name;
+    private final String displayName;
+    private final String description;
+    private final String unit;
+    private final DoubleSupplier evaluator;
+
+    private final int hash;
+
+    public Definition(final String name, final String displayName, final String description,
+                       final String unit, final ThrowingSupplier<Number> evaluator) {
+        this.name = name;
+        this.displayName = displayName;
+        this.description = description;
+        this.unit = unit;
+        this.evaluator = () -> {
+            try {
+                return evaluator.get().doubleValue();
+            } catch (final Throwable throwable) {
+                return -1;
+            }
+        };
+
+        this.hash = Objects.hash(name);
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public String getUnit() {
+        return unit;
+    }
+
+    public DoubleSupplier getEvaluator() {
+        return evaluator;
+    }
+
+    @Override
+    public boolean equals(final Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null || getClass() != that.getClass()) {
+            return false;
+        }
+        return Objects.equals(name, Definition.class.cast(that).name);
+    }
+
+    @Override
+    public int hashCode() {
+        return hash;
+    }
+}
diff --git a/geronimo-metrics-extensions/geronimo-metrics-extension-common/src/main/java/org/apache/geronimo/microprofile/metrics/extension/common/MicroprofileMetricsAdapter.java b/geronimo-metrics-extensions/geronimo-metrics-extension-common/src/main/java/org/apache/geronimo/microprofile/metrics/extension/common/MicroprofileMetricsAdapter.java
new file mode 100644 (file)
index 0000000..f9259d8
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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.geronimo.microprofile.metrics.extension.common;
+
+import static org.eclipse.microprofile.metrics.MetricType.GAUGE;
+
+import java.util.function.Consumer;
+
+import org.eclipse.microprofile.metrics.Gauge;
+import org.eclipse.microprofile.metrics.Metadata;
+import org.eclipse.microprofile.metrics.MetricRegistry;
+
+public class MicroprofileMetricsAdapter {
+    private final MetricRegistry registry;
+
+    public MicroprofileMetricsAdapter(final MetricRegistry registry) {
+        this.registry = registry;
+    }
+
+    public Consumer<Definition> registrer() {
+        return def -> registry.register(
+                new Metadata(def.getName(), def.getDisplayName(), def.getDescription(), GAUGE, def.getUnit()),
+                (Gauge<Double>) () -> def.getEvaluator().getAsDouble());
+    }
+
+    public Consumer<Definition> unregistrer() {
+        return def -> registry.remove(def.getName());
+    }
+}
diff --git a/geronimo-metrics-extensions/geronimo-metrics-extension-common/src/main/java/org/apache/geronimo/microprofile/metrics/extension/common/RegistryTypeLiteral.java b/geronimo-metrics-extensions/geronimo-metrics-extension-common/src/main/java/org/apache/geronimo/microprofile/metrics/extension/common/RegistryTypeLiteral.java
new file mode 100644 (file)
index 0000000..434168a
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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.geronimo.microprofile.metrics.extension.common;
+
+import java.lang.annotation.Annotation;
+
+import org.eclipse.microprofile.metrics.MetricRegistry;
+import org.eclipse.microprofile.metrics.annotation.RegistryType;
+
+public class RegistryTypeLiteral implements RegistryType {
+    private final MetricRegistry.Type type;
+
+    public RegistryTypeLiteral(final MetricRegistry.Type registryType) {
+        this.type = registryType;
+    }
+
+    @Override
+    public MetricRegistry.Type type() {
+        return type;
+    }
+
+    @Override
+    public Class<? extends Annotation> annotationType() {
+        return RegistryType.class;
+    }
+}
diff --git a/geronimo-metrics-extensions/geronimo-metrics-extension-common/src/main/java/org/apache/geronimo/microprofile/metrics/extension/common/ThrowingSupplier.java b/geronimo-metrics-extensions/geronimo-metrics-extension-common/src/main/java/org/apache/geronimo/microprofile/metrics/extension/common/ThrowingSupplier.java
new file mode 100644 (file)
index 0000000..0ec161f
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * 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.geronimo.microprofile.metrics.extension.common;
+
+@FunctionalInterface
+public interface ThrowingSupplier<T> {
+
+    T get() throws Throwable;
+}
index 4a4345a..c103c4c 100644 (file)
     </dependency>
 
     <dependency>
+      <groupId>org.apache.geronimo</groupId>
+      <artifactId>geronimo-metrics-extension-common</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
       <groupId>org.apache.geronimo.specs</groupId>
       <artifactId>geronimo-interceptor_1.2_spec</artifactId>
       <scope>test</scope>
index 25b4f99..4a22d30 100644 (file)
  */
 package org.apache.geronimo.microprofile.metrics.extension.sigar;
 
-import static org.eclipse.microprofile.metrics.MetricType.GAUGE;
-
 import java.io.File;
-import java.lang.annotation.Annotation;
 import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Stream;
@@ -31,10 +28,9 @@ import javax.enterprise.inject.spi.BeanManager;
 import javax.enterprise.inject.spi.BeforeShutdown;
 import javax.enterprise.inject.spi.Extension;
 
-import org.eclipse.microprofile.metrics.Gauge;
-import org.eclipse.microprofile.metrics.Metadata;
+import org.apache.geronimo.microprofile.metrics.extension.common.MicroprofileMetricsAdapter;
+import org.apache.geronimo.microprofile.metrics.extension.common.RegistryTypeLiteral;
 import org.eclipse.microprofile.metrics.MetricRegistry;
-import org.eclipse.microprofile.metrics.annotation.RegistryType;
 
 public class MicroprofileMetricsSigarRegistrar implements Extension {
 
@@ -53,19 +49,15 @@ public class MicroprofileMetricsSigarRegistrar implements Extension {
         final Set<Bean<?>> beans = beanManager.getBeans(MetricRegistry.class, new RegistryTypeLiteral(registryType));
         final MetricRegistry registry = MetricRegistry.class.cast(beanManager.getReference(
                 beanManager.resolve(beans), MetricRegistry.class, beanManager.createCreationalContext(null)));
-        registrar = new SigarRegistrar(
-                def -> registry.register(
-                    new Metadata(def.getName(), def.getDisplayName(), def.getDescription(), GAUGE, def.getUnit()),
-                    (Gauge<Double>) () -> def.getEvaluator().getAsDouble()),
-                def -> registry.remove(def.getName()));
+        final MicroprofileMetricsAdapter adapter = new MicroprofileMetricsAdapter(registry);
+        registrar = new SigarRegistrar(adapter.registrer(), adapter.unregistrer());
         registrar.start();
     }
 
     void beforeShutdown(@Observes final BeforeShutdown beforeShutdown) {
-        if (registrar == null) {
-            return;
+        if (registrar != null) {
+            registrar.stop();
         }
-        registrar.stop();
     }
 
     // let's try some well know temp folders and fallback on java io one
@@ -89,22 +81,4 @@ public class MicroprofileMetricsSigarRegistrar implements Extension {
                     .orElseGet(() -> new File(System.getProperty("java.io.tmpdir", "."))),
                 System.getProperty("geronimo.metrics.sigar.folder", "sigar"));
     }
-
-    private static class RegistryTypeLiteral implements RegistryType {
-        private final MetricRegistry.Type type;
-
-        private RegistryTypeLiteral(final MetricRegistry.Type registryType) {
-            this.type = registryType;
-        }
-
-        @Override
-        public MetricRegistry.Type type() {
-            return type;
-        }
-
-        @Override
-        public Class<? extends Annotation> annotationType() {
-            return RegistryType.class;
-        }
-    }
 }
index 02c7f1d..3853d63 100644 (file)
@@ -30,6 +30,8 @@ import java.util.function.DoubleSupplier;
 import java.util.stream.IntStream;
 import java.util.stream.Stream;
 
+import org.apache.geronimo.microprofile.metrics.extension.common.Definition;
+import org.apache.geronimo.microprofile.metrics.extension.common.ThrowingSupplier;
 import org.hyperic.sigar.Cpu;
 import org.hyperic.sigar.CpuInfo;
 import org.hyperic.sigar.Sigar;
@@ -299,72 +301,4 @@ public class SigarRegistrar {
                 "The time the CPU had to wait for data to be loaded, in [ms]", "ms",
                 () -> provider.get().getWait()));
     }
-
-    private interface ThrowingSupplier<T> {
-
-        T get() throws Throwable;
-    }
-
-    public static class Definition {
-        private final String name;
-        private final String displayName;
-        private final String description;
-        private final String unit;
-        private final DoubleSupplier evaluator;
-
-        private final int hash;
-
-        private Definition(final String name, final String displayName, final String description,
-                           final String unit, final ThrowingSupplier<Number> evaluator) {
-            this.name = name;
-            this.displayName = displayName;
-            this.description = description;
-            this.unit = unit;
-            this.evaluator = () -> {
-                try {
-                    return evaluator.get().doubleValue();
-                } catch (final Throwable throwable) {
-                    return -1;
-                }
-            };
-
-            this.hash = Objects.hash(name);
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        public String getDisplayName() {
-            return displayName;
-        }
-
-        public String getDescription() {
-            return description;
-        }
-
-        public String getUnit() {
-            return unit;
-        }
-
-        public DoubleSupplier getEvaluator() {
-            return evaluator;
-        }
-
-        @Override
-        public boolean equals(final Object that) {
-            if (this == that) {
-                return true;
-            }
-            if (that == null || getClass() != that.getClass()) {
-                return false;
-            }
-            return Objects.equals(name, Definition.class.cast(that).name);
-        }
-
-        @Override
-        public int hashCode() {
-            return hash;
-        }
-    }
 }
diff --git a/geronimo-metrics-extensions/geronimo-metrics-tomcat/pom.xml b/geronimo-metrics-extensions/geronimo-metrics-tomcat/pom.xml
new file mode 100644 (file)
index 0000000..b8bb0d0
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="
+            http://maven.apache.org/POM/4.0.0
+            http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <artifactId>geronimo-metrics-extensions</artifactId>
+    <groupId>org.apache.geronimo</groupId>
+    <version>1.0.1-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>geronimo-metrics-tomcat</artifactId>
+  <name>Geronimo Metrics :: Extensions :: Tomcat</name>
+  <packaging>bundle</packaging>
+
+  <properties>
+    <geronimo-metrics.Automatic-Module-Name>org.apache.geronimo.microprofile.metrics.tomcat</geronimo-metrics.Automatic-Module-Name>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.tomcat</groupId>
+      <artifactId>tomcat-catalina</artifactId>
+      <version>9.0.10</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-jcdi_2.0_spec</artifactId>
+      <version>1.0.1</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.geronimo</groupId>
+      <artifactId>geronimo-metrics-extension-common</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-interceptor_1.2_spec</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-atinject_1.0_spec</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-annotation_1.3_spec</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.meecrowave</groupId>
+      <artifactId>meecrowave-junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo</groupId>
+      <artifactId>geronimo-metrics</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/geronimo-metrics-extensions/geronimo-metrics-tomcat/src/main/java/org/apache/geronimo/microprofile/metrics/extension/tomcat/ServerRegistration.java b/geronimo-metrics-extensions/geronimo-metrics-tomcat/src/main/java/org/apache/geronimo/microprofile/metrics/extension/tomcat/ServerRegistration.java
new file mode 100644 (file)
index 0000000..babd654
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * 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.geronimo.microprofile.metrics.extension.tomcat;
+
+import java.util.function.Supplier;
+
+import org.apache.catalina.Server;
+
+@FunctionalInterface
+public interface ServerRegistration extends Supplier<Server> {
+}
diff --git a/geronimo-metrics-extensions/geronimo-metrics-tomcat/src/main/java/org/apache/geronimo/microprofile/metrics/extension/tomcat/TomcatExtension.java b/geronimo-metrics-extensions/geronimo-metrics-tomcat/src/main/java/org/apache/geronimo/microprofile/metrics/extension/tomcat/TomcatExtension.java
new file mode 100644 (file)
index 0000000..e0a925b
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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.geronimo.microprofile.metrics.extension.tomcat;
+
+import java.util.Set;
+
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.AfterDeploymentValidation;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.BeforeShutdown;
+import javax.enterprise.inject.spi.Extension;
+
+import org.apache.geronimo.microprofile.metrics.extension.common.MicroprofileMetricsAdapter;
+import org.apache.geronimo.microprofile.metrics.extension.common.RegistryTypeLiteral;
+import org.eclipse.microprofile.metrics.MetricRegistry;
+
+public class TomcatExtension implements Extension {
+    private TomcatRegistrar registrar;
+
+    void afterValidation(@Observes final AfterDeploymentValidation validation,
+                         final BeanManager beanManager) {
+        final MetricRegistry.Type registryType = MetricRegistry.Type.valueOf(
+                System.getProperty("geronimo.metrics.tomcat.registry.type", "BASE"));
+        final Set<Bean<?>> beans = beanManager.getBeans(MetricRegistry.class, new RegistryTypeLiteral(registryType));
+        final MetricRegistry registry = MetricRegistry.class.cast(beanManager.getReference(
+                beanManager.resolve(beans), MetricRegistry.class, beanManager.createCreationalContext(null)));
+        final MicroprofileMetricsAdapter adapter = new MicroprofileMetricsAdapter(registry);
+        registrar = new TomcatRegistrar(adapter.registrer(), adapter.unregistrer());
+        registrar.start();
+    }
+
+    void beforeShutdown(@Observes final BeforeShutdown beforeShutdown) {
+        if (registrar != null) {
+            registrar.stop();
+        }
+    }
+}
diff --git a/geronimo-metrics-extensions/geronimo-metrics-tomcat/src/main/java/org/apache/geronimo/microprofile/metrics/extension/tomcat/TomcatRegistrar.java b/geronimo-metrics-extensions/geronimo-metrics-tomcat/src/main/java/org/apache/geronimo/microprofile/metrics/extension/tomcat/TomcatRegistrar.java
new file mode 100644 (file)
index 0000000..a312221
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * 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.geronimo.microprofile.metrics.extension.tomcat;
+
+import java.lang.annotation.Annotation;
+import java.lang.management.ManagementFactory;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.ServiceLoader;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+
+import org.apache.catalina.Server;
+import org.apache.catalina.Service;
+import org.apache.catalina.connector.Connector;
+import org.apache.coyote.AbstractProtocol;
+import org.apache.geronimo.microprofile.metrics.extension.common.Definition;
+import org.apache.geronimo.microprofile.metrics.extension.common.ThrowingSupplier;
+import org.apache.tomcat.util.threads.ThreadPoolExecutor;
+
+// this is a class working outside a MP server, don't import CDI or anything not selfcontained!
+public class TomcatRegistrar {
+    private final Consumer<Definition> onRegister;
+    private final Consumer<Definition> onUnregister;
+
+    public TomcatRegistrar(final Consumer<Definition> onRegister,
+                           final Consumer<Definition> onUnregister) {
+        this.onRegister = onRegister;
+        this.onUnregister = onUnregister;
+    }
+
+    public void start() {
+        final Collection<Integer> ports = new HashSet<>();
+        Stream.concat(
+                findServers(),
+                StreamSupport.stream(ServiceLoader.load(ServerRegistration.class).spliterator(), false)
+                    .map(Supplier::get))
+            .filter(Objects::nonNull)
+            .distinct()
+            .map(Server::findServices)
+            .flatMap(Stream::of)
+            .map(Service::findConnectors)
+            .flatMap(Stream::of)
+            .map(Connector::getProtocolHandler)
+            .filter(AbstractProtocol.class::isInstance)
+            .map(AbstractProtocol.class::cast)
+            .forEach(protocol -> {
+                final Executor executor = protocol.getExecutor();
+                final int port = protocol.getPort();
+                if (!ports.add(port)) {
+                    return;
+                }
+                final String prefix = "server.executor.port_" + port + ".";
+                if (java.util.concurrent.ThreadPoolExecutor.class.isInstance(executor)) {
+                    final java.util.concurrent.ThreadPoolExecutor pool =
+                            java.util.concurrent.ThreadPoolExecutor.class.cast(executor);
+                    addGauge(prefix + "queue.size", "Connector Queue Size", () -> pool.getQueue().size());
+                    addGauge(prefix + "active", "Connector Active Count", pool::getActiveCount);
+                    addGauge(prefix + "tasks.completed", "Connector Completed Tasks", pool::getCompletedTaskCount);
+                    addGauge(prefix + "tasks.count", "Connector Tasks Count", pool::getTaskCount);
+                }
+                if (ThreadPoolExecutor.class.isInstance(executor)) {
+                    final ThreadPoolExecutor pool = ThreadPoolExecutor.class.cast(executor);
+                    addGauge(prefix + "submitted", "Connector Submitted Tasks", pool::getSubmittedCount);
+                }
+            });
+
+        // plain tomcat, test on jmx, not as rich as from the instance (this is why we have a SPI)
+        final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+        try {
+            server.queryMBeans(new ObjectName("*:type=ThreadPool,*"), null).stream()
+                  .map(ObjectInstance::getObjectName)
+                  .filter(it -> ports.add(getPort(it)))
+                  .forEach(name -> {
+                      final String prefix = "server.executor.port_" + getPort(name) + ".";
+                      addGauge(prefix + "thread.count", "Connector Thread Count", () -> Number.class.cast(server.getAttribute(name, "currentThreadCount")));
+                      addGauge(prefix + "active", "Connector Thread Busy", () -> Number.class.cast(server.getAttribute(name, "currentThreadsBusy")));
+                  });
+        } catch (final Exception e) {
+            // no-op
+        }
+    }
+
+    private int getPort(final ObjectName it) {
+        final String name = it.getKeyPropertyList().get("name");
+        final int sep = name.lastIndexOf('-');
+        final String port = name.substring(sep + 1);
+        return Integer.parseInt(port);
+    }
+
+    private void addGauge(final String name, final String descriptionAndDisplayName,
+                          final ThrowingSupplier<Number> supplier) {
+        onRegister.accept(new Definition(name, descriptionAndDisplayName, descriptionAndDisplayName, "count", supplier));
+    }
+
+    private Stream<Server> findServers() {
+        return Stream.of(findMeecrowave(), findTomEE());
+    }
+
+    private Server findTomEE() {
+        try {
+            final ClassLoader loader = Thread.currentThread().getContextClassLoader();
+            final Class<?> tomcatHelper = loader.loadClass("org.apache.tomee.loader.TomcatHelper");
+            return Server.class.cast(tomcatHelper.getMethod("").invoke(null));
+        } catch (final Exception | Error e) {
+            return null;
+        }
+    }
+
+    private Server findMeecrowave() {
+        try {
+            final ClassLoader loader = Thread.currentThread().getContextClassLoader();
+            final Class<?> meecrowaveClass = loader.loadClass("org.apache.meecrowave.Meecrowave");
+            final Class<?> cdi = loader.loadClass("javax.enterprise.inject.spi.CDI");
+            final Object current = cdi.getMethod("current").invoke(null);
+            final Object meecrowaveInstance = cdi.getMethod("select", Class.class, Annotation[].class)
+                                     .invoke(current, meecrowaveClass, new Annotation[0]);
+            final Object meecrowave = meecrowaveInstance.getClass().getMethod("get").invoke(meecrowaveInstance);
+            final Object tomcat = meecrowave.getClass().getMethod("getTomcat").invoke(meecrowave);
+            return Server.class.cast(tomcat.getClass().getMethod("getServer").invoke(tomcat));
+        } catch (final Exception | Error e) {
+            return null;
+        }
+    }
+
+    public void stop() {
+        // no-op for now
+    }
+}
diff --git a/geronimo-metrics-extensions/geronimo-metrics-tomcat/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/geronimo-metrics-extensions/geronimo-metrics-tomcat/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
new file mode 100644 (file)
index 0000000..744c683
--- /dev/null
@@ -0,0 +1 @@
+org.apache.geronimo.microprofile.metrics.extension.tomcat.TomcatExtension
diff --git a/geronimo-metrics-extensions/geronimo-metrics-tomcat/src/test/java/org/apache/geronimo/microprofile/metrics/extension/tomcat/TomcatExtensionTest.java b/geronimo-metrics-extensions/geronimo-metrics-tomcat/src/test/java/org/apache/geronimo/microprofile/metrics/extension/tomcat/TomcatExtensionTest.java
new file mode 100644 (file)
index 0000000..2576f3a
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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.geronimo.microprofile.metrics.extension.tomcat;
+
+import static org.junit.Assert.assertNotNull;
+
+import javax.enterprise.inject.spi.CDI;
+
+import org.apache.geronimo.microprofile.metrics.extension.common.RegistryTypeLiteral;
+import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.junit.MeecrowaveRule;
+import org.eclipse.microprofile.metrics.Gauge;
+import org.eclipse.microprofile.metrics.MetricRegistry;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+public class TomcatExtensionTest {
+    @ClassRule
+    public static final MeecrowaveRule MEECROWAVE = new MeecrowaveRule(new Meecrowave.Builder() {{
+        setTomcatNoJmx(false);
+    }}, "");
+
+    @Test
+    public void checkTomcatRegistration() {
+        final Gauge gauge = CDI.current()
+                               .select(MetricRegistry.class, new RegistryTypeLiteral(MetricRegistry.Type.BASE))
+                               .get()
+                               .getGauges()
+                               .get("server.executor.port_" + MEECROWAVE.getConfiguration().getHttpPort() + ".active");
+        assertNotNull(gauge);
+        assertNotNull(gauge.getValue());
+    }
+}
index 0ed496d..c517614 100644 (file)
@@ -33,5 +33,7 @@
 
   <modules>
     <module>geronimo-metrics-sigar</module>
+    <module>geronimo-metrics-tomcat</module>
+    <module>geronimo-metrics-extension-common</module>
   </modules>
 </project>