From df02c78181ce317f8951d035f66161fb63fc412c Mon Sep 17 00:00:00 2001 From: Kharkunov Eugene Date: Fri, 16 Aug 2024 12:17:44 +0300 Subject: [PATCH] Fix download cache size metric value. Unify information about download/upload caches. Add metrics to track download/upload cache file count. --- .../defold/extender/ExtenderController.java | 16 +++---- .../extender/metrics/MetricsWriter.java | 8 +++- .../extender/services/DataCacheService.java | 45 ++++++++++--------- 3 files changed, 39 insertions(+), 30 deletions(-) diff --git a/server/src/main/java/com/defold/extender/ExtenderController.java b/server/src/main/java/com/defold/extender/ExtenderController.java index 2e812251..9237fa64 100644 --- a/server/src/main/java/com/defold/extender/ExtenderController.java +++ b/server/src/main/java/com/defold/extender/ExtenderController.java @@ -206,8 +206,8 @@ public void buildEngine(HttpServletRequest _request, metricsWriter.measureReceivedRequest(request); // Get cached files from the cache service - long totalCacheDownloadSize = dataCacheService.getCachedFiles(uploadDirectory); - metricsWriter.measureCacheDownload(totalCacheDownloadSize); + DataCacheService.DataCacheServiceInfo totalCacheDownloadInfo = dataCacheService.getCachedFiles(uploadDirectory); + metricsWriter.measureCacheDownload(totalCacheDownloadInfo.cachedFileSize.longValue(), totalCacheDownloadInfo.cachedFileCount.intValue()); String[] buildEnvDescription = ExtenderUtil.getSdksForPlatform(platform, defoldSdkService.getPlatformSdkMappings(sdkVersion)); // Build engine locally or on remote builder @@ -266,8 +266,8 @@ public void buildEngine(HttpServletRequest _request, throw e; } finally { // Regardless of success/fail status, we want to cache the uploaded files - long totalUploadSize = dataCacheService.cacheFiles(uploadDirectory); - metricsWriter.measureCacheUpload(totalUploadSize); + DataCacheService.DataCacheServiceInfo uploadResultInfo = dataCacheService.cacheFiles(uploadDirectory); + metricsWriter.measureCacheUpload(uploadResultInfo.cachedFileSize.longValue(), uploadResultInfo.cachedFileCount.intValue()); metricsWriter.measureCounterBuild(platform, sdkVersionString, "sync", isSuccessfull); boolean deleteDirectory = true; @@ -338,8 +338,8 @@ public void buildEngineAsync(HttpServletRequest _request, metricsWriter.measureReceivedRequest(request); // Get cached files from the cache service - long totalCacheDownloadSize = dataCacheService.getCachedFiles(uploadDirectory); - metricsWriter.measureCacheDownload(totalCacheDownloadSize); + DataCacheService.DataCacheServiceInfo totalCacheDownloadInfo = dataCacheService.getCachedFiles(uploadDirectory); + metricsWriter.measureCacheDownload(totalCacheDownloadInfo.cachedFileSize.longValue(), totalCacheDownloadInfo.cachedFileCount.intValue()); String[] buildEnvDescription = ExtenderUtil.getSdksForPlatform(platform, defoldSdkService.getPlatformSdkMappings(sdkVersion)); // Build engine locally or on remote builder @@ -365,8 +365,8 @@ public void buildEngineAsync(HttpServletRequest _request, throw e; } finally { // Regardless of success/fail status, we want to cache the uploaded files - long totalUploadSize = dataCacheService.cacheFiles(uploadDirectory); - metricsWriter.measureCacheUpload(totalUploadSize); + DataCacheService.DataCacheServiceInfo uploadResultInfo = dataCacheService.cacheFiles(uploadDirectory); + metricsWriter.measureCacheUpload(uploadResultInfo.cachedFileSize.longValue(), uploadResultInfo.cachedFileCount.intValue()); boolean deleteDirectory = true; if (DM_DEBUG_KEEP_JOB_FOLDER != null) { diff --git a/server/src/main/java/com/defold/extender/metrics/MetricsWriter.java b/server/src/main/java/com/defold/extender/metrics/MetricsWriter.java index 2185e451..eb55dbda 100644 --- a/server/src/main/java/com/defold/extender/metrics/MetricsWriter.java +++ b/server/src/main/java/com/defold/extender/metrics/MetricsWriter.java @@ -24,7 +24,9 @@ public MetricsWriter(MeterRegistry registry, com.defold.extender.Timer timer) { DistributionSummary.builder("extender.job.requestSize").baseUnit(BaseUnits.BYTES).register(registry); DistributionSummary.builder("extender.job.zipSize").baseUnit(BaseUnits.BYTES).register(registry); DistributionSummary.builder("extender.job.cache.uploadSize").baseUnit(BaseUnits.BYTES).register(registry); + DistributionSummary.builder("extender.job.cache.uploadCount").baseUnit(BaseUnits.FILES).register(registry); DistributionSummary.builder("extender.job.cache.downloadSize").baseUnit(BaseUnits.BYTES).register(registry); + DistributionSummary.builder("extender.job.cache.downloadCount").baseUnit(BaseUnits.FILES).register(registry); } public MetricsWriter(final MeterRegistry registry) { @@ -70,14 +72,16 @@ public void measureSentResponse() { metricsTimer(this.registry, "extender.job.write", timer.start()); } - public void measureCacheUpload(long uploadSize) { + public void measureCacheUpload(long uploadSize, int uploadCount) { metricsTimer(this.registry, "extender.job.cache.upload", timer.start()); metricsSummary(this.registry, "extender.job.cache.uploadSize", uploadSize); + metricsSummary(this.registry, "extender.job.cache.uploadCount", uploadCount); } - public void measureCacheDownload(long downloadSize) { + public void measureCacheDownload(long downloadSize, int downloadCount) { metricsTimer(this.registry, "extender.job.cache.download", timer.start()); metricsSummary(this.registry, "extender.job.cache.downloadSize", downloadSize); + metricsSummary(this.registry, "extender.job.cache.downloadCount", downloadCount); } public void measureCounterBuild(String platform, String sdk, String buildType, Boolean isSuccessfull) { diff --git a/server/src/main/java/com/defold/extender/services/DataCacheService.java b/server/src/main/java/com/defold/extender/services/DataCacheService.java index 02908705..e3cc238c 100644 --- a/server/src/main/java/com/defold/extender/services/DataCacheService.java +++ b/server/src/main/java/com/defold/extender/services/DataCacheService.java @@ -21,6 +21,7 @@ import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; @Service @@ -40,6 +41,11 @@ public class DataCacheService { private DataCache dataCache; + public class DataCacheServiceInfo { + public AtomicInteger cachedFileCount = new AtomicInteger(); + public AtomicLong cachedFileSize = new AtomicLong(); + } + DataCacheService(final CacheKeyGenerator cacheKeyGenerator, final CacheInfoFileParser cacheInfoFileParser, final CacheInfoFileWriter cacheInfoFileWriter, @@ -60,30 +66,29 @@ private boolean isCached(final String key) { return dataCache.exists(key); } - public long cacheFiles(final File directory) throws IOException { + public DataCacheServiceInfo cacheFiles(final File directory) throws IOException { + DataCacheServiceInfo result = new DataCacheServiceInfo(); if (! cacheIsEnabled) { - return 0; + return result; } LOGGER.debug(String.format("Caching files in directory %s", directory.getPath())); - final AtomicLong totalbytesCached = new AtomicLong(); - final AtomicLong totalFilesCached = new AtomicLong(); Files.walk(directory.toPath()) .filter(Files::isRegularFile) .filter(path -> ! FILE_CACHE_INFO_FILE.equals(path.getFileName().toString())) .forEach(path -> { try { long fileSize = upload(path.toFile()); - totalbytesCached.addAndGet(fileSize); - totalFilesCached.addAndGet(fileSize >= fileSizeThreshold ? 1 : 0); + result.cachedFileSize.addAndGet(fileSize); + result.cachedFileCount.addAndGet(fileSize >= fileSizeThreshold ? 1 : 0); } catch (IOException e) { LOGGER.error("Could not cache file " + path.toString(), e); } }); - LOGGER.info(String.format("Cached %d bytes in %d files", totalbytesCached.longValue(), totalFilesCached.longValue())); - return totalbytesCached.longValue(); + LOGGER.info(String.format("Cached %d bytes in %d files", result.cachedFileSize.longValue(), result.cachedFileCount.intValue())); + return result; } private long upload(File file) throws IOException { @@ -102,9 +107,10 @@ private long upload(File file) throws IOException { } // Step through the entries in the json and download them from the key-value server - public int getCachedFiles(File directory) throws IOException, ExtenderException { + public DataCacheServiceInfo getCachedFiles(File directory) throws IOException, ExtenderException { + DataCacheServiceInfo result = new DataCacheServiceInfo(); if (! cacheIsEnabled) { - return 0; + return result; } File cacheInfoFile = new File(directory, FILE_CACHE_INFO_FILE); @@ -112,22 +118,21 @@ public int getCachedFiles(File directory) throws IOException, ExtenderException // Support older editors that don't supply a cache info file if (!cacheInfoFile.exists()) { LOGGER.info("No cache info file found, skipping cache"); - return 0; + return result; } LOGGER.info("Downloading cached files"); final CacheInfoWrapper wrapper = cacheInfoFileParser.parse(cacheInfoFile); if (wrapper == null) { LOGGER.info("Couldn't parse the cache info file. Ignoring"); - return 0; + return result; } List cacheEntries = wrapper.getEntries(); // we can face null pointer in cacheEntries if client, who requestd a build, don't have access to /query endpoint if (cacheEntries == null) { - return 0; + return result; } - int numCachedFiles = 0; for (CacheEntry entry : cacheEntries) { // Check if entry is cached @@ -139,7 +144,7 @@ public int getCachedFiles(File directory) throws IOException, ExtenderException File destination = new File(directory, entry.getPath()); makeParentDirectories(destination); - downloadFile(entry, destination); + result.cachedFileSize.addAndGet(downloadFile(entry, destination)); if (! destination.exists()) { throw new ExtenderException(String.format("Failed downloading '%s' (%s) from cache", @@ -147,12 +152,12 @@ public int getCachedFiles(File directory) throws IOException, ExtenderException } verifyCacheKey(destination, entry.getKey()); - numCachedFiles++; + result.cachedFileCount.addAndGet(1); } - LOGGER.info(String.format("Downloaded %d cached files", numCachedFiles)); + LOGGER.info(String.format("Downloaded %d bytes in %d cached files", result.cachedFileSize.longValue(), result.cachedFileCount.intValue())); - return numCachedFiles; + return result; } private void verifyCacheEntry(CacheEntry entry) throws ExtenderException { @@ -175,13 +180,13 @@ private boolean makeParentDirectories(File file) { return file.getParentFile().exists() || file.getParentFile().mkdirs(); } - private void downloadFile(CacheEntry entry, File destination) throws ExtenderException, IOException { + private long downloadFile(CacheEntry entry, File destination) throws ExtenderException, IOException { try (InputStream inputStream = dataCache.get(entry.getKey())) { if (inputStream == null) { throw new ExtenderException(String.format("Cache object %s (%s) was not found", entry.getPath(), entry.getKey())); } - Files.copy( + return Files.copy( inputStream, destination.toPath(), StandardCopyOption.REPLACE_EXISTING);