com.netflix.hystrix.serial.SerialHystrixDashboardData.java Source code

Java tutorial

Introduction

Here is the source code for com.netflix.hystrix.serial.SerialHystrixDashboardData.java

Source

/**
 * Copyright 2016 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.serial;

import com.fasterxml.jackson.core.JsonGenerator;
import com.netflix.hystrix.HystrixCircuitBreaker;
import com.netflix.hystrix.HystrixCollapserKey;
import com.netflix.hystrix.HystrixCollapserMetrics;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixCommandMetrics;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.HystrixEventType;
import com.netflix.hystrix.HystrixThreadPoolKey;
import com.netflix.hystrix.HystrixThreadPoolMetrics;
import com.netflix.hystrix.metric.consumer.HystrixDashboardStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.functions.Func0;

import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

public class SerialHystrixDashboardData extends SerialHystrixMetric {

    private static final Logger logger = LoggerFactory.getLogger(SerialHystrixDashboardData.class);

    @Deprecated
    public static byte[] toBytes(HystrixDashboardStream.DashboardData dashboardData) {
        throw new UnsupportedOperationException(
                "Not implemented anymore.  Will be implemented in a new class shortly");
    }

    public static String toJsonString(HystrixDashboardStream.DashboardData dashboardData) {
        StringWriter jsonString = new StringWriter();

        try {
            JsonGenerator json = jsonFactory.createGenerator(jsonString);
            writeDashboardData(json, dashboardData);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return jsonString.getBuffer().toString();
    }

    public static List<String> toMultipleJsonStrings(HystrixDashboardStream.DashboardData dashboardData) {
        List<String> jsonStrings = new ArrayList<String>();

        for (HystrixCommandMetrics commandMetrics : dashboardData.getCommandMetrics()) {
            jsonStrings.add(toJsonString(commandMetrics));
        }

        for (HystrixThreadPoolMetrics threadPoolMetrics : dashboardData.getThreadPoolMetrics()) {
            jsonStrings.add(toJsonString(threadPoolMetrics));
        }

        for (HystrixCollapserMetrics collapserMetrics : dashboardData.getCollapserMetrics()) {
            jsonStrings.add(toJsonString(collapserMetrics));
        }

        return jsonStrings;
    }

    private static void writeDashboardData(JsonGenerator json, HystrixDashboardStream.DashboardData dashboardData) {
        try {
            json.writeStartArray();

            for (HystrixCommandMetrics commandMetrics : dashboardData.getCommandMetrics()) {
                writeCommandMetrics(commandMetrics, json);
            }

            for (HystrixThreadPoolMetrics threadPoolMetrics : dashboardData.getThreadPoolMetrics()) {
                writeThreadPoolMetrics(threadPoolMetrics, json);
            }

            for (HystrixCollapserMetrics collapserMetrics : dashboardData.getCollapserMetrics()) {
                writeCollapserMetrics(collapserMetrics, json);
            }

            json.writeEndArray();

            json.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String toJsonString(HystrixCommandMetrics commandMetrics) {
        StringWriter jsonString = new StringWriter();

        try {
            JsonGenerator json = jsonFactory.createGenerator(jsonString);
            writeCommandMetrics(commandMetrics, json);
            json.close();
            return jsonString.getBuffer().toString();
        } catch (IOException ioe) {
            throw new RuntimeException(ioe);
        }
    }

    public static String toJsonString(HystrixThreadPoolMetrics threadPoolMetrics) {
        StringWriter jsonString = new StringWriter();

        try {
            JsonGenerator json = jsonFactory.createGenerator(jsonString);
            writeThreadPoolMetrics(threadPoolMetrics, json);
            json.close();
            return jsonString.getBuffer().toString();
        } catch (IOException ioe) {
            throw new RuntimeException(ioe);
        }
    }

    public static String toJsonString(HystrixCollapserMetrics collapserMetrics) {
        StringWriter jsonString = new StringWriter();

        try {
            JsonGenerator json = jsonFactory.createGenerator(jsonString);
            writeCollapserMetrics(collapserMetrics, json);
            json.close();
            return jsonString.getBuffer().toString();
        } catch (IOException ioe) {
            throw new RuntimeException(ioe);
        }
    }

    private static void writeCommandMetrics(final HystrixCommandMetrics commandMetrics, JsonGenerator json)
            throws IOException {
        HystrixCommandKey key = commandMetrics.getCommandKey();
        HystrixCircuitBreaker circuitBreaker = HystrixCircuitBreaker.Factory.getInstance(key);

        json.writeStartObject();
        json.writeStringField("type", "HystrixCommand");
        json.writeStringField("name", key.name());
        json.writeStringField("group", commandMetrics.getCommandGroup().name());
        json.writeNumberField("currentTime", System.currentTimeMillis());

        // circuit breaker
        if (circuitBreaker == null) {
            // circuit breaker is disabled and thus never open
            json.writeBooleanField("isCircuitBreakerOpen", false);
        } else {
            json.writeBooleanField("isCircuitBreakerOpen", circuitBreaker.isOpen());
        }
        HystrixCommandMetrics.HealthCounts healthCounts = commandMetrics.getHealthCounts();
        json.writeNumberField("errorPercentage", healthCounts.getErrorPercentage());
        json.writeNumberField("errorCount", healthCounts.getErrorCount());
        json.writeNumberField("requestCount", healthCounts.getTotalRequests());

        // rolling counters
        safelyWriteNumberField(json, "rollingCountBadRequests", new Func0<Long>() {
            @Override
            public Long call() {
                return commandMetrics.getRollingCount(HystrixEventType.BAD_REQUEST);
            }
        });
        safelyWriteNumberField(json, "rollingCountCollapsedRequests", new Func0<Long>() {
            @Override
            public Long call() {
                return commandMetrics.getRollingCount(HystrixEventType.COLLAPSED);
            }
        });
        safelyWriteNumberField(json, "rollingCountEmit", new Func0<Long>() {
            @Override
            public Long call() {
                return commandMetrics.getRollingCount(HystrixEventType.EMIT);
            }
        });
        safelyWriteNumberField(json, "rollingCountExceptionsThrown", new Func0<Long>() {
            @Override
            public Long call() {
                return commandMetrics.getRollingCount(HystrixEventType.EXCEPTION_THROWN);
            }
        });
        safelyWriteNumberField(json, "rollingCountFailure", new Func0<Long>() {
            @Override
            public Long call() {
                return commandMetrics.getRollingCount(HystrixEventType.FAILURE);
            }
        });
        safelyWriteNumberField(json, "rollingCountFallbackEmit", new Func0<Long>() {
            @Override
            public Long call() {
                return commandMetrics.getRollingCount(HystrixEventType.FALLBACK_EMIT);
            }
        });
        safelyWriteNumberField(json, "rollingCountFallbackFailure", new Func0<Long>() {
            @Override
            public Long call() {
                return commandMetrics.getRollingCount(HystrixEventType.FALLBACK_FAILURE);
            }
        });
        safelyWriteNumberField(json, "rollingCountFallbackMissing", new Func0<Long>() {
            @Override
            public Long call() {
                return commandMetrics.getRollingCount(HystrixEventType.FALLBACK_MISSING);
            }
        });
        safelyWriteNumberField(json, "rollingCountFallbackRejection", new Func0<Long>() {
            @Override
            public Long call() {
                return commandMetrics.getRollingCount(HystrixEventType.FALLBACK_REJECTION);
            }
        });
        safelyWriteNumberField(json, "rollingCountFallbackSuccess", new Func0<Long>() {
            @Override
            public Long call() {
                return commandMetrics.getRollingCount(HystrixEventType.FALLBACK_SUCCESS);
            }
        });
        safelyWriteNumberField(json, "rollingCountResponsesFromCache", new Func0<Long>() {
            @Override
            public Long call() {
                return commandMetrics.getRollingCount(HystrixEventType.RESPONSE_FROM_CACHE);
            }
        });
        safelyWriteNumberField(json, "rollingCountSemaphoreRejected", new Func0<Long>() {
            @Override
            public Long call() {
                return commandMetrics.getRollingCount(HystrixEventType.SEMAPHORE_REJECTED);
            }
        });
        safelyWriteNumberField(json, "rollingCountShortCircuited", new Func0<Long>() {
            @Override
            public Long call() {
                return commandMetrics.getRollingCount(HystrixEventType.SHORT_CIRCUITED);
            }
        });
        safelyWriteNumberField(json, "rollingCountSuccess", new Func0<Long>() {
            @Override
            public Long call() {
                return commandMetrics.getRollingCount(HystrixEventType.SUCCESS);
            }
        });
        safelyWriteNumberField(json, "rollingCountThreadPoolRejected", new Func0<Long>() {
            @Override
            public Long call() {
                return commandMetrics.getRollingCount(HystrixEventType.THREAD_POOL_REJECTED);
            }
        });
        safelyWriteNumberField(json, "rollingCountTimeout", new Func0<Long>() {
            @Override
            public Long call() {
                return commandMetrics.getRollingCount(HystrixEventType.TIMEOUT);
            }
        });

        json.writeNumberField("currentConcurrentExecutionCount",
                commandMetrics.getCurrentConcurrentExecutionCount());
        json.writeNumberField("rollingMaxConcurrentExecutionCount",
                commandMetrics.getRollingMaxConcurrentExecutions());

        // latency percentiles
        json.writeNumberField("latencyExecute_mean", commandMetrics.getExecutionTimeMean());
        json.writeObjectFieldStart("latencyExecute");
        json.writeNumberField("0", commandMetrics.getExecutionTimePercentile(0));
        json.writeNumberField("25", commandMetrics.getExecutionTimePercentile(25));
        json.writeNumberField("50", commandMetrics.getExecutionTimePercentile(50));
        json.writeNumberField("75", commandMetrics.getExecutionTimePercentile(75));
        json.writeNumberField("90", commandMetrics.getExecutionTimePercentile(90));
        json.writeNumberField("95", commandMetrics.getExecutionTimePercentile(95));
        json.writeNumberField("99", commandMetrics.getExecutionTimePercentile(99));
        json.writeNumberField("99.5", commandMetrics.getExecutionTimePercentile(99.5));
        json.writeNumberField("100", commandMetrics.getExecutionTimePercentile(100));
        json.writeEndObject();
        //
        json.writeNumberField("latencyTotal_mean", commandMetrics.getTotalTimeMean());
        json.writeObjectFieldStart("latencyTotal");
        json.writeNumberField("0", commandMetrics.getTotalTimePercentile(0));
        json.writeNumberField("25", commandMetrics.getTotalTimePercentile(25));
        json.writeNumberField("50", commandMetrics.getTotalTimePercentile(50));
        json.writeNumberField("75", commandMetrics.getTotalTimePercentile(75));
        json.writeNumberField("90", commandMetrics.getTotalTimePercentile(90));
        json.writeNumberField("95", commandMetrics.getTotalTimePercentile(95));
        json.writeNumberField("99", commandMetrics.getTotalTimePercentile(99));
        json.writeNumberField("99.5", commandMetrics.getTotalTimePercentile(99.5));
        json.writeNumberField("100", commandMetrics.getTotalTimePercentile(100));
        json.writeEndObject();

        // property values for reporting what is actually seen by the command rather than what was set somewhere
        HystrixCommandProperties commandProperties = commandMetrics.getProperties();

        json.writeNumberField("propertyValue_circuitBreakerRequestVolumeThreshold",
                commandProperties.circuitBreakerRequestVolumeThreshold().get());
        json.writeNumberField("propertyValue_circuitBreakerSleepWindowInMilliseconds",
                commandProperties.circuitBreakerSleepWindowInMilliseconds().get());
        json.writeNumberField("propertyValue_circuitBreakerErrorThresholdPercentage",
                commandProperties.circuitBreakerErrorThresholdPercentage().get());
        json.writeBooleanField("propertyValue_circuitBreakerForceOpen",
                commandProperties.circuitBreakerForceOpen().get());
        json.writeBooleanField("propertyValue_circuitBreakerForceClosed",
                commandProperties.circuitBreakerForceClosed().get());
        json.writeBooleanField("propertyValue_circuitBreakerEnabled",
                commandProperties.circuitBreakerEnabled().get());

        json.writeStringField("propertyValue_executionIsolationStrategy",
                commandProperties.executionIsolationStrategy().get().name());
        json.writeNumberField("propertyValue_executionIsolationThreadTimeoutInMilliseconds",
                commandProperties.executionTimeoutInMilliseconds().get());
        json.writeNumberField("propertyValue_executionTimeoutInMilliseconds",
                commandProperties.executionTimeoutInMilliseconds().get());
        json.writeBooleanField("propertyValue_executionIsolationThreadInterruptOnTimeout",
                commandProperties.executionIsolationThreadInterruptOnTimeout().get());
        json.writeStringField("propertyValue_executionIsolationThreadPoolKeyOverride",
                commandProperties.executionIsolationThreadPoolKeyOverride().get());
        json.writeNumberField("propertyValue_executionIsolationSemaphoreMaxConcurrentRequests",
                commandProperties.executionIsolationSemaphoreMaxConcurrentRequests().get());
        json.writeNumberField("propertyValue_fallbackIsolationSemaphoreMaxConcurrentRequests",
                commandProperties.fallbackIsolationSemaphoreMaxConcurrentRequests().get());

        /*
         * The following are commented out as these rarely change and are verbose for streaming for something people don't change.
         * We could perhaps allow a property or request argument to include these.
         */

        //                    json.put("propertyValue_metricsRollingPercentileEnabled", commandProperties.metricsRollingPercentileEnabled().get());
        //                    json.put("propertyValue_metricsRollingPercentileBucketSize", commandProperties.metricsRollingPercentileBucketSize().get());
        //                    json.put("propertyValue_metricsRollingPercentileWindow", commandProperties.metricsRollingPercentileWindowInMilliseconds().get());
        //                    json.put("propertyValue_metricsRollingPercentileWindowBuckets", commandProperties.metricsRollingPercentileWindowBuckets().get());
        //                    json.put("propertyValue_metricsRollingStatisticalWindowBuckets", commandProperties.metricsRollingStatisticalWindowBuckets().get());
        json.writeNumberField("propertyValue_metricsRollingStatisticalWindowInMilliseconds",
                commandProperties.metricsRollingStatisticalWindowInMilliseconds().get());

        json.writeBooleanField("propertyValue_requestCacheEnabled", commandProperties.requestCacheEnabled().get());
        json.writeBooleanField("propertyValue_requestLogEnabled", commandProperties.requestLogEnabled().get());

        json.writeNumberField("reportingHosts", 1); // this will get summed across all instances in a cluster
        json.writeStringField("threadPool", commandMetrics.getThreadPoolKey().name());

        json.writeEndObject();
    }

    private static void writeThreadPoolMetrics(final HystrixThreadPoolMetrics threadPoolMetrics, JsonGenerator json)
            throws IOException {
        HystrixThreadPoolKey key = threadPoolMetrics.getThreadPoolKey();

        json.writeStartObject();

        json.writeStringField("type", "HystrixThreadPool");
        json.writeStringField("name", key.name());
        json.writeNumberField("currentTime", System.currentTimeMillis());

        json.writeNumberField("currentActiveCount", threadPoolMetrics.getCurrentActiveCount().intValue());
        json.writeNumberField("currentCompletedTaskCount",
                threadPoolMetrics.getCurrentCompletedTaskCount().longValue());
        json.writeNumberField("currentCorePoolSize", threadPoolMetrics.getCurrentCorePoolSize().intValue());
        json.writeNumberField("currentLargestPoolSize", threadPoolMetrics.getCurrentLargestPoolSize().intValue());
        json.writeNumberField("currentMaximumPoolSize", threadPoolMetrics.getCurrentMaximumPoolSize().intValue());
        json.writeNumberField("currentPoolSize", threadPoolMetrics.getCurrentPoolSize().intValue());
        json.writeNumberField("currentQueueSize", threadPoolMetrics.getCurrentQueueSize().intValue());
        json.writeNumberField("currentTaskCount", threadPoolMetrics.getCurrentTaskCount().longValue());
        safelyWriteNumberField(json, "rollingCountThreadsExecuted", new Func0<Long>() {
            @Override
            public Long call() {
                return threadPoolMetrics.getRollingCount(HystrixEventType.ThreadPool.EXECUTED);
            }
        });
        json.writeNumberField("rollingMaxActiveThreads", threadPoolMetrics.getRollingMaxActiveThreads());
        safelyWriteNumberField(json, "rollingCountCommandRejections", new Func0<Long>() {
            @Override
            public Long call() {
                return threadPoolMetrics.getRollingCount(HystrixEventType.ThreadPool.REJECTED);
            }
        });

        json.writeNumberField("propertyValue_queueSizeRejectionThreshold",
                threadPoolMetrics.getProperties().queueSizeRejectionThreshold().get());
        json.writeNumberField("propertyValue_metricsRollingStatisticalWindowInMilliseconds",
                threadPoolMetrics.getProperties().metricsRollingStatisticalWindowInMilliseconds().get());

        json.writeNumberField("reportingHosts", 1); // this will get summed across all instances in a cluster

        json.writeEndObject();
    }

    private static void writeCollapserMetrics(final HystrixCollapserMetrics collapserMetrics, JsonGenerator json)
            throws IOException {
        HystrixCollapserKey key = collapserMetrics.getCollapserKey();

        json.writeStartObject();

        json.writeStringField("type", "HystrixCollapser");
        json.writeStringField("name", key.name());
        json.writeNumberField("currentTime", System.currentTimeMillis());

        safelyWriteNumberField(json, "rollingCountRequestsBatched", new Func0<Long>() {
            @Override
            public Long call() {
                return collapserMetrics.getRollingCount(HystrixEventType.Collapser.ADDED_TO_BATCH);
            }
        });
        safelyWriteNumberField(json, "rollingCountBatches", new Func0<Long>() {
            @Override
            public Long call() {
                return collapserMetrics.getRollingCount(HystrixEventType.Collapser.BATCH_EXECUTED);
            }
        });
        safelyWriteNumberField(json, "rollingCountResponsesFromCache", new Func0<Long>() {
            @Override
            public Long call() {
                return collapserMetrics.getRollingCount(HystrixEventType.Collapser.RESPONSE_FROM_CACHE);
            }
        });

        // batch size percentiles
        json.writeNumberField("batchSize_mean", collapserMetrics.getBatchSizeMean());
        json.writeObjectFieldStart("batchSize");
        json.writeNumberField("25", collapserMetrics.getBatchSizePercentile(25));
        json.writeNumberField("50", collapserMetrics.getBatchSizePercentile(50));
        json.writeNumberField("75", collapserMetrics.getBatchSizePercentile(75));
        json.writeNumberField("90", collapserMetrics.getBatchSizePercentile(90));
        json.writeNumberField("95", collapserMetrics.getBatchSizePercentile(95));
        json.writeNumberField("99", collapserMetrics.getBatchSizePercentile(99));
        json.writeNumberField("99.5", collapserMetrics.getBatchSizePercentile(99.5));
        json.writeNumberField("100", collapserMetrics.getBatchSizePercentile(100));
        json.writeEndObject();

        // shard size percentiles (commented-out for now)
        //json.writeNumberField("shardSize_mean", collapserMetrics.getShardSizeMean());
        //json.writeObjectFieldStart("shardSize");
        //json.writeNumberField("25", collapserMetrics.getShardSizePercentile(25));
        //json.writeNumberField("50", collapserMetrics.getShardSizePercentile(50));
        //json.writeNumberField("75", collapserMetrics.getShardSizePercentile(75));
        //json.writeNumberField("90", collapserMetrics.getShardSizePercentile(90));
        //json.writeNumberField("95", collapserMetrics.getShardSizePercentile(95));
        //json.writeNumberField("99", collapserMetrics.getShardSizePercentile(99));
        //json.writeNumberField("99.5", collapserMetrics.getShardSizePercentile(99.5));
        //json.writeNumberField("100", collapserMetrics.getShardSizePercentile(100));
        //json.writeEndObject();

        //json.writeNumberField("propertyValue_metricsRollingStatisticalWindowInMilliseconds", collapserMetrics.getProperties().metricsRollingStatisticalWindowInMilliseconds().get());
        json.writeBooleanField("propertyValue_requestCacheEnabled",
                collapserMetrics.getProperties().requestCacheEnabled().get());
        json.writeNumberField("propertyValue_maxRequestsInBatch",
                collapserMetrics.getProperties().maxRequestsInBatch().get());
        json.writeNumberField("propertyValue_timerDelayInMilliseconds",
                collapserMetrics.getProperties().timerDelayInMilliseconds().get());

        json.writeNumberField("reportingHosts", 1); // this will get summed across all instances in a cluster

        json.writeEndObject();
    }

    protected static void safelyWriteNumberField(JsonGenerator json, String name, Func0<Long> metricGenerator)
            throws IOException {
        try {
            json.writeNumberField(name, metricGenerator.call());
        } catch (NoSuchFieldError error) {
            logger.error("While publishing Hystrix metrics stream, error looking up eventType for : " + name
                    + ".  Please check that all Hystrix versions are the same!");
            json.writeNumberField(name, 0L);
        }
    }
}