When a site built on the Wikimedia pageviews API (wikimedia.org/api/rest_v1/metrics/pageviews/...) stops updating, the failure is usually upstream, and you can prove it in three curls before you touch the host.
Symptom
Static pages stop regenerating. Local logs show a clean, repeating error, e.g.:
E2026-08-16T06:15:15 - "fetch_traffic" - urllib.error.HTTPError('HTTP Error 404: Not Found')
S2026-08-16T06:15:15 - "get_wiki_info" - succeededNote get_wiki_info (MediaWiki action API) succeeds while fetch_traffic (AQS) 404s. Network and DNS are fine; only the analytics dataset is missing.
AQS returns a semantic 404 with a body that says so, not an error page:
{"detail":"The date(s) you used are valid, but we either do not have data for those date(s), or the project you asked for is not loaded yet","status":404}Three-step triage
- Bisect the last good date on AQS, from two different networks (your laptop and the server) so you don't blame egress:
for d in 2026/08/13 2026/08/14 2026/08/15; do
printf "%s -> " "$d"
curl -sS -o /dev/null -w "%{http_code}\n" \
"https://wikimedia.org/api/rest_v1/metrics/pageviews/top/en.wikipedia/all-access/$d"
doneCheck whether it's the
topendpoint or the whole dataset. Hitaggregateandper-articlefor the same dates, and a second project (de.wikipedia). If all of them stop on the same day, it's the dataset load, not an endpoint bug.Check the dumps, which reveal which stage of the Wikimedia pipeline died — this is the step people skip:
- Hourly:
https://dumps.wikimedia.org/other/pageviews/YYYY/YYYY-MM/ - Daily rollup:
https://dumps.wikimedia.org/other/pageview_complete/YYYY/YYYY-MM/
- Hourly:
curl -sS "https://dumps.wikimedia.org/other/pageview_complete/2026/2026-08/" \
| grep -oE 'pageviews-202608[0-9]{2}-user' | sort -u | tail -5Interpretation:
- hourly current, daily rollup behind -> the daily aggregation/AQS load job stalled.
- hourly also stopped -> the refinery/Airflow pipeline itself is down. AQS will stay 404 until it is restarted and backfilled.
The daily rollup and the AQS load are fed by the same stage, so pageview_complete's last date and AQS's last 200 normally match exactly. That correspondence is what upgrades "probably upstream" to "provably upstream".
Don't expect a status page
wikimediastatus.net covers reader-facing site availability, not the analytics pipeline; an AQS stall will not appear there. Search Phabricator instead: this recurs (e.g. T427171 "PageView tool not updated since 21 May 2026", T330184 "Missing Pageviews Data" where the dumps were missing and the API 404'd for the same day). Grep your own historical logs for the previous occurrence to date the last one.
The trap after upstream recovers
A common design is a nightly cron that launches one poller per language with a bounded poll window:
get_data.py --update --lang en --project wikipedia --poll 36h --poll-interval 15mwith the target date defaulting to date.today() at launch. Consequences:
- Pollers pile up. One batch per night that never succeeds. 28 languages x 2 nights = 56 stuck processes; at ~23 MB RSS each that is ~1.3 GB, enough to exhaust swap on a 4 GB box.
ps -eo pid,lstart,etime,args | grep get_dataand group bylstartto count batches. - Days silently fall off the end. A batch whose 36h window expires before upstream backfills is gone forever; the code just
breaks out of the poll loop. Only the days whose pollers are still alive recover on their own. - So after upstream returns, each expired day needs an explicit backfill run, and the backfill window is usually relative to today (
for day in range(N, 1, -1)= today-N .. today-2), not an absolute date.
Verify recovery, don't assume
Compare the newest generated day page on disk against the newest 200 from AQS:
find static/en/wikipedia/2026 -name '*.html' -newermt '2026-08-01' \
-printf '%T@ %p\n' | sort -rn | head -3If the newest day page equals the last date AQS serves, your pipeline is healthy and merely starved; there is nothing to fix locally.
While you're on the box
An app writing nginx logs to its own directory (/home/<user>/<app>/logs/access.log) is invisible to /etc/logrotate.d/nginx, which globs only /var/log/nginx/*.log. These grow without bound and are a frequent co-discovery when you ssh in to debug something else.