Back to Repositories

Testing Hystrix Request Event Serialization in Netflix/Hystrix

This test suite validates the serialization of Hystrix request events in Netflix’s Hystrix library. It ensures proper JSON formatting of various request scenarios including success, failure, fallback, and caching behaviors.

Test Coverage Overview

The test suite provides comprehensive coverage of Hystrix request event serialization.

Key areas tested include:
  • Empty request serialization
  • Single command execution scenarios (success, failure, timeout)
  • Multiple command executions with same/different keys
  • Caching behavior and cache key handling
  • Request collapsing with different batch sizes
  • Fallback scenarios and error handling

Implementation Analysis

The testing approach uses JUnit to validate JSON serialization of HystrixRequestEvents. Each test case constructs specific execution scenarios using SimpleExecution implementations to verify the correct JSON output format and structure.

Key patterns include:
  • Mock execution results with controlled latencies
  • Verification of event ordering and counts
  • Cache key and collapser key handling
  • Complex event sequence validation

Technical Details

Testing tools and configuration:
  • JUnit test framework
  • Custom SimpleExecution class implementing HystrixInvokableInfo
  • ExecutionResult for event tracking
  • Mock implementations of Hystrix keys and metrics
  • JSON string comparison for verification

Best Practices Demonstrated

The test suite exemplifies high-quality testing practices for complex serialization logic.

Notable practices include:
  • Comprehensive edge case coverage
  • Clear test method naming
  • Isolated test scenarios
  • Thorough assertion checking
  • Modular test setup with reusable components

netflix/hystrix

