Skip to content

feat: export prometheus metrics#49

Merged
DeepSpace2 merged 2 commits into
masterfrom
feat-metrics
Jun 13, 2026
Merged

feat: export prometheus metrics#49
DeepSpace2 merged 2 commits into
masterfrom
feat-metrics

Conversation

@DeepSpace2

@DeepSpace2 DeepSpace2 commented Jun 13, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Optional Prometheus metrics support (enable via METRICS; default endpoint http://:9100/metrics; port configurable)
  • Documentation

    • Added Monitoring guide with Prometheus scrape example
    • Updated configuration docs (presentation tweaks; TZ default now empty; DOCKER_HOSTS listed before DOCKER_HOST)
    • Enhanced CLI and Docker Compose usage (hover-to-copy flags tip; note about using CLI flags via YAML command)

@DeepSpace2 DeepSpace2 added the feature New feature label Jun 13, 2026
@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 206b9e33-1ba7-4996-90db-62d32f5b3b81

📥 Commits

Reviewing files that changed from the base of the PR and between 4d93c1b and 7dcd8c3.

📒 Files selected for processing (2)
  • pkg/clients/adguardhome/adguardhome.go
  • pkg/clients/pihole/pihole.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/clients/pihole/pihole.go
  • pkg/clients/adguardhome/adguardhome.go

📝 Walkthrough

Walkthrough

This PR adds comprehensive Prometheus metrics instrumentation: a metrics package with Prometheus metrics and helpers, a /metrics HTTP server, an HTTP client instrumentation layer, client API changes to return affected-entry counts, processor integration emitting and updating metrics, config validation/tests for metrics port, dependency bumps, and documentation.

Changes

Prometheus Metrics System

Layer / File(s) Summary
Metrics package definition and Prometheus setup
pkg/metrics/metrics.go
Exports service/action constants; defines Prometheus gauge for discovered containers, counters for managed DNS/proxy entries and Docker events, counters for API request errors, and histograms for scan and API request durations; provides helper functions to increment/observe these metrics.
Metrics HTTP server
pkg/metrics/server.go
Implements Serve function creating HTTP server bound to configured port, exposing /metrics endpoint via Prometheus handler, with graceful context-based startup and shutdown.
HTTP request instrumentation layer
pkg/clients/common/common.go
Exports NewInstrumentedRoundTripper creating a round tripper wrapper that measures request duration, derives HTTP status group, and invokes observer callback with service, method, status, and latency for all client requests.
Metrics configuration and validation
pkg/config/config.go, pkg/config/config_test.go
Adds Metrics, MetricsServerPort, and RunInterval config fields; implements port range validation (1–65535); updates test suite with boundary and error cases for port validation and assertions of default 9100 port across config scenarios.
AdGuard Home client instrumentation
pkg/clients/adguardhome/adguardhome.go, pkg/clients/adguardhome/adguardhome_test.go
Wires instrumented HTTP transport into client; updates AddDnsRewrites and DeleteDnsRewrites to return count of newly added/deleted entries alongside error; test suite validates returned counts match affected domains.
Pi-hole client instrumentation
pkg/clients/pihole/pihole.go, pkg/clients/pihole/pihole_test.go
Wires instrumented HTTP transport into client; updates all four DNS/CNAME record mutation methods to return count of newly added/deleted entries; test suite validates returned counts reflect only operations that created/deleted records.
NPM client instrumentation
pkg/clients/npm/npm.go, pkg/clients/npm/npm_test.go
Wires instrumented HTTP transport into client; updates AddProxyHost and DeleteProxyHosts to return boolean indicating whether operation created/deleted a record; test suite adapts to discard boolean while asserting error conditions.
Processor integration with metrics
pkg/processor/processor.go
Updates scan loop to emit discovered container count and total scan duration; captures operation counts from client methods and increments service-specific entry created/deleted counters; increments API request error counters on failures; tracks handled Docker events per host; returns immediately on service API errors.
Application metrics server startup
main.go
Adds metrics import; conditionally starts metrics server when enabled in config, spawning in goroutine, handling startup errors, and triggering graceful shutdown on failure.
Dependency updates
go.mod
Adds github.com/prometheus/client_golang and related transitive Prometheus dependencies; bumps golang.org/x/sys and google.golang.org/protobuf versions.
Documentation updates
docs/monitoring.md, docs/configuration.md, docs/usage.md, mkdocs.yml
Adds new monitoring documentation describing Prometheus metrics, configuration environment variables, default endpoint, and example scrape config; reorders environment variables in config reference and changes TZ default; updates usage docs to clarify CLI flag clipboard feature and Docker Compose command field requirement; updates mkdocs navigation and markdown extensions.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • DeepSpace2/PlugNPiN#44: Modifies processor handlers and container processing paths related to this PR's processor changes.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: export prometheus metrics' directly and concisely summarizes the main objective of the PR, which is adding Prometheus metrics export functionality across multiple files and components.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/clients/pihole/pihole.go (1)

97-150: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Counters incremented before verifying API success in Pi-hole client. All four DNS/CNAME management methods increment their counters during the loop that builds the payload, before executing the PATCH request and verifying its success. If the PATCH fails, the methods return the incremented count alongside an error, causing metrics to count entries as added/deleted even though the operation failed. Additionally, the recursive retry on 401 may re-execute the entire method and re-increment the counter for the same entries.

  • pkg/clients/pihole/pihole.go#L97-L150: AddDnsRecords increments numOfAddedDnsRecords at line 108 before the PATCH at line 135.
  • pkg/clients/pihole/pihole.go#L152-L205: DeleteDnsRecords increments numOfDeletedDnsRecords at line 163 before the PATCH at line 190.
  • pkg/clients/pihole/pihole.go#L246-L299: AddCNameRecords increments numOfAddedCNameRecords at line 257 before the PATCH at line 284.
  • pkg/clients/pihole/pihole.go#L301-L354: DeleteCNameRecords increments numOfDeletedCNameRecords at line 312 before the PATCH at line 339.

Track which entries would be added/deleted in a temporary slice during the loop, then set the counter to the slice length only after confirming the PATCH succeeded (statusCode < 400).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/clients/pihole/pihole.go` around lines 97 - 150, For each Pi‑Hole
DNS/CNAME management function, stop incrementing the metrics during the
payload-build loop and instead collect the affected entries in a temporary
slice, perform the PATCH, and only set the counter to len(slice) after verifying
statusCode < 400; specifically: in pkg/clients/pihole/pihole.go (97-150) update
AddDnsRecords to gather new domains into a temp slice (e.g., toAdd) and only
assign numOfAddedDnsRecords = len(toAdd) after a successful PATCH and not before
retrying on 401 (ensure refreshAuth retry does not re-count by returning the
result of the retried call unchanged); in pkg/clients/pihole/pihole.go (152-205)
update DeleteDnsRecords similarly to collect toDelete and set
numOfDeletedDnsRecords after successful PATCH; in pkg/clients/pihole/pihole.go
(246-299) update AddCNameRecords to collect toAddCNames and set
numOfAddedCNameRecords = len(toAddCNames) only after success; and in
pkg/clients/pihole/pihole.go (301-354) update DeleteCNameRecords to collect
toDeleteCNames and set numOfDeletedCNameRecords after success; keep error
handling and 401 retry logic but ensure counters are only set post-success so
retries don’t double-count.
🧹 Nitpick comments (1)
pkg/metrics/server.go (1)

33-38: ⚡ Quick win

Consider using context-aware listener creation.

The static analysis tool correctly identifies that net.Listen doesn't accept a context. For proper cancellation during startup, prefer (*net.ListenConfig).Listen:

lc := net.ListenConfig{}
listener, err := lc.Listen(ctx, "tcp", server.Addr)

This allows the listen operation to be cancelled if the context is done during startup.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/metrics/server.go` around lines 33 - 38, The code currently calls
net.Listen("tcp", server.Addr) which cannot be cancelled; replace it with a
context-aware call using a net.ListenConfig, e.g. create lc :=
net.ListenConfig{} and call listener, err := lc.Listen(ctx, "tcp", server.Addr)
(ensure a context.Context named ctx is available in the surrounding function or
add one as a parameter), then keep the existing error handling (log.Error and
sending to errCh) unchanged; also ensure listener is closed on shutdown as
before. Reference the net.Listen usage and the variables listener, err,
server.Addr and errCh when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/clients/adguardhome/adguardhome.go`:
- Around line 73-83: In both AddDnsRewrites
(pkg/clients/adguardhome/adguardhome.go lines 73-83) and DeleteDnsRewrites
(pkg/clients/adguardhome/adguardhome.go lines 95-105) move the counter
increments (numOfAddedRewrites and numOfDeletedRewrites) so they occur only
after confirming the request succeeded: after the POST/DELETE call returns,
check for err, then check statusCode for >= 400 (handle 401 as currently done),
and only increment the counter when statusCode < 400; update the logic in each
site accordingly (no other files need changes).

---

Outside diff comments:
In `@pkg/clients/pihole/pihole.go`:
- Around line 97-150: For each Pi‑Hole DNS/CNAME management function, stop
incrementing the metrics during the payload-build loop and instead collect the
affected entries in a temporary slice, perform the PATCH, and only set the
counter to len(slice) after verifying statusCode < 400; specifically: in
pkg/clients/pihole/pihole.go (97-150) update AddDnsRecords to gather new domains
into a temp slice (e.g., toAdd) and only assign numOfAddedDnsRecords =
len(toAdd) after a successful PATCH and not before retrying on 401 (ensure
refreshAuth retry does not re-count by returning the result of the retried call
unchanged); in pkg/clients/pihole/pihole.go (152-205) update DeleteDnsRecords
similarly to collect toDelete and set numOfDeletedDnsRecords after successful
PATCH; in pkg/clients/pihole/pihole.go (246-299) update AddCNameRecords to
collect toAddCNames and set numOfAddedCNameRecords = len(toAddCNames) only after
success; and in pkg/clients/pihole/pihole.go (301-354) update DeleteCNameRecords
to collect toDeleteCNames and set numOfDeletedCNameRecords after success; keep
error handling and 401 retry logic but ensure counters are only set post-success
so retries don’t double-count.

---

Nitpick comments:
In `@pkg/metrics/server.go`:
- Around line 33-38: The code currently calls net.Listen("tcp", server.Addr)
which cannot be cancelled; replace it with a context-aware call using a
net.ListenConfig, e.g. create lc := net.ListenConfig{} and call listener, err :=
lc.Listen(ctx, "tcp", server.Addr) (ensure a context.Context named ctx is
available in the surrounding function or add one as a parameter), then keep the
existing error handling (log.Error and sending to errCh) unchanged; also ensure
listener is closed on shutdown as before. Reference the net.Listen usage and the
variables listener, err, server.Addr and errCh when making the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3cf6ebdc-f012-4213-9ebb-695d94b221e2

📥 Commits

Reviewing files that changed from the base of the PR and between 869267e and 4d93c1b.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (19)
  • docs/configuration.md
  • docs/monitoring.md
  • docs/usage.md
  • go.mod
  • main.go
  • mkdocs.yml
  • pkg/cli/cli.go
  • pkg/clients/adguardhome/adguardhome.go
  • pkg/clients/adguardhome/adguardhome_test.go
  • pkg/clients/common/common.go
  • pkg/clients/npm/npm.go
  • pkg/clients/npm/npm_test.go
  • pkg/clients/pihole/pihole.go
  • pkg/clients/pihole/pihole_test.go
  • pkg/config/config.go
  • pkg/config/config_test.go
  • pkg/metrics/metrics.go
  • pkg/metrics/server.go
  • pkg/processor/processor.go

Comment thread pkg/clients/adguardhome/adguardhome.go
@DeepSpace2
DeepSpace2 merged commit 5853dda into master Jun 13, 2026
8 checks passed
@DeepSpace2
DeepSpace2 deleted the feat-metrics branch June 13, 2026 18:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant