Skip to content

Commit 249a3cb

Browse files
committed
Add telemetry for storing dependency caches
1 parent 11480e3 commit 249a3cb

File tree

3 files changed

+93
-7
lines changed

3 files changed

+93
-7
lines changed

lib/analyze-action.js

Lines changed: 27 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/analyze-action.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ import {
2626
isCodeScanningEnabled,
2727
} from "./config-utils";
2828
import { uploadDatabases } from "./database-upload";
29-
import { uploadDependencyCaches } from "./dependency-caching";
29+
import {
30+
DependencyCacheUploadStatusReport,
31+
uploadDependencyCaches,
32+
} from "./dependency-caching";
3033
import { getDiffInformedAnalysisBranches } from "./diff-informed-analysis-utils";
3134
import { EnvVar } from "./environment";
3235
import { Feature, Features } from "./feature-flags";
@@ -55,10 +58,15 @@ interface AnalysisStatusReport
5558
extends uploadLib.UploadStatusReport,
5659
QueriesStatusReport {}
5760

61+
interface DependencyCachingUploadStatusReport {
62+
dependency_caching_upload_results?: string;
63+
}
64+
5865
interface FinishStatusReport
5966
extends StatusReportBase,
6067
DatabaseCreationTimings,
61-
AnalysisStatusReport {}
68+
AnalysisStatusReport,
69+
DependencyCachingUploadStatusReport {}
6270

