class MetricsMetadataHandler extends MetadataHandler {

    @Override
    public GetSplitsResponse doGetSplits(BlockAllocator blockAllocator, GetSplitsRequest getSplitsRequest)
            throws Exception
    {
        validateTable(getSplitsRequest.getTableName());

        //Handle requests for the METRIC_TABLE which requires only 1 split to list available metrics.
        if (METRIC_TABLE_NAME.equals(getSplitsRequest.getTableName().getTableName())) {
            //The request is just for meta-data about what metrics exist.
            Split metricsSplit = Split.newBuilder(makeSpillLocation(getSplitsRequest), makeEncryptionKey()).build();
            return new GetSplitsResponse(getSplitsRequest.getCatalogName(), metricsSplit);
        }

        //handle generating splits for reading actual metrics data.
        try (ConstraintEvaluator constraintEvaluator = new ConstraintEvaluator(blockAllocator,
                METRIC_DATA_TABLE.getSchema(),
                getSplitsRequest.getConstraints())) {
            ListMetricsRequest listMetricsRequest = new ListMetricsRequest();
            MetricUtils.pushDownPredicate(getSplitsRequest.getConstraints(), listMetricsRequest);
            listMetricsRequest.setNextToken(getSplitsRequest.getContinuationToken());

            String period = getPeriodFromConstraint(getSplitsRequest.getConstraints());
            Set<Split> splits = new HashSet<>();
            ListMetricsResult result = invoker.invoke(() -> metrics.listMetrics(listMetricsRequest));

            List<MetricStat> metricStats = new ArrayList<>(100);
            for (Metric nextMetric : result.getMetrics()) {
                for (String nextStatistic : STATISTICS) {
                    if (MetricUtils.applyMetricConstraints(constraintEvaluator, nextMetric, nextStatistic)) {
                        metricStats.add(new MetricStat()
                                .withMetric(new Metric()
                                        .withNamespace(nextMetric.getNamespace())
                                        .withMetricName(nextMetric.getMetricName())
                                        .withDimensions(nextMetric.getDimensions()))
                                .withPeriod(Integer.valueOf(period))
                                .withStat(nextStatistic));
                    }
                }
            }

            List<List<MetricStat>> partitions = Lists.partition(metricStats, calculateSplitSize(metricStats.size()));
            for (List<MetricStat> partition : partitions) {
                String serializedMetricStats = MetricStatSerDe.serialize(partition);
                splits.add(Split.newBuilder(makeSpillLocation(getSplitsRequest), makeEncryptionKey())
                        .add(MetricStatSerDe.SERIALIZED_METRIC_STATS_FIELD_NAME, serializedMetricStats)
                        .build());
            }

            String continuationToken = null;
            if (result.getNextToken() != null &&
                    !result.getNextToken().equalsIgnoreCase(listMetricsRequest.getNextToken())) {
                continuationToken = result.getNextToken();
            }

            return new GetSplitsResponse(getSplitsRequest.getCatalogName(), splits, continuationToken);
        }
    }

    public  MetricsMetadataHandler();
    @VisibleForTesting protected  MetricsMetadataHandler(AmazonCloudWatch metrics,
            EncryptionKeyFactory keyFactory,
            AWSSecretsManager secretsManager,
            AmazonAthena athena,
            String spillBucket,
            String spillPrefix);

}