Browse Source

set root cause as the exception_name in micrometer tags (#1883)

* set root cause as the exception_name in micrometer tags

* set root cause as the exception_name in other metrics system

* set root cause as the exception_name in other metrics system

* Update ExceptionUtilsTest.java

* reformat

* reformat

* add root_cause_name instead of changing exception_name

Co-authored-by: Marvin Froeder <velo@users.noreply.github.com>
pull/1889/head
chao-chang-paypay 2 years ago committed by GitHub
parent
commit
62277a9df6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 44
      core/src/main/java/feign/utils/ExceptionUtils.java
  2. 41
      core/src/test/java/feign/utils/ExceptionUtilsTest.java
  3. 5
      dropwizard-metrics4/src/main/java/feign/metrics4/BaseMeteredClient.java
  4. 5
      dropwizard-metrics5/src/main/java/feign/metrics5/BaseMeteredClient.java
  5. 3
      dropwizard-metrics5/src/main/java/feign/metrics5/MeteredDecoder.java
  6. 6
      dropwizard-metrics5/src/main/java/feign/metrics5/MeteredInvocationHandleFactory.java
  7. 4
      micrometer/src/main/java/feign/micrometer/FeignMetricTagResolver.java
  8. 4
      micrometer/src/main/java/feign/micrometer/MeteredDecoder.java
  9. 3
      micrometer/src/test/java/feign/micrometer/AbstractMetricsTestBase.java

44
core/src/main/java/feign/utils/ExceptionUtils.java

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
/*
* Copyright 2012-2022 The Feign Authors
*
* 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 feign.utils;
import java.util.HashSet;
import java.util.Set;
public class ExceptionUtils {
/**
* Introspects the {@link Throwable} to obtain the root cause.
*
* <p>
* This method walks through the exception chain to the last element, "root" of the tree, using
* {@link Throwable#getCause()}, and returns that exception.
*
* @param throwable the throwable to get the root cause for, may be null
* @return the root cause of the {@link Throwable}, {@code null} if null throwable input
*/
public static Throwable getRootCause(Throwable throwable) {
if (throwable == null) {
return null;
}
Throwable rootCause = throwable;
// this is to avoid infinite loops for recursive cases
final Set<Throwable> seenThrowables = new HashSet<>();
seenThrowables.add(rootCause);
while ((rootCause.getCause() != null && !seenThrowables.contains(rootCause.getCause()))) {
seenThrowables.add(rootCause.getCause());
rootCause = rootCause.getCause();
}
return rootCause;
}
}

41
core/src/test/java/feign/utils/ExceptionUtilsTest.java

@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
/*
* Copyright 2012-2022 The Feign Authors
*
* 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 feign.utils;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class ExceptionUtilsTest {
@Test
public void rootCauseOfNullIsNull() {
Throwable e = null;
Throwable rootCause = ExceptionUtils.getRootCause(e);
assertThat(rootCause).isNull();
}
@Test
public void rootCauseIsSelf() {
Throwable e = new Exception();
Throwable rootCause = ExceptionUtils.getRootCause(e);
assertThat(rootCause).isSameAs(e);
}
@Test
public void rootCauseIsDifferent() {
Throwable rootCause = new Exception();
Throwable e = new Exception(rootCause);
Throwable actualRootCause = ExceptionUtils.getRootCause(e);
assertThat(actualRootCause).isSameAs(rootCause);
}
}

5
dropwizard-metrics4/src/main/java/feign/metrics4/BaseMeteredClient.java

@ -18,6 +18,7 @@ import com.codahale.metrics.Timer; @@ -18,6 +18,7 @@ import com.codahale.metrics.Timer;
import feign.FeignException;
import feign.RequestTemplate;
import feign.Response;
import feign.utils.ExceptionUtils;
class BaseMeteredClient {
@ -65,6 +66,8 @@ class BaseMeteredClient { @@ -65,6 +66,8 @@ class BaseMeteredClient {
httpResponseCode(template),
"exception_name",
e.getClass().getSimpleName(),
"root_cause_name",
ExceptionUtils.getRootCause(e).getClass().getSimpleName(),
"status_group",
e.status() / 100 + "xx",
"http_status",
@ -82,6 +85,8 @@ class BaseMeteredClient { @@ -82,6 +85,8 @@ class BaseMeteredClient {
httpResponseCode(template),
"exception_name",
e.getClass().getSimpleName(),
"root_cause_name",
ExceptionUtils.getRootCause(e).getClass().getSimpleName(),
"uri",
template.methodMetadata().template().path()),
metricSuppliers.meters())

5
dropwizard-metrics5/src/main/java/feign/metrics5/BaseMeteredClient.java

@ -17,6 +17,7 @@ import feign.AsyncClient; @@ -17,6 +17,7 @@ import feign.AsyncClient;
import feign.FeignException;
import feign.RequestTemplate;
import feign.Response;
import feign.utils.ExceptionUtils;
import io.dropwizard.metrics5.MetricName;
import io.dropwizard.metrics5.MetricRegistry;
import io.dropwizard.metrics5.Timer;
@ -60,6 +61,8 @@ public class BaseMeteredClient { @@ -60,6 +61,8 @@ public class BaseMeteredClient {
.counter(
httpResponseCode(template)
.tagged("exception_name", e.getClass().getSimpleName())
.tagged("root_cause_name",
ExceptionUtils.getRootCause(e).getClass().getSimpleName())
.tagged("http_status", String.valueOf(e.status()))
.tagged("status_group", e.status() / 100 + "xx")
.tagged("uri", template.methodMetadata().template().path()))
@ -71,6 +74,8 @@ public class BaseMeteredClient { @@ -71,6 +74,8 @@ public class BaseMeteredClient {
.counter(
httpResponseCode(template)
.tagged("exception_name", e.getClass().getSimpleName())
.tagged("root_cause_name",
ExceptionUtils.getRootCause(e).getClass().getSimpleName())
.tagged("uri", template.methodMetadata().template().path()))
.inc();
}

3
dropwizard-metrics5/src/main/java/feign/metrics5/MeteredDecoder.java

@ -21,6 +21,7 @@ import feign.RequestTemplate; @@ -21,6 +21,7 @@ import feign.RequestTemplate;
import feign.Response;
import feign.codec.DecodeException;
import feign.codec.Decoder;
import feign.utils.ExceptionUtils;
import io.dropwizard.metrics5.MetricRegistry;
import io.dropwizard.metrics5.Timer.Context;
@ -64,6 +65,7 @@ public class MeteredDecoder implements Decoder { @@ -64,6 +65,7 @@ public class MeteredDecoder implements Decoder {
metricRegistry.meter(
metricName.metricName(template.methodMetadata(), template.feignTarget(), "error_count")
.tagged("exception_name", e.getClass().getSimpleName())
.tagged("root_cause_name", ExceptionUtils.getRootCause(e).getClass().getSimpleName())
.tagged("uri", template.methodMetadata().template().path()),
metricSuppliers.meters()).mark();
throw e;
@ -71,6 +73,7 @@ public class MeteredDecoder implements Decoder { @@ -71,6 +73,7 @@ public class MeteredDecoder implements Decoder {
metricRegistry.meter(
metricName.metricName(template.methodMetadata(), template.feignTarget(), "error_count")
.tagged("exception_name", e.getClass().getSimpleName())
.tagged("root_cause_name", ExceptionUtils.getRootCause(e).getClass().getSimpleName())
.tagged("uri", template.methodMetadata().template().path()),
metricSuppliers.meters()).mark();
throw new IOException(e);

6
dropwizard-metrics5/src/main/java/feign/metrics5/MeteredInvocationHandleFactory.java

@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
*/
package feign.metrics5;
import feign.utils.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationHandler;
@ -86,7 +86,9 @@ public class MeteredInvocationHandleFactory implements InvocationHandlerFactory @@ -86,7 +86,9 @@ public class MeteredInvocationHandleFactory implements InvocationHandlerFactory
metricRegistry
.meter(metricName.metricName(clientClass, method, target.url())
.resolve("exception")
.tagged("exception_name", e.getClass().getSimpleName()),
.tagged("exception_name", e.getClass().getSimpleName())
.tagged("root_cause_name",
ExceptionUtils.getRootCause(e).getClass().getSimpleName()),
metricSuppliers.meters())
.mark();

