private static @Nullable SystemOpsStatistic measureConnectionSpeedOnFile(@NotNull JpsNettyClient nettyClient, @NotNull String fileName,
                                                                           @Nullable SystemOpsStatistic previousSystemStats) {
    Map<String, String> headers = JpsServerAuthUtil.getRequestHeaders();
    String url = calculateURL(fileName);
    LOG.info("Checking connection speed base on the file: " + fileName);
    long start = System.currentTimeMillis();
    try (CloseableHttpClient client = HttpClientBuilder.create().build()) {
      HttpGet httpRequest = new HttpGet(url);
      headers.forEach((k, v) -> httpRequest.setHeader(k, v));
      HttpResponse response = client.execute(httpRequest);
      HttpEntity responseEntity = response.getEntity();
      if (response.getStatusLine().getStatusCode() == 200) {
        long fileSize = responseEntity.getContentLength();
        Header header = response.getFirstHeader(CDN_CACHE_HEADER);

        File downloadedFile = saveToFile(FileUtil.createTempFile("download.", ".tmp").toPath(), responseEntity, null).toFile();
        long downloadTime = System.currentTimeMillis() - start;
        long bytesPerSecond = fileSize / downloadTime * 1000;

        if (header != null && header.getValue().startsWith("Hit")) {
          // This is an exceptional case and should take place in production because connection speed files don't cached by CDN
          LOG.info("Speed of connection to CDN: " + StringUtil.formatFileSize(bytesPerSecond) + "/s; " + formatInternetSpeed(bytesPerSecond * 8));
        }
        else {
          LOG.info("Speed of connection to S3: " + StringUtil.formatFileSize(bytesPerSecond) + "/s; " + formatInternetSpeed(bytesPerSecond * 8));
        }

        long decompressionSpeedBytesPesSec;
        if (previousSystemStats == null) {
          start = System.currentTimeMillis();
          ZipUtil.extract(downloadedFile, FileUtil.createTempDirectory("decompress", ".tmp"), null);
          long decompressionTime = System.currentTimeMillis() - start;
          decompressionSpeedBytesPesSec = fileSize / decompressionTime * 1000;
          LOG.info("Time spent to decompress file " + fileName + " " + decompressionTime + "ms");
        } else {
          // We reuse decompression value because it measures only once
          decompressionSpeedBytesPesSec = previousSystemStats.getDecompressionSpeedBytesPesSec();
        }
        start = System.currentTimeMillis();
        FileUtil.delete(downloadedFile);
        long deletionTime = System.currentTimeMillis() - start;
        if (deletionTime == 0) deletionTime = 1;
        long deletionSpeedBytesPerSec = fileSize / deletionTime * 1000 ;
        LOG.info("Time spent to delete file " + fileName + " " + deletionTime + "ms");
        return new SystemOpsStatistic(bytesPerSecond, decompressionSpeedBytesPesSec, deletionSpeedBytesPerSec);
      } else {
        String errorText = StreamUtil.readText(new InputStreamReader(responseEntity.getContent(), StandardCharsets.UTF_8));
        LOG.warn("Request: " + url + " Error: " + response.getStatusLine().getStatusCode() + " body: " + errorText);
      }
    } catch (IOException e) {
      LOG.warn("Failed to download/delete/decompress file for measurement system stats", e);
    }
    return null;
  }
private static @Nullable SystemOpsStatistic measureConnectionSpeedOnFile(@NotNull JpsNettyClient nettyClient, @NotNull String fileName,
                                                                           @Nullable SystemOpsStatistic previousSystemStats)