Skip to content

Conversation

metalmatze
Copy link

Closes #516

This PR implements native Prometheus metrics support for AdGuard Home, addressing the long-standing community request for built-in monitoring capabilities.

🚀 Features Added

  • DNS Query Metrics: Track total queries and breakdown by result type (filtered, not_filtered, safe_browsing, safe_search, parental)
  • Response Time Histograms: Native exponential histograms for DNS query response times by result type
  • Standard Go Metrics: Built-in Go runtime and process collector metrics
  • Metrics Endpoint: /metrics endpoint (unauthenticated, similar to /dns-query)

📊 Metrics Exposed

  • adguard_dns_queries_total{result} - Total DNS queries by processing result
  • adguard_dns_response_time_seconds{result} - DNS response time histograms
  • Standard Go metrics (memory, goroutines, GC, etc.)
  • Process metrics (CPU, memory, file descriptors)

🏗️ Implementation Details

  • New Package: internal/metrics/dns.go with clean API for metric collection
  • Integration: Seamlessly integrated into existing stats processing (internal/stats/unit.go)
  • Registry: Custom Prometheus registry with proper metric registration
  • Testing: Comprehensive unit tests for all metrics functionality
  • Performance: Minimal overhead using efficient Prometheus client library

🔧 Technical Approach

  • Uses native exponential histograms with factor 1.1 for automatic bucket generation
  • Metrics collection integrated into existing stats flow without performance impact
  • Endpoint follows existing patterns (no auth required, similar to DoH endpoint)
  • Clean separation of concerns with dedicated metrics package

Testing & Validation

  • Unit tests for all metric types and registration
  • Integration with the existing stats system verified
  • Metrics endpoint accessibility confirmed
  • Real-world testing: Successfully running in production at developer's home environment
  • Future roadmap: Additional metrics and alerting rules planned post-merge

Real Examples

I've deployed a binary with the changes in this PR on my NAS and put my home network's load on this instance.

Here we can see the rate(adguard_dns_queries_total[5m]) query. It shows the requests per second grouped by result type:

Screenshot 2025-07-18 at 15 50 00

Here we can see a 1000 * histogram_quantile(0.75, sum by(result) (rate(adguard_dns_response_time_seconds[5m]))) query. It shows the milliseconds (hence 1000 *) over time. 75% of requests by result type are faster than the given duration and 25% are slower.

Screenshot 2025-07-18 at 15 50 16

Copy link

@windsurf-bot windsurf-bot bot left a comment

Choose a reason for hiding this comment

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

💡 To request another review, post a new comment with "/windsurf-review".

Comment on lines +192 to +191
// Register metrics endpoint without control prefix, similar to /dns-query
// Use empty method to bypass auth/gzip middleware like dns-query does
httpRegister("", "/metrics", web.metricsHandler.ServeHTTP)
Copy link

Choose a reason for hiding this comment

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

While it makes sense to have the metrics endpoint unauthenticated like the /dns-query endpoint for Prometheus scraping, it would be good to document the security considerations of exposing metrics without authentication. Consider adding a comment explaining what information is exposed and any potential security implications.

- Add prometheus/client_golang dependency
- Initialize Prometheus registry with Go and process collectors
- Expose metrics endpoint at /metrics (without auth, similar to /dns-query)
- Set up base infrastructure for future DNS filtering metrics
- Create metrics/dns.go with counters for total and blocked queries
- Integrate metrics collection in stats unit.add() method
- Register DNS metrics in web API Prometheus registry
- Add comprehensive tests for metrics functionality

Metrics exposed:
- adguard_dns_queries_total: Total DNS queries processed
- adguard_dns_queries_by_result_total: Queries by result type (filtered, not_filtered, etc.)
- adguard_dns_queries_blocked_total: Legacy metric for blocked queries

The metrics mirror the dashboard counters exactly, providing real-time DNS query statistics for monitoring and alerting.
- Add native exponential histogram for DNS response times
- Track response times by result type (filtered, not_filtered, etc.)
- Use factor 1.1 for automatic bucket generation
- Integrate with existing stats processing flow
@metalmatze metalmatze force-pushed the feature/prometheus-metrics branch from 2916d13 to 7058411 Compare July 18, 2025 14:41
@Somalia0932
Copy link

highly needed

@metalmatze
Copy link
Author

Yep. I'm running this custom build for months now. It works great.

It would be fantastic to get a review!

@metalmatze
Copy link
Author

Do you have any updates on this? If there's interest in merging this, I will rebase.
@ainar-g can you help triage this PR and get someone to review it? That'd be great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Metrics endpoint for Prometheus

2 participants