feat(monitor): add metrics, new features, and fix middleware bugs#1833
feat(monitor): add metrics, new features, and fix middleware bugs#1833ReneWerner87 wants to merge 13 commits into
Conversation
Agent-Logs-Url: https://github.com/gofiber/contrib/sessions/8ce24309-9791-42c3-8cfe-09157fce8acd Co-authored-by: gaby <835733+gaby@users.noreply.github.com>
Agent-Logs-Url: https://github.com/gofiber/contrib/sessions/8ce24309-9791-42c3-8cfe-09157fce8acd Co-authored-by: gaby <835733+gaby@users.noreply.github.com>
…nic on process error, APIOnly override logic Agent-Logs-Url: https://github.com/gofiber/contrib/sessions/6da9d492-f179-4c24-9e49-d2afbdb03db7 Co-authored-by: gaby <835733+gaby@users.noreply.github.com>
Agent-Logs-Url: https://github.com/gofiber/contrib/sessions/487134b0-4d76-49f4-a3bd-06a4d75c4f12 Co-authored-by: gaby <835733+gaby@users.noreply.github.com>
Agent-Logs-Url: https://github.com/gofiber/contrib/sessions/6b4667ef-7e6d-4c21-a14b-a672ea5edde8 Co-authored-by: gaby <835733+gaby@users.noreply.github.com>
…nil-safe process, APIOnly default, improved test Agent-Logs-Url: https://github.com/gofiber/contrib/sessions/5107777e-20e7-4972-a097-544f30f8fda9 Co-authored-by: gaby <835733+gaby@users.noreply.github.com>
…bal tests, typed JSON assertions, close resp.Body Agent-Logs-Url: https://github.com/gofiber/contrib/sessions/50b76845-c4b0-4416-8204-1a577a58c8dc Co-authored-by: gaby <835733+gaby@users.noreply.github.com>
…ts chart first-point Agent-Logs-Url: https://github.com/gofiber/contrib/sessions/12a845e9-53a4-436f-8abd-ecff91228479 Co-authored-by: gaby <835733+gaby@users.noreply.github.com>
…data+mutex Agent-Logs-Url: https://github.com/gofiber/contrib/sessions/77ad6db7-2000-4c9a-b60a-d2cb6a63abce Co-authored-by: gaby <835733+gaby@users.noreply.github.com>
… assertions Agent-Logs-Url: https://github.com/gofiber/contrib/sessions/32b1ff60-29cc-45fc-979f-523680edd736 Co-authored-by: gaby <835733+gaby@users.noreply.github.com>
Removed comments regarding APIOnly inheritance behavior.
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 59 minutes and 59 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (2)
📒 Files selected for processing (4)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Adds new monitor metrics (requests, goroutines, uptime), improves JSON safety/precision, and extends UI/tests/workflow coverage for the monitor middleware.
Changes:
- Add
pid.requests(uint64 encoded as string),pid.goroutines, andpid.uptimeto the monitor JSON payload. - Update the dashboard UI to display/chart requests and goroutines, and show uptime.
- Extend monitor tests and CI matrix (adds Go
1.26.x) to cover the new fields and behaviors.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
v3/monitor/monitor.go |
Adds atomic-backed request counter, uptime/goroutine metrics, and snapshot-based JSON response generation. |
v3/monitor/index.go |
Adds new UI elements and charts for requests/goroutines and an uptime display; updates JS sampling logic. |
v3/monitor/monitor_test.go |
Adds typed JSON assertions, request counter test, and improves response body handling. |
v3/monitor/config_test.go |
Adds coverage for ConfigDefault.APIOnly inheritance behavior. |
.github/workflows/test-monitor.yml |
Expands Go test matrix to include 1.26.x. |
v3/swaggerui/go.mod |
Removes trailing blank line at EOF. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Caller sets Title but leaves APIOnly unset — should inherit from ConfigDefault. | ||
| cfg := configDefault(Config{Title: "custom"}) | ||
| assert.Equal(t, true, cfg.APIOnly) | ||
| }) |
There was a problem hiding this comment.
The APIOnly inheritance behavior being tested here highlights an API limitation/bug: because APIOnly is a bool, configDefault cannot distinguish “unset” from “explicitly false”. If ConfigDefault.APIOnly is set to true, callers cannot override it back to false (passing Config{APIOnly:false} will still inherit true). Consider adjusting the config API (e.g., APIOnly *bool, or a separate APIOnlySet flag) and add a subtest that asserts Config{APIOnly:false} overrides a true default.
| }) | |
| }) | |
| t.Run("explicit false overrides true default", func(t *testing.T) { | |
| t.Skip("pending config API change: APIOnly is a bool, so configDefault cannot distinguish unset from explicitly false") | |
| cfg := configDefault(Config{APIOnly: false}) | |
| assert.Equal(t, false, cfg.APIOnly) | |
| }) |
| const reqsBig = BigInt(json.pid.requests); | ||
| const reqsDelta = reqsChart.data.datasets[0].data.length === 0 ? 0 : Number(reqsBig - prevRequestsBig); | ||
| reqsChart.data.datasets[0].data.push(reqsDelta); |
There was a problem hiding this comment.
reqsDelta is computed as Number(reqsBig - prevRequestsBig), which can lose precision (or become Infinity) if the per-refresh delta exceeds JS’s safe integer range. Since pid.requests is intentionally encoded as a string to preserve uint64 precision, consider clamping at Number.MAX_SAFE_INTEGER (or otherwise handling large deltas explicitly) so the chart doesn’t silently display incorrect values under high traffic.
| resp, err := app.Test(req) | ||
| assert.Equal(t, nil, err) | ||
| assert.Equal(t, 200, resp.StatusCode) | ||
| defer resp.Body.Close() //nolint:errcheck |
There was a problem hiding this comment.
The deferred resp.Body.Close() is marked //nolint:errcheck, but this test already asserts close errors in the loop above. Consider using t.Cleanup (or a deferred closure that asserts) to check the close error here too, so lint suppression isn’t needed and resource-close failures are still surfaced.
| defer resp.Body.Close() //nolint:errcheck | |
| t.Cleanup(func() { | |
| assert.NoError(t, resp.Body.Close()) | |
| }) |
There was a problem hiding this comment.
Code Review
This pull request enhances the monitor middleware by adding Uptime, Total Requests, and Goroutine metrics, along with corresponding dashboard UI updates. It improves robustness by initializing atomic values to prevent panics and handling cases where process information is unavailable. Feedback indicates that the "Total Requests" counter is misleading as it only tracks requests to the monitor endpoint rather than the entire application, and notes potential performance concerns regarding frequent connection scanning.
| } | ||
|
|
||
| // Increment the absolute request counter | ||
| monitTotalRequests.Add(1) |
There was a problem hiding this comment.
The monitTotalRequests counter is incremented here, but since this middleware returns a terminal response (HTML or JSON) and does not call c.Next() for other routes, it effectively only counts requests made to the monitor endpoint itself. This makes the 'Total Requests' metric in the dashboard misleading as it does not reflect the total traffic of the entire Fiber application. To accurately monitor total application requests, this logic would need to be part of a separate middleware that wraps the entire app, or the monitor middleware would need to be split into a collector and a viewer.
| if pidConns, err := net.ConnectionsPid("tcp", p.Pid); err == nil { | ||
| monitPIDConns.Store(len(pidConns)) | ||
| } |
There was a problem hiding this comment.
Calling net.ConnectionsPid every refresh interval (default 3s) can be performance-intensive on systems with a very high number of open connections, as it requires scanning process network state. While this was present in the previous version, consider if this metric is critical enough to justify the overhead in high-throughput environments.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| reqsMetric.innerHTML = json.pid.requests; | ||
| goroutinesMetric.innerHTML = json.pid.goroutines; | ||
| uptimeMetric.innerHTML = formatUptime(json.pid.uptime); |
There was a problem hiding this comment.
reqsMetric, goroutinesMetric, and uptimeMetric are assigned with innerHTML even though they display plain text. Using innerHTML unnecessarily increases XSS risk if the JSON payload ever contains unexpected strings; prefer textContent (or innerText) for these fields.
| reqsMetric.innerHTML = json.pid.requests; | |
| goroutinesMetric.innerHTML = json.pid.goroutines; | |
| uptimeMetric.innerHTML = formatUptime(json.pid.uptime); | |
| reqsMetric.textContent = json.pid.requests; | |
| goroutinesMetric.textContent = json.pid.goroutines; | |
| uptimeMetric.textContent = formatUptime(json.pid.uptime); |
All original changes preserved from the same branch.