Skip to content

telemetry: structured git mirror checkout, hydration, and maintenance reports - #43

Merged
piob-io merged 1 commit into
mainfrom
devin/1787595928-git-mirror-telemetry
Sep 17, 2026
Merged

piob-io merged 1 commit into
mainfrom
devin/1787595928-git-mirror-telemetry

Conversation

@piob-io

@piob-io piob-io commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Upgrades the action's guest→vm-agent internal-metrics channel from counters to structured payloads, so the fa agent can build per-checkout / per-hydration / per-maintenance-run ClickHouse rows. Companion to FastActions/fa#5231 (agent-side ingest) and FastActions/fa#5450 (target-mirror stamping). Rebased onto main after #55 (bounded incremental mirror maintenance) merged; the single commit instruments runMirrorMaintenance and syncMirrorFromRemote.

  • src/mirror-telemetry.ts (new): dumb payload builders with closed enums — ServingMode (mirror / hydrating / fallback-contention / fallback-error / bypass), Outcome (success / failure / timeout) — plus packSizeBytes / packNames (one readdir of objects/pack), dirSizeBytes (du -sb, runner-local workspace only), refCount (git show-ref | wc -l), and classifyError. All reporting is fire-and-forget with every error swallowed; telemetry can never fail the job.

  • src/internal-metrics.ts: adds reportStructuredMetric(metricType, payload) which rides the existing /internal envelope in a new payload field (same 5s timeout, errors swallowed); legacy reportInternalMetric unchanged.

  • src/git-source-provider.ts: getSource emits one checkout report from a finally block (so fallback and failure paths still report), with serving mode chosen where the mirror path is picked: 409/Code.Abortedfallback-contention, other cache/mirror failures → fallback-error, initial mirror clone → hydrating (plus a hydration clone-detail report with duration/bytes/ref count), otherwise mirror or bypass. Phase durations: sticky-disk setup, clone-from-mirror, delta fetch (bytes + ms), full checkout, submodules, LFS; repo shape: mirror size, ref count, shallow/filter/submodules/LFS flags.

  • Every report names its target mirror. Checkout, hydration, and maintenance payloads carry sticky_disk_key = stickyDiskKeyFor(owner, repo) (<owner>-<repo>, the same key setupCache requests), set before cache setup so fallback-contention / fallback-error / bypass rows — where no disk is ever mounted — still say which mirror they were about. The agent uses it to stamp the row's mirror identity; it is never an OTel label.

  • Mirror measurements never walk the sticky disk. Every mirror size (mirror_size_bytes, hydration clone_bytes, refresh/gc bytes deltas) is the byte total of <mirror>/objects/pack — a flat handful of large files, so one readdir plus a few stats instead of a du over every loose object and ref, each of which is a cold random read on a freshly mounted block device. Because Post step: bounded incremental mirror maintenance; maintenance failure no longer vetoes the commit #55's mirror sync runs with fetch.unpackLimit=1, every fetch lands as a pack, so refresh bytes is exactly the fetched bytes; gc bytes is the pack-consolidation saving only (kept packs are never rewritten, so it is the delta of the rolled-up small packs). Only the workspace delta_fetch_bytes still uses du -sb, on the runner-local .git/objects that holds just the delta.

  • State is persisted before any measurement. setBlacksmithCachePerformedHydration / setBlacksmithCacheMirrorChanged(true) run as soon as ensureMirror returns, and syncMirrorFromRemote takes an onMirrorChanged callback fired the moment the mirror has changed (post-fetch, or purge-only), before its own size read — so a cancel during telemetry can never leave the post step treating a changed mirror as unchanged.

  • src/blacksmith-cache.ts + src/main.ts: syncMirrorFromRemote records duration and pack-size delta (durationMs, bytes = fetched, mirrorSizeBytes; only a delta where both reads succeeded is reported), and a structured refresh maintenance row is emitted wherever the sync runs — the main step for full checkouts, the post step for the deferred shallow-checkout sync. The post-step runMirrorMaintenance (Post step: bounded incremental mirror maintenance; maintenance failure no longer vetoes the commit #55's .keep marking + geometric repack + pack-refs) measures duration and reclaimed pack bytes and emits a maintenance row under the existing gc operation — the agent's operation enum is closed (refresh|gc|fsck) and gc is the pack-consolidation slot, whichever git verb performs it, so no fa/ClickHouse/dashboard change is needed.

  • No-op maintenance emits no row. OperationResult.skipped means the operation did no work; skipped syncs and skipped maintenance are not reported. cleanup() starts from maintenanceResult = {success: true, timedOut: false, skipped: true}, so a mirror that is not maintained (no mirror, sync failed, or not committing) never yields a row; when maintenance does run, the sorted .pack names are snapshotted before and after (pack names are content hashes, so any roll-up rewrites the set) and a run that changed nothing is marked skipped, so the gc counter and rows reflect real repack work rather than one row per commit path:

    const before = packNamesOrNull(mirrorPath)
    await markKeepPacks(...); await exec('timeout', [..., 'repack', '-d', '-l', '-n', '--geometric=2', '--write-midx']); await exec('timeout', [..., 'pack-refs', '--all'])
    const after = packNamesOrNull(mirrorPath)
    if (before && after && samePackNames(before, after)) return {success: true, timedOut: false, skipped: true, bytes: 0, ...}

    Maintenance failure/timeout keeps Post step: bounded incremental mirror maintenance; maintenance failure no longer vetoes the commit #55's semantics (logged, git_mirror_gc_failure metric, commit still lands) and additionally produces a gc row with outcome=failure|timeout.

    __test__/mirror-gc-git.test.ts exercises the telemetry against real git (single-pack mirror → geometric repack rolls nothing → skipped; two similarly sized packs → rolled to one → real run with durationMs/mirrorSizeBytes; shouldCommit=falseskipped), plus the pack measurement helpers (loose objects excluded; missing pack dir measures 0, not unmeasurable). Post step: bounded incremental mirror maintenance; maintenance failure no longer vetoes the commit #55's mirror-maintenance-git.test.ts / mirror-cleanup.test.ts assert the same skipped/measurement fields on their fixtures.

Existing failure counters unchanged — fleet alerting surface preserved. No fsck run exists in the action today, so no fsck row is emitted (the enum supports it for when one is added). Final hydration persistence truth is stamped agent-side at teardown; the guest reports contribute clone-phase detail only.

dist/index.js rebuilt (tsc && ncc build).


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled. (Staging)


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Link to Devin session: https://app.devin.ai/sessions/53ae2d32138144f4832eae008103aa71
Open in Devin Desktop: https://app.devin.ai/desktop/session/53ae2d32138144f4832eae008103aa71?variant=devin
Requested by: @piob-io

@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@piob-io
piob-io marked this pull request as ready for review August 24, 2026 21:40
Comment thread src/git-source-provider.ts
Comment thread src/git-source-provider.ts Outdated
Comment thread src/git-source-provider.ts
@piob-io
piob-io requested a review from ajwerner August 24, 2026 21:44
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1787595928-git-mirror-telemetry branch from 72baab9 to dd7a3dd Compare August 24, 2026 21:46
Comment thread src/blacksmith-cache.ts Outdated
Comment thread src/blacksmith-cache.ts Outdated
Comment thread src/git-source-provider.ts
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1787595928-git-mirror-telemetry branch from dd7a3dd to 16750a1 Compare August 24, 2026 21:53
Comment thread src/main.ts
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1787595928-git-mirror-telemetry branch from 16750a1 to b348b13 Compare August 24, 2026 22:00
Comment thread src/git-source-provider.ts
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1787595928-git-mirror-telemetry branch from b348b13 to e86d13b Compare August 24, 2026 22:08
Comment thread src/mirror-telemetry.ts
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1787595928-git-mirror-telemetry branch from e86d13b to e836bd2 Compare August 24, 2026 22:20
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1787595928-git-mirror-telemetry branch from e836bd2 to b67c523 Compare August 31, 2026 13:16
Comment thread src/main.ts
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1787595928-git-mirror-telemetry branch from b67c523 to 941615e Compare August 31, 2026 13:23

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread src/git-source-provider.ts Outdated
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1787595928-git-mirror-telemetry branch 4 times, most recently from 6dedeef to 75491d8 Compare September 4, 2026 20:07
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1787595928-git-mirror-telemetry branch from 75491d8 to 0dbdb43 Compare September 8, 2026 13:16

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread src/git-source-provider.ts
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1787595928-git-mirror-telemetry branch from 0dbdb43 to 58ce834 Compare September 8, 2026 13:26

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread src/blacksmith-cache.ts
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1787595928-git-mirror-telemetry branch 3 times, most recently from 8e3e269 to f6c5f4a Compare September 9, 2026 13:15

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit f6c5f4a. Configure here.

Comment thread src/git-source-provider.ts Outdated
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1787595928-git-mirror-telemetry branch from f6c5f4a to edec05e Compare September 9, 2026 13:21
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1787595928-git-mirror-telemetry branch from edec05e to 27e77c7 Compare September 16, 2026 18:29
@devin-ai-integration
devin-ai-integration Bot changed the base branch from main to devin/1789579599-bounded-mirror-maintenance September 16, 2026 18:29
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1787595928-git-mirror-telemetry branch from 27e77c7 to 8143300 Compare September 16, 2026 19:47
… reports

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1787595928-git-mirror-telemetry branch from 8143300 to c5dcd97 Compare September 17, 2026 12:55
@devin-ai-integration
devin-ai-integration Bot changed the base branch from devin/1789579599-bounded-mirror-maintenance to main September 17, 2026 12:55
@piob-io
piob-io merged commit a6f249f into main Sep 17, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants