Skip to content

feat: add Python trending charts to Copilot Token Usage Analyzer#24434

Merged
pelikhan merged 3 commits intomainfrom
copilot/add-python-trending-charts
Apr 4, 2026
Merged

feat: add Python trending charts to Copilot Token Usage Analyzer#24434
pelikhan merged 3 commits intomainfrom
copilot/add-python-trending-charts

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 4, 2026

The Copilot Token Usage Analyzer report was static per-run with no historical trending. This adds persistent cache-memory data collection and three Python-generated charts embedded directly in each report issue.

Frontmatter changes

  • Added upload-asset: safe-output to enable chart hosting
  • Added shared/charts-with-trending.md import — pulls in Python venv (numpy, pandas, matplotlib, seaborn, scipy) and cache-memory integration

New analysis phases

Phase 1.5 — Persist to cache-memory (runs after per-workflow stats are computed):

  • trending/token-usage/history.jsonl — daily aggregated totals (tokens, runs, cost, turns)
  • trending/token-usage/workflows.jsonl — per-workflow daily breakdown for heatmap

Phase 3.5 — Generate charts (three charts, conditionally):

Chart Condition Description
🔥 Top Consumers Always Horizontal Seaborn bar, top-10 workflows by tokens
📈 Daily Trend ≥ 2 history points Dual-axis line: total tokens (red) / total runs (blue)
🗓️ Workflow Heatmap ≥ 3 history points YlOrRd heatmap, top-8 workflows × up to 14 recent dates

Charts are uploaded via upload_asset with explicit file-existence guards before each upload call. Chart sections in the issue body are conditionally omitted when not generated.

