Historical Metrics & Time-Series Storage
User Story
AS A network administrator
I WANT to query historical network metrics over configurable time ranges
SO THAT I can identify trends, investigate past incidents and generate reports.
Acceptance Criteria
Given the daemon has been running for multiple time windows
When I query /metrics/history?start=1735171200&end=1735257600
Then I receive a JSON response containing aggregated stats for each 1-minute window within that range
Given the database exceeds the 7-day retention policy
When the daemon performs automatic cleanup
Then records older than 7 days are deleted, and only recent data remains
Given no time range is specified in the request
When I query /metrics/history
Then the API returns the last 24 hours of data by default
Given I request data with start > end or invalid timestamps
When the API validates the request
Then it returns a 400 Bad Request with a descriptive error message
Additional acceptance criteria:
Tasks
Backend (C++):
Testing:
Documentation:
Technical Notes
Response Format Example:
{
"start": 1735171200,
"end": 1735257600,
"windows": [
{
"timestamp": 1735257540,
"window_start": 1735257540,
"total_bytes": 1048576,
"total_packets": 2048,
"bytes_per_second": 17476,
"protocol_breakdown": {"TCP": 800000, "UDP": 248576},
"active_flows": [...]
},
{
"timestamp": 1735257480,
...
}
]
}
Database Impact:
- 1 minute of data ≈ 50-200 flow records (typical workload)
- 7 days × 1440 minutes = 10,080 windows
- Estimated DB size: 50-200 MB (with indexes)
Performance Safeguards:
- Limit max query range to 30 days (prevent OOM on large queries)
- Use
LIMIT clause to cap response size (default: 1440 windows = 24 hours)
- Cleanup runs at low-traffic hours (00:00 UTC)
Historical Metrics & Time-Series Storage
User Story
AS A network administrator
I WANT to query historical network metrics over configurable time ranges
SO THAT I can identify trends, investigate past incidents and generate reports.
Acceptance Criteria
Given the daemon has been running for multiple time windows
When I query
/metrics/history?start=1735171200&end=1735257600Then I receive a JSON response containing aggregated stats for each 1-minute window within that range
Given the database exceeds the 7-day retention policy
When the daemon performs automatic cleanup
Then records older than 7 days are deleted, and only recent data remains
Given no time range is specified in the request
When I query
/metrics/historyThen the API returns the last 24 hours of data by default
Given I request data with
start > endor invalid timestampsWhen the API validates the request
Then it returns a 400 Bad Request with a descriptive error message
Additional acceptance criteria:
agg_statstable)/metrics/historyendpoint supports query parameters:start(Unix timestamp),end(Unix timestamp),limit(max windows)/metricsstructure but includes an array of time-windowed snapshotswindow_startfor efficient range queries (already exists)/metricsendpoint (historical queries run in separate thread pool)Tasks
Backend (C++):
GET /metrics/historyendpoint toNetMonDaemon.cppstart,end,limit)StatsPersistence::loadHistoryRange(start, end, limit)StatsPersistence.cppwith time-range query:loadHistoryRange(int64_t start, int64_t end, size_t limit)methodSELECT * FROM agg_stats WHERE window_start BETWEEN ? AND ? ORDER BY window_start DESC LIMIT ?StatsPersistence.cpp:cleanupOldRecords(int retention_days)methodDELETE FROM agg_stats WHERE window_start < (strftime('%s', 'now') - (? * 86400))NetMonDaemon::run():persistence_->cleanupOldRecords(7)dailyTesting:
StatsPersistence::loadHistoryRange()with mock data (3-day range)StatsPersistence::cleanupOldRecords()verifies deletion of old rowsPOST /metrics/historywith valid/invalid timestamps/metrics/historywith 10,080 windows (7 days of 1-min data) completes in <500msDocumentation:
docs/api.mdwith/metrics/historyendpoint specificationcurlcommands for common queries (last hour, specific date range)Technical Notes
Response Format Example:
{ "start": 1735171200, "end": 1735257600, "windows": [ { "timestamp": 1735257540, "window_start": 1735257540, "total_bytes": 1048576, "total_packets": 2048, "bytes_per_second": 17476, "protocol_breakdown": {"TCP": 800000, "UDP": 248576}, "active_flows": [...] }, { "timestamp": 1735257480, ... } ] }Database Impact:
Performance Safeguards:
LIMITclause to cap response size (default: 1440 windows = 24 hours)