Skip to content

AI-7163 Monitor Dispatcher GitHub requests and throttling - #25331

Merged
AAraKKe merged 1 commit into
masterfrom
aarakke/AI-7163-github-metrics
Sep 25, 2026
Merged

AAraKKe merged 1 commit into
masterfrom
aarakke/AI-7163-github-metrics

Conversation

@AAraKKe

@AAraKKe AAraKKe commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

What does this PR do?

Adds GitHub request and throttle metrics under agent_integrations.test_dispatcher, using the existing buffered monitoring sink.

Metrics Type and unit Emission boundary
requests.count Count, requests One per actual GitHub API attempt, including rate-limit replays and artifact redirect refreshes. Anonymous storage downloads are excluded.
requests.fault Count, 0/1 per attempt Failed attempts emit 1; successes, expected artifact redirects and local cancellations emit 0.
requests.throttled Count, 0/1 per attempt Only GitHub rate-limit rejections emit 1. Local bucket/governor waits and ordinary permission denials do not.
requests.retried Count, 0/1 per attempt Initial sends emit 0; each additional actual send emits 1.
requests.duration Distribution, seconds Monotonic HTTP elapsed time, excluding limiter waits and retry backoff.
throttle.wait.duration Distribution, seconds Actual blocked time for local bucket waits, budget pacing and rate-limit pauses, including interrupted waits. Sample counts represent wait episodes, not rejected requests.
requests.polling_interval Distribution, seconds Time between successive poll starts of the same batch, emitted through the runner's normal metric policy. No first-poll sample or cadence change.
requests.rate_limit.remaining, requests.rate_limit.limit, requests.rate_limit.used Gauge, requests Raw budget observations from response headers on successful and failed attempts.
requests.rate_limit.reset_in Gauge, seconds Nonnegative time until the response's reset epoch.

All Dispatcher metrics reuse GITHUB_RUN_ID as ci.pipeline.id, bound before resolution and protected from caller overrides. Reruns retain the same ID; local invocations without it omit the tag. GitHub metrics carry only that ID and relevant status/reason dimensions. Budget gauges additionally carry github.rate_limit.resource, with unknown for an absent resource header. Polling keeps the runner's normal dimensions, including its component.

Sum event counts; requests.throttled / requests.count gives the rate-limit rejection fraction over matching windows. Duration distributions aggregate observations across pipelines. Keep budget resources separate, and do not sum pipeline observations of the same shared budget; use minimum remaining or maximum used to monitor pressure. Missing, malformed or non-finite budget values produce no sample, never a fabricated zero.

A generic optional client observer reports attempts and terminal failures; the Dispatcher owns emission, including PR-resolution requests and waits. Failed attempts and terminal failures log at ERROR; successful requests, cancellation and measured waits log at DEBUG. Logging is injected; response headers are not copied into log tags, and signed queries and credentials are excluded. Budget emission is separate from log-field construction.

Observer failures cannot change request behavior. Cancellation propagates without retry or terminal failure. Metrics remain disabled for --dry-run and --resolve-only.

Validation: 55 filtered tests passed after rebasing onto master, covering GitHub metrics, pipeline identity, polling, logging, unresolved run dimensions, cleanup and mode suppression. ddev --no-interactive test --lint ddev passed formatting, lint and mypy (237 source files). No live GitHub/Datadog validation yet.

Motivation

Implements AI-7163 to distinguish GitHub latency, faults, retries and rate-limit rejections from local pacing and Dispatcher execution outcomes.

Builds on the execution metrics merged in #25317. Developer tooling only; qa/skip-qa.

Review checklist (to be filled by reviewers)

  • Feature or bugfix MUST have appropriate tests (unit, integration, e2e)
  • Add qa/required if this PR needs QA validation, or qa/skip-qa if it does not. Exactly one of the two is required.
  • If you need to backport this PR to another branch, you can add the backport/<branch-name> label to the PR and it will automatically open a backport PR once this one is merged

