Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

APPSERV-59 Updates to MicroProfile Metrics 2.3 #4582

Merged
merged 33 commits into from
Apr 3, 2020
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
e8e1864
APPSERV-59 initial update to MP Metrics 2.3
jbee Mar 11, 2020
fe4d320
APPSERV-59 deletes outdates class
jbee Mar 11, 2020
cf7ed86
APPSERV-59 adds javadoc to AnnotationReader
jbee Mar 11, 2020
3d387fd
APPSERV-59 prepares unit tests for AnnotationReader
jbee Mar 11, 2020
46d4ac6
APPSERV-59 adds unit tests for AnnotationReader
jbee Mar 12, 2020
28793a1
APPSERV-59 makes AnnotationReader metadata automatically pick a Metri…
jbee Mar 12, 2020
1bc821a
APPSERV-59 more tests for the AnnotationReader
jbee Mar 13, 2020
e863711
APPSERV-59 final set of AnnotationReader tests and a fix
jbee Mar 13, 2020
6eea00c
APPSERV-59 adds tests for AnnotationReader#getOrRegister
jbee Mar 16, 2020
8b31d11
APPSERV-59 adds unit tests for CountedInterceptor
jbee Mar 16, 2020
3cdabfc
APPSERV-59 adds tests for MeterdInterceptor
jbee Mar 16, 2020
5d92c7c
APPSERV-59 adds tests for TimedInterceptor and SimplyTimedInterceptor
jbee Mar 16, 2020
a6e468b
APPSERV-59 adds tests for ConcurrentGuageInterceptor
jbee Mar 16, 2020
bbf36c5
APPSERV-59 concurrent gauges test finishing touches
jbee Mar 17, 2020
8b9fc52
APPSERV-59 adds OpenMetrics exporter and tests
jbee Mar 17, 2020
c6be0f4
APPSERV-59 more tests for the OpenMetricsExporter
jbee Mar 18, 2020
79047c6
APPSERV-59 ensure no duplicate TYPE or HELP lines are exported; adds …
jbee Mar 18, 2020
1a9a061
APPSERV-59 adds JSON exporter and tests from specification
jbee Mar 18, 2020
e54bdf7
APPSERV-59 adds JSON export and tests
jbee Mar 18, 2020
6a27065
APPSERV-59 connect REST API with JsonExporter implementation
jbee Mar 19, 2020
41e6aa6
APPSERV-59 fixes the REST API to exporter connection and JSON GET nes…
jbee Mar 19, 2020
e8b91d0
APPSERV-59 fixes misunderstanding on class level annotation naming ru…
jbee Mar 20, 2020
f70304a
APPSERV-59 fixes unit to Metadata from annotation for none, Gauge ann…
jbee Mar 20, 2020
be3244f
APPSERV-59 fixes CDI Metric qualifier setup, fixes display name incon…
jbee Mar 20, 2020
9e33890
fixes (work-around) CDI InjectionPoint implementation issue for param…
jbee Mar 30, 2020
996464e
APPSERV-59 removes unused imports
jbee Mar 31, 2020
0a601cd
Merge branch 'master' into APPSERV-59-mp-metrics-2.3
jbee Mar 31, 2020
bf3bbe0
APPSERV-59 work around gauge discovery order dependency with lazy gau…
jbee Mar 31, 2020
0c0c5ad
APPSERV-59 fixes details in OpenMetrics and Json export formatting; f…
jbee Mar 31, 2020
41df514
APPSERV-59 updates copyright headers
jbee Mar 31, 2020
0218a1d
Merge branch 'master' into APPSERV-59-mp-metrics-2.3
jbee Mar 31, 2020
4ce0dd8
APPSERV-59 renamed classes and methods as suggested by review
jbee Apr 2, 2020
a4cdc26
Merge branch 'APPSERV-59-mp-metrics-2.3' of github.com:jbee/Payara in…
jbee Apr 2, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions appserver/payara-appserver-modules/microprofile/metrics/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -112,5 +112,15 @@
<groupId>fish.payara.monitoring-console</groupId>
<artifactId>monitoring-console-api</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>jakarta.json</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
*
* Copyright (c) [2018-2020] Payara Foundation and/or its affiliates. All rights reserved.
*
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
Expand All @@ -11,20 +11,20 @@
* https://github.com/payara/Payara/blob/master/LICENSE.txt
* See the License for the specific
* language governing permissions and limitations under the License.
*
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/legal/LICENSE.txt.
*
*
* GPL Classpath Exception:
* The Payara Foundation designates this particular file as subject to the "Classpath"
* exception as provided by the Payara Foundation in the GPL Version 2 section of the License
* file that accompanied this code.
*
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
Expand All @@ -40,8 +40,6 @@
package fish.payara.microprofile.metrics;