Phase 4 updated — Issue body template now embeds the chart images.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw ase,codename,all-C (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw 7946378/b045/vetrev-parse .cfg git rev-�� --show-toplevel ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet /usr/bin/git 5448-34696/test-git 7946378/b223/vetrev-parse tartedAt,updated--show-toplevel git (http block)
  • https://api.github.com/orgs/test-owner/actions/secrets
    • Triggering command: /usr/bin/gh gh api /orgs/test-owner/actions/secrets --jq .secrets[].name -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json cii.go x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh api /orgs/test-owner/actions/secrets --jq .secrets[].name --write ../../../**/*.jsGOMOD 64/bin/go --ignore-path ../../../.pretti-c /usr/bin/git go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/actions/ai-inference/git/ref/tags/v1
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq .object.sha --git-dir x_amd64/vet /usr/bin/git g_.a LamLkoYmy 64/pkg/tool/linu--show-toplevel git rev-�� --show-toplevel 64/pkg/tool/linu/tmp/go-build1077946378/b113/vet.cfg /usr/bin/infocmp ortcfg .cfg 64/pkg/tool/linu--show-toplevel infocmp (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v3
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq .object.sha ons-test2813538837 ^remote\..*\.gh-resolved$ ache/node/24.14.1/x64/bin/node -json GO111MODULE x_amd64/compile infocmp t-74�� k/gh-aw/gh-aw/.github/workflows/artifacts-summary.md x_amd64/compile /usr/bin/gh -json age/common.go x_amd64/compile gh (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v5
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha 85/001/test-complex-frontmatter-with-tools.md 7946378/b029/vet.cfg .cfg GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linuInitial commit -o U6Bt6UXbr -trimpath ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet -p github.com/segmerev-parse -lang=go1.17 ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha --get-regexp ^remote\..*\.gh-resolved$ /usr/bin/git 2135797988/.githgit GO111MODULE 64/pkg/tool/linu--show-toplevel git rev-�� --show-toplevel 64/pkg/tool/linux_amd64/vet /usr/bin/git 489146213 eFae/0ahu769BnKYrev-parse .cfg git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha --show-toplevel /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet /usr/bin/git -unreachable=falgit /tmp/go-build107rev-parse 7946378/b316/vet--show-toplevel git rev-�� .*/\1/p /opt/hostedtoolcache/go/1.25.8/x1 /usr/bin/gh licyMinIntegritygit /tmp/go-build107rev-parse Name,createdAt,s--show-toplevel gh (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v6
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha --oneline resolved$ /usr/bin/git -json GO111MODULE x_amd64/vet git rev-�� --show-toplevel x_amd64/vet /usr/bin/git g_.a GO111MODULE 64/pkg/tool/linu--show-toplevel git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha /tmp/gh-aw-test-runs/20260404-035448-34696/test-346075182 status /usr/bin/git .github/workflowgit GO111MODULE x_amd64/vet git rev-�� --show-toplevel x_amd64/vet /usr/bin/git g_.a GO111MODULE 64/pkg/tool/linu--show-toplevel git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha --show-toplevel ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet /usr/bin/git FieldEnforcementgit 7946378/b074/vetrev-parse e/git git rev-�� --show-toplevel e/git /usr/bin/git mplied /tmp/go-build107rev-parse 1/x64/bin/node git (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v8
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha -json GO111MODULE x_amd64/asm GOINSECURE GOMOD GOMODCACHE x_amd64/asm env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha go1.25.8 -c=4 -nolocalimports -importcfg /tmp/go-build1077946378/b431/importcfg -pack /tmp/go-build1077946378/b431/_testmain.go env -json GO111MODULE x_amd64/vet GOINSECURE mcpgodebug GOMODCACHE x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha -json ag.go x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet (http block)
  • https://api.github.com/repos/actions/setup-go/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha user.name epo}/actions/runs/3/artifacts /usr/bin/git e GO111MODULE x_amd64/vet git rev-�� --git-dir x_amd64/vet /usr/bin/git g_.a pMTTxllzq 64/pkg/tool/linu--show-toplevel git (http block)
  • https://api.github.com/repos/actions/setup-node/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha -u epo}/actions/runs/2/artifacts /usr/bin/git e elect.go x_amd64/vet git conf�� user.name Test User /usr/bin/git g_.a GO111MODULE x_amd64/compile git (http block)
  • https://api.github.com/repos/actions/upload-artifact/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq .object.sha -bool -buildtags 7946378/b440/styles.test -errorsas -ifaceassert -nilfunc 7946378/b440/styles.test e=/t�� t0 git-upload-pack '/tmp/TestParseDefaultBranchFromLsRemoteWithRealGitmain_branch2966922897/001' (http block)
  • https://api.github.com/repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b
    • Triggering command: /usr/bin/gh gh api /repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b --jq .object.sha (http block)
  • https://api.github.com/repos/github/gh-aw
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw --jq .visibility --get-regexp --local repository(owne-f (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v0.1.2
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v0.1.2 --jq .object.sha -b resolved$ /usr/bin/git go1.25.8 -c=4 -nolocalimports git rev-�� --show-toplevel /tmp/go-build1077946378/b446/_testmain.go /usr/bin/git g_.a GO111MODULE x_amd64/compile git (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.0.0 --jq .object.sha -bool -buildtags /usr/lib/git-core/git -errorsas -ifaceassert -nilfunc /usr/lib/git-core/git --gi�� for-each-ref --format=%(objectname) /usr/bin/git -json /unsafebytes/unsrev-parse x_amd64/asm git (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.2.3
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.2.3 --jq .object.sha -bool -buildtags 1/x64/bin/node -errorsas -ifaceassert -nilfunc 1/x64/bin/node unpa�� --pack_header=2,3 -q /usr/bin/git -json GO111MODULE x_amd64/compile git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/1/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/1/artifacts --jq .artifacts[].name .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE fips140/subtle GOMODCACHE 64/pkg/tool/linux_amd64/vet env 8443290/b173/_pkg_.a .cfg x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh run download 1 --dir test-logs/run-1 .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE fips140deps/godeconfig GOMODCACHE 64/pkg/tool/linutest@example.com env 8443290/b211/_pkg_.a V4ci/NWzImF-917Hk3aRqV4ci 64/pkg/tool/linux_amd64/link GOINSECURE l/ascii GOMODCACHE 64/pkg/tool/linux_amd64/link (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/1/artifacts --jq .artifacts[].name GO111MODULE 1/x64/bin/node GOINSECURE GOMOD GOMODCACHE go 1/x6�� y_with_repos_array_c2260290392/001 GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/12345/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12345/artifacts --jq .artifacts[].name .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env 8443290/b163/_pkg_.a 38wk/F3_s36TZU8RlNGu_38wk x_amd64/link GOINSECURE g/x/crypto/cryptconfig GOMODCACHE x_amd64/link (http block)
    • Triggering command: /usr/bin/gh gh run download 12345 --dir test-logs/run-12345 .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE 8443290/b011/ GOMODCACHE 64/pkg/tool/linux_amd64/vet env 8443290/b154/_pkg_.a .cfg stants.test GOINSECURE fips140/ecdh ache/go/1.25.8/xadd stants.test (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12345/artifacts --jq .artifacts[].name GO111MODULE tions/setup/js/node_modules/.bin/node GOINSECURE GOMOD GOMODCACHE go 1/x6�� -json GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/12346/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12346/artifacts --jq .artifacts[].name .cfg x_amd64/link GOINSECURE g/x/crypto/interrev-parse GOMODCACHE x_amd64/link env 8443290/b167/_pkg_.a vMoO/r1c5PlYHcFDLvhFNvMoO 64/pkg/tool/linux_amd64/compile GOINSECURE fips140/ed25519 GOMODCACHE OG/9Aq1qxlSUU6ukhG-tg7q/lPc9iaf6mWeQdRYXmAgk (http block)
    • Triggering command: /usr/bin/gh gh run download 12346 --dir test-logs/run-12346 .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE 8443290/b011/ GOMODCACHE 64/pkg/tool/linutest@example.com env 8443290/b176/_pkg_.a GO111MODULE x_amd64/vet GOINSECURE light ache/go/1.25.8/x64/src/runtime/i/tmp/TestHashConsistency_GoAndJavaScript1994499885/001/test-inlined-imports-enabled-with-env-template-expressions-in-body.md x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12346/artifacts --jq .artifacts[].name GO111MODULE 1/x64/bin/npx GOINSECURE GOMOD GOMODCACHE go env 11/001/test-inlined-imports-enabled-with-env-template-expressions-in-body.md GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/2/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/2/artifacts --jq .artifacts[].name .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linuTest User env 8443290/b181/_pkg_.a GO111MODULE 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh run download 2 --dir test-logs/run-2 GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/2/artifacts --jq .artifacts[].name GO111MODULE tions/setup/node_modules/.bin/sh GOINSECURE GOMOD GOMODCACHE go env */*.ts' '**/*.json' --ignore-patremote.origin.url GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/3/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/3/artifacts --jq .artifacts[].name .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env 3076427272 llzq/kleu3xr21GcpMTTxllzq ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/xremote.origin.url (http block)
    • Triggering command: /usr/bin/gh gh run download 3 --dir test-logs/run-3 GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/3/artifacts --jq .artifacts[].name GO111MODULE tions/setup/js/node_modules/.bin/sh GOINSECURE GOMOD GOMODCACHE go env y_with_repos_array_c2260290392/001 GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/4/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/4/artifacts --jq .artifacts[].name .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE lite GOMODCACHE 64/pkg/tool/linutest@example.com env y.md GO111MODULE ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet GOINSECURE fips140/hkdf 8443290/b006/sym--get ache/go/1.25.8/xremote.origin.url (http block)
    • Triggering command: /usr/bin/gh gh run download 4 --dir test-logs/run-4 GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env 8443290/b215/_pkg_.a GO111MODULE eutil.test GOINSECURE ntio/asm/base64 GOMODCACHE eutil.test (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/4/artifacts --jq .artifacts[].name mLsRemoteWithRealGitcustom_branch29058349/001' tions/setup/js/node_modules/.bin/sh GOINSECURE GOMOD GOMODCACHE go env y_with_repos_array_c2260290392/001 GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/5/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/5/artifacts --jq .artifacts[].name GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env 3076427272 ijPK/XGaGIDA5hxg1y3cTijPK x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh run download 5 --dir test-logs/run-5 GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linuTest User env 8443290/b210/_pkg_.a d2UJ/DbmGN00V4XBV3gqgd2UJ 64/pkg/tool/linux_amd64/compile GOINSECURE l GOMODCACHE 64/pkg/tool/linux_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/5/artifacts --jq .artifacts[].name GO111MODULE tions/node_modules/.bin/sh GOINSECURE GOMOD GOMODCACHE go env ithout_min-integrity2874921664/001 GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/workflows
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path 66922897/001' 66922897/001' x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 100 GOMOD GOMODCACHE x_amd64/vet sm_w�� nts.s emclr_wasm.s x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 6 /maps GOMODCACHE 64/pkg/tool/linux_amd64/vet env 8443290/b103/_pkg_.a .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linuTest User (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v0.47.4
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v0.47.4 --jq .object.sha --show-toplevel 64/pkg/tool/linux_amd64/vet /usr/bin/git 8443290/b151/_pkgit I_fS/lEXOLD1Q0N_rev-parse x_amd64/vet git rev-�� --show-toplevel x_amd64/vet /usr/bin/git se 7946378/b020/vet-c ck git (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq .object.sha mpiledOutput819397868/001 .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE /go-yaml/ast 8443290/b047/sym--show-toplevel 64/pkg/tool/linux_amd64/vet env m_exec.js from: $(go env GOROOT)/lib/wasm/wasm_e--detach 8443290/b047/importcfg ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.2.3
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.2.3 --jq .object.sha -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.2.3 --jq .object.sha re GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go 2832�� -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v2.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha adata/main.go GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env 6922897/001 6922897/002/work-ifaceassert x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha re GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v3.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v3.0.0 --jq .object.sha -json GO111MODULE x_amd64/vet GOINSECURE xcontext GOMODCACHE x_amd64/vet env -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v3.0.0 --jq .object.sha re GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/githubnext/agentics/git/ref/tags/
    • Triggering command: /usr/bin/gh gh api /repos/githubnext/agentics/git/ref/tags/# --jq .object.sha (http block)
  • https://api.github.com/repos/nonexistent/action/git/ref/tags/v999.999.999
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq .object.sha mpiledOutput819397868/001 .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE /go-yaml/scannerrev-parse ache/go/1.25.8/x--show-toplevel 64/pkg/tool/linux_amd64/vet env RxJB/qfqEIUSRa-L-U7HTRxJB GO111MODULE ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linurev-parse (http block)
  • https://api.github.com/repos/nonexistent/repo/actions/runs/12345
    • Triggering command: /usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env 8443290/b207/_pkg_.a oYmy/n_pwg_VDfKQLamLkoYmy ck GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linu/tmp/go-build1077946378/b113/vet.cfg (http block)
    • Triggering command: /usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion GOINSECURE GOMOD GOMODCACHE go tion�� b/workflows GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet (http block)
  • https://api.github.com/repos/owner/repo/actions/workflows
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json gset/set.go x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo -nolocalimports -importcfg /tmp/go-build1077946378/b414/importcfg -pack /tmp/go-build1077946378/b414/_testmain.go env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo 64/bin/go GOINSECURE GOMOD GOMODCACHE go env ath ../../../.pr**/*.json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/owner/repo/contents/file.md
    • Triggering command: /tmp/go-build1077946378/b396/cli.test /tmp/go-build1077946378/b396/cli.test -test.testlogfile=/tmp/go-build1077946378/b396/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /tmp/go-build651331285/b396/cli.test /tmp/go-build651331285/b396/cli.test -test.testlogfile=/tmp/go-build651331285/b396/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true --show-toplevel git /usr/bin/git go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/test-owner/test-repo/actions/secrets
    • Triggering command: /usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name go1.25.8 -c=4 -nolocalimports -importcfg /tmp/go-build1077946378/b396/importcfg -pack /tmp/go-build1077946378/b396/_testmain.go env -json 2/compile.go x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name --write ../../../**/*.jsGOMOD 64/bin/go --ignore-path ../../../.pretti-c /usr/bin/git go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI and others added 2 commits April 4, 2026 04:00
)

- Add upload-asset safe-output and shared/charts-with-trending.md import
- Add Phase 1.5: persist daily aggregated totals and per-workflow breakdown to cache-memory
- Add Phase 3.5: generate top-consumers bar chart, daily trend line, and workflow heatmap
- Update issue body structure to embed chart images
- Recompile copilot-token-usage-analyzer.lock.yml"

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/df0735fe-5064-4d93-8fc3-68b5b7125447

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Add snazzy Python trending charts to Copilot Token Usage Analyzer feat: add Python trending charts to Copilot Token Usage Analyzer Apr 4, 2026
Copilot AI requested a review from pelikhan April 4, 2026 04:05
@pelikhan pelikhan marked this pull request as ready for review April 4, 2026 04:06
Copilot AI review requested due to automatic review settings April 4, 2026 04:06
@pelikhan pelikhan merged commit 4b16470 into main Apr 4, 2026
51 checks passed
@pelikhan pelikhan deleted the copilot/add-python-trending-charts branch April 4, 2026 04:06
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds persistent trending data collection and Python-generated charts to the Copilot Token Usage Analyzer report so each run can include historical visualizations.

Changes:

  • Enables upload-asset safe-output and imports shared chart/trending guidance.
  • Adds Phase 1.5 cache-memory persistence (history + per-workflow breakdown) and Phase 3.5 Python chart generation instructions.
  • Updates the locked workflow to provision Python + scientific libs, persist cache-memory between runs, and publish uploaded assets.
Show a summary per file
File Description
.github/workflows/copilot-token-usage-analyzer.md Adds cache-memory persistence + Python chart generation and embeds chart URLs into the report template.
.github/workflows/copilot-token-usage-analyzer.lock.yml Wires in upload_asset support, Python setup, cache-memory restore/save, and asset publishing jobs/permissions.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comments suppressed due to low confidence (1)

.github/workflows/copilot-token-usage-analyzer.md:263

  • The daily trend chart uses drop_duplicates('date'), which will silently discard additional runs on the same date. Since history.jsonl is appended to, this can under/over-report tokens/runs depending on which duplicate survives. Prefer grouping by date and summing (or otherwise aggregating) totals before plotting so multiple same-day entries are handled correctly.
if len(hist_rows) >= 2:
    df_hist = pd.DataFrame(hist_rows)
    df_hist['date'] = pd.to_datetime(df_hist['date'])
    df_hist = df_hist.sort_values('date').drop_duplicates('date')

  • Files reviewed: 2/2 changed files
  • Comments generated: 5

Comment on lines +149 to +158

# Append daily aggregated totals (one JSON object per line)
cat >> /tmp/gh-aw/cache-memory/trending/token-usage/history.jsonl << EOF
{"date":"${TODAY}","total_tokens":TOTAL_TOKENS,"total_runs":TOTAL_RUNS,"total_cost":TOTAL_COST,"total_turns":TOTAL_TURNS}
EOF

# Append per-workflow breakdown for heatmap (one entry per workflow — repeat for each workflow):
cat >> /tmp/gh-aw/cache-memory/trending/token-usage/workflows.jsonl << EOF
{"date":"${TODAY}","workflow":"WORKFLOW_NAME","tokens":TOKENS,"runs":RUNS,"cost":COST}
EOF
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

Phase 1.5 appends a new entry to history.jsonl on every run, but the charting script later only de-dupes by date (and does not aggregate). If the analyzer runs more than once per UTC day, this will create multiple same-day rows and make the daily trend inaccurate. Consider making this an upsert per date (rewrite the file with that date replaced) or aggregating before writing so history.jsonl has exactly one row per date.

This issue also appears on line 259 of the same file.

Suggested change
# Append daily aggregated totals (one JSON object per line)
cat >> /tmp/gh-aw/cache-memory/trending/token-usage/history.jsonl << EOF
{"date":"${TODAY}","total_tokens":TOTAL_TOKENS,"total_runs":TOTAL_RUNS,"total_cost":TOTAL_COST,"total_turns":TOTAL_TURNS}
EOF
# Append per-workflow breakdown for heatmap (one entry per workflow — repeat for each workflow):
cat >> /tmp/gh-aw/cache-memory/trending/token-usage/workflows.jsonl << EOF
{"date":"${TODAY}","workflow":"WORKFLOW_NAME","tokens":TOKENS,"runs":RUNS,"cost":COST}
EOF
HISTORY_FILE=/tmp/gh-aw/cache-memory/trending/token-usage/history.jsonl
WORKFLOWS_FILE=/tmp/gh-aw/cache-memory/trending/token-usage/workflows.jsonl
touch "${HISTORY_FILE}" "${WORKFLOWS_FILE}"
# Upsert daily aggregated totals so history.jsonl contains exactly one row per UTC date
TMP_HISTORY=$(mktemp)
grep -v "^{\"date\":\"${TODAY}\"," "${HISTORY_FILE}" > "${TMP_HISTORY}" || true
cat >> "${TMP_HISTORY}" << EOF
{"date":"${TODAY}","total_tokens":TOTAL_TOKENS,"total_runs":TOTAL_RUNS,"total_cost":TOTAL_COST,"total_turns":TOTAL_TURNS}
EOF
mv "${TMP_HISTORY}" "${HISTORY_FILE}"
# Upsert per-workflow breakdown for heatmap (one entry per workflow per UTC date — repeat for each workflow)
TMP_WORKFLOWS=$(mktemp)
grep -v "^{\"date\":\"${TODAY}\",\"workflow\":\"WORKFLOW_NAME\"," "${WORKFLOWS_FILE}" > "${TMP_WORKFLOWS}" || true
cat >> "${TMP_WORKFLOWS}" << EOF
{"date":"${TODAY}","workflow":"WORKFLOW_NAME","tokens":TOKENS,"runs":RUNS,"cost":COST}
EOF
mv "${TMP_WORKFLOWS}" "${WORKFLOWS_FILE}"

Copilot uses AI. Check for mistakes.

### 📊 Token Usage Charts

#### 🔥 Top Consumers
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

This section always embeds TOP_CONSUMERS_URL, but the Python script explicitly skips generating top_consumers.png when there are no workflows for today. In that case, the upload step is skipped and the issue body will contain an unresolved placeholder / broken image. Either (a) make the Top Consumers section conditional on TOP_CONSUMERS_URL being available (like the other charts) or (b) always generate a placeholder chart even when there is no data.

Suggested change
#### 🔥 Top Consumers
#### 🔥 Top Consumers
_(Include this section only when TOP_CONSUMERS_URL is available — omit it when the top consumers chart is not generated for the day)_

Copilot uses AI. Check for mistakes.
Comment on lines +329 to +346
- if: always()
name: Upload charts
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
if-no-files-found: warn
name: data-charts
path: /tmp/gh-aw/python/charts/*.png
retention-days: 30
- if: always()
name: Upload source files and data
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
if-no-files-found: warn
name: python-source-and-data
path: |
/tmp/gh-aw/python/*.py
/tmp/gh-aw/python/data/*
retention-days: 30
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

The 'Upload charts' and 'Upload source files and data' artifact steps run before the Copilot agent executes the Python script and writes any charts/scripts into /tmp/gh-aw/python. As a result, these uploads will consistently warn/no-op and won't capture the generated outputs. Move these artifact upload steps to after the agent step (or after safe-outputs assets are produced) so they actually publish the generated charts/source for debugging.

Suggested change
- if: always()
name: Upload charts
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
if-no-files-found: warn
name: data-charts
path: /tmp/gh-aw/python/charts/*.png
retention-days: 30
- if: always()
name: Upload source files and data
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
if-no-files-found: warn
name: python-source-and-data
path: |
/tmp/gh-aw/python/*.py
/tmp/gh-aw/python/data/*
retention-days: 30

Copilot uses AI. Check for mistakes.
runs-on: ubuntu-slim
permissions:
contents: read
contents: write
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

These jobs were changed to contents: write, but in this workflow their responsibilities appear limited to processing safe-outputs and creating/reporting issues (asset publishing is handled by the separate upload_assets job). Consider reverting to contents: read where possible to follow least-privilege, unless a write is required by a specific safe-output type enabled here.

Suggested change
contents: write
contents: read

Copilot uses AI. Check for mistakes.
runs-on: ubuntu-slim
permissions:
contents: read
contents: write
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

safe_outputs now requests contents: write, but the configured safe-output tools here are create_issue and upload_asset (and the actual asset push is done in the dedicated upload_assets job). If no safe-output type in this workflow writes to the repo, consider downgrading this permission to contents: read to reduce repo write surface area.

Suggested change
contents: write
contents: read

Copilot uses AI. Check for mistakes.
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.

[q] feat: add snazzy Python trending charts to Copilot Token Usage Analyzer (#24352)

3 participants