Python脚本如何全方位监控项目数据状态

wen python案例 31

本文目录导读:

Python脚本如何全方位监控项目数据状态

  1. 基础监控框架
  2. 系统资源监控
  3. 应用性能监控
  4. 数据库监控
  5. 文件和数据监控
  6. 数据完整性监控
  7. 告警系统
  8. 可视化仪表盘
  9. 配置模板
  10. 主程序入口
  11. 使用建议

我来提供一个全面的Python项目数据监控方案:

基础监控框架

核心监控类

import psutil
import json
import time
import logging
from datetime import datetime
from typing import Dict, Any, Optional
from pathlib import Path
import threading
class ProjectMonitor:
    """项目全方位监控器"""
    def __init__(self, config_path: str = "monitor_config.json"):
        self.config = self._load_config(config_path)
        self.logger = self._setup_logger()
        self.metrics = {}
        self.alerts = []
        self._running = False
    def _load_config(self, path: str) -> Dict:
        """加载监控配置"""
        with open(path, 'r') as f:
            return json.load(f)
    def _setup_logger(self) -> logging.Logger:
        """设置日志系统"""
        logger = logging.getLogger('ProjectMonitor')
        handler = logging.FileHandler('monitor.log')
        formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
        )
        handler.setFormatter(formatter)
        logger.addHandler(handler)
        return logger

系统资源监控

class SystemMonitor:
    """系统资源监控"""
    @staticmethod
    def get_cpu_info() -> Dict:
        """获取CPU信息"""
        return {
            'cpu_percent': psutil.cpu_percent(interval=1),
            'cpu_count': psutil.cpu_count(),
            'cpu_freq': psutil.cpu_freq()._asdict() if psutil.cpu_freq() else None,
            'load_avg': psutil.getloadavg()
        }
    @staticmethod
    def get_memory_info() -> Dict:
        """获取内存信息"""
        memory = psutil.virtual_memory()
        swap = psutil.swap_memory()
        return {
            'memory_total': memory.total,
            'memory_available': memory.available,
            'memory_percent': memory.percent,
            'swap_total': swap.total,
            'swap_percent': swap.percent
        }
    @staticmethod
    def get_disk_info() -> Dict:
        """获取磁盘信息"""
        disk_info = {}
        for partition in psutil.disk_partitions():
            try:
                usage = psutil.disk_usage(partition.mountpoint)
                disk_info[partition.mountpoint] = {
                    'total': usage.total,
                    'used': usage.used,
                    'free': usage.free,
                    'percent': usage.percent
                }
            except PermissionError:
                continue
        return disk_info
    @staticmethod
    def get_network_info() -> Dict:
        """获取网络信息"""
        net_io = psutil.net_io_counters()
        connections = psutil.net_connections()
        return {
            'bytes_sent': net_io.bytes_sent,
            'bytes_recv': net_io.bytes_recv,
            'packets_sent': net_io.packets_sent,
            'packets_recv': net_io.packets_recv,
            'active_connections': len(connections)
        }

应用性能监控

import time
from functools import wraps
from contextlib import contextmanager
class AppPerformanceMonitor:
    """应用性能监控"""
    def __init__(self):
        self.metrics = {
            'api_calls': {},
            'function_calls': {},
            'db_queries': []
        }
    @contextmanager
    def monitor_function(self, func_name: str):
        """监控函数执行时间"""
        start_time = time.time()
        try:
            yield
        finally:
            execution_time = time.time() - start_time
            if func_name not in self.metrics['function_calls']:
                self.metrics['function_calls'][func_name] = {
                    'count': 0,
                    'total_time': 0,
                    'avg_time': 0,
                    'max_time': 0,
                    'min_time': float('inf')
                }
            stats = self.metrics['function_calls'][func_name]
            stats['count'] += 1
            stats['total_time'] += execution_time
            stats['avg_time'] = stats['total_time'] / stats['count']
            stats['max_time'] = max(stats['max_time'], execution_time)
            stats['min_time'] = min(stats['min_time'], execution_time)
            # 记录慢查询
            if execution_time > 1.0:  # 超过1秒
                self._log_slow_query(func_name, execution_time)
    def _log_slow_query(self, func_name: str, execution_time: float):
        """记录慢查询"""
        self.metrics['db_queries'].append({
            'function': func_name,
            'execution_time': execution_time,
            'timestamp': time.time()
        })
