@Override
    public List<MetricSample> collect() {
        List<MetricSample> list = new ArrayList<>();
        if (!isCollectEnabled()) {
            return list;
        }
        collectRequests(list);
        collectQPS(list);
        collectRT(list);

        return list;
    }
@Test
    void testP95AndP99() throws InterruptedException {

        metricsDispatcher.addListener(collector);
        ConfigManager configManager = applicationModel.getApplicationConfigManager();
        MetricsConfig config = configManager.getMetrics().orElse(null);
        AggregationConfig aggregationConfig = new AggregationConfig();
        aggregationConfig.setEnabled(true);
        config.setAggregation(aggregationConfig);

        List<Long> requestTimes = new ArrayList<>(10000);

        for (int i = 0; i < 300; i++) {
            requestTimes.add(Double.valueOf(1000 * Math.random()).longValue());
        }

        Collections.sort(requestTimes);
        double p95Index = 0.95 * (requestTimes.size() - 1);
        double p99Index = 0.99 * (requestTimes.size() - 1);

        double manualP95 = requestTimes.get((int) Math.round(p95Index));
        double manualP99 = requestTimes.get((int) Math.round(p99Index));

        for (Long requestTime : requestTimes) {
            RequestEvent requestEvent = RequestEvent.toRequestEvent(
                    applicationModel,
                    null,
                    null,
                    null,
                    invocation,
                    MetricsSupport.getSide(invocation),
                    MethodMetric.isServiceLevel(applicationModel));
            TestRequestEvent testRequestEvent =
                    new TestRequestEvent(requestEvent.getSource(), requestEvent.getTypeWrapper());
            testRequestEvent.putAttachment(MetricsConstants.INVOCATION, invocation);
            testRequestEvent.putAttachment(ATTACHMENT_KEY_SERVICE, MetricsSupport.getInterfaceName(invocation));
            testRequestEvent.putAttachment(MetricsConstants.INVOCATION_SIDE, MetricsSupport.getSide(invocation));
            testRequestEvent.setRt(requestTime);
            MetricsEventBus.post(testRequestEvent, () -> null);
        }
        Thread.sleep(4000L);

        List<MetricSample> samples = collector.collect();

        GaugeMetricSample<?> p95Sample = samples.stream()
                .filter(sample -> sample.getName().endsWith("p95"))
                .map(sample -> (GaugeMetricSample<?>) sample)
                .findFirst()
                .orElse(null);

        GaugeMetricSample<?> p99Sample = samples.stream()
                .filter(sample -> sample.getName().endsWith("p99"))
                .map(sample -> (GaugeMetricSample<?>) sample)
                .findFirst()
                .orElse(null);

        Assertions.assertNotNull(p95Sample);
        Assertions.assertNotNull(p99Sample);

        double p95 = p95Sample.applyAsDouble();
        double p99 = p99Sample.applyAsDouble();

        // An error of less than 5% is allowed
        System.out.println(Math.abs(1 - p95 / manualP95));
        Assertions.assertTrue(Math.abs(1 - p95 / manualP95) < 0.05);
        Assertions.assertTrue(Math.abs(1 - p99 / manualP99) < 0.05);
    }