initial module

This commit is contained in:
2026-05-07 22:57:00 +03:30
commit 1e5deb18b3
27 changed files with 5271 additions and 0 deletions

92
docs/API.md Normal file
View File

@@ -0,0 +1,92 @@
# API
All JSON responses are compact, versioned, and timestamped.
```json
{
"version": 1,
"module": "1.0.0",
"timestamp": 1710000000,
"scope": "full"
}
```
## Authentication
If `monitor_api_token` is set, non-dashboard endpoints require one of:
- `Authorization: Bearer <token>`
- `X-Monitor-Token: <token>`
- `?token=<token>`
If `monitor_basic_auth` is set to `user:password`, every monitoring endpoint requires HTTP Basic auth. For public production deployments, prefer terminating authentication at Nginx with `auth_basic` and `auth_basic_user_file`.
## JSON Endpoints
### `/monitor/api`
Returns all sections:
- `system`
- `nginx`
- `network`
- `disk`
- `processes`
- `upstreams`
- `connections`
- `requests`
- `history`
### `/monitor/api/system`
Includes:
- `cpu.usage`
- `cpu.cores`
- `cpu.load`
- `memory.total`
- `memory.available`
- `memory.used`
- `memory.used_pct`
- `swap.total`
- `swap.free`
- `swap.used_pct`
- `uptime`
### `/monitor/api/requests`
Includes:
- total request and response counters
- request and response moving averages
- status counters
- method distribution
- response size histogram
- latency histogram
- latency percentiles `p50`, `p90`, `p95`, `p99`
- `top_urls`
- `user_agents`
### `/monitor/live`
SSE stream:
```text
retry: 3000
: heartbeat 42
id: 42
event: metrics
data: {"version":1,"timestamp":1710000000,...}
```
The dashboard uses SSE first and falls back to polling `/monitor/api`.
### `/monitor/metrics`
Prometheus text format with core counters and gauges:
- `nginx_monitor_requests_total`
- `nginx_monitor_active_connections`
- `nginx_monitor_cpu_usage_ratio`
- `nginx_monitor_memory_used_ratio`
- `nginx_monitor_latency_p95_ms`

60
docs/ARCHITECTURE.md Normal file
View File

@@ -0,0 +1,60 @@
# Architecture
## Request Path
The module registers two HTTP phase handlers:
- content phase: handles `/monitor`, `/monitor/api*`, `/monitor/live`, `/monitor/metrics`, and `/monitor/health`
- log phase: accounts completed application requests
Monitoring endpoints are excluded from request accounting to avoid dashboard polling skewing the service metrics.
## Shared Memory
The module allocates one shared memory zone named `ngx_http_monitoring`. The zone contains:
- global request, response, connection, and system counters
- fixed-size top URL and user-agent tables
- fixed-size upstream peer table
- per-worker metric slots keyed by `ngx_process_slot`
- fixed-size historical ring buffer
- collector lock and API rate-limit counters
Hot request-path updates use Nginx atomic operations. The shared slab mutex is used only for rare top-N slot creation or replacement and rate-limit window resets.
## Collection
Each worker owns a timer, but collection is guarded by an atomic shared lock, so only one worker performs a collection pass at a time. Collection reads:
- `/proc/stat`
- `/proc/loadavg`
- `/proc/meminfo`
- `/proc/net/dev`
- `/proc/diskstats`
- `/proc/uptime`
- `/proc/net/tcp`
- `/proc/net/tcp6`
- `/proc/net/sockstat`
- `/proc/mounts`
- `/proc/self/status`
- `/proc`
- `statvfs()`
- `getifaddrs()`
The collector computes deltas and moving averages, then appends a sample to the ring buffer according to `monitor_resolution`.
## Serialization
JSON and Prometheus responses are generated from shared-memory snapshots only. API handlers do not read `/proc`, do not allocate persistent state, and use one request-pool buffer per response.
## SSE
`/monitor/live` is a long-lived request. Each client owns two reusable output buffers and a timer. The writer skips a tick if the connection still has pending buffered output, preventing slow clients from accumulating unbounded memory.
## Upstreams
Upstream metrics are passively observed from Nginx upstream state recorded on proxied requests. This avoids active backend probing in workers. Failures are counted from zero or `5xx` upstream statuses.
## Compatibility
The module is designed as an Nginx dynamic HTTP module and should be built with `--with-compat` against the target Nginx source tree. Stub-status counters are compiled in when the target Nginx build includes `--with-http_stub_status_module`; otherwise request counters still work but low-level active/reading/writing/waiting counters remain zero.

51
docs/CONFIGURATION.md Normal file
View File

@@ -0,0 +1,51 @@
# Configuration
## Core
```nginx
monitor on | off;
monitor_dashboard on | off;
monitor_api on | off;
monitor_sse on | off;
```
`monitor` can be used at `http`, `server`, or `location` scope. A prefix location is recommended:
```nginx
location /monitor {
monitor on;
}
```
## Collection
```nginx
monitor_refresh_interval 1s;
monitor_history 5m;
monitor_resolution 1s;
monitor_shm_size 8m;
monitor_collect_system on;
monitor_collect_nginx on;
monitor_collect_network on;
monitor_access_log on;
monitor_max_top_urls 100;
```
`monitor_history / monitor_resolution` is capped by the compiled maximum of 3600 samples.
## Security
```nginx
monitor_allow 10.0.0.0/8;
monitor_allow 127.0.0.1/32;
monitor_deny all;
monitor_basic_auth off;
monitor_api_token "change-me";
monitor_rate_limit 120;
monitor_cors off;
```
ACL rules are evaluated in order. `monitor_basic_auth` accepts `off` or a literal `user:password`. For strong password storage, use Nginx `auth_basic` in the same location instead.
`monitor_cors` accepts `off`, `*`, or a literal origin such as `https://ops.example.com`.

48
docs/PERFORMANCE.md Normal file
View File

@@ -0,0 +1,48 @@
# Performance
## Hot Path
The log-phase request accounting path performs:
- one timestamp delta calculation
- atomic increments for request, status, method, latency, and size buckets
- one bounded top-URL table update
- optional user-agent and upstream updates
Top-N table insertion or replacement takes the shared slab mutex, but existing entries update with atomics only.
## Collector Cost
Collectors run from Nginx timers at `monitor_refresh_interval`. API requests do not trigger collection. Default collection is once per second.
For very large hosts, `/proc/net/tcp` and `/proc/net/tcp6` can be expensive because they scale with connection count. If needed, increase `monitor_refresh_interval` or disable system collection:
```nginx
monitor_collect_system off;
```
## Memory
Default shared memory is 8 MiB:
```nginx
monitor_shm_size 8m;
```
The default fixed-size structures are bounded:
- history samples: 3600 maximum
- top URLs: 256 maximum
- user agents: 64 maximum
- upstream peers: 128 maximum
- workers: 128 maximum
- interfaces, disks, filesystems: 32 each
## Operational Guidance
- Build with `--with-compat`.
- Build with `--with-http_stub_status_module` for exact Nginx connection counters.
- Keep dashboard access private with `monitor_allow` / `monitor_deny` or standard Nginx auth modules.
- Use `monitor_api_token` when exposing API or SSE across trust boundaries.
- Put `/monitor` behind an internal listener or VPN for production.
- Keep `monitor_resolution` at `1s` or higher on very busy systems.