6371
interface FinishWithTrapUploadStatusReport extends FinishStatusReport {
6472
/** Size of TRAP caches that we uploaded, in bytes. */
@@ -76,6 +84,7 @@ async function sendStatusReport(
7684
dbCreationTimings: DatabaseCreationTimings | undefined,
7785
didUploadTrapCaches: boolean,
7886
trapCacheCleanup: TrapCacheCleanupStatusReport | undefined,
87+
dependencyCacheResults: DependencyCacheUploadStatusReport | undefined,
7988
logger: Logger,
8089
) {
8190
const status = getActionsStatus(error, stats?.analyze_failure_language);
@@ -95,6 +104,9 @@ async function sendStatusReport(
95104
...(stats || {}),
96105
...(dbCreationTimings || {}),
97106
...(trapCacheCleanup || {}),
107+
dependency_caching_upload_results: JSON.stringify(
108+
dependencyCacheResults ?? {},
109+
),
98110
};
99111
if (config && didUploadTrapCaches) {
100112
const trapCacheUploadStatusReport: FinishWithTrapUploadStatusReport = {
@@ -209,6 +221,7 @@ async function run() {
209221
let trapCacheUploadTime: number | undefined = undefined;
210222
let dbCreationTimings: DatabaseCreationTimings | undefined = undefined;
211223
let didUploadTrapCaches = false;
224+
let dependencyCacheResults: DependencyCacheUploadStatusReport | undefined;
212225
util.initializeEnvironment(actionsUtil.getActionVersion());
213226

214227
// Make inputs accessible in the `post` step, details at
@@ -388,7 +401,11 @@ async function run() {
388401
Feature.JavaMinimizeDependencyJars,
389402
codeql,
390403
);
391-
await uploadDependencyCaches(config, logger, minimizeJavaJars);
404+
dependencyCacheResults = await uploadDependencyCaches(
405+
config,
406+
logger,
407+
minimizeJavaJars,
408+
);
392409
}
393410

394411
// We don't upload results in test mode, so don't wait for processing
@@ -431,6 +448,7 @@ async function run() {
431448
dbCreationTimings,
432449
didUploadTrapCaches,
433450
trapCacheCleanupTelemetry,
451+
dependencyCacheResults,
434452
logger,
435453
);
436454
return;
@@ -449,6 +467,7 @@ async function run() {
449467
dbCreationTimings,
450468
didUploadTrapCaches,
451469
trapCacheCleanupTelemetry,
470+
dependencyCacheResults,
452471
logger,
453472
);
454473
} else if (runStats) {
@@ -461,6 +480,7 @@ async function run() {
461480
dbCreationTimings,
462481
didUploadTrapCaches,
463482
trapCacheCleanupTelemetry,
483+
dependencyCacheResults,
464484
logger,
465485
);
466486
} else {
@@ -473,6 +493,7 @@ async function run() {
473493
dbCreationTimings,
474494
didUploadTrapCaches,
475495
trapCacheCleanupTelemetry,
496+
dependencyCacheResults,
476497
logger,
477498
);
478499
}

src/dependency-caching.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,18 +181,45 @@ export async function downloadDependencyCaches(
181181
return status;
182182
}
183183

184+
/** Enumerates possible outcomes for cache hits. */
185+
export enum CacheStoreResult {
186+
/** We were unable to calculate a hash for the key. */
187+
NoHash = "no-hash",
188+
/** There is nothing to store in the cache. */
189+
Empty = "empty",
190+
/** There already exists a cache with the key we are trying to store. */
191+
Duplicate = "duplicate",
192+
/** The cache was stored successfully. */
193+
Stored = "stored",
194+
}
195+
196+
/** Represents results of trying to upload a dependency cache for a language. */
197+
export interface DependencyCacheUploadStatus {
198+
result: CacheStoreResult;
199+
upload_size_bytes?: number;
200+
upload_duration_ms?: number;
201+
}
202+
203+
/** A partial mapping from languages to the results of uploading dependency caches for them. */
204+
export type DependencyCacheUploadStatusReport = Partial<
205+
Record<Language, DependencyCacheUploadStatus>
206+
>;
207+
184208
/**
185209
* Attempts to store caches for the languages that were analyzed.
186210
*
187211
* @param config The configuration for this workflow.
188212
* @param logger A logger to record some informational messages to.
189213
* @param minimizeJavaJars Whether the Java extractor should rewrite downloaded JARs to minimize their size.
214+
*
215+
* @returns A partial mapping of languages to results of uploading dependency caches for them.
190216
*/
191217
export async function uploadDependencyCaches(
192218
config: Config,
193219
logger: Logger,
194220
minimizeJavaJars: boolean,
195-
): Promise<void> {
221+
): Promise<DependencyCacheUploadStatusReport> {
222+
const status: DependencyCacheUploadStatusReport = {};
196223
for (const language of config.languages) {
197224
const cacheConfig = getDefaultCacheConfig()[language];
198225

@@ -208,6 +235,7 @@ export async function uploadDependencyCaches(
208235
const globber = await makeGlobber(cacheConfig.hash);
209236

210237
if ((await globber.glob()).length === 0) {
238+
status[language] = { result: CacheStoreResult.NoHash };
211239
logger.info(
212240
`Skipping upload of dependency cache for ${language} as we cannot calculate a hash for the cache key.`,
213241
);
@@ -228,6 +256,7 @@ export async function uploadDependencyCaches(
228256

229257
// Skip uploading an empty cache.
230258
if (size === 0) {
259+
status[language] = { result: CacheStoreResult.Empty };
231260
logger.info(
232261
`Skipping upload of dependency cache for ${language} since it is empty.`,
233262
);
@@ -241,7 +270,15 @@ export async function uploadDependencyCaches(
241270
);
242271

243272
try {
273+
const start = performance.now();
244274
await actionsCache.saveCache(cacheConfig.paths, key);
275+
const upload_duration_ms = Math.round(performance.now() - start);
276+
277+
status[language] = {
278+
result: CacheStoreResult.Stored,
279+
upload_size_bytes: Math.round(size),
280+
upload_duration_ms,
281+
};
245282
} catch (error) {
246283
// `ReserveCacheError` indicates that the cache key is already in use, which means that a
247284
// cache with that key already exists or is in the process of being uploaded by another
@@ -251,12 +288,16 @@ export async function uploadDependencyCaches(
251288
`Not uploading cache for ${language}, because ${key} is already in use.`,
252289
);
253290
logger.debug(error.message);
291+
292+
status[language] = { result: CacheStoreResult.Duplicate };
254293
} else {
255294
// Propagate other errors upwards.
256295
throw error;
257296
}
258297
}
259298
}
299+
300+
return status;
260301
}
261302

262303
/**

0 commit comments

Comments
 (0)