Skip to content

Commit 264f813

Browse files
ZackKanterclaude
andauthored
feat(instrumentation): instrument cache lifecycle with OTEL (renovatebot#41922)
* fix(cache): instrument repository cache load and save Wrap repository cache `load()` and `save()` calls with the existing `instrument()` helper to create OpenTelemetry spans for cache lifecycle operations. This gives operators visibility into repository cache performance, especially useful with S3 backends. Refs renovatebot#41760 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cache): instrument package cache init and destroy Wrap package cache `init()` and `destroy()` with `instrument()` to create OpenTelemetry spans, matching the repository cache instrumentation from the previous commit. Covers redis, sqlite, and file backends. Refs renovatebot#41760 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs: document cache lifecycle tracing in OpenTelemetry guide Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Move destroy() outside init instrument span Avoids nesting the package-cache.destroy span inside package-cache.init, making them sibling spans instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Use 'verb NounClass' span naming convention Rename instrument span names from dot-notation (e.g. 'package-cache.init') to 'verb NounClass' pattern (e.g. 'init PackageCache') per reviewer feedback. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 0fac483 commit 264f813

File tree

4 files changed

+35
-28
lines changed

4 files changed

+35
-28
lines changed

docs/usage/opentelemetry.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ Renovate provides instrumentation through traces for (non-exhaustively):
7777
- Any Git operations
7878
- Per-manager traces when performing the `lookup` and `extract` splits
7979
- Per-branch traces when performing the `update` split
80+
- Cache lifecycle operations (repository cache load/save, package cache init/destroy)
8081
- Important functions (more instrumentation be added)
8182

8283
As well as following [OpenTelemetry's semantic conventions](https://opentelemetry.io/docs/specs/semconv/) where possible, Renovate defines several Custom Attributes, which can be found in [`lib/instrumentation/types.ts`](https://github.com/renovatebot/renovate/blob/main/lib/instrumentation/types.ts).

lib/util/cache/package/backend.ts

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { AllConfig } from '../../../config/types.ts';
2+
import { instrument } from '../../../instrumentation/index.ts';
23
import { getEnv } from '../../env.ts';
34
import type { PackageCacheBase } from './impl/base.ts';
45
import { PackageCacheFile } from './impl/file.ts';
@@ -15,27 +16,28 @@ export function getCacheType(): typeof cacheType {
1516

1617
export async function init(config: AllConfig): Promise<void> {
1718
await destroy();
19+
await instrument('init PackageCache', async () => {
20+
if (config.redisUrl) {
21+
cacheProxy = await PackageCacheRedis.create(
22+
config.redisUrl,
23+
config.redisPrefix,
24+
);
25+
cacheType = 'redis';
26+
return;
27+
}
1828

19-
if (config.redisUrl) {
20-
cacheProxy = await PackageCacheRedis.create(
21-
config.redisUrl,
22-
config.redisPrefix,
23-
);
24-
cacheType = 'redis';
25-
return;
26-
}
29+
if (getEnv().RENOVATE_X_SQLITE_PACKAGE_CACHE && config.cacheDir) {
30+
cacheProxy = await PackageCacheSqlite.create(config.cacheDir);
31+
cacheType = 'sqlite';
32+
return;
33+
}
2734

28-
if (getEnv().RENOVATE_X_SQLITE_PACKAGE_CACHE && config.cacheDir) {
29-
cacheProxy = await PackageCacheSqlite.create(config.cacheDir);
30-
cacheType = 'sqlite';
31-
return;
32-
}
33-
34-
if (config.cacheDir) {
35-
cacheProxy = PackageCacheFile.create(config.cacheDir);
36-
cacheType = 'file';
37-
return;
38-
}
35+
if (config.cacheDir) {
36+
cacheProxy = PackageCacheFile.create(config.cacheDir);
37+
cacheType = 'file';
38+
return;
39+
}
40+
});
3941
}
4042

4143
export async function get<T = unknown>(
@@ -55,10 +57,12 @@ export async function set(
5557
}
5658

5759
export async function destroy(): Promise<void> {
58-
cacheType = undefined;
59-
try {
60-
await cacheProxy?.destroy();
61-
} finally {
62-
cacheProxy = undefined;
63-
}
60+
await instrument('destroy PackageCache', async () => {
61+
cacheType = undefined;
62+
try {
63+
await cacheProxy?.destroy();
64+
} finally {
65+
cacheProxy = undefined;
66+
}
67+
});
6468
}

lib/util/cache/repository/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { GlobalConfig } from '../../../config/global.ts';
2+
import { instrument } from '../../../instrumentation/index.ts';
23
import { logger } from '../../../logger/index.ts';
34
import { RepoCacheNull } from './impl/null.ts';
45
import type { RepoCache, RepoCacheData } from './types.ts';
@@ -23,7 +24,7 @@ export async function saveCache(): Promise<void> {
2324
if (GlobalConfig.get('dryRun')) {
2425
logger.info(`DRY-RUN: Would save repository cache.`);
2526
} else {
26-
await repoCache.save();
27+
await instrument('save RepoCache', () => repoCache.save());
2728
}
2829
}
2930

lib/util/cache/repository/init.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { instrument } from '../../../instrumentation/index.ts';
12
import { CacheFactory } from './impl/cache-factory.ts';
23
import { RepoCacheNull } from './impl/null.ts';
34
import { resetCache, setCache } from './index.ts';
@@ -23,14 +24,14 @@ export async function initRepoCache(config: RepoCacheConfig): Promise<void> {
2324

2425
if (repositoryCache === 'enabled') {
2526
const cache = CacheFactory.get(repository!, repoFingerprint, type);
26-
await cache.load();
27+
await instrument('load RepoCache', () => cache.load());
2728
setCache(cache);
2829
return;
2930
}
3031

3132
if (repositoryCache === 'reset') {
3233
const cache = CacheFactory.get(repository!, repoFingerprint, type);
33-
await cache.save();
34+
await instrument('save RepoCache', () => cache.save());
3435
setCache(cache);
3536
return;
3637
}

0 commit comments

Comments
 (0)