From 767cb9cb6ab3ac13e6cf9294b84ccaa6b74d0149 Mon Sep 17 00:00:00 2001 From: Ben Christensen Date: Mon, 3 Dec 2012 21:37:55 -0800 Subject: [PATCH 1/2] Remove Servo dependency from hystrix-core --- .../hystrix-servo-stream/build.gradle | 1 + hystrix-core/build.gradle | 1 - .../metrics/HystrixMetricsPublisher.java | 8 +- ...HystrixMetricsPublisherCommandDefault.java | 356 +----------------- .../HystrixMetricsPublisherDefault.java | 13 +- ...trixMetricsPublisherThreadPoolDefault.java | 208 +--------- .../HystrixMetricsServoPublisherAbstract.java | 85 ----- 7 files changed, 25 insertions(+), 647 deletions(-) delete mode 100644 hystrix-core/src/main/java/com/netflix/hystrix/strategy/metrics/HystrixMetricsServoPublisherAbstract.java diff --git a/hystrix-contrib/hystrix-servo-stream/build.gradle b/hystrix-contrib/hystrix-servo-stream/build.gradle index 9c4e62078..90a05be12 100644 --- a/hystrix-contrib/hystrix-servo-stream/build.gradle +++ b/hystrix-contrib/hystrix-servo-stream/build.gradle @@ -1,6 +1,7 @@ apply plugin: 'java' dependencies { compile project(':hystrix-core') + compile 'com.netflix.servo:servo-core:0.4.27' compile 'javax.servlet:javax.servlet-api:3.0.1' compile 'org.json:json:20090211' } diff --git a/hystrix-core/build.gradle b/hystrix-core/build.gradle index 110afec95..84c6f6b8c 100644 --- a/hystrix-core/build.gradle +++ b/hystrix-core/build.gradle @@ -1,6 +1,5 @@ apply plugin: 'java' dependencies { - compile 'com.netflix.servo:servo-core:0.4.27' compile 'com.netflix.archaius:archaius-core:0.4.1' compile 'org.slf4j:slf4j-api:1.7.0' compile 'com.google.code.findbugs:jsr305:2.0.0' diff --git a/hystrix-core/src/main/java/com/netflix/hystrix/strategy/metrics/HystrixMetricsPublisher.java b/hystrix-core/src/main/java/com/netflix/hystrix/strategy/metrics/HystrixMetricsPublisher.java index c5e37407a..4ee903d75 100644 --- a/hystrix-core/src/main/java/com/netflix/hystrix/strategy/metrics/HystrixMetricsPublisher.java +++ b/hystrix-core/src/main/java/com/netflix/hystrix/strategy/metrics/HystrixMetricsPublisher.java @@ -1,12 +1,12 @@ /** * Copyright 2012 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 - * + * + * 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. diff --git a/hystrix-core/src/main/java/com/netflix/hystrix/strategy/metrics/HystrixMetricsPublisherCommandDefault.java b/hystrix-core/src/main/java/com/netflix/hystrix/strategy/metrics/HystrixMetricsPublisherCommandDefault.java index e368db344..8c6f11eb3 100644 --- a/hystrix-core/src/main/java/com/netflix/hystrix/strategy/metrics/HystrixMetricsPublisherCommandDefault.java +++ b/hystrix-core/src/main/java/com/netflix/hystrix/strategy/metrics/HystrixMetricsPublisherCommandDefault.java @@ -1,371 +1,27 @@ -/** - * Copyright 2012 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.strategy.metrics; -import java.util.ArrayList; -import java.util.List; - import com.netflix.hystrix.HystrixCircuitBreaker; import com.netflix.hystrix.HystrixCommandGroupKey; import com.netflix.hystrix.HystrixCommandKey; import com.netflix.hystrix.HystrixCommandMetrics; import com.netflix.hystrix.HystrixCommandProperties; -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; /** - * Default implementation of {@link HystrixMetricsPublisherCommand} using Servo (https://github.com/Netflix/servo) + * Default implementation of {@link HystrixMetricsPublisherCommand} that does nothing. + *

+ * See Wiki docs about plugins for more information. * * @ExcludeFromJavadoc */ -public class HystrixMetricsPublisherCommandDefault extends HystrixMetricsServoPublisherAbstract implements HystrixMetricsPublisherCommand { - - private final HystrixCommandKey key; - private final HystrixCommandGroupKey commandGroupKey; - private final HystrixCommandMetrics metrics; - private final HystrixCircuitBreaker circuitBreaker; - private final HystrixCommandProperties properties; - private final Tag servoInstanceTag; - private final Tag servoTypeTag; +public class HystrixMetricsPublisherCommandDefault implements HystrixMetricsPublisherCommand { public HystrixMetricsPublisherCommandDefault(HystrixCommandKey commandKey, HystrixCommandGroupKey commandGroupKey, HystrixCommandMetrics metrics, HystrixCircuitBreaker circuitBreaker, HystrixCommandProperties properties) { - this.key = commandKey; - this.commandGroupKey = commandGroupKey; - this.metrics = metrics; - this.circuitBreaker = circuitBreaker; - this.properties = properties; - this.servoInstanceTag = new Tag() { - - @Override - public String getKey() { - return "instance"; - } - - @Override - public String getValue() { - return key.name(); - } - - @Override - public String tagString() { - return key.name(); - } - - }; - this.servoTypeTag = new Tag() { - - @Override - public String getKey() { - return "type"; - } - - @Override - public String getValue() { - return "HystrixCommand"; - } - - @Override - public String tagString() { - return "HystrixCommand"; - } - - }; + // do nothing by default } @Override public void initialize() { - /* list of monitors */ - List> monitors = getServoMonitors(); - - // publish metrics together under a single composite (it seems this name is ignored) - MonitorConfig commandMetricsConfig = MonitorConfig.builder("HystrixCommand_" + key.name()).build(); - BasicCompositeMonitor commandMetricsMonitor = new BasicCompositeMonitor(commandMetricsConfig, monitors); - - DefaultMonitorRegistry.getInstance().register(commandMetricsMonitor); - } - - @Override - protected Tag getServoTypeTag() { - return servoTypeTag; - } - - @Override - protected Tag getServoInstanceTag() { - return servoInstanceTag; - } - - /** - * Servo will flatten metric names as: getServoTypeTag()_getServoInstanceTag()_monitorName - */ - private List> getServoMonitors() { - - List> monitors = new ArrayList>(); - - monitors.add(new InformationalMetric(MonitorConfig.builder("isCircuitBreakerOpen").build()) { - @Override - public Boolean getValue() { - return circuitBreaker.isOpen(); - } - }); - - // allow Servo and monitor to know exactly at what point in time these stats are for so they can be plotted accurately - monitors.add(new GaugeMetric(MonitorConfig.builder("currentTime").withTag(DataSourceLevel.DEBUG).build()) { - @Override - public Number getValue() { - return System.currentTimeMillis(); - } - }); - - // cumulative counts - monitors.add(getCumulativeCountForEvent("countCollapsedRequests", metrics, HystrixRollingNumberEvent.COLLAPSED)); - monitors.add(getCumulativeCountForEvent("countExceptionsThrown", metrics, HystrixRollingNumberEvent.EXCEPTION_THROWN)); - monitors.add(getCumulativeCountForEvent("countFailure", metrics, HystrixRollingNumberEvent.FAILURE)); - 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)); - - // rolling counts - monitors.add(getRollingCountForEvent("rollingCountCollapsedRequests", metrics, HystrixRollingNumberEvent.COLLAPSED)); - monitors.add(getRollingCountForEvent("rollingCountExceptionsThrown", metrics, HystrixRollingNumberEvent.EXCEPTION_THROWN)); - monitors.add(getRollingCountForEvent("rollingCountFailure", metrics, HystrixRollingNumberEvent.FAILURE)); - 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(90); - } - }); - 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); - } - }); - - // group - monitors.add(new InformationalMetric(MonitorConfig.builder("commandGroup").build()) { - @Override - public String getValue() { - return commandGroupKey != null ? commandGroupKey.name() : null; - } - }); - - // properties (so the values can be inspected and monitored) - monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_rollingStatisticalWindowInMilliseconds").build()) { - @Override - public Number getValue() { - return properties.metricsRollingStatisticalWindowInMilliseconds().get(); - } - }); - monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_circuitBreakerRequestVolumeThreshold").build()) { - @Override - public Number getValue() { - return properties.circuitBreakerRequestVolumeThreshold().get(); - } - }); - monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_circuitBreakerSleepWindowInMilliseconds").build()) { - @Override - public Number getValue() { - return properties.circuitBreakerSleepWindowInMilliseconds().get(); - } - }); - monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_circuitBreakerErrorThresholdPercentage").build()) { - @Override - public Number getValue() { - return properties.circuitBreakerErrorThresholdPercentage().get(); - } - }); - monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_circuitBreakerForceOpen").build()) { - @Override - public Boolean getValue() { - return properties.circuitBreakerForceOpen().get(); - } - }); - monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_circuitBreakerForceClosed").build()) { - @Override - public Boolean getValue() { - return properties.circuitBreakerForceClosed().get(); - } - }); - monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_executionIsolationThreadTimeoutInMilliseconds").build()) { - @Override - public Number getValue() { - return properties.executionIsolationThreadTimeoutInMilliseconds().get(); - } - }); - monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_executionIsolationStrategy").build()) { - @Override - public String getValue() { - return properties.executionIsolationStrategy().get().name(); - } - }); - monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_metricsRollingPercentileEnabled").build()) { - @Override - public Boolean getValue() { - return properties.metricsRollingPercentileEnabled().get(); - } - }); - monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_requestCacheEnabled").build()) { - @Override - public Boolean getValue() { - return properties.requestCacheEnabled().get(); - } - }); - monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_requestLogEnabled").build()) { - @Override - public Boolean getValue() { - return properties.requestLogEnabled().get(); - } - }); - monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_executionIsolationSemaphoreMaxConcurrentRequests").build()) { - @Override - public Number getValue() { - return properties.executionIsolationSemaphoreMaxConcurrentRequests().get(); - } - }); - monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_fallbackIsolationSemaphoreMaxConcurrentRequests").build()) { - @Override - public Number getValue() { - return properties.fallbackIsolationSemaphoreMaxConcurrentRequests().get(); - } - }); - - return monitors; + // do nothing by default } } diff --git a/hystrix-core/src/main/java/com/netflix/hystrix/strategy/metrics/HystrixMetricsPublisherDefault.java b/hystrix-core/src/main/java/com/netflix/hystrix/strategy/metrics/HystrixMetricsPublisherDefault.java index e6ba1c1f0..7fb317550 100644 --- a/hystrix-core/src/main/java/com/netflix/hystrix/strategy/metrics/HystrixMetricsPublisherDefault.java +++ b/hystrix-core/src/main/java/com/netflix/hystrix/strategy/metrics/HystrixMetricsPublisherDefault.java @@ -1,12 +1,12 @@ /** * Copyright 2012 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 - * + * + * 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. @@ -15,9 +15,10 @@ */ package com.netflix.hystrix.strategy.metrics; - /** - * Default implementation of {@link HystrixMetricsPublisher} + * Default implementation of {@link HystrixMetricsPublisher}. + *

+ * See Wiki docs about plugins for more information. * * @ExcludeFromJavadoc */ diff --git a/hystrix-core/src/main/java/com/netflix/hystrix/strategy/metrics/HystrixMetricsPublisherThreadPoolDefault.java b/hystrix-core/src/main/java/com/netflix/hystrix/strategy/metrics/HystrixMetricsPublisherThreadPoolDefault.java index d875c037a..2ac0e4b5b 100644 --- a/hystrix-core/src/main/java/com/netflix/hystrix/strategy/metrics/HystrixMetricsPublisherThreadPoolDefault.java +++ b/hystrix-core/src/main/java/com/netflix/hystrix/strategy/metrics/HystrixMetricsPublisherThreadPoolDefault.java @@ -1,219 +1,25 @@ -/** - * Copyright 2012 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.strategy.metrics; -import java.util.ArrayList; -import java.util.List; - import com.netflix.hystrix.HystrixThreadPoolKey; import com.netflix.hystrix.HystrixThreadPoolMetrics; import com.netflix.hystrix.HystrixThreadPoolProperties; -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; /** - * Default implementation of {@link HystrixMetricsPublisherThreadPool} using Servo (https://github.com/Netflix/servo) + * Default implementation of {@link HystrixMetricsPublisherThreadPool} that does nothing. + *

+ * See Wiki docs about plugins for more information. * * @ExcludeFromJavadoc */ -public class HystrixMetricsPublisherThreadPoolDefault extends HystrixMetricsServoPublisherAbstract implements HystrixMetricsPublisherThreadPool { - - private final HystrixThreadPoolKey key; - private final HystrixThreadPoolMetrics metrics; - private final HystrixThreadPoolProperties properties; - private final Tag servoInstanceTag; - private final Tag servoTypeTag; +public class HystrixMetricsPublisherThreadPoolDefault implements HystrixMetricsPublisherThreadPool { public HystrixMetricsPublisherThreadPoolDefault(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolMetrics metrics, HystrixThreadPoolProperties properties) { - this.key = threadPoolKey; - this.metrics = metrics; - this.properties = properties; - - this.servoInstanceTag = new Tag() { - - @Override - public String getKey() { - return "instance"; - } - - @Override - public String getValue() { - return key.name(); - } - - @Override - public String tagString() { - return key.name(); - } - - }; - this.servoTypeTag = new Tag() { - - @Override - public String getKey() { - return "type"; - } - - @Override - public String getValue() { - return "HystrixThreadPool"; - } - - @Override - public String tagString() { - return "HystrixThreadPool"; - } - - }; + // do nothing by default } @Override public void initialize() { - /* list of monitors */ - List> monitors = getServoMonitors(); - - // publish metrics together under a single composite (it seems this name is ignored) - MonitorConfig commandMetricsConfig = MonitorConfig.builder("HystrixThreadPool_" + key.name()).build(); - BasicCompositeMonitor commandMetricsMonitor = new BasicCompositeMonitor(commandMetricsConfig, monitors); - - DefaultMonitorRegistry.getInstance().register(commandMetricsMonitor); - } - - @Override - protected Tag getServoTypeTag() { - return servoTypeTag; - } - - @Override - protected Tag getServoInstanceTag() { - return servoInstanceTag; - } - - /** - * Servo will flatten metric names as: getServoTypeTag()_getServoInstanceTag()_monitorName - */ - private List> getServoMonitors() { - - List> monitors = new ArrayList>(); - - monitors.add(new InformationalMetric(MonitorConfig.builder("name").build()) { - @Override - public String getValue() { - return key.name(); - } - }); - - // allow Servo and monitor to know exactly at what point in time these stats are for so they can be plotted accurately - monitors.add(new GaugeMetric(MonitorConfig.builder("currentTime").withTag(DataSourceLevel.DEBUG).build()) { - @Override - public Number getValue() { - return System.currentTimeMillis(); - } - }); - - monitors.add(new GaugeMetric(MonitorConfig.builder("threadActiveCount").build()) { - @Override - public Number getValue() { - return metrics.getCurrentActiveCount(); - } - }); - - monitors.add(new GaugeMetric(MonitorConfig.builder("completedTaskCount").build()) { - @Override - public Number getValue() { - return metrics.getCurrentCompletedTaskCount(); - } - }); - - monitors.add(new GaugeMetric(MonitorConfig.builder("largestPoolSize").build()) { - @Override - public Number getValue() { - return metrics.getCurrentLargestPoolSize(); - } - }); - - monitors.add(new GaugeMetric(MonitorConfig.builder("totalTaskCount").build()) { - @Override - public Number getValue() { - return metrics.getCurrentTaskCount(); - } - }); - - monitors.add(new GaugeMetric(MonitorConfig.builder("queueSize").build()) { - @Override - public Number getValue() { - return metrics.getCurrentQueueSize(); - } - }); - - monitors.add(new GaugeMetric(MonitorConfig.builder("rollingMaxActiveThreads").withTag(DataSourceLevel.DEBUG).build()) { - @Override - public Number getValue() { - return metrics.getRollingMaxActiveThreads(); - } - }); - - monitors.add(new CounterMetric(MonitorConfig.builder("countThreadsExecuted").build()) { - @Override - public Long getValue() { - return metrics.getCumulativeCountThreadsExecuted(); - } - }); - - monitors.add(new GaugeMetric(MonitorConfig.builder("rollingCountThreadsExecuted").withTag(DataSourceLevel.DEBUG).build()) { - @Override - public Number getValue() { - return metrics.getRollingCountThreadsExecuted(); - } - }); - - // properties - monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_corePoolSize").build()) { - @Override - public Number getValue() { - return properties.coreSize().get(); - } - }); - - monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_keepAliveTimeInMinutes").build()) { - @Override - public Number getValue() { - return properties.keepAliveTimeMinutes().get(); - } - }); - - monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_queueSizeRejectionThreshold").build()) { - @Override - public Number getValue() { - return properties.queueSizeRejectionThreshold().get(); - } - }); - - monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_maxQueueSize").build()) { - @Override - public Number getValue() { - return properties.maxQueueSize().get(); - } - }); - - return monitors; + // do nothing by default } -} \ No newline at end of file +} diff --git a/hystrix-core/src/main/java/com/netflix/hystrix/strategy/metrics/HystrixMetricsServoPublisherAbstract.java b/hystrix-core/src/main/java/com/netflix/hystrix/strategy/metrics/HystrixMetricsServoPublisherAbstract.java deleted file mode 100644 index 960835c47..000000000 --- a/hystrix-core/src/main/java/com/netflix/hystrix/strategy/metrics/HystrixMetricsServoPublisherAbstract.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Copyright 2012 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.strategy.metrics; - -import com.netflix.hystrix.HystrixCommandMetrics; -import com.netflix.hystrix.util.HystrixRollingNumberEvent; -import com.netflix.servo.annotations.DataSourceLevel; -import com.netflix.servo.annotations.DataSourceType; -import com.netflix.servo.monitor.AbstractMonitor; -import com.netflix.servo.monitor.Counter; -import com.netflix.servo.monitor.Gauge; -import com.netflix.servo.monitor.Monitor; -import com.netflix.servo.monitor.MonitorConfig; -import com.netflix.servo.tag.Tag; - -/** - * Utility used for Servo (https://github.com/Netflix/servo) based default implementations of metrics publishers. - */ -/* package */abstract class HystrixMetricsServoPublisherAbstract { - - protected abstract Tag getServoTypeTag(); - - protected abstract Tag getServoInstanceTag(); - - protected abstract class InformationalMetric extends AbstractMonitor { - public InformationalMetric(MonitorConfig config) { - super(config.withAdditionalTag(DataSourceType.INFORMATIONAL).withAdditionalTag(getServoTypeTag()).withAdditionalTag(getServoInstanceTag())); - } - } - - protected abstract class CounterMetric extends AbstractMonitor implements Counter { - public CounterMetric(MonitorConfig config) { - super(config.withAdditionalTag(DataSourceType.COUNTER).withAdditionalTag(getServoTypeTag()).withAdditionalTag(getServoInstanceTag())); - } - - @Override - public void increment() { - throw new IllegalStateException("We are wrapping a value instead."); - } - - @Override - public void increment(long arg0) { - throw new IllegalStateException("We are wrapping a value instead."); - } - } - - protected abstract class GaugeMetric extends AbstractMonitor implements Gauge { - public GaugeMetric(MonitorConfig config) { - super(config.withAdditionalTag(DataSourceType.GAUGE).withAdditionalTag(getServoTypeTag()).withAdditionalTag(getServoInstanceTag())); - } - } - - protected Monitor getCumulativeCountForEvent(String name, final HystrixCommandMetrics metrics, final HystrixRollingNumberEvent event) { - return new CounterMetric(MonitorConfig.builder(name).withTag(getServoTypeTag()).withTag(getServoInstanceTag()).build()) { - @Override - public Long getValue() { - return metrics.getCumulativeCount(event); - } - - }; - } - - protected Monitor getRollingCountForEvent(String name, final HystrixCommandMetrics metrics, final HystrixRollingNumberEvent event) { - return new GaugeMetric(MonitorConfig.builder(name).withTag(DataSourceLevel.DEBUG).withTag(getServoTypeTag()).withTag(getServoInstanceTag()).build()) { - @Override - public Number getValue() { - return metrics.getRollingCount(event); - } - - }; - } -} From 6dad25950ec33092e4a79d6eabd110019be6121c Mon Sep 17 00:00:00 2001 From: Ben Christensen Date: Mon, 3 Dec 2012 21:38:30 -0800 Subject: [PATCH 2/2] Servo Metrics Publisher as optional submodule --- .../build.gradle | 5 + .../HystrixServoMetricsPublisher.java | 56 +++ .../HystrixServoMetricsPublisherAbstract.java | 85 ++++ .../HystrixServoMetricsPublisherCommand.java | 370 ++++++++++++++++++ ...ystrixServoMetricsPublisherThreadPool.java | 218 +++++++++++ settings.gradle | 2 +- 6 files changed, 735 insertions(+), 1 deletion(-) create mode 100644 hystrix-contrib/hystrix-servo-metrics-publisher/build.gradle create mode 100644 hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisher.java create mode 100644 hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisherAbstract.java create mode 100644 hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisherCommand.java create mode 100644 hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisherThreadPool.java diff --git a/hystrix-contrib/hystrix-servo-metrics-publisher/build.gradle b/hystrix-contrib/hystrix-servo-metrics-publisher/build.gradle new file mode 100644 index 000000000..b923d68bc --- /dev/null +++ b/hystrix-contrib/hystrix-servo-metrics-publisher/build.gradle @@ -0,0 +1,5 @@ + apply plugin: 'java' + dependencies { + compile project(':hystrix-core') + compile 'com.netflix.servo:servo-core:0.4.27' + } diff --git a/hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisher.java b/hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisher.java new file mode 100644 index 000000000..7d81d391c --- /dev/null +++ b/hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisher.java @@ -0,0 +1,56 @@ +/** + * Copyright 2012 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.HystrixCircuitBreaker; +import com.netflix.hystrix.HystrixCommandGroupKey; +import com.netflix.hystrix.HystrixCommandKey; +import com.netflix.hystrix.HystrixCommandMetrics; +import com.netflix.hystrix.HystrixCommandProperties; +import com.netflix.hystrix.HystrixThreadPoolKey; +import com.netflix.hystrix.HystrixThreadPoolMetrics; +import com.netflix.hystrix.HystrixThreadPoolProperties; +import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisher; +import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisherCommand; +import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisherThreadPool; + +/** + * Servo implementation of {@link HystrixMetricsPublisher}. + *

+ * See Wiki docs about plugins for more information. + */ +public class HystrixServoMetricsPublisher extends HystrixMetricsPublisher { + + private static HystrixServoMetricsPublisher INSTANCE = new HystrixServoMetricsPublisher(); + + public static HystrixServoMetricsPublisher getInstance() { + return INSTANCE; + } + + private HystrixServoMetricsPublisher() { + } + + @Override + public HystrixMetricsPublisherCommand getMetricsPublisherForCommand(HystrixCommandKey commandKey, HystrixCommandGroupKey commandGroupKey, HystrixCommandMetrics metrics, HystrixCircuitBreaker circuitBreaker, HystrixCommandProperties properties) { + return new HystrixServoMetricsPublisherCommand(commandKey, commandGroupKey, metrics, circuitBreaker, properties); + } + + @Override + public HystrixMetricsPublisherThreadPool getMetricsPublisherForThreadPool(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolMetrics metrics, HystrixThreadPoolProperties properties) { + return new HystrixServoMetricsPublisherThreadPool(threadPoolKey, metrics, properties); + } + +} 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 new file mode 100644 index 000000000..330581b13 --- /dev/null +++ b/hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisherAbstract.java @@ -0,0 +1,85 @@ +/** + * Copyright 2012 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.HystrixCommandMetrics; +import com.netflix.hystrix.util.HystrixRollingNumberEvent; +import com.netflix.servo.annotations.DataSourceLevel; +import com.netflix.servo.annotations.DataSourceType; +import com.netflix.servo.monitor.AbstractMonitor; +import com.netflix.servo.monitor.Counter; +import com.netflix.servo.monitor.Gauge; +import com.netflix.servo.monitor.Monitor; +import com.netflix.servo.monitor.MonitorConfig; +import com.netflix.servo.tag.Tag; + +/** + * Utility used for Servo (https://github.com/Netflix/servo) based implementations of metrics publishers. + */ +/* package */abstract class HystrixServoMetricsPublisherAbstract { + + protected abstract Tag getServoTypeTag(); + + protected abstract Tag getServoInstanceTag(); + + protected abstract class InformationalMetric extends AbstractMonitor { + public InformationalMetric(MonitorConfig config) { + super(config.withAdditionalTag(DataSourceType.INFORMATIONAL).withAdditionalTag(getServoTypeTag()).withAdditionalTag(getServoInstanceTag())); + } + } + + protected abstract class CounterMetric extends AbstractMonitor implements Counter { + public CounterMetric(MonitorConfig config) { + super(config.withAdditionalTag(DataSourceType.COUNTER).withAdditionalTag(getServoTypeTag()).withAdditionalTag(getServoInstanceTag())); + } + + @Override + public void increment() { + throw new IllegalStateException("We are wrapping a value instead."); + } + + @Override + public void increment(long arg0) { + throw new IllegalStateException("We are wrapping a value instead."); + } + } + + protected abstract class GaugeMetric extends AbstractMonitor implements Gauge { + public GaugeMetric(MonitorConfig config) { + super(config.withAdditionalTag(DataSourceType.GAUGE).withAdditionalTag(getServoTypeTag()).withAdditionalTag(getServoInstanceTag())); + } + } + + protected Monitor getCumulativeCountForEvent(String name, final HystrixCommandMetrics metrics, final HystrixRollingNumberEvent event) { + return new CounterMetric(MonitorConfig.builder(name).withTag(getServoTypeTag()).withTag(getServoInstanceTag()).build()) { + @Override + public Long getValue() { + return metrics.getCumulativeCount(event); + } + + }; + } + + protected Monitor getRollingCountForEvent(String name, final HystrixCommandMetrics metrics, final HystrixRollingNumberEvent event) { + return new GaugeMetric(MonitorConfig.builder(name).withTag(DataSourceLevel.DEBUG).withTag(getServoTypeTag()).withTag(getServoInstanceTag()).build()) { + @Override + public Number getValue() { + return metrics.getRollingCount(event); + } + + }; + } +} 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 new file mode 100644 index 000000000..7fe95cb3d --- /dev/null +++ b/hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisherCommand.java @@ -0,0 +1,370 @@ +/** + * Copyright 2012 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 java.util.ArrayList; +import java.util.List; + +import com.netflix.hystrix.HystrixCircuitBreaker; +import com.netflix.hystrix.HystrixCommandGroupKey; +import com.netflix.hystrix.HystrixCommandKey; +import com.netflix.hystrix.HystrixCommandMetrics; +import com.netflix.hystrix.HystrixCommandProperties; +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; + +/** + * Implementation of {@link HystrixMetricsPublisherCommand} using Servo (https://github.com/Netflix/servo) + */ +public class HystrixServoMetricsPublisherCommand extends HystrixServoMetricsPublisherAbstract implements HystrixMetricsPublisherCommand { + + private final HystrixCommandKey key; + private final HystrixCommandGroupKey commandGroupKey; + private final HystrixCommandMetrics metrics; + private final HystrixCircuitBreaker circuitBreaker; + private final HystrixCommandProperties properties; + private final Tag servoInstanceTag; + private final Tag servoTypeTag; + + public HystrixServoMetricsPublisherCommand(HystrixCommandKey commandKey, HystrixCommandGroupKey commandGroupKey, HystrixCommandMetrics metrics, HystrixCircuitBreaker circuitBreaker, HystrixCommandProperties properties) { + this.key = commandKey; + this.commandGroupKey = commandGroupKey; + this.metrics = metrics; + this.circuitBreaker = circuitBreaker; + this.properties = properties; + this.servoInstanceTag = new Tag() { + + @Override + public String getKey() { + return "instance"; + } + + @Override + public String getValue() { + return key.name(); + } + + @Override + public String tagString() { + return key.name(); + } + + }; + this.servoTypeTag = new Tag() { + + @Override + public String getKey() { + return "type"; + } + + @Override + public String getValue() { + return "HystrixCommand"; + } + + @Override + public String tagString() { + return "HystrixCommand"; + } + + }; + } + + @Override + public void initialize() { + /* list of monitors */ + List> monitors = getServoMonitors(); + + // publish metrics together under a single composite (it seems this name is ignored) + MonitorConfig commandMetricsConfig = MonitorConfig.builder("HystrixCommand_" + key.name()).build(); + BasicCompositeMonitor commandMetricsMonitor = new BasicCompositeMonitor(commandMetricsConfig, monitors); + + DefaultMonitorRegistry.getInstance().register(commandMetricsMonitor); + } + + @Override + protected Tag getServoTypeTag() { + return servoTypeTag; + } + + @Override + protected Tag getServoInstanceTag() { + return servoInstanceTag; + } + + /** + * Servo will flatten metric names as: getServoTypeTag()_getServoInstanceTag()_monitorName + */ + private List> getServoMonitors() { + + List> monitors = new ArrayList>(); + + monitors.add(new InformationalMetric(MonitorConfig.builder("isCircuitBreakerOpen").build()) { + @Override + public Boolean getValue() { + return circuitBreaker.isOpen(); + } + }); + + // allow Servo and monitor to know exactly at what point in time these stats are for so they can be plotted accurately + monitors.add(new GaugeMetric(MonitorConfig.builder("currentTime").withTag(DataSourceLevel.DEBUG).build()) { + @Override + public Number getValue() { + return System.currentTimeMillis(); + } + }); + + // cumulative counts + monitors.add(getCumulativeCountForEvent("countCollapsedRequests", metrics, HystrixRollingNumberEvent.COLLAPSED)); + monitors.add(getCumulativeCountForEvent("countExceptionsThrown", metrics, HystrixRollingNumberEvent.EXCEPTION_THROWN)); + monitors.add(getCumulativeCountForEvent("countFailure", metrics, HystrixRollingNumberEvent.FAILURE)); + 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)); + + // rolling counts + monitors.add(getRollingCountForEvent("rollingCountCollapsedRequests", metrics, HystrixRollingNumberEvent.COLLAPSED)); + monitors.add(getRollingCountForEvent("rollingCountExceptionsThrown", metrics, HystrixRollingNumberEvent.EXCEPTION_THROWN)); + monitors.add(getRollingCountForEvent("rollingCountFailure", metrics, HystrixRollingNumberEvent.FAILURE)); + 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(90); + } + }); + 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); + } + }); + + // group + monitors.add(new InformationalMetric(MonitorConfig.builder("commandGroup").build()) { + @Override + public String getValue() { + return commandGroupKey != null ? commandGroupKey.name() : null; + } + }); + + // properties (so the values can be inspected and monitored) + monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_rollingStatisticalWindowInMilliseconds").build()) { + @Override + public Number getValue() { + return properties.metricsRollingStatisticalWindowInMilliseconds().get(); + } + }); + monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_circuitBreakerRequestVolumeThreshold").build()) { + @Override + public Number getValue() { + return properties.circuitBreakerRequestVolumeThreshold().get(); + } + }); + monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_circuitBreakerSleepWindowInMilliseconds").build()) { + @Override + public Number getValue() { + return properties.circuitBreakerSleepWindowInMilliseconds().get(); + } + }); + monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_circuitBreakerErrorThresholdPercentage").build()) { + @Override + public Number getValue() { + return properties.circuitBreakerErrorThresholdPercentage().get(); + } + }); + monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_circuitBreakerForceOpen").build()) { + @Override + public Boolean getValue() { + return properties.circuitBreakerForceOpen().get(); + } + }); + monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_circuitBreakerForceClosed").build()) { + @Override + public Boolean getValue() { + return properties.circuitBreakerForceClosed().get(); + } + }); + monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_executionIsolationThreadTimeoutInMilliseconds").build()) { + @Override + public Number getValue() { + return properties.executionIsolationThreadTimeoutInMilliseconds().get(); + } + }); + monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_executionIsolationStrategy").build()) { + @Override + public String getValue() { + return properties.executionIsolationStrategy().get().name(); + } + }); + monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_metricsRollingPercentileEnabled").build()) { + @Override + public Boolean getValue() { + return properties.metricsRollingPercentileEnabled().get(); + } + }); + monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_requestCacheEnabled").build()) { + @Override + public Boolean getValue() { + return properties.requestCacheEnabled().get(); + } + }); + monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_requestLogEnabled").build()) { + @Override + public Boolean getValue() { + return properties.requestLogEnabled().get(); + } + }); + monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_executionIsolationSemaphoreMaxConcurrentRequests").build()) { + @Override + public Number getValue() { + return properties.executionIsolationSemaphoreMaxConcurrentRequests().get(); + } + }); + monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_fallbackIsolationSemaphoreMaxConcurrentRequests").build()) { + @Override + public Number getValue() { + return properties.fallbackIsolationSemaphoreMaxConcurrentRequests().get(); + } + }); + + return monitors; + } + +} diff --git a/hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisherThreadPool.java b/hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisherThreadPool.java new file mode 100644 index 000000000..a8aca27b5 --- /dev/null +++ b/hystrix-contrib/hystrix-servo-metrics-publisher/src/main/java/com/netflix/hystrix/contrib/servopublisher/HystrixServoMetricsPublisherThreadPool.java @@ -0,0 +1,218 @@ +/** + * Copyright 2012 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 java.util.ArrayList; +import java.util.List; + +import com.netflix.hystrix.HystrixThreadPoolKey; +import com.netflix.hystrix.HystrixThreadPoolMetrics; +import com.netflix.hystrix.HystrixThreadPoolProperties; +import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisherThreadPool; +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; + +/** + * Implementation of {@link HystrixMetricsPublisherThreadPool} using Servo (https://github.com/Netflix/servo) + */ +public class HystrixServoMetricsPublisherThreadPool extends HystrixServoMetricsPublisherAbstract implements HystrixMetricsPublisherThreadPool { + + private final HystrixThreadPoolKey key; + private final HystrixThreadPoolMetrics metrics; + private final HystrixThreadPoolProperties properties; + private final Tag servoInstanceTag; + private final Tag servoTypeTag; + + public HystrixServoMetricsPublisherThreadPool(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolMetrics metrics, HystrixThreadPoolProperties properties) { + this.key = threadPoolKey; + this.metrics = metrics; + this.properties = properties; + + this.servoInstanceTag = new Tag() { + + @Override + public String getKey() { + return "instance"; + } + + @Override + public String getValue() { + return key.name(); + } + + @Override + public String tagString() { + return key.name(); + } + + }; + this.servoTypeTag = new Tag() { + + @Override + public String getKey() { + return "type"; + } + + @Override + public String getValue() { + return "HystrixThreadPool"; + } + + @Override + public String tagString() { + return "HystrixThreadPool"; + } + + }; + } + + @Override + public void initialize() { + /* list of monitors */ + List> monitors = getServoMonitors(); + + // publish metrics together under a single composite (it seems this name is ignored) + MonitorConfig commandMetricsConfig = MonitorConfig.builder("HystrixThreadPool_" + key.name()).build(); + BasicCompositeMonitor commandMetricsMonitor = new BasicCompositeMonitor(commandMetricsConfig, monitors); + + DefaultMonitorRegistry.getInstance().register(commandMetricsMonitor); + } + + @Override + protected Tag getServoTypeTag() { + return servoTypeTag; + } + + @Override + protected Tag getServoInstanceTag() { + return servoInstanceTag; + } + + /** + * Servo will flatten metric names as: getServoTypeTag()_getServoInstanceTag()_monitorName + */ + private List> getServoMonitors() { + + List> monitors = new ArrayList>(); + + monitors.add(new InformationalMetric(MonitorConfig.builder("name").build()) { + @Override + public String getValue() { + return key.name(); + } + }); + + // allow Servo and monitor to know exactly at what point in time these stats are for so they can be plotted accurately + monitors.add(new GaugeMetric(MonitorConfig.builder("currentTime").withTag(DataSourceLevel.DEBUG).build()) { + @Override + public Number getValue() { + return System.currentTimeMillis(); + } + }); + + monitors.add(new GaugeMetric(MonitorConfig.builder("threadActiveCount").build()) { + @Override + public Number getValue() { + return metrics.getCurrentActiveCount(); + } + }); + + monitors.add(new GaugeMetric(MonitorConfig.builder("completedTaskCount").build()) { + @Override + public Number getValue() { + return metrics.getCurrentCompletedTaskCount(); + } + }); + + monitors.add(new GaugeMetric(MonitorConfig.builder("largestPoolSize").build()) { + @Override + public Number getValue() { + return metrics.getCurrentLargestPoolSize(); + } + }); + + monitors.add(new GaugeMetric(MonitorConfig.builder("totalTaskCount").build()) { + @Override + public Number getValue() { + return metrics.getCurrentTaskCount(); + } + }); + + monitors.add(new GaugeMetric(MonitorConfig.builder("queueSize").build()) { + @Override + public Number getValue() { + return metrics.getCurrentQueueSize(); + } + }); + + monitors.add(new GaugeMetric(MonitorConfig.builder("rollingMaxActiveThreads").withTag(DataSourceLevel.DEBUG).build()) { + @Override + public Number getValue() { + return metrics.getRollingMaxActiveThreads(); + } + }); + + monitors.add(new CounterMetric(MonitorConfig.builder("countThreadsExecuted").build()) { + @Override + public Long getValue() { + return metrics.getCumulativeCountThreadsExecuted(); + } + }); + + monitors.add(new GaugeMetric(MonitorConfig.builder("rollingCountThreadsExecuted").withTag(DataSourceLevel.DEBUG).build()) { + @Override + public Number getValue() { + return metrics.getRollingCountThreadsExecuted(); + } + }); + + // properties + monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_corePoolSize").build()) { + @Override + public Number getValue() { + return properties.coreSize().get(); + } + }); + + monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_keepAliveTimeInMinutes").build()) { + @Override + public Number getValue() { + return properties.keepAliveTimeMinutes().get(); + } + }); + + monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_queueSizeRejectionThreshold").build()) { + @Override + public Number getValue() { + return properties.queueSizeRejectionThreshold().get(); + } + }); + + monitors.add(new InformationalMetric(MonitorConfig.builder("propertyValue_maxQueueSize").build()) { + @Override + public Number getValue() { + return properties.maxQueueSize().get(); + } + }); + + return monitors; + } + +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 4c3425a20..8a6f186ae 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,2 @@ rootProject.name='hystrix' -include 'hystrix-core', 'hystrix-examples', 'hystrix-contrib:hystrix-request-servlet', 'hystrix-contrib:hystrix-servo-stream' +include 'hystrix-core', 'hystrix-examples', 'hystrix-contrib:hystrix-request-servlet', 'hystrix-contrib:hystrix-servo-stream', 'hystrix-contrib:hystrix-servo-metrics-publisher'