public Map<ClusterInfo, DeploymentMetricsAggregator> requestMetricsGroupedByCluster(Collection<URI> hosts) {
        Map<ClusterInfo, DeploymentMetricsAggregator> clusterMetricsMap = new ConcurrentHashMap<>();

        long startTime = System.currentTimeMillis();
        List<Callable<Void>> jobs = hosts.stream()
                .map(hostUri -> (Callable<Void>) () -> {
                    try {
                        getHostMetrics(hostUri, clusterMetricsMap);
                    } catch (Exception e) {
                        log.log(Level.FINE, e, () -> "Failed to download metrics: " + e.getMessage());
                    }
                    return null;
                })
                .toList();
        try {
            executor.invokeAll(jobs, 1, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            throw new RuntimeException("Failed to retrieve metrics in time: " + e.getMessage(), e);
        }

        log.log(Level.FINE, () ->
                String.format("Metric retrieval for %d nodes took %d milliseconds", hosts.size(), System.currentTimeMillis() - startTime)
        );

        return clusterMetricsMap;
    }
@Test
    public void testMetricAggregation() throws IOException {
        List<URI> hosts = Stream.of(1, 2, 3, 4)
                .map(item -> URI.create("http://localhost:" + wireMock.port() + "/" + item))
                .toList();

        stubFor(get(urlEqualTo("/1"))
                .willReturn(aResponse()
                        .withStatus(200)
                        .withBody(contentMetrics())));

        stubFor(get(urlEqualTo("/2"))
                .willReturn(aResponse()
                        .withStatus(200)
                        .withBody(contentMetrics())));

        stubFor(get(urlEqualTo("/3"))
                .willReturn(aResponse()
                        .withStatus(200)
                        .withBody(containerMetrics())));

        stubFor(get(urlEqualTo("/4"))
                .willReturn(aResponse()
                        .withStatus(200)
                        .withBody(clustercontrollerMetrics())));

        ClusterInfo expectedContentCluster = new ClusterInfo("content_cluster_id", "content");
        ClusterInfo expectedContainerCluster = new ClusterInfo("container_cluster_id", "container");

        Map<ClusterInfo, DeploymentMetricsAggregator> aggregatorMap = new ClusterDeploymentMetricsRetriever().requestMetricsGroupedByCluster(hosts);
        assertEquals(Set.of(expectedContainerCluster, expectedContentCluster), aggregatorMap.keySet());

        compareAggregators(
                new DeploymentMetricsAggregator()
                        .addDocumentCount(6000.0)
                        .addReadLatency(3000 , 43)
                        .addReadLatency(3000 , 43) // there are 2 content nodes
                        .addMemoryUsage(0.89074, 0.8)
                        .addDiskUsage(0.83517, 0.75),
                aggregatorMap.get(expectedContentCluster)
        );

        compareAggregators(
                new DeploymentMetricsAggregator()
                        .addContainerLatency(3000, 43)
                        .addContainerLatency(2000, 0)
                        .addFeedLatency(3000, 43),
                aggregatorMap.get(expectedContainerCluster)

        );
        wireMock.stop();
    }