-
Notifications
You must be signed in to change notification settings - Fork 1
Add buildx disk usage logging after buildkit is ready #44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -353,6 +353,119 @@ export async function logDatabaseHashes(label: string): Promise<void> { | |
| } | ||
| } | ||
|
|
||
| /** | ||
| * Logs buildx disk usage to help identify cached layers. | ||
| * Uses a 5-second timeout to avoid blocking. | ||
| */ | ||
| export async function logBuildxDiskUsage(): Promise<void> { | ||
| try { | ||
| core.info("Checking buildx disk usage for cached layers:"); | ||
|
|
||
| const { stdout } = await execAsync( | ||
| `timeout 5s docker buildx du --verbose 2>&1`, | ||
| ); | ||
|
|
||
| const output = stdout.trim(); | ||
| if (!output) { | ||
| core.info("No disk usage data available."); | ||
| return; | ||
| } | ||
|
|
||
| // Parse and format the output for better readability. | ||
| const lines = output.split("\n"); | ||
| let totalSize = 0; | ||
| const cacheEntries: Array<{ | ||
| id: string; | ||
| size: number; | ||
| shared: boolean; | ||
| description: string; | ||
| }> = []; | ||
|
|
||
| for (const line of lines) { | ||
| // Parse lines that contain cache IDs and sizes. | ||
| // Expected format: ID SIZE [SHARED] DESCRIPTION | ||
| const match = line.match(/^(\S+)\s+(\d+(?:\.\d+)?[KMGT]?B?)\s+(.*?)$/); | ||
| if (match) { | ||
| const [, id, sizeStr, description] = match; | ||
| const isShared = description.includes("shared"); | ||
|
|
||
| // Convert size to bytes for aggregation. | ||
| const sizeBytes = parseSizeToBytes(sizeStr); | ||
| totalSize += sizeBytes; | ||
|
|
||
| cacheEntries.push({ | ||
| id: id, | ||
| size: sizeBytes, | ||
| shared: isShared, | ||
| description: description.trim(), | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| // Log summary. | ||
| if (cacheEntries.length > 0) { | ||
| core.info(`Found ${cacheEntries.length} cache entries`); | ||
| core.info(`Total cache size: ${formatBytes(totalSize)}`); | ||
|
|
||
| // Log all cache entries in build order (as returned by buildx du). | ||
| core.info("Cache entries in build order:"); | ||
| for (const entry of cacheEntries) { | ||
| const sharedLabel = entry.shared ? " [SHARED]" : ""; | ||
| core.info( | ||
| ` ${entry.id}: ${formatBytes(entry.size)}${sharedLabel} - ${entry.description}`, | ||
| ); | ||
| } | ||
| } else { | ||
| // If parsing failed, just log the raw output. | ||
| core.info("Raw disk usage output:"); | ||
| core.info(output); | ||
| } | ||
| } catch (error) { | ||
| const execError = error as { code?: number; message?: string }; | ||
| if (execError.code === 124) { | ||
| core.warning("buildx disk usage check timed out after 5 seconds."); | ||
| } else { | ||
| core.warning( | ||
| `Failed to get buildx disk usage: ${execError.message || "unknown error"}`, | ||
| ); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Parses a size string (e.g., "1.5GB", "500MB") to bytes. | ||
| */ | ||
| function parseSizeToBytes(sizeStr: string): number { | ||
| const match = sizeStr.match(/^(\d+(?:\.\d+)?)\s*([KMGT]?B?)$/i); | ||
| if (!match) return 0; | ||
|
|
||
| const value = parseFloat(match[1]); | ||
| const unit = match[2].toUpperCase(); | ||
|
|
||
| const multipliers: Record<string, number> = { | ||
| B: 1, | ||
| KB: 1024, | ||
| MB: 1024 * 1024, | ||
| GB: 1024 * 1024 * 1024, | ||
| TB: 1024 * 1024 * 1024 * 1024, | ||
| }; | ||
|
|
||
| return value * (multipliers[unit] || 1); | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Disk Size Parsing Fails Without 'B' SuffixThe |
||
|
|
||
| /** | ||
| * Formats bytes into a human-readable string. | ||
| */ | ||
| function formatBytes(bytes: number): string { | ||
| if (bytes === 0) return "0 B"; | ||
|
|
||
| const units = ["B", "KB", "MB", "GB", "TB"]; | ||
| const k = 1024; | ||
| const i = Math.floor(Math.log(bytes) / Math.log(k)); | ||
|
|
||
| return `${(bytes / Math.pow(k, i)).toFixed(2)} ${units[i]}`; | ||
| } | ||
|
|
||
| // stickyDiskTimeoutMs states the max amount of time this action will wait for the VM agent to | ||
| // expose the sticky disk from the storage agent, map it onto the host and then patch the drive | ||
| // into the VM. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parsing logic doesn't work as is.
On the version of buildx we install by default (v0.23.0),
docker buildx du --verboseoutputsStarting from v0.29.0, it uses this template:
https://github.com/docker/buildx/blob/beaebcbf39b9f61cda762669083450c65470ec00/commands/diskusage.go#L38-L60