import fish.payara.microprofile.metrics.admin.MetricsServiceConfiguration;
import fish.payara.microprofile.metrics.cdi.MetricsHelper;
import fish.payara.microprofile.metrics.exception.NoSuchMetricException;
import fish.payara.microprofile.metrics.exception.NoSuchRegistryException;
import fish.payara.microprofile.metrics.impl.MetricRegistryImpl;
import fish.payara.microprofile.metrics.jmx.MBeanMetadata;
Expand All @@ -52,10 +50,12 @@
import fish.payara.nucleus.executorservice.PayaraExecutorService;
import java.beans.PropertyChangeEvent;

import org.eclipse.microprofile.metrics.Counting;
import org.eclipse.microprofile.metrics.Gauge;
import org.eclipse.microprofile.metrics.Metadata;
import org.eclipse.microprofile.metrics.Metric;
import org.eclipse.microprofile.metrics.MetricRegistry;
import org.eclipse.microprofile.metrics.SimpleTimer;
import org.eclipse.microprofile.metrics.Timer;
import org.glassfish.api.StartupRunLevel;
import org.glassfish.api.admin.ServerEnvironment;
import org.glassfish.api.event.EventListener;
Expand All @@ -79,7 +79,6 @@
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.ToLongFunction;
import java.util.logging.Logger;
import org.eclipse.microprofile.metrics.MetricID;

Expand All @@ -104,7 +103,7 @@ public class MetricsService implements EventListener, ConfigListener, Monitoring

@Inject
MetricsServiceConfiguration configuration;

@Inject
private ServerEnvironment serverEnv;

Expand All @@ -126,10 +125,6 @@ public class MetricsService implements EventListener, ConfigListener, Monitoring

private final Map<String, MetricRegistryImpl> REGISTRIES = new ConcurrentHashMap<>();//stores registries of base, vendor, app1, app2, ... app(n) etc

public MetricsService() {

}

