2525import com .netflix .hystrix .HystrixCommandProperties ;
2626import com .netflix .hystrix .HystrixEventType ;
2727import com .netflix .hystrix .strategy .metrics .HystrixMetricsPublisherCommand ;
28+ import com .netflix .hystrix .util .HystrixRollingNumberEvent ;
2829import com .netflix .servo .DefaultMonitorRegistry ;
2930import com .netflix .servo .annotations .DataSourceLevel ;
3031import com .netflix .servo .monitor .BasicCompositeMonitor ;
3536
3637/**
3738 * Concrete Implementation of {@link HystrixMetricsPublisherCommand} using Servo (https://github.com/Netflix/servo)
39+ *
40+ * This class should encapsulate all logic around how to pull metrics. This will allow any other custom Servo publisher
41+ * to extend. Then, if that class wishes to override {@link #initialize()}, that concrete implementation can choose
42+ * by picking the set of semantic metrics and names, rather than providing an implementation of how.
3843 */
39- public class HystrixServoMetricsPublisherCommand extends HystrixServoMetricsPublisherCommandAbstract implements HystrixMetricsPublisherCommand {
44+ public class HystrixServoMetricsPublisherCommand extends HystrixServoMetricsPublisherAbstract implements HystrixMetricsPublisherCommand {
4045
4146 private final HystrixCommandKey key ;
4247 private final HystrixCommandGroupKey commandGroupKey ;
@@ -112,50 +117,127 @@ protected Tag getServoInstanceTag() {
112117 return servoInstanceTag ;
113118 }
114119
115- @ Override
116- protected long getCumulativeCount (HystrixEventType event ) {
117- return metrics .getCumulativeCount (getRollingNumberTypeFromEventType (event ));
118- }
119-
120- @ Override
121- protected long getRollingCount (HystrixEventType event ) {
122- return metrics .getRollingCount (getRollingNumberTypeFromEventType (event ));
123- }
124-
125- @ Override
126- protected int getExecutionLatencyMean () {
127- return metrics .getExecutionTimeMean ();
128- }
129-
130- @ Override
131- protected int getExecutionLatencyPercentile (double percentile ) {
132- return metrics .getExecutionTimePercentile (percentile );
133- }
134-
135- @ Override
136- protected int getTotalLatencyMean () {
137- return metrics .getTotalTimeMean ();
138- }
139-
140- @ Override
141- protected int getTotalLatencyPercentile (double percentile ) {
142- return metrics .getTotalTimePercentile (percentile );
120+ protected final HystrixRollingNumberEvent getRollingNumberTypeFromEventType (HystrixEventType event ) {
121+ switch (event ) {
122+ case BAD_REQUEST : return HystrixRollingNumberEvent .BAD_REQUEST ;
123+ case COLLAPSED : return HystrixRollingNumberEvent .COLLAPSED ;
124+ case EMIT : return HystrixRollingNumberEvent .EMIT ;
125+ case EXCEPTION_THROWN : return HystrixRollingNumberEvent .EXCEPTION_THROWN ;
126+ case FAILURE : return HystrixRollingNumberEvent .FAILURE ;
127+ case FALLBACK_EMIT : return HystrixRollingNumberEvent .FALLBACK_EMIT ;
128+ case FALLBACK_FAILURE : return HystrixRollingNumberEvent .FALLBACK_FAILURE ;
129+ case FALLBACK_REJECTION : return HystrixRollingNumberEvent .FALLBACK_REJECTION ;
130+ case FALLBACK_SUCCESS : return HystrixRollingNumberEvent .FALLBACK_SUCCESS ;
131+ case RESPONSE_FROM_CACHE : return HystrixRollingNumberEvent .RESPONSE_FROM_CACHE ;
132+ case SEMAPHORE_REJECTED : return HystrixRollingNumberEvent .SEMAPHORE_REJECTED ;
133+ case SHORT_CIRCUITED : return HystrixRollingNumberEvent .SHORT_CIRCUITED ;
134+ case SUCCESS : return HystrixRollingNumberEvent .SUCCESS ;
135+ case THREAD_POOL_REJECTED : return HystrixRollingNumberEvent .THREAD_POOL_REJECTED ;
136+ case TIMEOUT : return HystrixRollingNumberEvent .TIMEOUT ;
137+ default : throw new RuntimeException ("Unknown HystrixEventType : " + event );
138+ }
143139 }
144140
145- private final Func0 <Number > currentConcurrentExecutionCountThunk = new Func0 <Number >() {
141+ protected final Func0 <Number > currentConcurrentExecutionCountThunk = new Func0 <Number >() {
146142 @ Override
147143 public Integer call () {
148144 return metrics .getCurrentConcurrentExecutionCount ();
149145 }
150146 };
151147
152- private final Func0 <Number > errorPercentageThunk = new Func0 <Number >() {
148+ protected final Func0 <Number > rollingMaxConcurrentExecutionCountThunk = new Func0 <Number >() {
149+ @ Override
150+ public Long call () {
151+ return metrics .getRollingMaxConcurrentExecutions ();
152+ }
153+ };
154+
155+ protected final Func0 <Number > errorPercentageThunk = new Func0 <Number >() {
153156 @ Override
154157 public Integer call () {
155158 return metrics .getHealthCounts ().getErrorPercentage ();
156159 }
157160 };
158161
162+ protected final Func0 <Number > currentTimeThunk = new Func0 <Number >() {
163+ @ Override
164+ public Number call () {
165+ return System .currentTimeMillis ();
166+ }
167+ };
168+
169+ protected Monitor <?> getCumulativeMonitor (final String name , final HystrixEventType event ) {
170+ return new CounterMetric (MonitorConfig .builder (name ).withTag (getServoTypeTag ()).withTag (getServoInstanceTag ()).build ()) {
171+ @ Override
172+ public Long getValue () {
173+ return metrics .getCumulativeCount (getRollingNumberTypeFromEventType (event ));
174+ }
175+ };
176+ }
177+
178+ protected Monitor <?> getRollingMonitor (final String name , final HystrixEventType event ) {
179+ return new CounterMetric (MonitorConfig .builder (name ).withTag (getServoTypeTag ()).withTag (getServoInstanceTag ()).build ()) {
180+ @ Override
181+ public Long getValue () {
182+ return metrics .getRollingCount (getRollingNumberTypeFromEventType (event ));
183+ }
184+ };
185+ }
186+
187+ protected Monitor <?> getExecutionLatencyMeanMonitor (final String name ) {
188+ return new GaugeMetric (MonitorConfig .builder (name ).build ()) {
189+ @ Override
190+ public Number getValue () {
191+ return metrics .getExecutionTimeMean ();
192+ }
193+ };
194+ }
195+
196+ protected Monitor <?> getExecutionLatencyPercentileMonitor (final String name , final double percentile ) {
197+ return new GaugeMetric (MonitorConfig .builder (name ).build ()) {
198+ @ Override
199+ public Number getValue () {
200+ return metrics .getExecutionTimePercentile (percentile );
201+ }
202+ };
203+ }
204+
205+ protected Monitor <?> getTotalLatencyMeanMonitor (final String name ) {
206+ return new GaugeMetric (MonitorConfig .builder (name ).build ()) {
207+ @ Override
208+ public Number getValue () {
209+ return metrics .getTotalTimeMean ();
210+ }
211+ };
212+ }
213+
214+ protected Monitor <?> getTotalLatencyPercentileMonitor (final String name , final double percentile ) {
215+ return new GaugeMetric (MonitorConfig .builder (name ).build ()) {
216+ @ Override
217+ public Number getValue () {
218+ return metrics .getTotalTimePercentile (percentile );
219+ }
220+ };
221+ }
222+
223+ protected Monitor <?> getCurrentValueMonitor (final String name , final Func0 <Number > metricToEvaluate ) {
224+ return new GaugeMetric (MonitorConfig .builder (name ).build ()) {
225+ @ Override
226+ public Number getValue () {
227+ return metricToEvaluate .call ();
228+ }
229+ };
230+ }
231+
232+ protected Monitor <?> getCurrentValueMonitor (final String name , final Func0 <Number > metricToEvaluate , final Tag tag ) {
233+ return new GaugeMetric (MonitorConfig .builder (name ).withTag (tag ).build ()) {
234+ @ Override
235+ public Number getValue () {
236+ return metricToEvaluate .call ();
237+ }
238+ };
239+ }
240+
159241 /**
160242 * Servo will flatten metric names as: getServoTypeTag()_getServoInstanceTag()_monitorName
161243 */
@@ -171,12 +253,7 @@ public Boolean getValue() {
171253 });
172254
173255 // allow Servo and monitor to know exactly at what point in time these stats are for so they can be plotted accurately
174- monitors .add (new GaugeMetric (MonitorConfig .builder ("currentTime" ).withTag (DataSourceLevel .DEBUG ).build ()) {
175- @ Override
176- public Number getValue () {
177- return System .currentTimeMillis ();
178- }
179- });
256+ monitors .add (getCurrentValueMonitor ("currentTime" , currentTimeThunk , DataSourceLevel .DEBUG ));
180257
181258 // cumulative counts
182259 monitors .add (getCumulativeMonitor ("countBadRequests" , HystrixEventType .BAD_REQUEST ));
0 commit comments