# 装饰器版本
def monitor_performance(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        elapsed = time.time() - start
        # 记录到监控系统
        print(f"Function {func.__name__} took {elapsed:.2f}s")
        return result
    return wrapper

数据库监控

import sqlite3
from datetime import datetime, timedelta
import pandas as pd
class DatabaseMonitor:
    """数据库监控"""
    def __init__(self, db_path: str):
        self.db_path = db_path
        self.connection = sqlite3.connect(db_path)
    def monitor_query_performance(self, query: str) -> Dict:
        """监控查询性能"""
        cursor = self.connection.cursor()
        # 执行前
        start_time = time.time()
        cursor.execute(f"EXPLAIN QUERY PLAN {query}")
        query_plan = cursor.fetchall()
        # 执行查询
        cursor.execute(query)
        result = cursor.fetchall()
        # 执行后
        execution_time = time.time() - start_time
        return {
            'query': query,
            'execution_time': execution_time,
            'rows_affected': len(result),
            'query_plan': query_plan
        }
    def get_table_stats(self) -> Dict:
        """获取表统计信息"""
        cursor = self.connection.cursor()
        # 获取所有表
        cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")
        tables = cursor.fetchall()
        stats = {}
        for table in tables:
            table_name = table[0]
            # 获取行数
            cursor.execute(f"SELECT COUNT(*) FROM {table_name}")
            row_count = cursor.fetchone()[0]
            # 获取表大小
            cursor.execute(f"PRAGMA table_info({table_name})")
            columns = cursor.fetchall()
            stats[table_name] = {
                'row_count': row_count,
                'column_count': len(columns),
                'columns': [col[1] for col in columns]
            }
        return stats
    def monitor_connections(self) -> Dict:
        """监控数据库连接"""
        cursor = self.connection.cursor()
        cursor.execute("PRAGMA database_list")
        databases = cursor.fetchall()
        return {
            'active_connections': 1,  # SQLite单连接
            'database_backends': databases,
            'cache_size': self._get_cache_size(),
            'page_count': self._get_page_count()
        }
    def _get_cache_size(self) -> int:
        """获取缓存大小"""
        cursor = self.connection.cursor()
        cursor.execute("PRAGMA cache_size")
        return cursor.fetchone()[0]
    def _get_page_count(self) -> int:
        """获取页数"""
        cursor = self.connection.cursor()
        cursor.execute("PRAGMA page_count")
        return cursor.fetchone()[0]

文件和数据监控

import hashlib
import os
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class FileMonitor:
    """文件系统监控"""
    def __init__(self, watch_directory: str):
        self.watch_directory = watch_directory
        self.observer = Observer()
        self.file_stats = {}
    def start_monitoring(self):
        """开始监控文件变化"""
        event_handler = FileChangeHandler(self)
        self.observer.schedule(event_handler, self.watch_directory, recursive=True)
        self.observer.start()
    def stop_monitoring(self):
        """停止监控"""
        self.observer.stop()
        self.observer.join()
    def get_directory_stats(self) -> Dict:
        """获取目录统计信息"""
        stats = {
            'total_files': 0,
            'total_dirs': 0,
            'total_size': 0,
            'file_types': {}
        }
        for root, dirs, files in os.walk(self.watch_directory):
            stats['total_dirs'] += len(dirs)
            stats['total_files'] += len(files)
            for file in files:
                file_path = os.path.join(root, file)
                try:
                    file_size = os.path.getsize(file_path)
                    stats['total_size'] += file_size
                    # 统计文件类型
                    ext = os.path.splitext(file)[1]
                    if ext not in stats['file_types']:
                        stats['file_types'][ext] = {
                            'count': 0,
                            'total_size': 0
                        }
                    stats['file_types'][ext]['count'] += 1
                    stats['file_types'][ext]['total_size'] += file_size
                except OSError:
                    continue
        return stats
class FileChangeHandler(FileSystemEventHandler):
    """文件变化处理器"""
    def __init__(self, monitor):
        self.monitor = monitor
    def on_modified(self, event):
        if not event.is_directory:
            print(f"File modified: {event.src_path}")
            # 计算文件哈希值
            file_hash = self._calculate_hash(event.src_path)
            self.monitor.file_stats[event.src_path] = {
                'last_modified': datetime.now(),
                'hash': file_hash
            }
    def _calculate_hash(self, file_path: str) -> str:
        """计算文件哈希值"""
        hasher = hashlib.md5()
        with open(file_path, 'rb') as f:
            buf = f.read()
            hasher.update(buf)
        return hasher.hexdigest()

数据完整性监控

class DataIntegrityMonitor:
    """数据完整性监控"""
    def __init__(self, data_source):
        self.data_source = data_source
    def check_data_quality(self) -> Dict:
        """检查数据质量"""
        issues = []
        # 检查空值
        null_values = self._check_null_values()
        if null_values:
            issues.append({
                'type': 'null_values',
                'details': null_values
            })
        # 检查重复值
        duplicates = self._check_duplicates()
        if duplicates:
            issues.append({
                'type': 'duplicates',
                'details': duplicates
            })
        # 检查数据范围
        range_issues = self._check_data_range()
        if range_issues:
            issues.append({
                'type': 'range_issues',
                'details': range_issues
            })
        return {
            'has_issues': len(issues) > 0,
            'issues': issues,
            'timestamp': datetime.now()
        }
    def _check_null_values(self) -> List:
        """检查空值"""
        # 实现具体的空值检查逻辑
        pass
    def _check_duplicates(self) -> List:
        """检查重复数据"""
        # 实现具体的重复数据检查逻辑
        pass
    def _check_data_range(self) -> List:
        """检查数据范围"""
        # 实现具体的数据范围检查逻辑
        pass

告警系统

class AlertSystem:
    """告警系统"""
    def __init__(self, config: Dict):
        self.config = config
        self.alert_handlers = []
        self._setup_alert_handlers()
    def _setup_alert_handlers(self):
        """设置告警处理器"""
        if self.config.get('email'):
            self.alert_handlers.append(EmailAlertHandler(self.config['email']))
        if self.config.get('slack'):
            self.alert_handlers.append(SlackAlertHandler(self.config['slack']))
        if self.config.get('webhook'):
            self.alert_handlers.append(WebhookAlertHandler(self.config['webhook']))
    def send_alert(self, message: str, severity: str = 'info'):
        """发送告警"""
        alert = {
            'message': message,
            'severity': severity,
            'timestamp': datetime.now()
        }
        for handler in self.alert_handlers:
            try:
                handler.send(alert)
            except Exception as e:
                print(f"Failed to send alert: {e}")
class EmailAlertHandler:
    """邮件告警处理器"""
    def __init__(self, config: Dict):
        self.smtp_server = config['smtp_server']
        self.smtp_port = config['smtp_port']
        self.username = config['username']
        self.password = config['password']
        self.recipients = config['recipients']
    def send(self, alert: Dict):
        """发送邮件告警"""
        # 实现邮件发送逻辑
        pass
class SlackAlertHandler:
    """Slack告警处理器"""
    def __init__(self, config: Dict):
        self.webhook_url = config['webhook_url']
        self.channel = config.get('channel', '#monitoring')
    def send(self, alert: Dict):
        """发送Slack告警"""
        # 实现Slack发送逻辑
        pass
class WebhookAlertHandler:
    """Webhook告警处理器"""
    def __init__(self, config: Dict):
        self.url = config['url']
        self.headers = config.get('headers', {})
    def send(self, alert: Dict):
        """发送Webhook告警"""
        # 实现Webhook发送逻辑
        pass

可视化仪表盘

import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime, timedelta
class MonitorDashboard:
    """监控仪表盘"""
    def __init__(self, monitor: ProjectMonitor):
        self.monitor = monitor
        self.history = []
    def generate_report(self, duration: timedelta = timedelta(hours=1)):
        """生成监控报告"""
        report = {
            'timestamp': datetime.now(),
            'duration': duration,
            'system': self._get_system_stats(),
            'application': self._get_app_stats(),
            'database': self._get_db_stats(),
            'alerts': self.monitor.alerts[-10:]  # 最近10条告警
        }
        return report
    def _get_system_stats(self) -> Dict:
        """获取系统统计信息"""
        return {
            'cpu': SystemMonitor.get_cpu_info(),
            'memory': SystemMonitor.get_memory_info(),
            'disk': SystemMonitor.get_disk_info(),
            'network': SystemMonitor.get_network_info()
        }
    def _get_app_stats(self) -> Dict:
        """获取应用统计信息"""
        if hasattr(self.monitor, 'performance_monitor'):
            return self.monitor.performance_monitor.metrics
        return {}
    def _get_db_stats(self) -> Dict:
        """获取数据库统计信息"""
        if hasattr(self.monitor, 'db_monitor'):
            return self.monitor.db_monitor.get_table_stats()
        return {}
    def plot_cpu_usage(self, history: List):
        """绘制CPU使用率图表"""
        timestamps = [h['timestamp'] for h in history]
        cpu_values = [h['system']['cpu']['cpu_percent'] for h in history]
        plt.figure(figsize=(10, 6))
        plt.plot(timestamps, cpu_values, label='CPU Usage')
        plt.xlabel('Time')
        plt.ylabel('CPU Usage (%)')
        plt.title('CPU Usage Over Time')
        plt.legend()
        plt.grid(True)
        plt.show()
    def plot_memory_usage(self, history: List):
        """绘制内存使用率图表"""
        timestamps = [h['timestamp'] for h in history]
        memory_values = [h['system']['memory']['memory_percent'] for h in history]
        plt.figure(figsize=(10, 6))
        plt.plot(timestamps, memory_values, label='Memory Usage', color='red')
        plt.xlabel('Time')
        plt.ylabel('Memory Usage (%)')
        plt.title('Memory Usage Over Time')
        plt.legend()
        plt.grid(True)
        plt.show()

配置模板

{
    "monitoring": {
        "interval": 60,
        "system_monitor": true,
        "app_monitor": true,
        "database_monitor": true,
        "file_monitor": true
    },
    "alerts": {
        "email": {
            "smtp_server": "smtp.gmail.com",
            "smtp_port": 587,
            "username": "your-email@gmail.com",
            "password": "your-password",
            "recipients": ["admin@example.com"]
        },
        "slack": {
            "webhook_url": "https://hooks.slack.com/services/xxx",
            "channel": "#monitoring"
        },
        "webhook": {
            "url": "http://your-webhook-url",
            "headers": {
                "Authorization": "Bearer your-token"
            }
        }
    },
    "thresholds": {
        "cpu_warning": 80,
        "cpu_critical": 90,
        "memory_warning": 85,
        "memory_critical": 95,
        "disk_warning": 85,
        "disk_critical": 95
    },
    "exclude_patterns": ["*.log", "*.tmp", "__pycache__"]
}

主程序入口

def main():
    """主程序入口"""
    # 加载配置
    config = load_config('monitor_config.json')
    # 创建监控器
    monitor = ProjectMonitor()
    # 创建告警系统
    alert_system = AlertSystem(config.get('alerts', {}))
    # 创建仪表盘
    dashboard = MonitorDashboard(monitor)
    # 启动监控循环
    while True:
        try:
            # 收集指标
            metrics = monitor.collect_metrics()
            # 检查阈值
            check_thresholds(metrics, config['thresholds'], alert_system)
            # 生成报告
            if time.time() % 3600 == 0:  # 每小时生成报告
                report = dashboard.generate_report()
                save_report(report)
            # 等待下一次采集
            time.sleep(config['monitoring']['interval'])
        except KeyboardInterrupt:
            print("Monitoring stopped by user")
            break
        except Exception as e:
            print(f"Error in monitoring loop: {e}")
            time.sleep(10)
if __name__ == "__main__":
    main()

使用建议

  1. 逐步部署:从基础监控开始,逐步添加更多监控维度
  2. 设置合理阈值:根据项目特点设置告警阈值
  3. 定期审查:定期检查监控日志和报告
  4. 持续优化:根据实际需求调整监控策略
  5. 备份配置:定期备份监控配置文件

这个方案提供了全方位的监控能力,可以根据实际需求选择使用其中的部分或全部功能。

抱歉,评论功能暂时关闭!