@PostConstruct
public void init() {
if(events == null){
Expand All @@ -151,35 +146,41 @@ public void collect(MonitoringDataCollector rootCollector) {
if (!isEnabled())
return;
MonitoringDataCollector metricsCollector = rootCollector.in("metric");
for (Entry<String, ? extends MetricRegistry> registry : REGISTRIES.entrySet()) {
for (MetricRegistryImpl registry : REGISTRIES.values()) {
collectRegistry(registry, metricsCollector);
}
}

private static void collectRegistry(Entry<String, ? extends MetricRegistry> registry, MonitoringDataCollector collector) {
for (Entry<MetricID, Gauge> gauge : registry.getValue().getGauges().entrySet()) {
Object value = gauge.getValue().getValue();
if (value instanceof Number) {
tagCollector(gauge.getKey(), collector).collect(toName(gauge.getKey()), ((Number) value));
private static void collectRegistry(MetricRegistryImpl registry, MonitoringDataCollector collector) {
// OBS: this way of iterating the metrics in the registry is optimal because of its internal data organisation
for (String name : registry.getNames()) {
for (Entry<MetricID, Metric> entry : registry.getMetrics(name).entrySet()) {
MetricID metricID = entry.getKey();
Metric metric = entry.getValue();
MonitoringDataCollector metricCollector = tagCollector(metricID, collector);
if (metric instanceof Counting) {
metricCollector.collect(toName(metricID, "Count"), ((Counting) metric).getCount());
}
if (metric instanceof SimpleTimer) {
metricCollector.collect(toName(metricID, "Duration"), ((SimpleTimer) metric).getElapsedTime().toMillis());
}
if (metric instanceof Timer) {
metricCollector.collect(toName(metricID, "MaxDuration"), ((Timer) metric).getSnapshot().getMax());
}
if (metric instanceof Gauge) {
Object value = ((Gauge<?>) metric).getValue();
if (value instanceof Number) {
metricCollector.collect(toName(metricID, ""), ((Number) value));
}
}
}
}
collectMetrics(registry.getValue().getCounters(), counter -> counter.getCount(), collector);
collectMetrics(registry.getValue().getConcurrentGauges(), gauge -> gauge.getCount(), collector);
collectMetrics(registry.getValue().getHistograms(), histogram -> histogram.getCount(), collector);
collectMetrics(registry.getValue().getMeters(), meter -> meter.getCount(), collector);
collectMetrics(registry.getValue().getTimers(), timer -> timer.getCount(), collector);
}

private static <T extends Metric> void collectMetrics(Map<MetricID, T> metrics, ToLongFunction<T> count,
MonitoringDataCollector collector) {
for (Entry<MetricID, T> metric : metrics.entrySet()) {
tagCollector(metric.getKey(), collector).collect(toName(metric.getKey()), count.applyAsLong(metric.getValue()));
}
}

private static CharSequence toName(MetricID metric) {
private static String toName(MetricID metric, String suffix) {
String name = metric.getName();
return name.indexOf(' ') < 0 ? name : name.replace(' ', '.'); // trying to avoid replace
name = name.indexOf(' ') < 0 ? name : name.replace(' ', '.'); // trying to avoid replace
return name.endsWith(suffix) || suffix.isEmpty() ? name : name + suffix;
}

private static MonitoringDataCollector tagCollector(MetricID metric, MonitoringDataCollector collector) {
Expand Down Expand Up @@ -264,18 +265,18 @@ public void reregisterMetadataConfig() {
}
}

private MBeanMetadataConfig getConfig() {
InputStream defaultConfig = MetricsHelper.class.getResourceAsStream("/metrics.xml");
private MBeanMetadataConfig getConfig() {
InputStream defaultConfig = MetricsService.class.getResourceAsStream("/metrics.xml");
MBeanMetadataConfig config = JAXB.unmarshal(defaultConfig, MBeanMetadataConfig.class);

File metricsResource = new File(serverEnv.getConfigDirPath(), "metrics.xml");
if (metricsResource.exists()) {
try {
InputStream userMetrics = new FileInputStream(metricsResource);
MBeanMetadataConfig extraConfig = JAXB.unmarshal(userMetrics, MBeanMetadataConfig.class);
config.addBaseMetadata(extraConfig.getBaseMetadata());
config.addVendorMetadata(extraConfig.getVendorMetadata());

} catch (FileNotFoundException ex) {
//ignore
}
Expand Down Expand Up @@ -309,41 +310,21 @@ public boolean isSecurityEnabled() {
return Boolean.parseBoolean(metricsServiceConfiguration.getSecurityEnabled());
}

public <T extends Metric> T getApplicationMetric(MetricID metricID, Class<T> type) throws NoSuchRegistryException {
return getRegistryInternal(getApplicationName()).getMetric(metricID, type);
}

public Map<MetricID, Metric> getMetricsAsMap(String registryName) throws NoSuchRegistryException {
return getRegistry(registryName).getMetrics();
}

public Map<String, Metadata> getMetadataAsMap(String registryName) throws NoSuchRegistryException {
return getRegistry(registryName).getMetadata();
public <T extends Metric> T getApplicationMetric(MetricID metricID, Class<T> type) {
return getOrAddRegistryInternal(getApplicationName()).getMetric(metricID, type);
}

public Set<MetricID> getMetricsIDs(String registryName, String metricName) throws NoSuchRegistryException {
return getRegistryInternal(registryName).getMetricsIDs(metricName);
}

public Map<MetricID, Metric> getMetricsAsMap(String registryName, String metricName) throws NoSuchRegistryException {
return getRegistryInternal(registryName).getMetrics(metricName);
}

public Map<String, Metadata> getMetadataAsMap(String registryName, String metricName) throws NoSuchRegistryException, NoSuchMetricException {
Metadata metadata = getRegistryInternal(registryName).getMetadata(metricName);
if (metadata != null) {
return Collections.singletonMap(metricName, metadata);
}
throw new NoSuchMetricException(metricName);
}

/**
* Returns the Metrics registry based on respective registry name
*
*
* @param registryName
* @return
* @throws fish.payara.microprofile.metrics.exception.NoSuchRegistryException
*/
* @return
* @throws fish.payara.microprofile.metrics.exception.NoSuchRegistryException
*/
public MetricRegistry getRegistry(String registryName) throws NoSuchRegistryException {
return getRegistryInternal(registryName);
}
Expand All @@ -356,42 +337,39 @@ private MetricRegistryImpl getRegistryInternal(String registryName) throws NoSuc
return registry;
}

public Set<String> getApplicationRegistryNames() {
Set<String> applicationRegistries = new HashSet<>(REGISTRIES.keySet());
applicationRegistries.remove(BASE.getName());
applicationRegistries.remove(VENDOR.getName());
return applicationRegistries;
}

public Set<String> getAllRegistryNames() {
return REGISTRIES.keySet();
}

/**
* Returns the Metrics registry based on respective registry name,
* Returns the Metrics registry based on respective registry name,
* if not available then add the new MetricRegistry instance
*
*
* @param registryName
* @return
*/
* @return
*/
public MetricRegistry getOrAddRegistry(String registryName) {
return getOrAddRegistryInternal(registryName);
}

private MetricRegistryImpl getOrAddRegistryInternal(String registryName) {
return REGISTRIES.computeIfAbsent(registryName.toLowerCase(), key -> new MetricRegistryImpl());
}

public MetricRegistry getApplicationRegistry() {
return getOrAddRegistry(getApplicationName());
}

/**
* Remove the Metrics registry
*
*
* @param registryName
* @return
* @return
*/
public MetricRegistry removeRegistry(String registryName) {
return REGISTRIES.remove(registryName.toLowerCase());
}

/**
* Adds an application to the enabled map
*
Expand Down
Loading