4
micrometer/src/main/java/feign/micrometer/FeignMetricTagResolver.java

@ -15,6 +15,7 @@ package feign.micrometer; @@ -15,6 +15,7 @@ package feign.micrometer;
import feign.MethodMetadata;
import feign.Target;
import feign.utils.ExceptionUtils;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.Tags;
import java.lang.reflect.Method;
@ -50,6 +51,8 @@ public class FeignMetricTagResolver implements MetricTagResolver { @@ -50,6 +51,8 @@ public class FeignMetricTagResolver implements MetricTagResolver {
tags.add(Tag.of("host", extractHost(url)));
if (e != null) {
tags.add(Tag.of("exception_name", e.getClass().getSimpleName()));
tags.add(
Tag.of("root_cause_name", ExceptionUtils.getRootCause(e).getClass().getSimpleName()));
}
tags.addAll(Arrays.asList(extraTags));
return Tags.of(tags);
@ -72,4 +75,5 @@ public class FeignMetricTagResolver implements MetricTagResolver { @@ -72,4 +75,5 @@ public class FeignMetricTagResolver implements MetricTagResolver {
? targetUrl
: targetUrl.substring(0, 20);
}
}

4
micrometer/src/main/java/feign/micrometer/MeteredDecoder.java

@ -18,6 +18,7 @@ import feign.FeignException; @@ -18,6 +18,7 @@ import feign.FeignException;
import feign.RequestTemplate;
import feign.Response;
import feign.codec.Decoder;
import feign.utils.ExceptionUtils;
import io.micrometer.core.instrument.*;
import java.io.IOException;
import java.lang.reflect.Type;
@ -95,7 +96,8 @@ public class MeteredDecoder implements Decoder { @@ -95,7 +96,8 @@ public class MeteredDecoder implements Decoder {
final RequestTemplate template = response.request().requestTemplate();
final Tags allTags = metricTagResolver.tag(template.methodMetadata(), template.feignTarget(),
Tag.of("uri", template.methodMetadata().template().path()),
Tag.of("exception_name", e.getClass().getSimpleName()))
Tag.of("exception_name", e.getClass().getSimpleName()),
Tag.of("root_cause_name", ExceptionUtils.getRootCause(e).getClass().getSimpleName()))
.and(extraTags);
return meterRegistry.counter(metricName.name("error_count"), allTags);
}

3
micrometer/src/test/java/feign/micrometer/AbstractMetricsTestBase.java

@ -210,7 +210,8 @@ public abstract class AbstractMetricsTestBase<MR, METRIC_ID, METRIC> { @@ -210,7 +210,8 @@ public abstract class AbstractMetricsTestBase<MR, METRIC_ID, METRIC> {
assertThat(thrown.getMessage(), equalTo("Test error"));
assertThat(
getMetric("exception", "exception_name", "RuntimeException", "method", "get"),
getMetric("exception", "exception_name", "RuntimeException", "method", "get",
"root_cause_name", "RuntimeException"),
notNullValue());
}

Loading…
Cancel
Save