@AAraKKe AAraKKe added the qa/skip-qa Automatically skip this PR for the next QA label Sep 24, 2026
@dd-octo-sts dd-octo-sts Bot added the ddev label Sep 24, 2026
@AAraKKe
AAraKKe force-pushed the aarakke/AI-7163-github-metrics branch from 3472602 to 4335b72 Compare September 24, 2026 09:46
@cit-pr-commenter-54b7da

cit-pr-commenter-54b7da Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

evalya-impact-summary

evalya impact analysis
Impact analysis: RUN-ALL — every test task will run
Trigger:         empty diff (default branch, scheduled run, or shallow-clone fallback)
Test tasks:      0 (all selected)
Publish tasks:   2 (always emitted)
Diff:            empty (no diff information)

Learn more about CI impact filtering

@datadog-official

datadog-official Bot commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Tests  Code Coverage

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
• Patch Coverage: 99.06%
• Overall Coverage: 89.43%

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 9d4e558 | Docs | View more details | Give us feedback!

@AAraKKe
AAraKKe force-pushed the aarakke/AI-7163-github-metrics branch from 4335b72 to e590db7 Compare September 24, 2026 10:43
@AAraKKe

AAraKKe commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-24T16:35:22.942090Z 9d4e558 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e590db7f15

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

response.raise_for_status()
except httpx.HTTPStatusError as exc:
error = exc
self._report_attempt(attempts, method, endpoint, duration_seconds, response, error)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Classify invalid artifact responses before reporting success

When the artifact endpoint returns a non-302 success such as HTTP 200, a different redirect status, or a 302 without Location, this line reports the attempt with error=None before _resolve_artifact_redirect rejects the response. The artifact download therefore fails and produces a terminal error log, but requests.fault records 0 and the attempt is logged as completed, understating faults for malformed artifact responses. Validate the endpoint-specific 302/Location contract before notifying the observer, or otherwise report the later validation error against this attempt.

AGENTS.md reference: ddev/src/ddev/utils/github_async/AGENTS.md:L151-L157

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed. The 302/Location validation now runs before the attempt is reported, so malformed artifact responses count as faults. Added coverage for 200, 301, and missing or empty Location headers.

@AAraKKe
AAraKKe force-pushed the aarakke/AI-6485-dispatcher-execution-metrics branch 3 times, most recently from 003f883 to 7d1efb1 Compare September 24, 2026 13:38
Base automatically changed from aarakke/AI-6485-dispatcher-execution-metrics to master September 24, 2026 14:07
@AAraKKe
AAraKKe force-pushed the aarakke/AI-7163-github-metrics branch from e590db7 to 8de32b6 Compare September 24, 2026 15:37
@dd-octo-sts

dd-octo-sts Bot commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

❌ Dispatcher tests: failed

Dispatcher beta: informational only
Existing CI remains the merge signal.

Caution

3 integrations failed. 4 of 855 jobs failed.

  855/855 jobs

✅ 851 passed · ❌ 4 failed

Batches · ✅ batch-01 240/240 · ✅ batch-02 217/217 · ❌ batch-03 220/220 · ✅ batch-04 178/178

❌ postgres: 2 failed targets
❌ pgbouncer: 1 failed target
❌ silverstripe_cms: 1 failed target

Dispatcher finished on a42d369 — GitHub Run · Dispatcher Logs.

@AAraKKe
AAraKKe force-pushed the aarakke/AI-7163-github-metrics branch 2 times, most recently from 6f64223 to a089a7a Compare September 24, 2026 15:53
@AAraKKe

