"""Pull CF Analytics via GraphQL to see origin-status per CF PoP.""" import json, os, sys, urllib.request from datetime import datetime, timezone, timedelta ZONE = '1beb9917c22b54be32e5215df2c227ce' # CF API tokens live in 1Password (vault entry services/cloudflare.sops.yaml # currently holds metadata only). Provide via env vars before running. TOKENS = { 'full-dns': os.environ.get('CF_API_TOKEN_FULL_DNS', ''), 'legacy': os.environ.get('CF_API_TOKEN_LEGACY', ''), } since_30 = (datetime.now(timezone.utc) - timedelta(minutes=30)).strftime('%Y-%m-%dT%H:%M:%SZ') QUERY = ''' query($zone:String!, $since:Time!){ viewer { zones(filter:{zoneTag:$zone}){ httpRequestsAdaptiveGroups(limit:50, filter:{datetime_geq:$since}, orderBy:[count_DESC]){ count dimensions { coloCode edgeResponseStatus originResponseStatus clientRequestHTTPHost } } } } } ''' def gql(token, query, vars): req = urllib.request.Request( 'https://api.cloudflare.com/client/v4/graphql', data=json.dumps({'query': query, 'variables': vars}).encode(), headers={'Authorization': f'Bearer {token}', 'Content-Type': 'application/json'}, ) with urllib.request.urlopen(req, timeout=30) as r: return json.loads(r.read()) for name, tok in TOKENS.items(): print(f'\n===== Trying {name} token =====') try: r = gql(tok, QUERY, {'zone': ZONE, 'since': since_30}) if r.get('errors'): print('errors:', json.dumps(r['errors'], indent=2)[:600]) else: zones = r.get('data', {}).get('viewer', {}).get('zones', []) if not zones: print('no zones returned') continue groups = zones[0].get('httpRequestsAdaptiveGroups', []) print(f'{len(groups)} groups returned') print(f'{"count":>6} {"colo":5} {"edge":5} {"origin":6} host') for g in groups: d = g['dimensions'] print(f"{g['count']:>6} {d.get('coloCode','-'):5} " f"{str(d.get('edgeResponseStatus','-')):5} " f"{str(d.get('originResponseStatus','-')):6} " f"{d.get('clientRequestHTTPHost','-')}") except Exception as e: print(f'FAIL: {e}')