import datetime from typing import Dict from django.core.management.base import BaseCommand, CommandError from django.db import transaction from django.utils import timezone from domains.models import Domain, DomainTrafficDaily from core.goedge_client import GoEdgeClient class Command(BaseCommand): help = '从 GoEdge 读取各域名(serverId)的最近每日流量并写入 DomainTrafficDaily' def add_arguments(self, parser): parser.add_argument('--days', type=int, default=35, help='拉取最近N天数据(默认35)') parser.add_argument('--only-active', action='store_true', dest='only_active', default=False, help='仅拉取状态为active的域名') # 兼容文档中的别名参数 parser.add_argument('--active-only', action='store_true', dest='only_active', help='参数别名,等同 --only-active') @transaction.atomic def handle(self, *args, **options): days: int = options['days'] only_active: bool = options['only_active'] qs = Domain.objects.exclude(edge_server_id__isnull=True) if only_active: qs = qs.filter(status=Domain.STATUS_ACTIVE) domains = list(qs) if not domains: self.stdout.write(self.style.WARNING('没有可拉取的域名(缺少 edge_server_id)。')) return client = GoEdgeClient() total_written = 0 for d in domains: server_id = int(d.edge_server_id) try: stats = client.find_latest_server_daily_stats(server_id=server_id, days=days) except Exception as e: self.stderr.write(self.style.ERROR(f'[domain={d.name}] 拉取失败:{e}')) continue # 解析并入库 for s in stats: day_str = s.get('day') bytes_val = int(s.get('bytes') or 0) peak_mbps = float(s.get('peakBandwidthMbps') or 0.0) # 将 day 格式 YYYYMMDD 转为 date try: day_date = datetime.datetime.strptime(day_str, '%Y%m%d').date() except Exception: # 某些版本可能返回 YYYY-MM-DD try: day_date = datetime.datetime.strptime(day_str, '%Y-%m-%d').date() except Exception: self.stderr.write(self.style.WARNING(f'无法解析日期:{day_str}')) continue obj, created = DomainTrafficDaily.objects.update_or_create( domain=d, day=day_date, defaults={ 'bytes': bytes_val, 'peak_bandwidth_mbps': peak_mbps, } ) total_written += 1 self.stdout.write(self.style.SUCCESS(f'[domain={d.name}] 写入 {len(stats)} 条')) self.stdout.write(self.style.SUCCESS(f'完成,总写入记录:{total_written}'))