Real-time async network node monitoring — ICMP ping & TCP port checks with a live dashboard
Network Monitoring Utility is a high-performance web application that tracks whether your network nodes are reachable. It fires parallel ICMP and TCP checks using Python's native asyncio, persists results to SQLite, and surfaces everything through a sleek Streamlit dashboard that auto-refreshes in real time.
| Feature | Detail |
|---|---|
| Parallel checks | asyncio.gather — all nodes checked simultaneously |
| Check methods | ICMP echo (no-port nodes) · TCP connect (port nodes) |
| State detection | Log entry written only on status change |
| Scheduler | APScheduler — configurable interval (default 30 s) |
| Dashboard | Live table · status badges · latency breakdown |
| History | Full event log with recovery / outage counters |
network-monitoring-utility/
├── app/
│ ├── api/
│ │ ├── router.py # API router aggregator
│ │ └── routes/
│ │ ├── nodes.py # CRUD endpoints for nodes
│ │ └── logs.py # Status log endpoints
│ ├── config/
│ │ └── config.py # Pydantic settings (env / .env file)
│ ├── core/
│ │ ├── database.py # Async SQLAlchemy engine & session
│ │ └── logger.py # Loguru setup + stdlib bridge
│ ├── models/
│ │ ├── node.py # Node ORM model
│ │ └── status_log.py # StatusLog ORM model
│ ├── schemas/
│ │ ├── node.py # NodeCreate / NodeUpdate / NodeResponse
│ │ └── status_log.py # StatusLogResponse
│ ├── services/
│ │ ├── checker.py # Async checker (Phase 2)
│ │ └── scheduler.py # APScheduler background job (Phase 3)
│ └── main.py # FastAPI app + lifespan
├── frontend/
│ └── app.py # Streamlit dashboard
├── tests/
│ └── conftest.py # Shared fixtures (async client, test DB)
├── .github/workflows/ # CI pipeline
├── requirements.txt
├── pyproject.toml
├── TESTING.md
├── CONTRIBUTING.md
├── SECURITY.md
└── CODE_OF_CONDUCT.md
- Python 3.13+
- pip
git clone https://github.com/crissyro/network-monitoring-utility.git
cd network-monitoring-utility
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txtCreate a .env file in the project root to override defaults:
MONITORING_INTERVAL_SECONDS=30
MONITORING_TIMEOUT_SECONDS=5.0
LOG_LEVEL=INFO
LOG_FILE=logs/monitor.log # optional — omit to log to stdout only
DATABASE_URL=sqlite+aiosqlite:///./network_monitor.dbuvicorn app.main:app --reloadBackend is now live at http://localhost:8000.
Interactive API docs: http://localhost:8000/docs
streamlit run frontend/app.pyDashboard opens at http://localhost:8501.
| Method | Endpoint | Description |
|---|---|---|
GET |
/nodes |
List all monitored nodes |
POST |
/nodes |
Add a new node |
GET |
/nodes/{id} |
Get a single node |
PATCH |
/nodes/{id} |
Update address or port |
DELETE |
/nodes/{id} |
Remove a node |
GET |
/logs |
List all status-change events |
GET |
/nodes/{id}/logs |
List events for a specific node |
# TCP check (with port)
curl -X POST http://localhost:8000/nodes \
-H "Content-Type: application/json" \
-d '{"address": "8.8.8.8", "port": 53}'
# ICMP-only (no port)
curl -X POST http://localhost:8000/nodes \
-H "Content-Type: application/json" \
-d '{"address": "1.1.1.1"}'startup
└─ init_db() create tables if they don't exist
└─ start_scheduler() APScheduler fires run_checks() every N seconds
run_checks()
├─ SELECT all nodes from SQLite
├─ asyncio.gather(*[_check_node(n) for n in nodes])
│ ├─ port set → asyncio.open_connection (TCP)
│ └─ no port → icmplib.async_ping (ICMP, unprivileged)
└─ for each result:
├─ update last_status / last_latency / last_check_at
├─ if status changed → INSERT StatusLog row
│ ONLINE → logger.success(...)
│ OFFLINE → logger.warning(...)
└─ else → logger.info(...)
pytest # run all tests
pytest -v # verbose
pytest -k "nodes" # filter by nameTests use an in-memory SQLite database per test — no server needed, no state leakage between runs.
| Variable | Default | Description |
|---|---|---|
MONITORING_INTERVAL_SECONDS |
30 |
Seconds between check cycles |
MONITORING_TIMEOUT_SECONDS |
5.0 |
Per-node check timeout |
LOG_LEVEL |
INFO |
Minimum log level |
LOG_FILE |
"" |
Path to rotating log file (empty = disabled) |
LOG_ROTATION |
10 MB |
Rotate when file reaches this size |
LOG_RETENTION |
1 week |
Delete rotated files older than this |
DATABASE_URL |
sqlite+aiosqlite:///./network_monitor.db |
SQLAlchemy async DB URL |
DEBUG |
false |
Enable SQLAlchemy query echo & traceback vars |
Contributions are welcome! See CONTRIBUTING.md for guidelines.
See SECURITY.md for the vulnerability reporting process.
This project follows the Contributor Covenant.
Distributed under the MIT License.