org.wildfly.swarm.microprofile.metrics.runtime.MetricsRegistryImpl Maven / Gradle / Ivy
/*
* Copyright 2017 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* 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 org.wildfly.swarm.microprofile.metrics.runtime;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import javax.enterprise.inject.Vetoed;
import org.eclipse.microprofile.metrics.Counter;
import org.eclipse.microprofile.metrics.Gauge;
import org.eclipse.microprofile.metrics.Histogram;
import org.eclipse.microprofile.metrics.Metadata;
import org.eclipse.microprofile.metrics.Meter;
import org.eclipse.microprofile.metrics.Metric;
import org.eclipse.microprofile.metrics.MetricFilter;
import org.eclipse.microprofile.metrics.MetricRegistry;
import org.eclipse.microprofile.metrics.MetricType;
import org.eclipse.microprofile.metrics.Timer;
import org.jboss.logging.Logger;
import org.wildfly.swarm.microprofile.metrics.runtime.app.CounterImpl;
import org.wildfly.swarm.microprofile.metrics.runtime.app.ExponentiallyDecayingReservoir;
import org.wildfly.swarm.microprofile.metrics.runtime.app.HistogramImpl;
import org.wildfly.swarm.microprofile.metrics.runtime.app.MeterImpl;
import org.wildfly.swarm.microprofile.metrics.runtime.app.TimerImpl;
/**
* @author hrupp
*/
@Vetoed
public class MetricsRegistryImpl extends MetricRegistry {
private static final Logger LOGGER = Logger.getLogger(MetricsRegistryImpl.class);
private Map metadataMap = new java.util.HashMap<>();
private Map metricMap = new ConcurrentHashMap<>();
@Override
public T register(String name, T metric) throws IllegalArgumentException {
if (metricMap.keySet().contains(name)) {
throw new IllegalArgumentException("A metric with name " + name + " already exists");
}
MetricType type;
Class> metricCls = metric.getClass();
if (metricCls.getName().contains("Lambda")) {
String tname = metricCls.getGenericInterfaces()[0].getTypeName(); // TODO [0] is brittle
tname = tname.substring(tname.lastIndexOf('.') + 1);
tname = tname.toLowerCase();
type = MetricType.from(tname);
} else if (metricCls.isAnonymousClass()) {
type = MetricType.from(metricCls.getInterfaces().length == 0 ? metricCls.getSuperclass().getInterfaces()[0] : metricCls.getInterfaces()[0]);
} else {
if (!metricCls.isInterface()) {
// [0] is ok, as all our Impl classes implement exactly the one matching interface
type = MetricType.from(metricCls.getInterfaces()[0]);
} else {
type = MetricType.from(metricCls);
}
}
Metadata m = new Metadata(name, type);
metricMap.put(name, metric);
metadataMap.put(name, m);
return metric;
}
@Override
public T register(String name, T metric, Metadata metadata) throws IllegalArgumentException {
metadata.setName(name);
return register(metadata, metric);
}
@Override
public T register(Metadata metadata, T metric) throws IllegalArgumentException {
String name = metadata.getName();
if (name == null) {
throw new IllegalArgumentException("Metric name must not be null");
}
Metadata existingMetadata = metadataMap.get(name);
boolean reusableFlag = (existingMetadata == null || existingMetadata.isReusable());
//Gauges are not reusable
if (metadata.getTypeRaw().equals(MetricType.GAUGE)) {
reusableFlag = false;
}
if (metricMap.keySet().contains(metadata.getName()) && !reusableFlag) {
throw new IllegalArgumentException("A metric with name " + metadata.getName() + " already exists");
}
if (existingMetadata != null && !existingMetadata.getTypeRaw().equals(metadata.getTypeRaw())) {
throw new IllegalArgumentException("Passed metric type does not match existing type");
}
metricMap.put(name, metric);
metadataMap.put(name, metadata);
return metric;
}
@Override
public Counter counter(String name) {
return counter(new Metadata(name, MetricType.COUNTER));
}
@Override
public org.eclipse.microprofile.metrics.Counter counter(Metadata metadata) {
return get(metadata, MetricType.COUNTER);
}
@Override
public Histogram histogram(String name) {
return histogram(new Metadata(name, MetricType.HISTOGRAM));
}
@Override
public Histogram histogram(Metadata metadata) {
return get(metadata, MetricType.HISTOGRAM);
}
@Override
public Meter meter(String s) {
return meter(new Metadata(s, MetricType.METERED));
}
@Override
public Meter meter(Metadata metadata) {
return get(metadata, MetricType.METERED);
}
private T get(Metadata metadata, MetricType type) {
String name = metadata.getName();
LOGGER.debugf("Get metric [name: %s, type: %s]", name, type);
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("Name must not be null or empty");
}
if (!metadataMap.containsKey(name)) {
Metric m;
switch (type) {
case COUNTER:
m = new CounterImpl();
break;
case GAUGE:
throw new IllegalArgumentException("Gauge " + name + " was not registered, this should not happen");
case METERED:
m = new MeterImpl();
break;
case HISTOGRAM:
m = new HistogramImpl(new ExponentiallyDecayingReservoir());
break;
case TIMER:
m = new TimerImpl(new ExponentiallyDecayingReservoir());
break;
case INVALID:
default:
throw new IllegalStateException("Must not happen");
}
LOGGER.infof("Register metric [name: %s, type: %s]", name, type);
register(metadata, m);
} else if (!metadataMap.get(name).getTypeRaw().equals(metadata.getTypeRaw())) {
throw new IllegalArgumentException("Type of existing previously registered metric " + name + " does not " +
"match passed type");
}
return (T) metricMap.get(name);
}
@Override
public Timer timer(String s) {
return timer(new Metadata(s, MetricType.TIMER));
}
@Override
public Timer timer(Metadata metadata) {
return get(metadata, MetricType.TIMER);
}
@Override
public boolean remove(String metricName) {
if (metricMap.containsKey(metricName)) {
LOGGER.infof("Remove metric [name: %s]", metricName);
metricMap.remove(metricName);
metadataMap.remove(metricName);
return true;
}
return false;
}
@Override
public void removeMatching(MetricFilter metricFilter) {
Iterator> iterator = metricMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = iterator.next();
if (metricFilter.matches(entry.getKey(), entry.getValue())) {
remove(entry.getKey());
}
}
}
@Override
public java.util.SortedSet getNames() {
return new java.util.TreeSet<>(metricMap.keySet());
}
@Override
public SortedMap getGauges() {
return getGauges(MetricFilter.ALL);
}
@Override
public SortedMap getGauges(MetricFilter metricFilter) {
return getMetrics(MetricType.GAUGE, metricFilter);
}
@Override
public SortedMap getCounters() {
return getCounters(MetricFilter.ALL);
}
@Override
public SortedMap getCounters(MetricFilter metricFilter) {
return getMetrics(MetricType.COUNTER, metricFilter);
}
@Override
public java.util.SortedMap getHistograms() {
return getHistograms(MetricFilter.ALL);
}
@Override
public java.util.SortedMap getHistograms(MetricFilter metricFilter) {
return getMetrics(MetricType.HISTOGRAM, metricFilter);
}
@Override
public java.util.SortedMap getMeters() {
return getMeters(MetricFilter.ALL);
}
@Override
public java.util.SortedMap getMeters(MetricFilter metricFilter) {
return getMetrics(MetricType.METERED, metricFilter);
}
@Override
public java.util.SortedMap getTimers() {
return getTimers(MetricFilter.ALL);
}
@Override
public java.util.SortedMap getTimers(MetricFilter metricFilter) {
return getMetrics(MetricType.TIMER, metricFilter);
}
@Override
public Map getMetrics() {
return new HashMap<>(metricMap);
}
private SortedMap getMetrics(MetricType type, MetricFilter filter) {
SortedMap out = new TreeMap();
Iterator> iterator = metricMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = iterator.next();
if (filter.matches(entry.getKey(), entry.getValue())) {
out.put(entry.getKey(), (T) entry.getValue());
}
}
return out;
}
@Override
public Map getMetadata() {
return new HashMap<>(metadataMap);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy