From 11cc6a46651f78b882b0b047fad910b938941af3 Mon Sep 17 00:00:00 2001 From: Damilare Osibanjo <141376183+Dev-Dami@users.noreply.github.com> Date: Thu, 27 Nov 2025 23:32:06 +0100 Subject: [PATCH] ``` feat: Add CONTRIBUTING, API, architecture, and modules docs ``` --- CONTRIBUTING.md | 113 ++++++++++++++++++++++++++ README.md | 64 +++++++++------ docs/api.md | 121 +++++++++++++++++++++++++++ docs/architecture.md | 78 ++++++++++++++++++ docs/extending.md | 189 +++++++++++++++++++++++++++++++++++++++++++ docs/index.md | 33 ++++++++ docs/modules.md | 112 +++++++++++++++++++++++++ 7 files changed, 686 insertions(+), 24 deletions(-) create mode 100644 CONTRIBUTING.md create mode 100644 docs/api.md create mode 100644 docs/architecture.md create mode 100644 docs/extending.md create mode 100644 docs/index.md create mode 100644 docs/modules.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..265a9a2 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,113 @@ +# Contributing to gim + +Thank you for your interest in contributing to gim! This document outlines the process and guidelines for contributing to the project. + +## Project Overview + +gim is a fast, high-performance, modular system metrics and diagnostics CLI tool written in Rust. It collects and displays system metrics like CPU, memory, disk, and network usage. + +## Getting Started + +1. Fork the repository +2. Clone your fork: `git clone https://github.com/your-username/gim.git` +3. Create a new branch: `git checkout -b feature/your-feature-name` +4. Make your changes +5. Test thoroughly +6. Submit a pull request + +## Development Setup + +```bash +# Install Rust if you don't have it +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + +# Build the project +cargo build + +# Run the project +cargo run + +# Run tests +cargo test + +# Format code +cargo fmt + +# Check for linting issues +cargo clippy +``` + +## Project Structure + +``` +src/ +├── lib.rs # Main application logic +├── main.rs # Entry point +├── cli/ # Command line interface parsing +├── core/ # Core data structures and traits +├── modules/ # Metric collection modules +├── output/ # Output formatting logic +└── tui/ # Terminal UI (planned future feature) +``` + +## Adding New Modules + +To add a new metric collection module: + +1. Create a new file in `src/modules/` (e.g., `disk.rs`) +2. Implement the `MetricCollector` trait +3. Add the module to `src/modules/mod.rs` +4. Register the module in the main function in `src/lib.rs` +5. Update the CLI to accept your module as an argument (if needed) + +Example module implementation: +```rust +use crate::core::{MetricCollector, MetricData, MetricValue}; +use std::collections::HashMap; + +pub struct NewCollector {} + +impl NewCollector { + pub fn new() -> Self { + NewCollector {} + } +} + +impl MetricCollector for NewCollector { + fn collect(&self) -> Result> { + let mut metrics = HashMap::new(); + + // Collect your metrics here + metrics.insert("metric_name".to_string(), MetricValue::from(42)); + + Ok(MetricData { + timestamp: std::time::SystemTime::now(), + metrics, + }) + } + + fn name(&self) -> &'static str { + "module_name" + } +} +``` + +## Code Style + +- Follow Rust idioms and best practices +- Use `cargo fmt` to format code +- Add documentation comments for public APIs +- Write tests for new functionality +- Keep functions focused and well-named + +## Pull Request Guidelines + +1. Describe your changes clearly in the PR description +2. Include tests if adding new functionality +3. Ensure all tests pass before submitting +4. Link any relevant issues +5. Keep PRs focused on a single feature or fix + +## Questions? + +If you have questions, feel free to open an issue or reach out to the maintainers. \ No newline at end of file diff --git a/README.md b/README.md index 25e7eb6..7424a77 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,31 @@ # gim - GENERIC INFRASTRUCTURE MONITOR -gmi-cli is a fast, high performance, modular system metrics and diagnostics CLI tool written in Rust. +gim is a fast, high-performance, modular system metrics and diagnostics CLI tool written in Rust. -# why - use cases -- Monitoring system resources such as CPU, memory, disk usage, network traffic, and more. -- Diagnosing issues with system performance and stability. -- Gathering metrics for performance analysis and optimization. -- Providing insights into system health and performance trends. -- Automating routine tasks and alerts for system monitoring. +## Features -# planned features -- CPU, memory, disk, and network metric collectors -- Unified MetricCollector trait for easy module additions -- JSON, table, and raw output modes -- Optional ratatui-based live dashboard -- JSON config support +- **Modular Design**: Easy to extend with new metric collectors +- **Multiple Output Formats**: JSON, table, and raw output modes +- **Real-time Metrics**: CPU and memory usage statistics +- **Clean Architecture**: Well-structured codebase for easy maintenance -# Build & Run +## Use Cases + +- Monitor system resources (CPU, memory, disk, network) +- Diagnose performance issues +- Gather metrics for analysis +- Track system health trends + +## Installation & Usage + +### Build from Source ```bash +# Clone the repository +git clone https://github.com/your-repo/gim.git + # Build the project -cargo build +cargo build --release # Run with default settings cargo run @@ -35,16 +40,27 @@ cargo run -- --output raw cargo run -- --module cpu --output json ``` -# Current Features -- CPU metric collection (usage, core count) -- Memory metric collection (usage, available/free/used, swap) -- Unified MetricCollector trait for modules -- Multiple output formats (JSON, table, raw) -- CLI argument parsing with clap -- Basic architecture with core, modules, and output components +## Current Capabilities + +- **CPU Metrics**: Usage percentage, core count +- **Memory Metrics**: Total, used, free, available memory and swap +- **Output Options**: JSON, formatted table, or raw key-value pairs + +## Planned Features -# Next Steps - Disk and network metric collectors -- TUI dashboard implementation +- TUI dashboard with ratatui - Configuration file support - Live monitoring capabilities + +## Documentation + +- [API Documentation](docs/api.md) +- [Architecture](docs/architecture.md) +- [Modules Guide](docs/modules.md) +- [Extending Guide](docs/extending.md) +- [Contributing](CONTRIBUTING.md) + +## License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..e78547a --- /dev/null +++ b/docs/api.md @@ -0,0 +1,121 @@ +# gim API Documentation + +## Overview + +gim is a modular system metrics collection library with a CLI interface. The API is designed to be extensible, allowing for new metric collectors to be easily added while maintaining a consistent interface. + +## Core Components + +### MetricCollector Trait + +The `MetricCollector` trait is the core abstraction that all metric collection modules implement: + +```rust +pub trait MetricCollector { + fn collect(&self) -> Result>; + fn name(&self) -> &'static str; +} +``` + +- `collect()`: Gathers metrics and returns them as `MetricData` +- `name()`: Returns the identifier for the collector (e.g., "cpu", "memory") + +### MetricData Structure + +Represents the collected metrics with timestamp: + +```rust +pub struct MetricData { + pub timestamp: std::time::SystemTime, + pub metrics: HashMap, +} +``` + +### MetricValue Enum + +A flexible type to represent different metric value types: + +```rust +pub enum MetricValue { + Integer(i64), + Float(f64), + String(String), + Boolean(bool), + List(Vec), +} +``` + +## Available Modules + +### CPU Collector + +Collects CPU-related metrics: + +- `cpu_usage_percent`: Average CPU usage percentage +- `cpu_count`: Number of CPU cores +- Memory-related metrics are also available (total, used, free, swap) + +### Memory Collector + +Collects memory-related metrics: + +- `total_memory_bytes`: Total system memory in bytes +- `used_memory_bytes`: Currently used memory in bytes +- `free_memory_bytes`: Currently free memory in bytes +- `available_memory_bytes`: Available memory for applications +- `total_swap_bytes`, `used_swap_bytes`, `free_swap_bytes`: Swap memory metrics +- `memory_usage_percent`: Memory usage percentage + +## Output Formats + +The system supports multiple output formats through the `OutputFormat` enum: + +- `Table`: Formatted table with headers +- `Json`: JSON output with timestamp and metrics +- `Raw`: Raw key=value format + +## CLI Interface + +Command line arguments are handled by the `Cli` struct: + +```rust +pub struct Cli { + pub module: Option, // Module to run (cpu, memory, etc.) + pub output: Option, // Output format (json, table, raw) +} +``` + +### Usage Examples + +```bash +# Run with default modules and table output +cargo run + +# Run specific module +cargo run -- --module cpu + +# Use specific output format +cargo run -- --output json + +# Combine module and output format +cargo run -- --module memory --output raw +``` + +## Adding New Modules + +To add a new metric collection module: + +1. Create a struct that implements `MetricCollector` +2. Implement the required methods (`collect` and `name`) +3. Register the module in the main application logic +4. Optionally add CLI support for the new module + +## Library Functions + +### `run()` + +Main entry point that handles command parsing, module selection, and output formatting. + +### `format_output(data: &MetricData, format: OutputFormat)` + +Formats metric data according to the specified output format. \ No newline at end of file diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..3500daf --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,78 @@ +# Architecture + +## Overview + +gim follows a modular architecture with clear separation of concerns between metric collection, output formatting, and command-line interface handling. + +## Component Diagram + +``` +┌─────────────┐ ┌─────────────┐ ┌─────────────┐ +│ CLI │───▶│ Core │───▶│ Output │ +│ Parsing │ │ Metrics │ │ Formatting │ +└─────────────┘ └─────────────┘ └─────────────┘ + │ + ▼ + ┌─────────────┐ + │ Modules │ + │(CPU,Memory) │ + └─────────────┘ +``` + +## Core Components + +### 1. CLI Module +- Handles command-line argument parsing using `clap` +- Defines the `Cli` struct with `module` and `output` options +- Provides `parse_args()` function to parse command line + +### 2. Core Module +- Defines the `MetricCollector` trait that all collectors implement +- Provides `MetricData` struct to encapsulate collected metrics +- Defines `MetricValue` enum for flexible metric types + +### 3. Modules +- Individual metric collection implementations (CPU, Memory, etc.) +- Each implements the `MetricCollector` trait +- Responsible for gathering specific system metrics +- Return structured data via `MetricData` + +### 4. Output Module +- Handles formatting of collected metrics +- Supports multiple output formats: JSON, Table, Raw +- Contains formatter functions for each format type + +## Data Flow + +1. **Initialization**: CLI arguments are parsed to determine which modules to run and output format +2. **Collection**: Each selected module's `collect()` method is called to gather metrics +3. **Formatting**: Collected `MetricData` is formatted according to the specified output format +4. **Display**: Formatted output is printed to stdout + +## Extensibility + +The architecture is designed for easy extension: +- New modules can be added by implementing the `MetricCollector` trait +- New output formats can be added to the `OutputFormat` enum and formatter functions +- The core logic remains unchanged when adding new functionality + +## Key Data Structures + +### MetricData +```rust +struct MetricData { + timestamp: SystemTime, + metrics: HashMap +} +``` + +### MetricValue +```rust +enum MetricValue { + Integer(i64), + Float(f64), + String(String), + Boolean(bool), + List(Vec) +} +``` \ No newline at end of file diff --git a/docs/extending.md b/docs/extending.md new file mode 100644 index 0000000..e659bcb --- /dev/null +++ b/docs/extending.md @@ -0,0 +1,189 @@ +# Extending gim + +## Overview + +gim is designed to be easily extensible. You can add new metric collection modules, output formats, or enhance existing functionality. This guide covers how to extend the system. + +## Adding New Metric Collection Modules + +### 1. Create the Module File + +Create a new file in `src/modules/` (e.g., `disk.rs`): + +```rust +use crate::core::{MetricCollector, MetricData, MetricValue}; +use std::collections::HashMap; + +pub struct DiskCollector {} + +impl DiskCollector { + pub fn new() -> Self { + DiskCollector {} + } +} + +impl MetricCollector for DiskCollector { + fn collect(&self) -> Result> { + let mut metrics = HashMap::new(); + + // Collect your metrics + metrics.insert("disk_usage_percent".to_string(), MetricValue::from(42.5)); + metrics.insert("total_disk_space_bytes".to_string(), MetricValue::from(1000000000i64)); + + Ok(MetricData { + timestamp: std::time::SystemTime::now(), + metrics, + }) + } + + fn name(&self) -> &'static str { + "disk" + } +} +``` + +### 2. Register the Module + +In `src/modules/mod.rs`, add: + +```rust +pub mod cpu; +pub mod memory; +pub mod disk; // Add your module here +``` + +### 3. Update the Main Application + +In `src/lib.rs`, update the module selection logic: + +```rust +match args.module.as_deref() { + Some("cpu") => vec![Box::new(CpuCollector::new())], + Some("memory") => vec![Box::new(MemoryCollector::new())], + Some("disk") => vec![Box::new(DiskCollector::new())], // Add your module + // ... other cases + None => { + // Default to all collectors including your new one + vec![ + Box::new(CpuCollector::new()), + Box::new(MemoryCollector::new()), + Box::new(DiskCollector::new()), // Add your module to default list + ] + } +} +``` + +## Adding New Output Formats + +### 1. Extend the OutputFormat Enum + +In `src/output/mod.rs`, add your new format: + +```rust +pub enum OutputFormat { + Table, + Json, + Raw, + YourFormat, // Add your new format +} +``` + +### 2. Implement the Formatter + +Add a new formatter function and update `format_output`: + +```rust +pub fn format_output(data: &MetricData, format: OutputFormat) -> String { + match format { + OutputFormat::Json => format_json(data), + OutputFormat::Table => format_table(data), + OutputFormat::Raw => format_raw(data), + OutputFormat::YourFormat => format_your_format(data), // Add your format + } +} + +fn format_your_format(data: &MetricData) -> String { + // Implement your formatting logic here + // Return a formatted string +} +``` + +### 3. Update CLI Support + +In `src/cli/mod.rs`, if you want command-line support for your format: + +```rust +// Update the output format validation in src/lib.rs +match args.output.as_deref() { + Some("json") => OutputFormat::Json, + Some("table") => OutputFormat::Table, + Some("raw") => OutputFormat::Raw, + Some("your_format") => OutputFormat::YourFormat, // Add your format + // ... other cases +} +``` + +## Adding Configuration Support + +For adding configuration file support (planned feature), consider: + +1. Create a configuration structure in a new module +2. Use `serde` for serialization/deserialization +3. Load configuration at startup +4. Pass configuration to collectors and formatters + +## Testing Your Extensions + +### Unit Tests + +Add unit tests for your new modules: + +```rust +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_your_collector() { + let collector = YourCollector::new(); + let result = collector.collect(); + assert!(result.is_ok()); + // Add more specific assertions + } +} +``` + +### Integration Tests + +Consider adding integration tests in the `tests/` directory to test your module end-to-end. + +## Dependencies + +If your module requires new dependencies, add them to `Cargo.toml`: + +```toml +[dependencies] +# existing dependencies... +your_new_dependency = "version" +``` + +Make sure to follow Rust's dependency management best practices and consider the impact on the final binary size. + +## Performance Considerations + +- Keep collection operations efficient +- Avoid unnecessary system calls +- Cache values when appropriate +- Consider the impact of your module on overall performance +- Profile your module to identify bottlenecks + +## Best Practices + +1. Follow Rust idioms and naming conventions +2. Write clear, descriptive metric names +3. Include units in metric names where appropriate +4. Handle errors gracefully +5. Write comprehensive documentation +6. Add unit tests for your module +7. Consider edge cases and error conditions +8. Keep modules focused on a single domain \ No newline at end of file diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..2af78e4 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,33 @@ +# gim Documentation + +Welcome to the gim documentation. This is a fast, high-performance, modular system metrics and diagnostics CLI tool written in Rust. + +## Table of Contents + +- [API Documentation](api.md) - Detailed API reference +- [Architecture](architecture.md) - System architecture overview +- [Modules](modules.md) - Information about metric collection modules +- [Extending](extending.md) - How to add new modules and features + +## About gim + +gim (GENERIC INFRASTRUCTURE MONITOR) is designed to be: +- **Fast**: Written in Rust for high performance +- **Modular**: Easy to add new metric collectors +- **Flexible**: Multiple output formats (JSON, table, raw) +- **Extensible**: Clean trait-based architecture for easy extension + +## Current Features + +- CPU metric collection (usage, core count) +- Memory metric collection (usage, available/free/used, swap) +- Unified MetricCollector trait for easy module additions +- Multiple output formats (JSON, table, raw) +- CLI argument parsing with clap + +## Planned Features + +- Disk and network metric collectors +- TUI dashboard implementation +- Configuration file support +- Live monitoring capabilities \ No newline at end of file diff --git a/docs/modules.md b/docs/modules.md new file mode 100644 index 0000000..b960065 --- /dev/null +++ b/docs/modules.md @@ -0,0 +1,112 @@ +# Modules + +## Overview + +Modules in gim are responsible for collecting specific types of system metrics. Each module implements the `MetricCollector` trait and provides a focused set of related metrics. + +## Available Modules + +### CPU Module + +The CPU module collects processor-related metrics. + +**Name**: `"cpu"` + +**Collected Metrics**: +- `cpu_usage_percent`: Average CPU usage percentage across all cores +- `cpu_count`: Number of CPU cores available on the system + +**Implementation**: `CpuCollector` struct in `src/modules/cpu.rs` + +### Memory Module + +The Memory module collects system memory usage metrics. + +**Name**: `"memory"` + +**Collected Metrics**: +- `total_memory_bytes`: Total physical memory installed (in bytes) +- `used_memory_bytes`: Currently used physical memory (in bytes) +- `free_memory_bytes`: Currently free physical memory (in bytes) +- `available_memory_bytes`: Available memory for applications (in bytes) +- `total_swap_bytes`: Total swap space configured (in bytes) +- `used_swap_bytes`: Currently used swap space (in bytes) +- `free_swap_bytes`: Currently free swap space (in bytes) +- `memory_usage_percent`: Percentage of memory currently in use + +**Implementation**: `MemoryCollector` struct in `src/modules/memory.rs` + +## Creating New Modules + +To create a new metric collection module: + +### 1. Define Your Collector + +Create a new struct in `src/modules/your_module.rs`: + +```rust +use crate::core::{MetricCollector, MetricData, MetricValue}; +use std::collections::HashMap; + +pub struct YourCollector {} + +impl YourCollector { + pub fn new() -> Self { + YourCollector {} + } +} +``` + +### 2. Implement MetricCollector Trait + +```rust +impl MetricCollector for YourCollector { + fn collect(&self) -> Result> { + let mut metrics = HashMap::new(); + + // Collect your metrics here + metrics.insert("metric_name".to_string(), MetricValue::from(your_value)); + + Ok(MetricData { + timestamp: std::time::SystemTime::now(), + metrics, + }) + } + + fn name(&self) -> &'static str { + "your_module_name" + } +} +``` + +### 3. Register the Module + +Add your module to `src/modules/mod.rs`: + +```rust +pub mod cpu; +pub mod memory; +pub mod your_module; // Add this line +``` + +### 4. Update Main Application Logic + +In `src/lib.rs`, update the module selection logic: + +```rust +match args.module.as_deref() { + Some("cpu") => vec![Box::new(CpuCollector::new())], + Some("memory") => vec![Box::new(MemoryCollector::new())], + Some("your_module") => vec![Box::new(YourCollector::new())], // Add this line + // ... other cases +} +``` + +## Best Practices + +- Keep modules focused on a single domain of metrics +- Use descriptive names for metrics +- Follow consistent naming conventions (snake_case) +- Include units in metric names when appropriate (e.g., `_bytes`, `_percent`) +- Handle errors gracefully and return appropriate error types +- Document your metrics clearly \ No newline at end of file