mirror of
https://github.com/m1ngsama/tracker.git
synced 2025-12-24 10:51:43 +00:00
Release v1.0.0: Complete system monitoring solution
Major improvements and features: - Integrate all monitoring modules (config, alert, logger, temperature) - Add comprehensive error handling throughout codebase - Fix data exporter directory creation issue - Improve process monitor CPU accuracy with proper intervals - Fix logger file handle management New features: - Alert system with configurable thresholds - Automatic logging to daily log files - Data export to JSON/CSV formats - Configuration management via config.json - Temperature monitoring support CI/CD: - Add GitHub Actions workflows for automated testing - Add release workflow for automatic package building - Multi-platform testing (Linux, macOS, Windows) - Python 3.8-3.12 compatibility testing Package distribution: - Add setup.py and pyproject.toml for PyPI distribution - Add MANIFEST.in for proper file inclusion - Add comprehensive CHANGELOG.md - Update README with full documentation Bug fixes: - Fix ResourceWarning in logger - Add ZombieProcess exception handling - Improve error handling in all metric collection methods
This commit is contained in:
parent
af5388cc49
commit
5529c0d573
12 changed files with 541 additions and 70 deletions
61
.github/workflows/ci.yml
vendored
Normal file
61
.github/workflows/ci.yml
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
python test_tracker.py
|
||||
|
||||
- name: Test basic execution
|
||||
run: |
|
||||
python tracker.py
|
||||
timeout-minutes: 1
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Install linting tools
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install flake8 pylint
|
||||
|
||||
- name: Lint with flake8
|
||||
run: |
|
||||
# Stop build if there are Python syntax errors or undefined names
|
||||
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||
# Exit-zero treats all errors as warnings
|
||||
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
|
||||
continue-on-error: true
|
||||
47
.github/workflows/release.yml
vendored
Normal file
47
.github/workflows/release.yml
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*.*.*'
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install build twine
|
||||
|
||||
- name: Build package
|
||||
run: |
|
||||
python -m build
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
files: |
|
||||
dist/*
|
||||
generate_release_notes: true
|
||||
draft: false
|
||||
prerelease: false
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Publish to PyPI
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
env:
|
||||
TWINE_USERNAME: __token__
|
||||
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
||||
run: |
|
||||
twine upload dist/* --skip-existing
|
||||
continue-on-error: true
|
||||
62
CHANGELOG.md
Normal file
62
CHANGELOG.md
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.0.0] - 2025-11-25
|
||||
|
||||
### Added
|
||||
- Initial release of System Tracker
|
||||
- Real-time CPU usage monitoring
|
||||
- Memory utilization tracking with detailed statistics
|
||||
- Disk I/O statistics and usage monitoring
|
||||
- Network traffic analysis (bytes sent/received, packets)
|
||||
- Process monitoring with top processes by CPU usage
|
||||
- Temperature sensor monitoring (platform-dependent)
|
||||
- Configurable alert system with thresholds for CPU, memory, and disk
|
||||
- Comprehensive logging system with daily log files
|
||||
- Data export functionality (JSON and CSV formats)
|
||||
- Configuration management via `config.json`
|
||||
- Continuous monitoring mode with customizable intervals
|
||||
- CLI arguments support for flexible operation
|
||||
- Cross-platform support (Linux, macOS, Windows)
|
||||
|
||||
### Features
|
||||
- **Configuration System**: JSON-based configuration with sensible defaults
|
||||
- **Alert System**: Real-time alerts when system metrics exceed configured thresholds
|
||||
- **Logging**: Automatic daily log file creation in `logs/` directory
|
||||
- **Data Export**: Export monitoring data to `exports/` directory
|
||||
- **Process Monitor**: Enhanced CPU usage tracking with accurate process information
|
||||
- **Temperature Monitoring**: System temperature sensors (when available)
|
||||
- **Error Handling**: Comprehensive error handling throughout the codebase
|
||||
- **Modular Architecture**: Clean separation of concerns with dedicated modules
|
||||
|
||||
### Technical Improvements
|
||||
- Fixed data exporter directory creation issue
|
||||
- Improved process monitor CPU data accuracy with proper interval handling
|
||||
- Added error handling to all system metric collection methods
|
||||
- Resolved logger file handle management issues
|
||||
- Enhanced zombie process handling in process monitoring
|
||||
|
||||
### CI/CD
|
||||
- GitHub Actions workflow for automated testing across multiple OS and Python versions
|
||||
- Automated release workflow with package building
|
||||
- Code quality checks with flake8 linting
|
||||
- Multi-platform testing (Ubuntu, macOS, Windows)
|
||||
- Python 3.8-3.12 compatibility testing
|
||||
|
||||
### Documentation
|
||||
- Comprehensive README with installation and usage instructions
|
||||
- Configuration file documentation
|
||||
- MIT License
|
||||
- Project structure documentation
|
||||
- Contributing guidelines
|
||||
|
||||
### Dependencies
|
||||
- psutil >= 5.9.0
|
||||
- GPUtil >= 1.4.0
|
||||
- requests >= 2.28.0
|
||||
|
||||
[1.0.0]: https://github.com/m1ngsama/tracker/releases/tag/v1.0.0
|
||||
6
MANIFEST.in
Normal file
6
MANIFEST.in
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
include README.md
|
||||
include LICENSE
|
||||
include CHANGELOG.md
|
||||
include requirements.txt
|
||||
include config.json
|
||||
recursive-include tests *.py
|
||||
102
README.md
102
README.md
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
A comprehensive system monitoring tool for tracking various machine health metrics and performance indicators.
|
||||
|
||||
[](https://github.com/m1ngsama/tracker/actions/workflows/ci.yml)
|
||||
[](https://github.com/m1ngsama/tracker/actions/workflows/release.yml)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
|
||||
## Features
|
||||
|
||||
- **CPU Monitoring**: Real-time CPU usage percentage tracking
|
||||
|
|
@ -10,36 +14,124 @@ A comprehensive system monitoring tool for tracking various machine health metri
|
|||
- **Network Traffic Analysis**: Track network bytes sent/received
|
||||
- **Process Monitoring**: View top processes by CPU usage
|
||||
- **Temperature Sensors**: Monitor system temperatures (if available)
|
||||
- **System Uptime Tracking**: Track how long the system has been running
|
||||
- **Alert System**: Configurable thresholds for CPU, memory, and disk alerts
|
||||
- **Logging**: Automatic logging of all metrics to daily log files
|
||||
- **Data Export**: Export monitoring data to JSON or CSV formats
|
||||
- **Configuration**: Customizable settings via JSON config file
|
||||
|
||||
## Installation
|
||||
|
||||
### From PyPI (coming soon)
|
||||
|
||||
```bash
|
||||
pip install system-tracker
|
||||
```
|
||||
|
||||
### From Source
|
||||
|
||||
```bash
|
||||
git clone https://github.com/m1ngsama/tracker.git
|
||||
cd tracker
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Basic usage:
|
||||
### Basic usage:
|
||||
```bash
|
||||
python tracker.py
|
||||
```
|
||||
|
||||
Continuous monitoring mode:
|
||||
### Continuous monitoring mode:
|
||||
```bash
|
||||
python tracker.py --continuous --interval 5
|
||||
```
|
||||
|
||||
Command line options:
|
||||
### Command line options:
|
||||
- `-c, --continuous`: Run in continuous monitoring mode
|
||||
- `-i, --interval`: Set update interval in seconds (default: 5)
|
||||
|
||||
## Configuration
|
||||
|
||||
The `config.json` file allows you to customize the tracker behavior:
|
||||
|
||||
```json
|
||||
{
|
||||
"update_interval": 5,
|
||||
"display": {
|
||||
"show_cpu": true,
|
||||
"show_memory": true,
|
||||
"show_disk": true,
|
||||
"show_network": true,
|
||||
"show_processes": true,
|
||||
"show_temperatures": true
|
||||
},
|
||||
"process_limit": 5,
|
||||
"alert_thresholds": {
|
||||
"cpu_percent": 80,
|
||||
"memory_percent": 85,
|
||||
"disk_percent": 90
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
The tracker provides:
|
||||
- **Console Output**: Real-time metrics displayed in the terminal
|
||||
- **Log Files**: Daily logs stored in `logs/` directory
|
||||
- **Alerts**: Visual and logged warnings when thresholds are exceeded
|
||||
- **Export Data**: Optional data export to `exports/` directory
|
||||
|
||||
## Requirements
|
||||
|
||||
- Python 3.8+
|
||||
- psutil
|
||||
- GPUtil (for GPU monitoring)
|
||||
- requests
|
||||
|
||||
## Development
|
||||
|
||||
### Running Tests
|
||||
|
||||
```bash
|
||||
python test_tracker.py
|
||||
```
|
||||
|
||||
### Project Structure
|
||||
|
||||
```
|
||||
tracker/
|
||||
├── tracker.py # Main application
|
||||
├── process_monitor.py # Process monitoring module
|
||||
├── temperature_monitor.py # Temperature sensors module
|
||||
├── config_manager.py # Configuration management
|
||||
├── alert_system.py # Alert and threshold management
|
||||
├── logger.py # Logging functionality
|
||||
├── data_exporter.py # Data export utilities
|
||||
├── config.json # Configuration file
|
||||
└── requirements.txt # Python dependencies
|
||||
```
|
||||
|
||||
## CI/CD
|
||||
|
||||
This project uses GitHub Actions for:
|
||||
- **Continuous Integration**: Automated testing on multiple OS and Python versions
|
||||
- **Automated Releases**: Automatic package building and release creation on version tags
|
||||
- **Code Quality**: Linting and syntax checking
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! Please feel free to submit a Pull Request.
|
||||
|
||||
## License
|
||||
|
||||
MIT License
|
||||
MIT License - see [LICENSE](LICENSE) file for details
|
||||
|
||||
## Author
|
||||
|
||||
m1ngsama
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
- Built with [psutil](https://github.com/giampaolo/psutil) for cross-platform system monitoring
|
||||
|
|
|
|||
|
|
@ -10,6 +10,13 @@ from datetime import datetime
|
|||
class DataExporter:
|
||||
def __init__(self, output_dir='exports'):
|
||||
self.output_dir = output_dir
|
||||
self._ensure_directory()
|
||||
|
||||
def _ensure_directory(self):
|
||||
"""Ensure the output directory exists"""
|
||||
import os
|
||||
if not os.path.exists(self.output_dir):
|
||||
os.makedirs(self.output_dir)
|
||||
|
||||
def export_to_json(self, data, filename=None):
|
||||
"""Export data to JSON format"""
|
||||
|
|
@ -18,10 +25,12 @@ class DataExporter:
|
|||
|
||||
filepath = f"{self.output_dir}/{filename}"
|
||||
|
||||
with open(filepath, 'w') as f:
|
||||
json.dump(data, f, indent=2)
|
||||
|
||||
return filepath
|
||||
try:
|
||||
with open(filepath, 'w') as f:
|
||||
json.dump(data, f, indent=2)
|
||||
return filepath
|
||||
except IOError as e:
|
||||
raise IOError(f"Failed to export data to JSON: {e}")
|
||||
|
||||
def export_to_csv(self, data, filename=None):
|
||||
"""Export data to CSV format"""
|
||||
|
|
@ -30,11 +39,13 @@ class DataExporter:
|
|||
|
||||
filepath = f"{self.output_dir}/{filename}"
|
||||
|
||||
if isinstance(data, list) and len(data) > 0:
|
||||
keys = data[0].keys()
|
||||
with open(filepath, 'w', newline='') as f:
|
||||
writer = csv.DictWriter(f, fieldnames=keys)
|
||||
writer.writeheader()
|
||||
writer.writerows(data)
|
||||
|
||||
return filepath
|
||||
try:
|
||||
if isinstance(data, list) and len(data) > 0:
|
||||
keys = data[0].keys()
|
||||
with open(filepath, 'w', newline='') as f:
|
||||
writer = csv.DictWriter(f, fieldnames=keys)
|
||||
writer.writeheader()
|
||||
writer.writerows(data)
|
||||
return filepath
|
||||
except IOError as e:
|
||||
raise IOError(f"Failed to export data to CSV: {e}")
|
||||
|
|
|
|||
27
logger.py
27
logger.py
|
|
@ -22,16 +22,25 @@ class TrackerLogger:
|
|||
f"tracker_{datetime.now().strftime('%Y%m%d')}.log"
|
||||
)
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||
handlers=[
|
||||
logging.FileHandler(log_file),
|
||||
logging.StreamHandler()
|
||||
]
|
||||
)
|
||||
# Clear any existing handlers to prevent duplicate logging
|
||||
logger = logging.getLogger('SystemTracker')
|
||||
logger.handlers.clear()
|
||||
|
||||
self.logger = logging.getLogger('SystemTracker')
|
||||
# Create handlers
|
||||
file_handler = logging.FileHandler(log_file)
|
||||
stream_handler = logging.StreamHandler()
|
||||
|
||||
# Create formatter and add it to handlers
|
||||
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||
file_handler.setFormatter(formatter)
|
||||
stream_handler.setFormatter(formatter)
|
||||
|
||||
# Add handlers to logger
|
||||
logger.addHandler(file_handler)
|
||||
logger.addHandler(stream_handler)
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
self.logger = logger
|
||||
|
||||
def log_stats(self, stats_type, stats_data):
|
||||
"""Log system statistics"""
|
||||
|
|
|
|||
|
|
@ -9,10 +9,19 @@ class ProcessMonitor:
|
|||
def get_top_processes(self, limit=5):
|
||||
"""Get top processes by CPU usage"""
|
||||
processes = []
|
||||
for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent']):
|
||||
# First collect all processes
|
||||
for proc in psutil.process_iter(['pid', 'name']):
|
||||
try:
|
||||
processes.append(proc.info)
|
||||
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
||||
# Get CPU percent with interval for more accurate reading
|
||||
cpu_percent = proc.cpu_percent(interval=0.1)
|
||||
memory_percent = proc.memory_percent()
|
||||
processes.append({
|
||||
'pid': proc.info['pid'],
|
||||
'name': proc.info['name'],
|
||||
'cpu_percent': cpu_percent,
|
||||
'memory_percent': memory_percent
|
||||
})
|
||||
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
||||
pass
|
||||
|
||||
processes.sort(key=lambda x: x['cpu_percent'] or 0, reverse=True)
|
||||
|
|
@ -20,17 +29,23 @@ class ProcessMonitor:
|
|||
|
||||
def get_process_count(self):
|
||||
"""Get total number of running processes"""
|
||||
return len(psutil.pids())
|
||||
try:
|
||||
return len(psutil.pids())
|
||||
except Exception:
|
||||
return 0
|
||||
|
||||
def display_processes(self):
|
||||
"""Display top processes"""
|
||||
print(f"\nTop Processes by CPU Usage:")
|
||||
print(f"{'PID':<10}{'Name':<30}{'CPU%':<10}{'Memory%':<10}")
|
||||
print("-" * 60)
|
||||
try:
|
||||
print(f"\nTop Processes by CPU Usage:")
|
||||
print(f"{'PID':<10}{'Name':<30}{'CPU%':<10}{'Memory%':<10}")
|
||||
print("-" * 60)
|
||||
|
||||
for proc in self.get_top_processes():
|
||||
cpu = proc['cpu_percent'] if proc['cpu_percent'] is not None else 0
|
||||
mem = proc['memory_percent'] if proc['memory_percent'] is not None else 0
|
||||
print(f"{proc['pid']:<10}{proc['name']:<30}{cpu:<10.2f}{mem:<10.2f}")
|
||||
for proc in self.get_top_processes():
|
||||
cpu = proc['cpu_percent'] if proc['cpu_percent'] is not None else 0
|
||||
mem = proc['memory_percent'] if proc['memory_percent'] is not None else 0
|
||||
print(f"{proc['pid']:<10}{proc['name']:<30}{cpu:<10.2f}{mem:<10.2f}")
|
||||
|
||||
print(f"\nTotal Processes: {self.get_process_count()}")
|
||||
print(f"\nTotal Processes: {self.get_process_count()}")
|
||||
except Exception as e:
|
||||
print(f"Error displaying processes: {e}")
|
||||
|
|
|
|||
44
pyproject.toml
Normal file
44
pyproject.toml
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
[build-system]
|
||||
requires = ["setuptools>=45", "wheel", "setuptools_scm[toml]>=6.2"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "system-tracker"
|
||||
version = "1.0.0"
|
||||
description = "A comprehensive system monitoring tool for tracking machine health metrics"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.8"
|
||||
license = {text = "MIT"}
|
||||
authors = [
|
||||
{name = "m1ngsama"}
|
||||
]
|
||||
keywords = ["monitoring", "system", "performance", "metrics", "health-check"]
|
||||
classifiers = [
|
||||
"Development Status :: 4 - Beta",
|
||||
"Intended Audience :: Developers",
|
||||
"Intended Audience :: System Administrators",
|
||||
"Topic :: System :: Monitoring",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
]
|
||||
dependencies = [
|
||||
"psutil>=5.9.0",
|
||||
"GPUtil>=1.4.0",
|
||||
"requests>=2.28.0",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://github.com/m1ngsama/tracker"
|
||||
Repository = "https://github.com/m1ngsama/tracker"
|
||||
Issues = "https://github.com/m1ngsama/tracker/issues"
|
||||
|
||||
[project.scripts]
|
||||
tracker = "tracker:main"
|
||||
|
||||
[tool.setuptools]
|
||||
packages = ["tracker"]
|
||||
47
setup.py
Normal file
47
setup.py
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
from setuptools import setup, find_packages
|
||||
|
||||
with open("README.md", "r", encoding="utf-8") as fh:
|
||||
long_description = fh.read()
|
||||
|
||||
with open("requirements.txt", "r", encoding="utf-8") as fh:
|
||||
requirements = [line.strip() for line in fh if line.strip() and not line.startswith("#")]
|
||||
|
||||
setup(
|
||||
name="system-tracker",
|
||||
version="1.0.0",
|
||||
author="m1ngsama",
|
||||
author_email="",
|
||||
description="A comprehensive system monitoring tool for tracking machine health metrics",
|
||||
long_description=long_description,
|
||||
long_description_content_type="text/markdown",
|
||||
url="https://github.com/m1ngsama/tracker",
|
||||
packages=find_packages(),
|
||||
classifiers=[
|
||||
"Development Status :: 4 - Beta",
|
||||
"Intended Audience :: Developers",
|
||||
"Intended Audience :: System Administrators",
|
||||
"Topic :: System :: Monitoring",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Operating System :: OS Independent",
|
||||
"Operating System :: POSIX :: Linux",
|
||||
"Operating System :: MacOS",
|
||||
"Operating System :: Microsoft :: Windows",
|
||||
],
|
||||
python_requires=">=3.8",
|
||||
install_requires=requirements,
|
||||
entry_points={
|
||||
"console_scripts": [
|
||||
"tracker=tracker:main",
|
||||
],
|
||||
},
|
||||
include_package_data=True,
|
||||
package_data={
|
||||
"": ["config.json"],
|
||||
},
|
||||
)
|
||||
26
test_export.py
Normal file
26
test_export.py
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Test data export functionality"""
|
||||
|
||||
from data_exporter import DataExporter
|
||||
|
||||
# Test data
|
||||
test_data = [
|
||||
{'timestamp': '2025-11-25 15:00:00', 'cpu': 45.2, 'memory': 60.1},
|
||||
{'timestamp': '2025-11-25 15:05:00', 'cpu': 52.3, 'memory': 62.5},
|
||||
{'timestamp': '2025-11-25 15:10:00', 'cpu': 48.9, 'memory': 61.8}
|
||||
]
|
||||
|
||||
exporter = DataExporter()
|
||||
|
||||
# Test JSON export
|
||||
json_file = exporter.export_to_json(test_data)
|
||||
print(f"✓ JSON export successful: {json_file}")
|
||||
|
||||
# Test CSV export
|
||||
csv_file = exporter.export_to_csv(test_data)
|
||||
print(f"✓ CSV export successful: {csv_file}")
|
||||
|
||||
print("\nExport directory contents:")
|
||||
import os
|
||||
for file in os.listdir('exports'):
|
||||
print(f" - {file}")
|
||||
115
tracker.py
115
tracker.py
|
|
@ -8,46 +8,70 @@ import time
|
|||
import argparse
|
||||
from datetime import datetime
|
||||
from process_monitor import ProcessMonitor
|
||||
from temperature_monitor import TemperatureMonitor
|
||||
from config_manager import Config
|
||||
from alert_system import AlertSystem
|
||||
from logger import TrackerLogger
|
||||
|
||||
|
||||
class SystemTracker:
|
||||
def __init__(self):
|
||||
def __init__(self, config_file='config.json'):
|
||||
self.start_time = time.time()
|
||||
self.config = Config(config_file)
|
||||
self.process_monitor = ProcessMonitor()
|
||||
self.temperature_monitor = TemperatureMonitor()
|
||||
self.alert_system = AlertSystem(self.config)
|
||||
self.logger = TrackerLogger()
|
||||
|
||||
def get_cpu_usage(self):
|
||||
"""Get current CPU usage percentage"""
|
||||
return psutil.cpu_percent(interval=1, percpu=False)
|
||||
try:
|
||||
return psutil.cpu_percent(interval=1, percpu=False)
|
||||
except Exception as e:
|
||||
self.logger.log_error(f"Failed to get CPU usage: {e}")
|
||||
return 0.0
|
||||
|
||||
def get_memory_info(self):
|
||||
"""Get memory usage statistics"""
|
||||
mem = psutil.virtual_memory()
|
||||
return {
|
||||
'total': mem.total,
|
||||
'available': mem.available,
|
||||
'percent': mem.percent,
|
||||
'used': mem.used
|
||||
}
|
||||
try:
|
||||
mem = psutil.virtual_memory()
|
||||
return {
|
||||
'total': mem.total,
|
||||
'available': mem.available,
|
||||
'percent': mem.percent,
|
||||
'used': mem.used
|
||||
}
|
||||
except Exception as e:
|
||||
self.logger.log_error(f"Failed to get memory info: {e}")
|
||||
return {'total': 0, 'available': 0, 'percent': 0, 'used': 0}
|
||||
|
||||
def get_disk_usage(self):
|
||||
"""Get disk usage statistics"""
|
||||
disk = psutil.disk_usage('/')
|
||||
return {
|
||||
'total': disk.total,
|
||||
'used': disk.used,
|
||||
'free': disk.free,
|
||||
'percent': disk.percent
|
||||
}
|
||||
try:
|
||||
disk = psutil.disk_usage('/')
|
||||
return {
|
||||
'total': disk.total,
|
||||
'used': disk.used,
|
||||
'free': disk.free,
|
||||
'percent': disk.percent
|
||||
}
|
||||
except Exception as e:
|
||||
self.logger.log_error(f"Failed to get disk usage: {e}")
|
||||
return {'total': 0, 'used': 0, 'free': 0, 'percent': 0}
|
||||
|
||||
def get_network_stats(self):
|
||||
"""Get network I/O statistics"""
|
||||
net = psutil.net_io_counters()
|
||||
return {
|
||||
'bytes_sent': net.bytes_sent,
|
||||
'bytes_recv': net.bytes_recv,
|
||||
'packets_sent': net.packets_sent,
|
||||
'packets_recv': net.packets_recv
|
||||
}
|
||||
try:
|
||||
net = psutil.net_io_counters()
|
||||
return {
|
||||
'bytes_sent': net.bytes_sent,
|
||||
'bytes_recv': net.bytes_recv,
|
||||
'packets_sent': net.packets_sent,
|
||||
'packets_recv': net.packets_recv
|
||||
}
|
||||
except Exception as e:
|
||||
self.logger.log_error(f"Failed to get network stats: {e}")
|
||||
return {'bytes_sent': 0, 'bytes_recv': 0, 'packets_sent': 0, 'packets_recv': 0}
|
||||
|
||||
def display_stats(self):
|
||||
"""Display all system statistics"""
|
||||
|
|
@ -55,21 +79,44 @@ class SystemTracker:
|
|||
print(f"System Tracker - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
print(f"{'='*50}\n")
|
||||
|
||||
print(f"CPU Usage: {self.get_cpu_usage()}%")
|
||||
# CPU monitoring
|
||||
if self.config.get('display.show_cpu', True):
|
||||
cpu_usage = self.get_cpu_usage()
|
||||
print(f"CPU Usage: {cpu_usage}%")
|
||||
self.logger.log_stats('CPU', f"{cpu_usage}%")
|
||||
self.alert_system.check_cpu_alert(cpu_usage)
|
||||
|
||||
mem = self.get_memory_info()
|
||||
print(f"Memory: {mem['percent']}% ({mem['used'] / (1024**3):.2f}GB / {mem['total'] / (1024**3):.2f}GB)")
|
||||
# Memory monitoring
|
||||
if self.config.get('display.show_memory', True):
|
||||
mem = self.get_memory_info()
|
||||
print(f"Memory: {mem['percent']}% ({mem['used'] / (1024**3):.2f}GB / {mem['total'] / (1024**3):.2f}GB)")
|
||||
self.logger.log_stats('Memory', f"{mem['percent']}%")
|
||||
self.alert_system.check_memory_alert(mem['percent'])
|
||||
|
||||
disk = self.get_disk_usage()
|
||||
print(f"Disk: {disk['percent']}% ({disk['used'] / (1024**3):.2f}GB / {disk['total'] / (1024**3):.2f}GB)")
|
||||
# Disk monitoring
|
||||
if self.config.get('display.show_disk', True):
|
||||
disk = self.get_disk_usage()
|
||||
print(f"Disk: {disk['percent']}% ({disk['used'] / (1024**3):.2f}GB / {disk['total'] / (1024**3):.2f}GB)")
|
||||
self.logger.log_stats('Disk', f"{disk['percent']}%")
|
||||
self.alert_system.check_disk_alert(disk['percent'])
|
||||
|
||||
net = self.get_network_stats()
|
||||
print(f"Network: Sent {net['bytes_sent'] / (1024**2):.2f}MB | Recv {net['bytes_recv'] / (1024**2):.2f}MB")
|
||||
# Network monitoring
|
||||
if self.config.get('display.show_network', True):
|
||||
net = self.get_network_stats()
|
||||
print(f"Network: Sent {net['bytes_sent'] / (1024**2):.2f}MB | Recv {net['bytes_recv'] / (1024**2):.2f}MB")
|
||||
self.logger.log_stats('Network', f"Sent: {net['bytes_sent']} Recv: {net['bytes_recv']}")
|
||||
|
||||
self.process_monitor.display_processes()
|
||||
# Process monitoring
|
||||
if self.config.get('display.show_processes', True):
|
||||
self.process_monitor.display_processes()
|
||||
|
||||
# Temperature monitoring
|
||||
if self.config.get('display.show_temperatures', True):
|
||||
self.temperature_monitor.display_temperatures()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
def main():
|
||||
"""Main entry point for the tracker application"""
|
||||
parser = argparse.ArgumentParser(description='System Tracker - Monitor machine health')
|
||||
parser.add_argument('-c', '--continuous', action='store_true', help='Run continuously')
|
||||
parser.add_argument('-i', '--interval', type=int, default=5, help='Update interval in seconds')
|
||||
|
|
@ -86,3 +133,7 @@ if __name__ == "__main__":
|
|||
print("\n\nTracker stopped by user")
|
||||
else:
|
||||
tracker.display_stats()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
|||
Loading…
Reference in a new issue