hystrix-serialization/src/test/java/com/netflix/hystrix/serial/SerialHystrixRequestEventsTest.java

            
/**
 * Copyright 2016 Netflix, Inc.
 * <p/>
 * 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
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * 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.netflix.hystrix.ExecutionResult;
import com.netflix.hystrix.HystrixCollapserKey;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixCommandMetrics;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.HystrixEventType;
import com.netflix.hystrix.HystrixInvokableInfo;
import com.netflix.hystrix.HystrixThreadPoolKey;
import com.netflix.hystrix.metric.HystrixRequestEvents;
import org.junit.Test;

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

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class SerialHystrixRequestEventsTest {

    private static final HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey("GROUP");
    private static final HystrixThreadPoolKey threadPoolKey = HystrixThreadPoolKey.Factory.asKey("ThreadPool");
    private static final HystrixCommandKey fooKey = HystrixCommandKey.Factory.asKey("Foo");
    private static final HystrixCommandKey barKey = HystrixCommandKey.Factory.asKey("Bar");
    private static final HystrixCollapserKey collapserKey = HystrixCollapserKey.Factory.asKey("FooCollapser");

    @Test
    public void testEmpty() throws IOException {
        HystrixRequestEvents request = new HystrixRequestEvents(new ArrayList<HystrixInvokableInfo<?>>());
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertEquals("[]", actual);
    }

    @Test
    public void testSingleSuccess() throws IOException {
        List<HystrixInvokableInfo<?>> executions = new ArrayList<HystrixInvokableInfo<?>>();
        executions.add(new SimpleExecution(fooKey, 100, HystrixEventType.SUCCESS));
        HystrixRequestEvents request = new HystrixRequestEvents(executions);
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertEquals("[{\"name\":\"Foo\",\"events\":[\"SUCCESS\"],\"latencies\":[100]}]", actual);
    }

    @Test
    public void testSingleFailureFallbackMissing() throws IOException {
        List<HystrixInvokableInfo<?>> executions = new ArrayList<HystrixInvokableInfo<?>>();
        executions.add(new SimpleExecution(fooKey, 101, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_MISSING));
        HystrixRequestEvents request = new HystrixRequestEvents(executions);
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertEquals("[{\"name\":\"Foo\",\"events\":[\"FAILURE\",\"FALLBACK_MISSING\"],\"latencies\":[101]}]", actual);
    }

    @Test
    public void testSingleFailureFallbackSuccess() throws IOException {
        List<HystrixInvokableInfo<?>> executions = new ArrayList<HystrixInvokableInfo<?>>();
        executions.add(new SimpleExecution(fooKey, 102, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_SUCCESS));
        HystrixRequestEvents request = new HystrixRequestEvents(executions);
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertEquals("[{\"name\":\"Foo\",\"events\":[\"FAILURE\",\"FALLBACK_SUCCESS\"],\"latencies\":[102]}]", actual);
    }

    @Test
    public void testSingleFailureFallbackRejected() throws IOException {
        List<HystrixInvokableInfo<?>> executions = new ArrayList<HystrixInvokableInfo<?>>();
        executions.add(new SimpleExecution(fooKey, 103, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_REJECTION));
        HystrixRequestEvents request = new HystrixRequestEvents(executions);
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertEquals("[{\"name\":\"Foo\",\"events\":[\"FAILURE\",\"FALLBACK_REJECTION\"],\"latencies\":[103]}]", actual);
    }

    @Test
    public void testSingleFailureFallbackFailure() throws IOException {
        List<HystrixInvokableInfo<?>> executions = new ArrayList<HystrixInvokableInfo<?>>();
        executions.add(new SimpleExecution(fooKey, 104, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_FAILURE));
        HystrixRequestEvents request = new HystrixRequestEvents(executions);
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertEquals("[{\"name\":\"Foo\",\"events\":[\"FAILURE\",\"FALLBACK_FAILURE\"],\"latencies\":[104]}]", actual);
    }

    @Test
    public void testSingleTimeoutFallbackSuccess() throws IOException {
        List<HystrixInvokableInfo<?>> executions = new ArrayList<HystrixInvokableInfo<?>>();
        executions.add(new SimpleExecution(fooKey, 105, HystrixEventType.TIMEOUT, HystrixEventType.FALLBACK_SUCCESS));
        HystrixRequestEvents request = new HystrixRequestEvents(executions);
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertEquals("[{\"name\":\"Foo\",\"events\":[\"TIMEOUT\",\"FALLBACK_SUCCESS\"],\"latencies\":[105]}]", actual);
    }

    @Test
    public void testSingleSemaphoreRejectedFallbackSuccess() throws IOException {
        List<HystrixInvokableInfo<?>> executions = new ArrayList<HystrixInvokableInfo<?>>();
        executions.add(new SimpleExecution(fooKey, 1, HystrixEventType.SEMAPHORE_REJECTED, HystrixEventType.FALLBACK_SUCCESS));
        HystrixRequestEvents request = new HystrixRequestEvents(executions);
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertEquals("[{\"name\":\"Foo\",\"events\":[\"SEMAPHORE_REJECTED\",\"FALLBACK_SUCCESS\"],\"latencies\":[1]}]", actual);
    }

    @Test
    public void testSingleThreadPoolRejectedFallbackSuccess() throws IOException {
        List<HystrixInvokableInfo<?>> executions = new ArrayList<HystrixInvokableInfo<?>>();
        executions.add(new SimpleExecution(fooKey, 1, HystrixEventType.THREAD_POOL_REJECTED, HystrixEventType.FALLBACK_SUCCESS));
        HystrixRequestEvents request = new HystrixRequestEvents(executions);
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertEquals("[{\"name\":\"Foo\",\"events\":[\"THREAD_POOL_REJECTED\",\"FALLBACK_SUCCESS\"],\"latencies\":[1]}]", actual);
    }

    @Test
    public void testSingleShortCircuitedFallbackSuccess() throws IOException {
        List<HystrixInvokableInfo<?>> executions = new ArrayList<HystrixInvokableInfo<?>>();
        executions.add(new SimpleExecution(fooKey, 1, HystrixEventType.SHORT_CIRCUITED, HystrixEventType.FALLBACK_SUCCESS));
        HystrixRequestEvents request = new HystrixRequestEvents(executions);
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertEquals("[{\"name\":\"Foo\",\"events\":[\"SHORT_CIRCUITED\",\"FALLBACK_SUCCESS\"],\"latencies\":[1]}]", actual);
    }

    @Test
    public void testSingleBadRequest() throws IOException {
        List<HystrixInvokableInfo<?>> executions = new ArrayList<HystrixInvokableInfo<?>>();
        executions.add(new SimpleExecution(fooKey, 50, HystrixEventType.BAD_REQUEST));
        HystrixRequestEvents request = new HystrixRequestEvents(executions);
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertEquals("[{\"name\":\"Foo\",\"events\":[\"BAD_REQUEST\"],\"latencies\":[50]}]", actual);
    }

    @Test
    public void testTwoSuccessesSameKey() throws IOException {
        List<HystrixInvokableInfo<?>> executions = new ArrayList<HystrixInvokableInfo<?>>();
        HystrixInvokableInfo<Integer> foo1 = new SimpleExecution(fooKey, 23, HystrixEventType.SUCCESS);
        HystrixInvokableInfo<Integer> foo2 = new SimpleExecution(fooKey, 34, HystrixEventType.SUCCESS);
        executions.add(foo1);
        executions.add(foo2);
        HystrixRequestEvents request = new HystrixRequestEvents(executions);
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertEquals("[{\"name\":\"Foo\",\"events\":[\"SUCCESS\"],\"latencies\":[23,34]}]", actual);
    }

    @Test
    public void testTwoSuccessesDifferentKey() throws IOException {
        List<HystrixInvokableInfo<?>> executions = new ArrayList<HystrixInvokableInfo<?>>();
        HystrixInvokableInfo<Integer> foo1 = new SimpleExecution(fooKey, 23, HystrixEventType.SUCCESS);
        HystrixInvokableInfo<Integer> bar1 = new SimpleExecution(barKey, 34, HystrixEventType.SUCCESS);
        executions.add(foo1);
        executions.add(bar1);
        HystrixRequestEvents request = new HystrixRequestEvents(executions);
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertTrue(actual.equals("[{\"name\":\"Foo\",\"events\":[\"SUCCESS\"],\"latencies\":[23]},{\"name\":\"Bar\",\"events\":[\"SUCCESS\"],\"latencies\":[34]}]") ||
                actual.equals("[{\"name\":\"Bar\",\"events\":[\"SUCCESS\"],\"latencies\":[34]},{\"name\":\"Foo\",\"events\":[\"SUCCESS\"],\"latencies\":[23]}]"));
    }

    @Test
    public void testTwoFailuresSameKey() throws IOException {
        List<HystrixInvokableInfo<?>> executions = new ArrayList<HystrixInvokableInfo<?>>();
        HystrixInvokableInfo<Integer> foo1 = new SimpleExecution(fooKey, 56, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_SUCCESS);
        HystrixInvokableInfo<Integer> foo2 = new SimpleExecution(fooKey, 67, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_SUCCESS);
        executions.add(foo1);
        executions.add(foo2);
        HystrixRequestEvents request = new HystrixRequestEvents(executions);
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertEquals("[{\"name\":\"Foo\",\"events\":[\"FAILURE\",\"FALLBACK_SUCCESS\"],\"latencies\":[56,67]}]", actual);
    }

    @Test
    public void testTwoSuccessesOneFailureSameKey() throws IOException {
        List<HystrixInvokableInfo<?>> executions = new ArrayList<HystrixInvokableInfo<?>>();
        HystrixInvokableInfo<Integer> foo1 = new SimpleExecution(fooKey, 10, HystrixEventType.SUCCESS);
        HystrixInvokableInfo<Integer> foo2 = new SimpleExecution(fooKey, 67, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_SUCCESS);
        HystrixInvokableInfo<Integer> foo3 = new SimpleExecution(fooKey, 11, HystrixEventType.SUCCESS);
        executions.add(foo1);
        executions.add(foo2);
        executions.add(foo3);
        HystrixRequestEvents request = new HystrixRequestEvents(executions);
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertTrue(actual.equals("[{\"name\":\"Foo\",\"events\":[\"SUCCESS\"],\"latencies\":[10,11]},{\"name\":\"Foo\",\"events\":[\"FAILURE\",\"FALLBACK_SUCCESS\"],\"latencies\":[67]}]") ||
                actual.equals("[{\"name\":\"Foo\",\"events\":[\"FAILURE\",\"FALLBACK_SUCCESS\"],\"latencies\":[67]},{\"name\":\"Foo\",\"events\":[\"SUCCESS\"],\"latencies\":[10,11]}]"));
    }

    @Test
    public void testSingleResponseFromCache() throws IOException {
        List<HystrixInvokableInfo<?>> executions = new ArrayList<HystrixInvokableInfo<?>>();
        HystrixInvokableInfo<Integer> foo1 = new SimpleExecution(fooKey, 23, "cacheKeyA", HystrixEventType.SUCCESS);
        HystrixInvokableInfo<Integer> cachedFoo1 = new SimpleExecution(fooKey, "cacheKeyA");
        executions.add(foo1);
        executions.add(cachedFoo1);
        HystrixRequestEvents request = new HystrixRequestEvents(executions);
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertEquals("[{\"name\":\"Foo\",\"events\":[\"SUCCESS\"],\"latencies\":[23],\"cached\":1}]", actual);
    }

    @Test
    public void testMultipleResponsesFromCache() throws IOException {
        List<HystrixInvokableInfo<?>> executions = new ArrayList<HystrixInvokableInfo<?>>();
        HystrixInvokableInfo<Integer> foo1 = new SimpleExecution(fooKey, 23, "cacheKeyA", HystrixEventType.SUCCESS);
        HystrixInvokableInfo<Integer> cachedFoo1 = new SimpleExecution(fooKey, "cacheKeyA");
        HystrixInvokableInfo<Integer> anotherCachedFoo1 = new SimpleExecution(fooKey, "cacheKeyA");
        executions.add(foo1);
        executions.add(cachedFoo1);
        executions.add(anotherCachedFoo1);
        HystrixRequestEvents request = new HystrixRequestEvents(executions);
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertEquals("[{\"name\":\"Foo\",\"events\":[\"SUCCESS\"],\"latencies\":[23],\"cached\":2}]", actual);
    }

    @Test
    public void testMultipleCacheKeys() throws IOException {
        List<HystrixInvokableInfo<?>> executions = new ArrayList<HystrixInvokableInfo<?>>();
        HystrixInvokableInfo<Integer> foo1 = new SimpleExecution(fooKey, 23, "cacheKeyA", HystrixEventType.SUCCESS);
        HystrixInvokableInfo<Integer> cachedFoo1 = new SimpleExecution(fooKey, "cacheKeyA");
        HystrixInvokableInfo<Integer> foo2 = new SimpleExecution(fooKey, 67, "cacheKeyB", HystrixEventType.SUCCESS);
        HystrixInvokableInfo<Integer> cachedFoo2 = new SimpleExecution(fooKey, "cacheKeyB");
        executions.add(foo1);
        executions.add(cachedFoo1);
        executions.add(foo2);
        executions.add(cachedFoo2);
        HystrixRequestEvents request = new HystrixRequestEvents(executions);
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertTrue(actual.equals("[{\"name\":\"Foo\",\"events\":[\"SUCCESS\"],\"latencies\":[67],\"cached\":1},{\"name\":\"Foo\",\"events\":[\"SUCCESS\"],\"latencies\":[23],\"cached\":1}]") ||
                actual.equals("[{\"name\":\"Foo\",\"events\":[\"SUCCESS\"],\"latencies\":[23],\"cached\":1},{\"name\":\"Foo\",\"events\":[\"SUCCESS\"],\"latencies\":[67],\"cached\":1}]"));
    }

    @Test
    public void testSingleSuccessMultipleEmits() throws IOException {
        List<HystrixInvokableInfo<?>> executions = new ArrayList<HystrixInvokableInfo<?>>();
        executions.add(new SimpleExecution(fooKey, 100, HystrixEventType.EMIT, HystrixEventType.EMIT, HystrixEventType.EMIT, HystrixEventType.SUCCESS));
        HystrixRequestEvents request = new HystrixRequestEvents(executions);
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertEquals("[{\"name\":\"Foo\",\"events\":[{\"name\":\"EMIT\",\"count\":3},\"SUCCESS\"],\"latencies\":[100]}]", actual);
    }

    @Test
    public void testSingleSuccessMultipleEmitsAndFallbackEmits() throws IOException {
        List<HystrixInvokableInfo<?>> executions = new ArrayList<HystrixInvokableInfo<?>>();
        executions.add(new SimpleExecution(fooKey, 100, HystrixEventType.EMIT, HystrixEventType.EMIT, HystrixEventType.EMIT, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_EMIT, HystrixEventType.FALLBACK_EMIT, HystrixEventType.FALLBACK_SUCCESS));
        HystrixRequestEvents request = new HystrixRequestEvents(executions);
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertEquals("[{\"name\":\"Foo\",\"events\":[{\"name\":\"EMIT\",\"count\":3},\"FAILURE\",{\"name\":\"FALLBACK_EMIT\",\"count\":2},\"FALLBACK_SUCCESS\"],\"latencies\":[100]}]", actual);
    }

    @Test
    public void testCollapsedBatchOfOne() throws IOException {
        List<HystrixInvokableInfo<?>> executions = new ArrayList<HystrixInvokableInfo<?>>();
        executions.add(new SimpleExecution(fooKey, 53, collapserKey, 1, HystrixEventType.SUCCESS));
        HystrixRequestEvents request = new HystrixRequestEvents(executions);
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertEquals("[{\"name\":\"Foo\",\"events\":[\"SUCCESS\"],\"latencies\":[53],\"collapsed\":{\"name\":\"FooCollapser\",\"count\":1}}]", actual);
    }

    @Test
    public void testCollapsedBatchOfSix() throws IOException {
        List<HystrixInvokableInfo<?>> executions = new ArrayList<HystrixInvokableInfo<?>>();
        executions.add(new SimpleExecution(fooKey, 53, collapserKey, 6, HystrixEventType.SUCCESS));
        HystrixRequestEvents request = new HystrixRequestEvents(executions);
        String actual = SerialHystrixRequestEvents.toJsonString(request);
        assertEquals("[{\"name\":\"Foo\",\"events\":[\"SUCCESS\"],\"latencies\":[53],\"collapsed\":{\"name\":\"FooCollapser\",\"count\":6}}]", actual);
    }

    private class SimpleExecution implements HystrixInvokableInfo<Integer> {
        private final HystrixCommandKey commandKey;
        private final ExecutionResult executionResult;
        private final String cacheKey;
        private final HystrixCollapserKey collapserKey;

        public SimpleExecution(HystrixCommandKey commandKey, int latency, HystrixEventType... events) {
            this.commandKey = commandKey;
            this.executionResult = ExecutionResult.from(events).setExecutionLatency(latency);
            this.cacheKey = null;
            this.collapserKey = null;
        }

        public SimpleExecution(HystrixCommandKey commandKey, int latency, String cacheKey, HystrixEventType... events) {
            this.commandKey = commandKey;
            this.executionResult = ExecutionResult.from(events).setExecutionLatency(latency);
            this.cacheKey = cacheKey;
            this.collapserKey = null;
        }

        public SimpleExecution(HystrixCommandKey commandKey, String cacheKey) {
            this.commandKey = commandKey;
            this.executionResult = ExecutionResult.from(HystrixEventType.RESPONSE_FROM_CACHE);
            this.cacheKey = cacheKey;
            this.collapserKey = null;
        }

        public SimpleExecution(HystrixCommandKey commandKey, int latency, HystrixCollapserKey collapserKey, int batchSize, HystrixEventType... events) {
            this.commandKey = commandKey;
            ExecutionResult interimResult = ExecutionResult.from(events).setExecutionLatency(latency);
            for (int i = 0; i < batchSize; i++) {
                interimResult = interimResult.addEvent(HystrixEventType.COLLAPSED);
            }
            this.executionResult = interimResult;
            this.cacheKey = null;
            this.collapserKey = collapserKey;
        }

        @Override
        public HystrixCommandGroupKey getCommandGroup() {
            return groupKey;
        }

        @Override
        public HystrixCommandKey getCommandKey() {
            return commandKey;
        }

        @Override
        public HystrixThreadPoolKey getThreadPoolKey() {
            return threadPoolKey;
        }

        @Override
        public String getPublicCacheKey() {
            return cacheKey;
        }

        @Override
        public HystrixCollapserKey getOriginatingCollapserKey() {
            return collapserKey;
        }

        @Override
        public HystrixCommandMetrics getMetrics() {
            return null;
        }

        @Override
        public HystrixCommandProperties getProperties() {
            return null;
        }

        @Override
        public boolean isCircuitBreakerOpen() {
            return false;
        }

        @Override
        public boolean isExecutionComplete() {
            return true;
        }

        @Override
        public boolean isExecutedInThread() {
            return false; //do i want this?
        }

        @Override
        public boolean isSuccessfulExecution() {
            return executionResult.getEventCounts().contains(HystrixEventType.SUCCESS);
        }

        @Override
        public boolean isFailedExecution() {
            return executionResult.getEventCounts().contains(HystrixEventType.FAILURE);
        }

        @Override
        public Throwable getFailedExecutionException() {
            return null;
        }

        @Override
        public boolean isResponseFromFallback() {
            return executionResult.getEventCounts().contains(HystrixEventType.FALLBACK_SUCCESS);
        }

        @Override
        public boolean isResponseTimedOut() {
            return executionResult.getEventCounts().contains(HystrixEventType.TIMEOUT);
        }

        @Override
        public boolean isResponseShortCircuited() {
            return executionResult.getEventCounts().contains(HystrixEventType.SHORT_CIRCUITED);
        }

        @Override
        public boolean isResponseFromCache() {
            return executionResult.getEventCounts().contains(HystrixEventType.RESPONSE_FROM_CACHE);
        }

        @Override
        public boolean isResponseRejected() {
            return executionResult.isResponseRejected();
        }

        @Override
        public boolean isResponseSemaphoreRejected() {
            return executionResult.getEventCounts().contains(HystrixEventType.SEMAPHORE_REJECTED);
        }

        @Override
        public boolean isResponseThreadPoolRejected() {
            return executionResult.getEventCounts().contains(HystrixEventType.THREAD_POOL_REJECTED);
        }

        @Override
        public List<HystrixEventType> getExecutionEvents() {
            return executionResult.getOrderedList();
        }

        @Override
        public int getNumberEmissions() {
            return executionResult.getEventCounts().getCount(HystrixEventType.EMIT);
        }

        @Override
        public int getNumberFallbackEmissions() {
            return executionResult.getEventCounts().getCount(HystrixEventType.FALLBACK_EMIT);
        }

        @Override
        public int getNumberCollapsed() {
            return executionResult.getEventCounts().getCount(HystrixEventType.COLLAPSED);
        }

        @Override
        public int getExecutionTimeInMilliseconds() {
            return executionResult.getExecutionLatency();
        }

        @Override
        public long getCommandRunStartTimeInNanos() {
            return System.currentTimeMillis();
        }

        @Override
        public ExecutionResult.EventCounts getEventCounts() {
            return executionResult.getEventCounts();
        }

        @Override
        public String toString() {
            return "SimpleExecution{" +
                    "commandKey=" + commandKey.name() +
                    ", executionResult=" + executionResult +
                    ", cacheKey='" + cacheKey + '\'' +
                    ", collapserKey=" + collapserKey +
                    '}';
        }
    }
}