Add telemetry for storing dependency caches

This commit is contained in:
Michael B. Gale
2025-09-23 11:48:49 +01:00
parent 11480e326c
commit 249a3cbb5c
3 changed files with 93 additions and 7 deletions
+24 -3
View File
@@ -26,7 +26,10 @@ import {
isCodeScanningEnabled,
} from "./config-utils";
import { uploadDatabases } from "./database-upload";
import { uploadDependencyCaches } from "./dependency-caching";
import {
DependencyCacheUploadStatusReport,
uploadDependencyCaches,
} from "./dependency-caching";
import { getDiffInformedAnalysisBranches } from "./diff-informed-analysis-utils";
import { EnvVar } from "./environment";
import { Feature, Features } from "./feature-flags";
@@ -55,10 +58,15 @@ interface AnalysisStatusReport
extends uploadLib.UploadStatusReport,
QueriesStatusReport {}
interface DependencyCachingUploadStatusReport {
dependency_caching_upload_results?: string;
}
interface FinishStatusReport
extends StatusReportBase,
DatabaseCreationTimings,
AnalysisStatusReport {}
AnalysisStatusReport,
DependencyCachingUploadStatusReport {}
interface FinishWithTrapUploadStatusReport extends FinishStatusReport {
/** Size of TRAP caches that we uploaded, in bytes. */
@@ -76,6 +84,7 @@ async function sendStatusReport(
dbCreationTimings: DatabaseCreationTimings | undefined,
didUploadTrapCaches: boolean,
trapCacheCleanup: TrapCacheCleanupStatusReport | undefined,
dependencyCacheResults: DependencyCacheUploadStatusReport | undefined,
logger: Logger,
) {
const status = getActionsStatus(error, stats?.analyze_failure_language);
@@ -95,6 +104,9 @@ async function sendStatusReport(
...(stats || {}),
...(dbCreationTimings || {}),
...(trapCacheCleanup || {}),
dependency_caching_upload_results: JSON.stringify(
dependencyCacheResults ?? {},
),
};
if (config && didUploadTrapCaches) {
const trapCacheUploadStatusReport: FinishWithTrapUploadStatusReport = {
@@ -209,6 +221,7 @@ async function run() {
let trapCacheUploadTime: number | undefined = undefined;
let dbCreationTimings: DatabaseCreationTimings | undefined = undefined;
let didUploadTrapCaches = false;
let dependencyCacheResults: DependencyCacheUploadStatusReport | undefined;
util.initializeEnvironment(actionsUtil.getActionVersion());
// Make inputs accessible in the `post` step, details at
@@ -388,7 +401,11 @@ async function run() {
Feature.JavaMinimizeDependencyJars,
codeql,
);
await uploadDependencyCaches(config, logger, minimizeJavaJars);
dependencyCacheResults = await uploadDependencyCaches(
config,
logger,
minimizeJavaJars,
);
}
// We don't upload results in test mode, so don't wait for processing
@@ -431,6 +448,7 @@ async function run() {
dbCreationTimings,
didUploadTrapCaches,
trapCacheCleanupTelemetry,
dependencyCacheResults,
logger,
);
return;
@@ -449,6 +467,7 @@ async function run() {
dbCreationTimings,
didUploadTrapCaches,
trapCacheCleanupTelemetry,
dependencyCacheResults,
logger,
);
} else if (runStats) {
@@ -461,6 +480,7 @@ async function run() {
dbCreationTimings,
didUploadTrapCaches,
trapCacheCleanupTelemetry,
dependencyCacheResults,
logger,
);
} else {
@@ -473,6 +493,7 @@ async function run() {
dbCreationTimings,
didUploadTrapCaches,
trapCacheCleanupTelemetry,
dependencyCacheResults,
logger,
);
}
+42 -1
View File
@@ -181,18 +181,45 @@ export async function downloadDependencyCaches(
return status;
}
/** Enumerates possible outcomes for cache hits. */
export enum CacheStoreResult {
/** We were unable to calculate a hash for the key. */
NoHash = "no-hash",
/** There is nothing to store in the cache. */
Empty = "empty",
/** There already exists a cache with the key we are trying to store. */
Duplicate = "duplicate",
/** The cache was stored successfully. */
Stored = "stored",
}
/** Represents results of trying to upload a dependency cache for a language. */
export interface DependencyCacheUploadStatus {
result: CacheStoreResult;
upload_size_bytes?: number;
upload_duration_ms?: number;
}
/** A partial mapping from languages to the results of uploading dependency caches for them. */
export type DependencyCacheUploadStatusReport = Partial<
Record<Language, DependencyCacheUploadStatus>
>;
/**
* Attempts to store caches for the languages that were analyzed.
*
* @param config The configuration for this workflow.
* @param logger A logger to record some informational messages to.
* @param minimizeJavaJars Whether the Java extractor should rewrite downloaded JARs to minimize their size.
*
* @returns A partial mapping of languages to results of uploading dependency caches for them.
*/
export async function uploadDependencyCaches(
config: Config,
logger: Logger,
minimizeJavaJars: boolean,
): Promise<void> {
): Promise<DependencyCacheUploadStatusReport> {
const status: DependencyCacheUploadStatusReport = {};
for (const language of config.languages) {
const cacheConfig = getDefaultCacheConfig()[language];
@@ -208,6 +235,7 @@ export async function uploadDependencyCaches(
const globber = await makeGlobber(cacheConfig.hash);
if ((await globber.glob()).length === 0) {
status[language] = { result: CacheStoreResult.NoHash };
logger.info(
`Skipping upload of dependency cache for ${language} as we cannot calculate a hash for the cache key.`,
);
@@ -228,6 +256,7 @@ export async function uploadDependencyCaches(
// Skip uploading an empty cache.
if (size === 0) {
status[language] = { result: CacheStoreResult.Empty };
logger.info(
`Skipping upload of dependency cache for ${language} since it is empty.`,
);
@@ -241,7 +270,15 @@ export async function uploadDependencyCaches(
);
try {
const start = performance.now();
await actionsCache.saveCache(cacheConfig.paths, key);
const upload_duration_ms = Math.round(performance.now() - start);
status[language] = {
result: CacheStoreResult.Stored,
upload_size_bytes: Math.round(size),
upload_duration_ms,
};
} catch (error) {
// `ReserveCacheError` indicates that the cache key is already in use, which means that a
// cache with that key already exists or is in the process of being uploaded by another
@@ -251,12 +288,16 @@ export async function uploadDependencyCaches(
`Not uploading cache for ${language}, because ${key} is already in use.`,
);
logger.debug(error.message);
status[language] = { result: CacheStoreResult.Duplicate };
} else {
// Propagate other errors upwards.
throw error;
}
}
}
return status;
}
/**