74 lines
3.0 KiB
Python
74 lines
3.0 KiB
Python
|
|
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}'))
|