diff --git a/hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisherAbstract.java b/hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisherAbstract.java index a534bcebf..e84622628 100644 --- a/hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisherAbstract.java +++ b/hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisherAbstract.java @@ -15,7 +15,6 @@ */ package com.netflix.hystrix.contrib.servopublisher; -import com.netflix.hystrix.HystrixCommandMetrics; import com.netflix.hystrix.HystrixMetrics; import com.netflix.hystrix.util.HystrixRollingNumberEvent; import com.netflix.servo.annotations.DataSourceLevel; diff --git a/hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisherCommand.java b/hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisherCommand.java index deff70860..3ae3fe758 100644 --- a/hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisherCommand.java +++ b/hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisherCommand.java @@ -23,19 +23,20 @@ import com.netflix.hystrix.HystrixCommandKey; import com.netflix.hystrix.HystrixCommandMetrics; import com.netflix.hystrix.HystrixCommandProperties; +import com.netflix.hystrix.HystrixEventType; import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisherCommand; -import com.netflix.hystrix.util.HystrixRollingNumberEvent; import com.netflix.servo.DefaultMonitorRegistry; import com.netflix.servo.annotations.DataSourceLevel; import com.netflix.servo.monitor.BasicCompositeMonitor; import com.netflix.servo.monitor.Monitor; import com.netflix.servo.monitor.MonitorConfig; import com.netflix.servo.tag.Tag; +import rx.functions.Func0; /** - * Implementation of {@link HystrixMetricsPublisherCommand} using Servo (https://github.com/Netflix/servo) + * Concrete Implementation of {@link HystrixMetricsPublisherCommand} using Servo (https://github.com/Netflix/servo) */ -public class HystrixServoMetricsPublisherCommand extends HystrixServoMetricsPublisherAbstract implements HystrixMetricsPublisherCommand { +public class HystrixServoMetricsPublisherCommand extends HystrixServoMetricsPublisherCommandAbstract implements HystrixMetricsPublisherCommand { private final HystrixCommandKey key; private final HystrixCommandGroupKey commandGroupKey; @@ -111,6 +112,50 @@ protected Tag getServoInstanceTag() { return servoInstanceTag; } + @Override + protected long getCumulativeCount(HystrixEventType event) { + return metrics.getCumulativeCount(getRollingNumberTypeFromEventType(event)); + } + + @Override + protected long getRollingCount(HystrixEventType event) { + return metrics.getRollingCount(getRollingNumberTypeFromEventType(event)); + } + + @Override + protected int getExecutionLatencyMean() { + return metrics.getExecutionTimeMean(); + } + + @Override + protected int getExecutionLatencyPercentile(double percentile) { + return metrics.getExecutionTimePercentile(percentile); + } + + @Override + protected int getTotalLatencyMean() { + return metrics.getTotalTimeMean(); + } + + @Override + protected int getTotalLatencyPercentile(double percentile) { + return metrics.getTotalTimePercentile(percentile); + } + + private final Func0 currentConcurrentExecutionCountThunk = new Func0() { + @Override + public Integer call() { + return metrics.getCurrentConcurrentExecutionCount(); + } + }; + + private final Func0 errorPercentageThunk = new Func0() { + @Override + public Integer call() { + return metrics.getHealthCounts().getErrorPercentage(); + } + }; + /** * Servo will flatten metric names as: getServoTypeTag()_getServoInstanceTag()_monitorName */ @@ -134,153 +179,64 @@ public Number getValue() { }); // cumulative counts - monitors.add(getCumulativeCountForEvent("countBadRequests", metrics, HystrixRollingNumberEvent.BAD_REQUEST)); - monitors.add(getCumulativeCountForEvent("countCollapsedRequests", metrics, HystrixRollingNumberEvent.COLLAPSED)); - monitors.add(getCumulativeCountForEvent("countEmit", metrics, HystrixRollingNumberEvent.EMIT)); - monitors.add(getCumulativeCountForEvent("countExceptionsThrown", metrics, HystrixRollingNumberEvent.EXCEPTION_THROWN)); - monitors.add(getCumulativeCountForEvent("countFailure", metrics, HystrixRollingNumberEvent.FAILURE)); - monitors.add(getCumulativeCountForEvent("countFallbackEmit", metrics, HystrixRollingNumberEvent.FALLBACK_EMIT)); - monitors.add(getCumulativeCountForEvent("countFallbackFailure", metrics, HystrixRollingNumberEvent.FALLBACK_FAILURE)); - monitors.add(getCumulativeCountForEvent("countFallbackRejection", metrics, HystrixRollingNumberEvent.FALLBACK_REJECTION)); - monitors.add(getCumulativeCountForEvent("countFallbackSuccess", metrics, HystrixRollingNumberEvent.FALLBACK_SUCCESS)); - monitors.add(getCumulativeCountForEvent("countResponsesFromCache", metrics, HystrixRollingNumberEvent.RESPONSE_FROM_CACHE)); - monitors.add(getCumulativeCountForEvent("countSemaphoreRejected", metrics, HystrixRollingNumberEvent.SEMAPHORE_REJECTED)); - monitors.add(getCumulativeCountForEvent("countShortCircuited", metrics, HystrixRollingNumberEvent.SHORT_CIRCUITED)); - monitors.add(getCumulativeCountForEvent("countSuccess", metrics, HystrixRollingNumberEvent.SUCCESS)); - monitors.add(getCumulativeCountForEvent("countThreadPoolRejected", metrics, HystrixRollingNumberEvent.THREAD_POOL_REJECTED)); - monitors.add(getCumulativeCountForEvent("countTimeout", metrics, HystrixRollingNumberEvent.TIMEOUT)); + monitors.add(getCumulativeMonitor("countBadRequests", HystrixEventType.BAD_REQUEST)); + monitors.add(getCumulativeMonitor("countCollapsedRequests", HystrixEventType.COLLAPSED)); + monitors.add(getCumulativeMonitor("countEmit", HystrixEventType.EMIT)); + monitors.add(getCumulativeMonitor("countExceptionsThrown", HystrixEventType.EXCEPTION_THROWN)); + monitors.add(getCumulativeMonitor("countFailure", HystrixEventType.FAILURE)); + monitors.add(getCumulativeMonitor("countFallbackEmit", HystrixEventType.FALLBACK_EMIT)); + monitors.add(getCumulativeMonitor("countFallbackFailure", HystrixEventType.FALLBACK_FAILURE)); + monitors.add(getCumulativeMonitor("countFallbackRejection", HystrixEventType.FALLBACK_REJECTION)); + monitors.add(getCumulativeMonitor("countFallbackSuccess", HystrixEventType.FALLBACK_SUCCESS)); + monitors.add(getCumulativeMonitor("countResponsesFromCache", HystrixEventType.RESPONSE_FROM_CACHE)); + monitors.add(getCumulativeMonitor("countSemaphoreRejected", HystrixEventType.SEMAPHORE_REJECTED)); + monitors.add(getCumulativeMonitor("countShortCircuited", HystrixEventType.SHORT_CIRCUITED)); + monitors.add(getCumulativeMonitor("countSuccess", HystrixEventType.SUCCESS)); + monitors.add(getCumulativeMonitor("countThreadPoolRejected", HystrixEventType.THREAD_POOL_REJECTED)); + monitors.add(getCumulativeMonitor("countTimeout", HystrixEventType.TIMEOUT)); // rolling counts - monitors.add(getRollingCountForEvent("rollingCountBadRequests", metrics, HystrixRollingNumberEvent.BAD_REQUEST)); - monitors.add(getRollingCountForEvent("rollingCountCollapsedRequests", metrics, HystrixRollingNumberEvent.COLLAPSED)); - monitors.add(getRollingCountForEvent("rollingCountEmit", metrics, HystrixRollingNumberEvent.EMIT)); - monitors.add(getRollingCountForEvent("rollingCountExceptionsThrown", metrics, HystrixRollingNumberEvent.EXCEPTION_THROWN)); - monitors.add(getRollingCountForEvent("rollingCountFailure", metrics, HystrixRollingNumberEvent.FAILURE)); - monitors.add(getRollingCountForEvent("rollingCountFallbackEmit", metrics, HystrixRollingNumberEvent.FALLBACK_EMIT)); - monitors.add(getRollingCountForEvent("rollingCountFallbackFailure", metrics, HystrixRollingNumberEvent.FALLBACK_FAILURE)); - monitors.add(getRollingCountForEvent("rollingCountFallbackRejection", metrics, HystrixRollingNumberEvent.FALLBACK_REJECTION)); - monitors.add(getRollingCountForEvent("rollingCountFallbackSuccess", metrics, HystrixRollingNumberEvent.FALLBACK_SUCCESS)); - monitors.add(getRollingCountForEvent("rollingCountResponsesFromCache", metrics, HystrixRollingNumberEvent.RESPONSE_FROM_CACHE)); - monitors.add(getRollingCountForEvent("rollingCountSemaphoreRejected", metrics, HystrixRollingNumberEvent.SEMAPHORE_REJECTED)); - monitors.add(getRollingCountForEvent("rollingCountShortCircuited", metrics, HystrixRollingNumberEvent.SHORT_CIRCUITED)); - monitors.add(getRollingCountForEvent("rollingCountSuccess", metrics, HystrixRollingNumberEvent.SUCCESS)); - monitors.add(getRollingCountForEvent("rollingCountThreadPoolRejected", metrics, HystrixRollingNumberEvent.THREAD_POOL_REJECTED)); - monitors.add(getRollingCountForEvent("rollingCountTimeout", metrics, HystrixRollingNumberEvent.TIMEOUT)); - - // the number of executionSemaphorePermits in use right now - monitors.add(new GaugeMetric(MonitorConfig.builder("executionSemaphorePermitsInUse").build()) { - @Override - public Number getValue() { - return metrics.getCurrentConcurrentExecutionCount(); - } - }); - - // error percentage derived from current metrics - monitors.add(new GaugeMetric(MonitorConfig.builder("errorPercentage").build()) { - @Override - public Number getValue() { - return metrics.getHealthCounts().getErrorPercentage(); - } - }); - - // latency metrics - monitors.add(new GaugeMetric(MonitorConfig.builder("latencyExecute_mean").build()) { - @Override - public Number getValue() { - return metrics.getExecutionTimeMean(); - } - }); - monitors.add(new GaugeMetric(MonitorConfig.builder("latencyExecute_percentile_5").build()) { - @Override - public Number getValue() { - return metrics.getExecutionTimePercentile(5); - } - }); - monitors.add(new GaugeMetric(MonitorConfig.builder("latencyExecute_percentile_25").build()) { - @Override - public Number getValue() { - return metrics.getExecutionTimePercentile(25); - } - }); - monitors.add(new GaugeMetric(MonitorConfig.builder("latencyExecute_percentile_50").build()) { - @Override - public Number getValue() { - return metrics.getExecutionTimePercentile(50); - } - }); - monitors.add(new GaugeMetric(MonitorConfig.builder("latencyExecute_percentile_75").build()) { - @Override - public Number getValue() { - return metrics.getExecutionTimePercentile(75); - } - }); - monitors.add(new GaugeMetric(MonitorConfig.builder("latencyExecute_percentile_90").build()) { - @Override - public Number getValue() { - return metrics.getExecutionTimePercentile(90); - } - }); - monitors.add(new GaugeMetric(MonitorConfig.builder("latencyExecute_percentile_99").build()) { - @Override - public Number getValue() { - return metrics.getExecutionTimePercentile(99); - } - }); - monitors.add(new GaugeMetric(MonitorConfig.builder("latencyExecute_percentile_995").build()) { - @Override - public Number getValue() { - return metrics.getExecutionTimePercentile(99.5); - } - }); - - monitors.add(new GaugeMetric(MonitorConfig.builder("latencyTotal_mean").build()) { - @Override - public Number getValue() { - return metrics.getTotalTimeMean(); - } - }); - monitors.add(new GaugeMetric(MonitorConfig.builder("latencyTotal_percentile_5").build()) { - @Override - public Number getValue() { - return metrics.getTotalTimePercentile(5); - } - }); - monitors.add(new GaugeMetric(MonitorConfig.builder("latencyTotal_percentile_25").build()) { - @Override - public Number getValue() { - return metrics.getTotalTimePercentile(25); - } - }); - monitors.add(new GaugeMetric(MonitorConfig.builder("latencyTotal_percentile_50").build()) { - @Override - public Number getValue() { - return metrics.getTotalTimePercentile(50); - } - }); - monitors.add(new GaugeMetric(MonitorConfig.builder("latencyTotal_percentile_75").build()) { - @Override - public Number getValue() { - return metrics.getTotalTimePercentile(75); - } - }); - monitors.add(new GaugeMetric(MonitorConfig.builder("latencyTotal_percentile_90").build()) { - @Override - public Number getValue() { - return metrics.getTotalTimePercentile(90); - } - }); - monitors.add(new GaugeMetric(MonitorConfig.builder("latencyTotal_percentile_99").build()) { - @Override - public Number getValue() { - return metrics.getTotalTimePercentile(99); - } - }); - monitors.add(new GaugeMetric(MonitorConfig.builder("latencyTotal_percentile_995").build()) { - @Override - public Number getValue() { - return metrics.getTotalTimePercentile(99.5); - } - }); + monitors.add(getRollingMonitor("rollingCountBadRequests", HystrixEventType.BAD_REQUEST)); + monitors.add(getRollingMonitor("rollingCountCollapsedRequests", HystrixEventType.COLLAPSED)); + monitors.add(getRollingMonitor("rollingCountEmit", HystrixEventType.EMIT)); + monitors.add(getRollingMonitor("rollingCountExceptionsThrown", HystrixEventType.EXCEPTION_THROWN)); + monitors.add(getRollingMonitor("rollingCountFailure", HystrixEventType.FAILURE)); + monitors.add(getRollingMonitor("rollingCountFallbackEmit", HystrixEventType.FALLBACK_EMIT)); + monitors.add(getRollingMonitor("rollingCountFallbackFailure", HystrixEventType.FALLBACK_FAILURE)); + monitors.add(getRollingMonitor("rollingCountFallbackRejection", HystrixEventType.FALLBACK_REJECTION)); + monitors.add(getRollingMonitor("rollingCountFallbackSuccess", HystrixEventType.FALLBACK_SUCCESS)); + monitors.add(getRollingMonitor("rollingCountResponsesFromCache", HystrixEventType.RESPONSE_FROM_CACHE)); + monitors.add(getRollingMonitor("rollingCountSemaphoreRejected", HystrixEventType.SEMAPHORE_REJECTED)); + monitors.add(getRollingMonitor("rollingCountShortCircuited", HystrixEventType.SHORT_CIRCUITED)); + monitors.add(getRollingMonitor("rollingCountSuccess", HystrixEventType.SUCCESS)); + monitors.add(getRollingMonitor("rollingCountThreadPoolRejected", HystrixEventType.THREAD_POOL_REJECTED)); + monitors.add(getRollingMonitor("rollingCountTimeout", HystrixEventType.TIMEOUT)); + + // the number of executionSemaphorePermits in use right now + monitors.add(getCurrentValueMonitor("executionSemaphorePermitsInUse", currentConcurrentExecutionCountThunk)); + + // error percentage derived from current metrics + monitors.add(getCurrentValueMonitor("errorPercentage", errorPercentageThunk)); + + // execution latency metrics + monitors.add(getExecutionLatencyMeanMonitor("latencyExecute_mean")); + monitors.add(getExecutionLatencyPercentileMonitor("latencyExecute_percentile_5", 5)); + monitors.add(getExecutionLatencyPercentileMonitor("latencyExecute_percentile_25", 25)); + monitors.add(getExecutionLatencyPercentileMonitor("latencyExecute_percentile_50", 50)); + monitors.add(getExecutionLatencyPercentileMonitor("latencyExecute_percentile_75", 75)); + monitors.add(getExecutionLatencyPercentileMonitor("latencyExecute_percentile_90", 90)); + monitors.add(getExecutionLatencyPercentileMonitor("latencyExecute_percentile_99", 99)); + monitors.add(getExecutionLatencyPercentileMonitor("latencyExecute_percentile_995", 99.5)); + + // total latency metrics + monitors.add(getTotalLatencyMeanMonitor("latencyTotal_mean")); + monitors.add(getTotalLatencyPercentileMonitor("latencyTotal_percentile_5", 5)); + monitors.add(getTotalLatencyPercentileMonitor("latencyTotal_percentile_25", 25)); + monitors.add(getTotalLatencyPercentileMonitor("latencyTotal_percentile_50", 50)); + monitors.add(getTotalLatencyPercentileMonitor("latencyTotal_percentile_75", 75)); + monitors.add(getTotalLatencyPercentileMonitor("latencyTotal_percentile_90", 90)); + monitors.add(getTotalLatencyPercentileMonitor("latencyTotal_percentile_99", 99)); + monitors.add(getTotalLatencyPercentileMonitor("latencyTotal_percentile_995", 995)); // group monitors.add(new InformationalMetric(MonitorConfig.builder("commandGroup").build()) { diff --git a/hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisherCommandAbstract.java b/hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisherCommandAbstract.java new file mode 100644 index 000000000..d9c01e987 --- /dev/null +++ b/hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisherCommandAbstract.java @@ -0,0 +1,124 @@ +/** + * Copyright 2015 Netflix, Inc. + * + * 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 com.netflix.hystrix.contrib.servopublisher; + +import com.netflix.hystrix.HystrixEventType; +import com.netflix.hystrix.util.HystrixRollingNumberEvent; +import com.netflix.servo.monitor.Monitor; +import com.netflix.servo.monitor.MonitorConfig; +import rx.functions.Func0; + +/** + * Servo publisher for HystrixCommand metrics. It makes no assumptions on how metrics are gathered. + */ +/* package */abstract class HystrixServoMetricsPublisherCommandAbstract extends HystrixServoMetricsPublisherAbstract { + + protected abstract long getCumulativeCount(HystrixEventType event); + + protected abstract long getRollingCount(HystrixEventType event); + + protected abstract int getExecutionLatencyMean(); + + protected abstract int getExecutionLatencyPercentile(double percentile); + + protected abstract int getTotalLatencyMean(); + + protected abstract int getTotalLatencyPercentile(double percentile); + + protected final HystrixRollingNumberEvent getRollingNumberTypeFromEventType(HystrixEventType event) { + switch (event) { + case BAD_REQUEST: return HystrixRollingNumberEvent.BAD_REQUEST; + case COLLAPSED: return HystrixRollingNumberEvent.COLLAPSED; + case EMIT: return HystrixRollingNumberEvent.EMIT; + case EXCEPTION_THROWN: return HystrixRollingNumberEvent.EXCEPTION_THROWN; + case FAILURE: return HystrixRollingNumberEvent.FAILURE; + case FALLBACK_EMIT: return HystrixRollingNumberEvent.FALLBACK_EMIT; + case FALLBACK_FAILURE: return HystrixRollingNumberEvent.FALLBACK_FAILURE; + case FALLBACK_REJECTION: return HystrixRollingNumberEvent.FALLBACK_REJECTION; + case FALLBACK_SUCCESS: return HystrixRollingNumberEvent.FALLBACK_SUCCESS; + case RESPONSE_FROM_CACHE: return HystrixRollingNumberEvent.RESPONSE_FROM_CACHE; + case SEMAPHORE_REJECTED: return HystrixRollingNumberEvent.SEMAPHORE_REJECTED; + case SHORT_CIRCUITED: return HystrixRollingNumberEvent.SHORT_CIRCUITED; + case SUCCESS: return HystrixRollingNumberEvent.SUCCESS; + case THREAD_POOL_REJECTED: return HystrixRollingNumberEvent.THREAD_POOL_REJECTED; + case TIMEOUT: return HystrixRollingNumberEvent.TIMEOUT; + default: throw new RuntimeException("Unknown HystrixEventType : " + event); + } + } + + protected Monitor getCumulativeMonitor(final String name, final HystrixEventType event) { + return new CounterMetric(MonitorConfig.builder(name).withTag(getServoTypeTag()).withTag(getServoInstanceTag()).build()) { + @Override + public Long getValue() { + return getCumulativeCount(event); + } + }; + } + + protected Monitor getRollingMonitor(final String name, final HystrixEventType event) { + return new CounterMetric(MonitorConfig.builder(name).withTag(getServoTypeTag()).withTag(getServoInstanceTag()).build()) { + @Override + public Long getValue() { + return getRollingCount(event); + } + }; + } + + protected Monitor getExecutionLatencyMeanMonitor(final String name) { + return new GaugeMetric(MonitorConfig.builder(name).build()) { + @Override + public Number getValue() { + return getExecutionLatencyMean(); + } + }; + } + + protected Monitor getExecutionLatencyPercentileMonitor(final String name, final double percentile) { + return new GaugeMetric(MonitorConfig.builder(name).build()) { + @Override + public Number getValue() { + return getExecutionLatencyPercentile(percentile); + } + }; + } + + protected Monitor getTotalLatencyMeanMonitor(final String name) { + return new GaugeMetric(MonitorConfig.builder(name).build()) { + @Override + public Number getValue() { + return getTotalLatencyMean(); + } + }; + } + + protected Monitor getTotalLatencyPercentileMonitor(final String name, final double percentile) { + return new GaugeMetric(MonitorConfig.builder(name).build()) { + @Override + public Number getValue() { + return getTotalLatencyPercentile(percentile); + } + }; + } + + protected Monitor getCurrentValueMonitor(final String name, final Func0 metricToEvaluate) { + return new GaugeMetric(MonitorConfig.builder(name).build()) { + @Override + public Number getValue() { + return metricToEvaluate.call(); + } + }; + } +}