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.
|
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
|
## Features
|
||||||
|
|
||||||
- **CPU Monitoring**: Real-time CPU usage percentage tracking
|
- **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
|
- **Network Traffic Analysis**: Track network bytes sent/received
|
||||||
- **Process Monitoring**: View top processes by CPU usage
|
- **Process Monitoring**: View top processes by CPU usage
|
||||||
- **Temperature Sensors**: Monitor system temperatures (if available)
|
- **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
|
## Installation
|
||||||
|
|
||||||
|
### From PyPI (coming soon)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
pip install system-tracker
|
||||||
|
```
|
||||||
|
|
||||||
|
### From Source
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/m1ngsama/tracker.git
|
||||||
|
cd tracker
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Basic usage:
|
### Basic usage:
|
||||||
```bash
|
```bash
|
||||||
python tracker.py
|
python tracker.py
|
||||||
```
|
```
|
||||||
|
|
||||||
Continuous monitoring mode:
|
### Continuous monitoring mode:
|
||||||
```bash
|
```bash
|
||||||
python tracker.py --continuous --interval 5
|
python tracker.py --continuous --interval 5
|
||||||
```
|
```
|
||||||
|
|
||||||
Command line options:
|
### Command line options:
|
||||||
- `-c, --continuous`: Run in continuous monitoring mode
|
- `-c, --continuous`: Run in continuous monitoring mode
|
||||||
- `-i, --interval`: Set update interval in seconds (default: 5)
|
- `-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
|
## Requirements
|
||||||
|
|
||||||
- Python 3.8+
|
- Python 3.8+
|
||||||
- psutil
|
- psutil
|
||||||
- GPUtil (for GPU monitoring)
|
- 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
|
## 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:
|
class DataExporter:
|
||||||
def __init__(self, output_dir='exports'):
|
def __init__(self, output_dir='exports'):
|
||||||
self.output_dir = output_dir
|
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):
|
def export_to_json(self, data, filename=None):
|
||||||
"""Export data to JSON format"""
|
"""Export data to JSON format"""
|
||||||
|
|
@ -18,10 +25,12 @@ class DataExporter:
|
||||||
|
|
||||||
filepath = f"{self.output_dir}/{filename}"
|
filepath = f"{self.output_dir}/{filename}"
|
||||||
|
|
||||||
with open(filepath, 'w') as f:
|
try:
|
||||||
json.dump(data, f, indent=2)
|
with open(filepath, 'w') as f:
|
||||||
|
json.dump(data, f, indent=2)
|
||||||
return filepath
|
return filepath
|
||||||
|
except IOError as e:
|
||||||
|
raise IOError(f"Failed to export data to JSON: {e}")
|
||||||
|
|
||||||
def export_to_csv(self, data, filename=None):
|
def export_to_csv(self, data, filename=None):
|
||||||
"""Export data to CSV format"""
|
"""Export data to CSV format"""
|
||||||
|
|
@ -30,11 +39,13 @@ class DataExporter:
|
||||||
|
|
||||||
filepath = f"{self.output_dir}/{filename}"
|
filepath = f"{self.output_dir}/{filename}"
|
||||||
|
|
||||||
if isinstance(data, list) and len(data) > 0:
|
try:
|
||||||
keys = data[0].keys()
|
if isinstance(data, list) and len(data) > 0:
|
||||||
with open(filepath, 'w', newline='') as f:
|
keys = data[0].keys()
|
||||||
writer = csv.DictWriter(f, fieldnames=keys)
|
with open(filepath, 'w', newline='') as f:
|
||||||
writer.writeheader()
|
writer = csv.DictWriter(f, fieldnames=keys)
|
||||||
writer.writerows(data)
|
writer.writeheader()
|
||||||
|
writer.writerows(data)
|
||||||
return filepath
|
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"
|
f"tracker_{datetime.now().strftime('%Y%m%d')}.log"
|
||||||
)
|
)
|
||||||
|
|
||||||
logging.basicConfig(
|
# Clear any existing handlers to prevent duplicate logging
|
||||||
level=logging.INFO,
|
logger = logging.getLogger('SystemTracker')
|
||||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
logger.handlers.clear()
|
||||||
handlers=[
|
|
||||||
logging.FileHandler(log_file),
|
|
||||||
logging.StreamHandler()
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
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):
|
def log_stats(self, stats_type, stats_data):
|
||||||
"""Log system statistics"""
|
"""Log system statistics"""
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,19 @@ class ProcessMonitor:
|
||||||
def get_top_processes(self, limit=5):
|
def get_top_processes(self, limit=5):
|
||||||
"""Get top processes by CPU usage"""
|
"""Get top processes by CPU usage"""
|
||||||
processes = []
|
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:
|
try:
|
||||||
processes.append(proc.info)
|
# Get CPU percent with interval for more accurate reading
|
||||||
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
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
|
pass
|
||||||
|
|
||||||
processes.sort(key=lambda x: x['cpu_percent'] or 0, reverse=True)
|
processes.sort(key=lambda x: x['cpu_percent'] or 0, reverse=True)
|
||||||
|
|
@ -20,17 +29,23 @@ class ProcessMonitor:
|
||||||
|
|
||||||
def get_process_count(self):
|
def get_process_count(self):
|
||||||
"""Get total number of running processes"""
|
"""Get total number of running processes"""
|
||||||
return len(psutil.pids())
|
try:
|
||||||
|
return len(psutil.pids())
|
||||||
|
except Exception:
|
||||||
|
return 0
|
||||||
|
|
||||||
def display_processes(self):
|
def display_processes(self):
|
||||||
"""Display top processes"""
|
"""Display top processes"""
|
||||||
print(f"\nTop Processes by CPU Usage:")
|
try:
|
||||||
print(f"{'PID':<10}{'Name':<30}{'CPU%':<10}{'Memory%':<10}")
|
print(f"\nTop Processes by CPU Usage:")
|
||||||
print("-" * 60)
|
print(f"{'PID':<10}{'Name':<30}{'CPU%':<10}{'Memory%':<10}")
|
||||||
|
print("-" * 60)
|
||||||
|
|
||||||
for proc in self.get_top_processes():
|
for proc in self.get_top_processes():
|
||||||
cpu = proc['cpu_percent'] if proc['cpu_percent'] is not None else 0
|
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
|
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"{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
|
import argparse
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from process_monitor import ProcessMonitor
|
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:
|
class SystemTracker:
|
||||||
def __init__(self):
|
def __init__(self, config_file='config.json'):
|
||||||
self.start_time = time.time()
|
self.start_time = time.time()
|
||||||
|
self.config = Config(config_file)
|
||||||
self.process_monitor = ProcessMonitor()
|
self.process_monitor = ProcessMonitor()
|
||||||
|
self.temperature_monitor = TemperatureMonitor()
|
||||||
|
self.alert_system = AlertSystem(self.config)
|
||||||
|
self.logger = TrackerLogger()
|
||||||
|
|
||||||
def get_cpu_usage(self):
|
def get_cpu_usage(self):
|
||||||
"""Get current CPU usage percentage"""
|
"""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):
|
def get_memory_info(self):
|
||||||
"""Get memory usage statistics"""
|
"""Get memory usage statistics"""
|
||||||
mem = psutil.virtual_memory()
|
try:
|
||||||
return {
|
mem = psutil.virtual_memory()
|
||||||
'total': mem.total,
|
return {
|
||||||
'available': mem.available,
|
'total': mem.total,
|
||||||
'percent': mem.percent,
|
'available': mem.available,
|
||||||
'used': mem.used
|
'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):
|
def get_disk_usage(self):
|
||||||
"""Get disk usage statistics"""
|
"""Get disk usage statistics"""
|
||||||
disk = psutil.disk_usage('/')
|
try:
|
||||||
return {
|
disk = psutil.disk_usage('/')
|
||||||
'total': disk.total,
|
return {
|
||||||
'used': disk.used,
|
'total': disk.total,
|
||||||
'free': disk.free,
|
'used': disk.used,
|
||||||
'percent': disk.percent
|
'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):
|
def get_network_stats(self):
|
||||||
"""Get network I/O statistics"""
|
"""Get network I/O statistics"""
|
||||||
net = psutil.net_io_counters()
|
try:
|
||||||
return {
|
net = psutil.net_io_counters()
|
||||||
'bytes_sent': net.bytes_sent,
|
return {
|
||||||
'bytes_recv': net.bytes_recv,
|
'bytes_sent': net.bytes_sent,
|
||||||
'packets_sent': net.packets_sent,
|
'bytes_recv': net.bytes_recv,
|
||||||
'packets_recv': net.packets_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):
|
def display_stats(self):
|
||||||
"""Display all system statistics"""
|
"""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"System Tracker - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||||
print(f"{'='*50}\n")
|
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()
|
# Memory monitoring
|
||||||
print(f"Memory: {mem['percent']}% ({mem['used'] / (1024**3):.2f}GB / {mem['total'] / (1024**3):.2f}GB)")
|
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()
|
# Disk monitoring
|
||||||
print(f"Disk: {disk['percent']}% ({disk['used'] / (1024**3):.2f}GB / {disk['total'] / (1024**3):.2f}GB)")
|
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()
|
# Network monitoring
|
||||||
print(f"Network: Sent {net['bytes_sent'] / (1024**2):.2f}MB | Recv {net['bytes_recv'] / (1024**2):.2f}MB")
|
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 = argparse.ArgumentParser(description='System Tracker - Monitor machine health')
|
||||||
parser.add_argument('-c', '--continuous', action='store_true', help='Run continuously')
|
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')
|
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")
|
print("\n\nTracker stopped by user")
|
||||||
else:
|
else:
|
||||||
tracker.display_stats()
|
tracker.display_stats()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue