#!/usr/bin/env python3 """ AWS 统一账单数据分析工具 - 重构版本 功能: 1. 多维度异常检测 (账户级、服务级、标签级) 2. 基于历史数据的基线计算和阈值检测 3. 自动化飞书通知和告警 4. 支持不同环境的独立分析和汇总报告 5. 标签级别的成本监控和趋势分析 6. 支持合并环境报告或分别发送 用法示例: python -m aws.main_analyze --date 2025-08-24 # 分析指定日期的所有环境 python -m aws.main_analyze --config aws/config.json # 分析前天的所有环境数据 python -m aws.main_analyze --env nonprod --dry-run # 仅分析非生产环境不发送通知 python -m aws.main_analyze --env prod --account-id 730335266318 # 分析指定生产账户 """ import argparse import sys from datetime import datetime, timedelta from aws.src.analysis.analyzer import BillingAnalyzer def parse_args(): """解析命令行参数""" parser = argparse.ArgumentParser( description='AWS 账单异常分析工具', formatter_class=argparse.RawDescriptionHelpFormatter, epilog=__doc__ ) # 分析范围参数 parser.add_argument('--env', choices=['all', 'nonprod', 'prod', 'shared'], help='指定要分析的环境 (默认: all)') parser.add_argument('--account-id', action='append', dest='account_ids', help='指定要分析的账户ID (可以指定多个)') # 日期参数 parser.add_argument('--date', type=str, help='分析日期 (YYYY-MM-DD,默认: 前天)') # 配置文件 parser.add_argument('--config', type=str, help='配置文件路径 (默认: 自动查找)') # 执行控制参数 parser.add_argument('--dry-run', action='store_true', help='试运行模式,执行分析但不发送通知') parser.add_argument('--no-notifications', action='store_true', help='禁用所有通知发送') # 调试选项 parser.add_argument('--verbose', '-v', action='store_true', help='详细输出') parser.add_argument('--debug', action='store_true', help='调试模式') return parser.parse_args() def validate_args(args): """验证参数有效性""" errors = [] # 验证日期格式 if args.date: try: target_date = datetime.strptime(args.date, '%Y-%m-%d') # 检查日期不能是未来 if target_date.date() > datetime.now().date(): errors.append("分析日期不能是未来日期") # 检查日期不能太久远 days_ago = (datetime.now().date() - target_date.date()).days if days_ago > 90: errors.append("分析日期不能超过90天前") except ValueError: errors.append("日期格式错误,应为 YYYY-MM-DD") return errors def determine_target_date(date_str: str = None) -> datetime: """确定目标分析日期 Args: date_str: 日期字符串 Returns: 目标日期对象 """ if date_str: return datetime.strptime(date_str, '%Y-%m-%d') else: # 默认分析前天的数据(避免数据延迟问题) return datetime.now() - timedelta(days=2) def main(): """主函数""" args = parse_args() # 验证参数 errors = validate_args(args) if errors: print("参数错误:") for error in errors: print(f" - {error}") sys.exit(1) # 确定目标日期 target_date = determine_target_date(args.date) if args.dry_run: print("试运行模式 - 执行分析但不发送通知") if args.debug: print("调试模式已启用") try: # 初始化分析器 analyzer = BillingAnalyzer(config_path=args.config) # 确定要分析的环境 environments = [] if args.env == 'all' or args.env is None: environments = analyzer.env_manager.list_environments() else: environments = [args.env] # 执行分析 results = analyzer.analyze( environments=environments, target_date=target_date, account_ids=args.account_ids, dry_run=args.dry_run, send_notifications=not args.no_notifications and not args.dry_run ) # 检查分析结果 overall_summary = results.get('overall_summary', {}) total_anomalies = overall_summary.get('total_anomalies', 0) critical_anomalies = overall_summary.get('critical_anomalies', 0) # 设置退出代码 if critical_anomalies > 0: print(f"\n🚨 发现 {critical_anomalies} 个严重异常!") sys.exit(2) # 严重异常 elif total_anomalies > 0: print(f"\n⚠️ 发现 {total_anomalies} 个警告异常") sys.exit(1) # 警告异常 else: print("\n✅ 分析完成,未发现异常") sys.exit(0) # 正常 except KeyboardInterrupt: print("\n用户中断操作") sys.exit(130) except Exception as e: print(f"\n✗ 分析失败: {e}") if args.verbose or args.debug: import traceback traceback.print_exc() sys.exit(1) if __name__ == "__main__": main()