"""Single-field usage lookup against Apollo GraphOS.""" import argparse import json import os import sys import urllib.request from datetime import datetime, timedelta, timezone from src.config import DEFAULT_VARIANT, FIELD_USAGE_QUERY, GRAPH_ID, GRAPHOS_API def lookup_field(parent_type: str, field_name: str, months: int, graph_id: str) -> None: """Query GraphOS for usage of a single Type.field and print results.""" api_key = os.environ.get('APOLLO_KEY') if not api_key: print('Error: APOLLO_KEY environment variable not set', file=sys.stderr) sys.exit(1) since = datetime.now(timezone.utc) - timedelta(days=months * 30) since_str = since.strftime('%Y-%m-%dT00:00:00Z') query = FIELD_USAGE_QUERY % (graph_id, since_str, parent_type, field_name) payload = json.dumps({'query': query}).encode() req = urllib.request.Request( GRAPHOS_API, data=payload, headers={ 'Content-Type': 'application/json', 'x-api-key': api_key, }, ) with urllib.request.urlopen(req) as resp: data = json.loads(resp.read()) if 'errors' in data: for err in data['errors']: print(f'GraphQL error: {err["message"]}', file=sys.stderr) sys.exit(1) records = data['data']['service']['statsWindow']['fieldUsage'] if not records: print(f'\n {parent_type}.{field_name} — NO USAGE in the last {months} months\n') return total_executions = 0 total_operations = 0 by_query: dict[str, dict[str, int]] = {} for record in records: query_name = record['groupBy']['queryName'] or '(anonymous)' executions = record['metrics']['estimatedExecutionCount'] operations = record['metrics']['referencingOperationCount'] total_executions += executions total_operations += operations if query_name in by_query: by_query[query_name]['executions'] += executions by_query[query_name]['operations'] += operations else: by_query[query_name] = {'executions': executions, 'operations': operations} print(f'\n {parent_type}.{field_name} — last {months} months (since {since_str})') print(f' Total executions: {total_executions:,}') print(f' Total referencing operations: {total_operations:,}') print('\n Breakdown by operation:') print(f' {"Operation":<50} {"Executions":>15} {"Operations":>15}') print(f' {"─" * 80}') for name, counts in sorted(by_query.items(), key=lambda x: x[1]['executions'], reverse=True): print(f' {name:<50} {counts["executions"]:>15,} {counts["operations"]:>15,}') print() def main() -> None: parser = argparse.ArgumentParser(description='Check field usage in Apollo GraphOS') parser.add_argument('field', help='Type.fieldName (e.g. Query.product, Vendor.subaccountId)') parser.add_argument('--months', type=int, default=3, help='Lookback period in months (default: 3)') parser.add_argument('--graph-id', default=GRAPH_ID, help=f'Graph ID (default: {GRAPH_ID})') parser.add_argument('--variant', default=DEFAULT_VARIANT, help=f'Graph variant (default: {DEFAULT_VARIANT})') args = parser.parse_args() parts = args.field.split('.', 1) if len(parts) != 2: print(f"Error: expected Type.fieldName, got '{args.field}'", file=sys.stderr) sys.exit(1) parent_type, field_name = parts lookup_field(parent_type, field_name, args.months, args.graph_id) if __name__ == '__main__': main()