Skip to content

Commit

Permalink
Merge pull request #571 from Azquelt/proxy-metric-registry
Browse files Browse the repository at this point in the history
Support running against both MP Metrics 2.3 and 3.0
  • Loading branch information
Azquelt authored Aug 13, 2020
2 parents ab7b622 + efde1ce commit 4d82449
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,23 @@
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Optional;
import java.util.concurrent.ExecutionException;

import javax.inject.Inject;

import org.eclipse.microprofile.fault.tolerance.tck.config.ConfigAnnotationAsset;
import org.eclipse.microprofile.fault.tolerance.tck.metrics.util.MetricDefinition;
import org.eclipse.microprofile.fault.tolerance.tck.metrics.util.MetricDefinition.InvocationFallback;
import org.eclipse.microprofile.fault.tolerance.tck.metrics.util.MetricDefinition.RetryResult;
import org.eclipse.microprofile.fault.tolerance.tck.metrics.util.MetricDefinition.RetryRetried;
import org.eclipse.microprofile.fault.tolerance.tck.metrics.util.MetricDefinition.TimeoutTimedOut;
import org.eclipse.microprofile.fault.tolerance.tck.metrics.util.MetricDefinition;
import org.eclipse.microprofile.fault.tolerance.tck.metrics.util.MetricGetter;
import org.eclipse.microprofile.fault.tolerance.tck.metrics.util.MetricRegistryProxy;
import org.eclipse.microprofile.fault.tolerance.tck.util.Packages;
import org.eclipse.microprofile.metrics.Metadata;
import org.eclipse.microprofile.metrics.MetricRegistry;
import org.eclipse.microprofile.metrics.MetricRegistry.Type;
import org.eclipse.microprofile.metrics.MetricUnits;
import org.eclipse.microprofile.metrics.annotation.RegistryType;
Expand Down Expand Up @@ -89,7 +92,7 @@ public static WebArchive deploy() {

@Inject
@RegistryType(type = Type.BASE)
private MetricRegistry metricRegistry;
private MetricRegistryProxy metricRegistry;

@Test
public void testAllMetrics() throws InterruptedException, ExecutionException {
Expand Down Expand Up @@ -151,8 +154,44 @@ public void testMetricUnits() throws InterruptedException, ExecutionException {

assertNotNull(metadata, "Missing metadata for metric " + metric);

assertEquals(metadata.getUnit().orElse(MetricUnits.NONE), metric.getUnit(), "Incorrect unit for metric " + metric);
assertEquals(getUnit(metadata), metric.getUnit(), "Incorrect unit for metric " + metric);
}
}

/**
* Gets metric unit from metadata via reflection which works for Metrics 2.x and 3.x
*
* @param metadata the metadata
* @return the unit or {@code MetricUnits.NONE} if the metadata has no unit
*/
private String getUnit(Metadata metadata) {
Method getUnit = null;
try {
// Look for Metrics 3.0 method
getUnit = Metadata.class.getMethod("unit");
}
catch (NoSuchMethodException e) {
// Look for Metrics 2.x method
try {
getUnit = Metadata.class.getMethod("getUnit");
}
catch (NoSuchMethodException e1) {
throw new RuntimeException(e1);
}
}

if (!getUnit.getReturnType().equals(Optional.class)) {
throw new RuntimeException("Method found to get unit has wrong return type: " + getUnit);
}

Optional<String> optional;
try {
optional = (Optional<String>) getUnit.invoke(metadata);
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException("Failure calling method to get unit: " + getUnit, e);
}
return optional.orElse(MetricUnits.NONE);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@

import org.eclipse.microprofile.metrics.Counter;
import org.eclipse.microprofile.metrics.MetricID;
import org.eclipse.microprofile.metrics.MetricRegistry;

/**
* Allows tests to get the value of a counter and compare it with a baseline.
Expand All @@ -35,11 +34,11 @@
*/
public class CounterMetric {

private MetricRegistry registry;
private MetricRegistryProxy registry;
private MetricID metricId;
private long baseline;

public CounterMetric(MetricRegistry registry, MetricID metricId) {
public CounterMetric(MetricRegistryProxy registry, MetricID metricId) {
this.registry = registry;
this.metricId = metricId;
this.baseline = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import org.eclipse.microprofile.metrics.Counter;
import org.eclipse.microprofile.metrics.Gauge;
import org.eclipse.microprofile.metrics.MetricID;
import org.eclipse.microprofile.metrics.MetricRegistry;

/**
* Allows tests to get the value of a {@code Gauge<Long>} and compare it with a baseline.
Expand All @@ -39,11 +38,11 @@
*/
public class GaugeMetric {

private MetricRegistry registry;
private MetricRegistryProxy registry;
private MetricID metricId;
private long baseline;

public GaugeMetric(MetricRegistry registry, MetricID metricId) {
public GaugeMetric(MetricRegistryProxy registry, MetricID metricId) {
this.registry = registry;
this.metricId = metricId;
this.baseline = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
import org.eclipse.microprofile.metrics.Histogram;
import org.eclipse.microprofile.metrics.Metric;
import org.eclipse.microprofile.metrics.MetricID;
import org.eclipse.microprofile.metrics.MetricRegistry;
import org.eclipse.microprofile.metrics.Tag;

/**
Expand All @@ -63,7 +62,7 @@
*/
public class MetricGetter {

private MetricRegistry registry;
private MetricRegistryProxy registry;
private final Tag methodTag;

private Map<MetricID, CounterMetric> counterMetrics = new HashMap<>();
Expand All @@ -72,7 +71,7 @@ public class MetricGetter {
public MetricGetter(Class<?> clazz, String methodName) {
validateClassAndMethodName(clazz, methodName);
methodTag = new Tag("method", clazz.getCanonicalName() + "." + methodName);
registry = CDI.current().select(MetricRegistry.class, RegistryTypeLiteral.BASE).get();
registry = CDI.current().select(MetricRegistryProxy.class, RegistryTypeLiteral.BASE).get();
}

public CounterMetric getInvocations(InvocationResult result, InvocationFallback fallbackUsed) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
*******************************************************************************
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* 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.eclipse.microprofile.fault.tolerance.tck.metrics.util;

import java.lang.reflect.Proxy;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.CDI;

import org.eclipse.microprofile.metrics.MetricRegistry.Type;
import org.eclipse.microprofile.metrics.annotation.RegistryType;

/**
* Registers a MetricRegistryProxy bean for the BASE scope
*/
@ApplicationScoped
public class MetricRegistryProvider {

@Produces
@RegistryType(type = Type.BASE)
public MetricRegistryProxy getBaseRegistry() {
Object metricRegistry = CDI.current().select(MetricRegistryProxyHandler.METRIC_REGISTRY_CLAZZ, RegistryTypeLiteral.BASE).get();
return getProxy(metricRegistry);
}

private MetricRegistryProxy getProxy(Object metricRegistry) {
MetricRegistryProxyHandler handler = new MetricRegistryProxyHandler(metricRegistry);
ClassLoader cl = MetricRegistryProvider.class.getClassLoader();
return (MetricRegistryProxy) Proxy.newProxyInstance(cl, new Class<?>[]{MetricRegistryProxy.class}, handler);

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
*******************************************************************************
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* 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.eclipse.microprofile.fault.tolerance.tck.metrics.util;

import java.util.Map;
import java.util.SortedMap;

import org.eclipse.microprofile.metrics.Counter;
import org.eclipse.microprofile.metrics.Gauge;
import org.eclipse.microprofile.metrics.Metadata;
import org.eclipse.microprofile.metrics.Metric;
import org.eclipse.microprofile.metrics.MetricID;

/**
* Interface which includes the methods we need to call on MetricRegistry
* <p>
* This allows us to proxy these calls so that this code can run against MP Metrics 2.3 and MP Metrics 3.0
* where MetricRegistry was changed from an abstract class to an interface
*/
public interface MetricRegistryProxy {

Map<MetricID, Metric> getMetrics();

SortedMap<MetricID, Counter> getCounters();

@SuppressWarnings("rawtypes") // Must match MetricRegistry signature
SortedMap<MetricID, Gauge> getGauges();

Map<String, Metadata> getMetadata();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
*******************************************************************************
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* 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.eclipse.microprofile.fault.tolerance.tck.metrics.util;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
* Invocation handler which dynamically loads the MetricRegistry class and invokes its methods by reflection
*/
public class MetricRegistryProxyHandler implements InvocationHandler {

private static final String METRIC_REGISTRY_CLASS_NAME = "org.eclipse.microprofile.metrics.MetricRegistry";

public static final Class<?> METRIC_REGISTRY_CLAZZ;

private final Object metricRegistryInstance;

static {
try {
METRIC_REGISTRY_CLAZZ = Class.forName(METRIC_REGISTRY_CLASS_NAME);
}
catch (ClassNotFoundException e) {
throw new RuntimeException("Failed to find MetricRegistry class", e);
}
}

public MetricRegistryProxyHandler(Object metricRegistryInstance) {
METRIC_REGISTRY_CLAZZ.cast(metricRegistryInstance); // Check instance is correct class
this.metricRegistryInstance = metricRegistryInstance;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Method realMethod = METRIC_REGISTRY_CLAZZ.getMethod(method.getName(), method.getParameterTypes());
try {
return realMethod.invoke(metricRegistryInstance, args);
}
catch (InvocationTargetException e) {
throw e.getCause();
}
}

}

0 comments on commit 4d82449

Please sign in to comment.