AAraKKe commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a089a7a36a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if slept:
self.on_event(
WaitEvent(
reason=WaitReason(reason),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve neutral reasons when reporting a completed wait

If the wall clock moves backward between reserve() and the following self.now() call, a healthy request can have a positive delay while its reason remains PacingReason.NONE. After the sleep completes, converting that value with WaitReason(reason) raises ValueError because WaitReason has no NONE member, turning an otherwise successful limiter acquisition into a failed GitHub request. This is also reproducible with the public injectable now clock; handle the neutral reason explicitly rather than letting instrumentation alter request behavior.

Useful? React with 👍 / 👎.

@AAraKKe AAraKKe Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The moment we get comments asking about preventing an issue with a backward running clock you know we have reached the point in which now we are clawing hyper weird edge cases.

I just want to leave here for the record the response Astra game me when it read the comment and I told it "if we start having problems with clocks running backward we have bigger problems than Dispatcher thinking it is rate limited in a unexpected way".

I’m thinking about how to explain that the clock on the machine can go backwards without contradicting physics. I could phrase it as, "The machine's clock can go backwards without breaking any physical laws." It looks like the user responded humorously, which is nice! They acknowledged this point as an edge case. I wouldn't want to ignore this detail, though I’d prefer to keep the explanation concise.

You have to love this dystopian present so we can be prepare for a very awkward future 😅

PS: I am ignoring the NONE case so this is not a concern. At least we are covered the day this happens. I don't trust the GH runners xD

@AAraKKe
AAraKKe force-pushed the aarakke/AI-7163-github-metrics branch from a089a7a to 9d4e558 Compare September 24, 2026 16:17
@AAraKKe
AAraKKe marked this pull request as ready for review September 24, 2026 16:30
@AAraKKe
AAraKKe requested a review from a team as a code owner September 24, 2026 16:30
@dd-octo-sts

dd-octo-sts Bot commented Sep 24, 2026

Copy link
Copy Markdown
Contributor

Validation Report

All 21 validations passed.

Show details
Validation Description Status
agent-reqs Verify check versions match the Agent requirements file ✅
ci Validate CI configuration and code coverage settings ✅
codeowners Validate every integration has a CODEOWNERS entry ✅
config Validate default configuration files against spec.yaml ✅
dep Verify dependency pins are consistent and Agent-compatible ✅
http Validate integrations use the HTTP wrapper correctly ✅
imports Validate check imports do not use deprecated modules ✅
integration-style Validate check code style conventions ✅
jmx-metrics Validate JMX metrics definition files and config ✅
labeler Validate PR labeler config matches integration directories ✅
legacy-signature Validate no integration uses the legacy Agent check signature ✅
license-headers Validate Python files have proper license headers ✅
licenses Validate third-party license attribution list ✅
metadata Validate metadata.csv metric definitions ✅
models Validate configuration data models match spec.yaml ✅
openmetrics Validate OpenMetrics integrations disable the metric limit ✅
package Validate Python package metadata and naming ✅
qa-label Validate the pull request declares whether it needs QA for the next Agent release ✅
readmes Validate README files have required sections ✅
saved-views Validate saved view JSON file structure and fields ✅
version Validate version consistency between package and changelog ✅

View full run

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9d4e55821d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

error = httpx.HTTPError(f"Expected 302 redirect from {endpoint}, got {response.status_code}")
elif not response.headers.get("location"):
error = httpx.HTTPError(f"Missing Location header on redirect from {endpoint}")
self._report_attempt(attempts, method, endpoint, duration_seconds, response, error)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Exclude accepted cancellation responses from failures

When cancel_workflow_run receives the documented 409 for a run that has already become terminal, this reports the attempt as CLIENT_ERROR, and _request also emits a terminal failure before cancel_workflow_run catches and accepts that status. Consequently, the normal shutdown race where a workflow completes before cancellation increments requests.fault and produces error logs even though the endpoint call returns successfully; handle the accepted 409 before notifying the observer.

AGENTS.md reference: ddev/src/ddev/utils/github_async/AGENTS.md:L164-L165

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I'm keeping this as a request fault. These metrics and logs describe the HTTP request, not the Dispatcher outcome. A 409 is still a failed request, even when the cancellation code tolerates it because the run is already terminal.

@HadhemiDD HadhemiDD left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@AAraKKe
AAraKKe added this pull request to the merge queue Sep 25, 2026
Merged via the queue into master with commit 93de4e3 Sep 25, 2026
390 of 404 checks passed
@AAraKKe
AAraKKe deleted the aarakke/AI-7163-github-metrics branch September 25, 2026 09:22
@dd-octo-sts dd-octo-sts Bot added this to the 7.85.0 milestone Sep 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ddev qa/skip-qa Automatically skip this PR for the next QA team/agent-integrations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants