Repository navigation
feat(querylog): ignore domains (exact/wildcard/regex) in query log - #2084
Conversation
There was a problem hiding this comment.
Pull request overview
Adds support for suppressing specific domains from being written to the query log via a new queryLog.ignore.domains configuration, complementing the existing queryLog.ignore.sudn behavior. This fits into Blocky’s resolver pipeline by filtering log entries at QueryLoggingResolver.ignore() using the existing stringcache matcher stack (regex → wildcard → exact).
Changes:
- Add
queryLog.ignore.domainsto config and log output, and build an in-memory matcher atQueryLoggingResolverconstruction time. - Apply the matcher in
QueryLoggingResolver.ignore()to skip logging matching domains. - Add resolver/config tests and update configuration documentation with the new option and examples.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| resolver/query_logging_resolver.go | Builds and applies a domain ignore matcher to skip query log entries. |
| resolver/query_logging_resolver_test.go | Adds tests covering exact/wildcard ignore behavior and matcher construction/validation. |
| config/query_log.go | Extends query log config with ignore.domains and logs configured ignore rules. |
| config/query_log_test.go | Adds tests for logging and YAML parsing of ignore.domains. |
| docs/configuration.md | Documents the new queryLog.ignore.domains option and provides an example config. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The lone-slash guard only caught "/"; entries like "//" or "/ /" passed validation and compiled to an empty regex, which matches every domain and silently dropped the whole query log. Strip the surrounding slashes and reject any entry whose inner pattern is empty after trimming.
Drop the misleading "same syntax as blocklists" wording (blocklists also accept ABP markers and IDNA normalization that this field does not) in favor of the actually-supported forms. Regenerate config.schema.json, which was missing the ignore.domains field and would have failed generate-check and emitted a schema-mismatch warning at startup.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2084 +/- ##
==========================================
+ Coverage 86.14% 86.21% +0.07%
==========================================
Files 112 112
Lines 8336 8367 +31
==========================================
+ Hits 7181 7214 +33
+ Misses 934 932 -2
Partials 221 221 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/0xerr0r/blocky](https://github.com/0xERR0R/blocky) | minor | `v0.31.0` → `v0.32.0` | --- ### Release Notes <details> <summary>0xERR0R/blocky (ghcr.io/0xerr0r/blocky)</summary> ### [`v0.32.0`](https://github.com/0xERR0R/blocky/releases/tag/v0.32.0) [Compare Source](0xERR0R/blocky@v0.31.0...v0.32.0) #### Changelog ##### Features - [`c851293`](0xERR0R/blocky@c851293): feat(blocking): log the matched rule in the block reason ([#​2091](0xERR0R/blocky#2091)) ([@​0xERR0R](https://github.com/0xERR0R)) - [`87be127`](0xERR0R/blocky@87be127): feat(cache): Shard the result cache to remove the single-lock read ceiling ([#​2097](0xERR0R/blocky#2097)) ([@​0xERR0R](https://github.com/0xERR0R)) - [`7c6da15`](0xERR0R/blocky@7c6da15): feat(config): structurally merge config folder files ([#​1827](0xERR0R/blocky#1827)) ([#​2112](0xERR0R/blocky#2112)) ([@​0xERR0R](https://github.com/0xERR0R)) - [`e7958e0`](0xERR0R/blocky@e7958e0): feat(lists): opt-in on-disk download cache with conditional revalidation ([#​2087](0xERR0R/blocky#2087)) ([@​0xERR0R](https://github.com/0xERR0R)) - [`b82199b`](0xERR0R/blocky@b82199b): feat(querylog): ignore domains (exact/wildcard/regex) in query log ([#​2084](0xERR0R/blocky#2084)) ([@​0xERR0R](https://github.com/0xERR0R)) - [`bee2d8b`](0xERR0R/blocky@bee2d8b): feat(resolver): UDP-first plain-DNS upstream and EDNS0 buffer floor ([#​2100](0xERR0R/blocky#2100)) ([@​0xERR0R](https://github.com/0xERR0R)) - [`0b70e5c`](0xERR0R/blocky@0b70e5c): feat(resolver): add DNS rebinding protection ([#​2111](0xERR0R/blocky#2111)) ([@​0xERR0R](https://github.com/0xERR0R)) - [`1b8e08a`](0xERR0R/blocky@1b8e08a): feat(resolver): pool DoT connections and enable TLS session resumption ([#​2098](0xERR0R/blocky#2098)) ([@​0xERR0R](https://github.com/0xERR0R)) - [`4018d9e`](0xERR0R/blocky@4018d9e): feat: in-memory statistics subsystem with /api/stats REST endpoint ([#​2093](0xERR0R/blocky#2093)) ([@​0xERR0R](https://github.com/0xERR0R)) - [`7abca44`](0xERR0R/blocky@7abca44): feat: support PROXY protocol on proxied DoT/DoH listeners ([#​2094](0xERR0R/blocky#2094)) ([@​kastakhov](https://github.com/kastakhov)) ##### Bug fixes - [`2496d12`](0xERR0R/blocky@2496d12): fix(dnssec): close DNSSEC validation bypass & cache-scope pollution (GHSA-x845-2f78-7v36) ([#​2119](0xERR0R/blocky#2119)) ([@​0xERR0R](https://github.com/0xERR0R)) - [`06555e0`](0xERR0R/blocky@06555e0): fix(metrics): bound reason label cardinality for blocked responses ([#​2114](0xERR0R/blocky#2114)) ([@​0xERR0R](https://github.com/0xERR0R)) - [`e0ea9b3`](0xERR0R/blocky@e0ea9b3): fix(resolver): eliminate recursive RLock deadlock in blocking group resolution ([#​2106](0xERR0R/blocky#2106)) ([@​0xERR0R](https://github.com/0xERR0R)) - [`80f742e`](0xERR0R/blocky@80f742e): fix(server): answer browser CORS preflights for custom headers and Private Network Access ([#​2109](0xERR0R/blocky#2109)) ([@​0xERR0R](https://github.com/0xERR0R)) - [`9702c8f`](0xERR0R/blocky@9702c8f): fix(stats): populate allow/denylist counts in /api/stats at startup ([#​2113](0xERR0R/blocky#2113)) ([@​0xERR0R](https://github.com/0xERR0R)) ##### Build and dependencies - [`821e378`](0xERR0R/blocky@821e378): build(deps): bump codecov/codecov-action from 6 to 7 ([#​2089](0xERR0R/blocky#2089)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`d63f84b`](0xERR0R/blocky@d63f84b): build(deps): bump github.com/0xERR0R/expiration-cache from 0.1.0 to 0.2.0 ([#​2095](0xERR0R/blocky#2095)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`81f2b2a`](0xERR0R/blocky@81f2b2a): build(deps): bump github.com/onsi/ginkgo/v2 from 2.29.0 to 2.30.0 ([#​2108](0xERR0R/blocky#2108)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`9c5abdf`](0xERR0R/blocky@9c5abdf): build(deps): bump github.com/onsi/ginkgo/v2 from 2.30.0 to 2.31.0 ([#​2116](0xERR0R/blocky#2116)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`6c0ec5f`](0xERR0R/blocky@6c0ec5f): build(deps): bump github.com/onsi/gomega from 1.41.0 to 1.42.0 ([#​2115](0xERR0R/blocky#2115)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`4beb9fe`](0xERR0R/blocky@4beb9fe): build(deps): bump github.com/quic-go/quic-go from 0.59.1 to 0.60.0 ([#​2090](0xERR0R/blocky#2090)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`8fe2202`](0xERR0R/blocky@8fe2202): build(deps): bump golang.org/x/net from 0.55.0 to 0.56.0 ([#​2101](0xERR0R/blocky#2101)) ([@​dependabot](https://github.com/dependabot)\[bot]) - [`52fa6a4`](0xERR0R/blocky@52fa6a4): build(deps): bump golang.org/x/sys from 0.45.0 to 0.46.0 ([#​2096](0xERR0R/blocky#2096)) ([@​dependabot](https://github.com/dependabot)\[bot]) ##### Misc - [`1c9f717`](0xERR0R/blocky@1c9f717): ci(e2e): speed up e2e job via Ginkgo proc oversubscription ([#​2085](0xERR0R/blocky#2085)) ([@​0xERR0R](https://github.com/0xERR0R)) - [`8d49922`](0xERR0R/blocky@8d49922): ci: cross-compile multi-arch docker image instead of QEMU emulation ([#​2081](0xERR0R/blocky#2081)) ([@​0xERR0R](https://github.com/0xERR0R)) - [`355a9a1`](0xERR0R/blocky@355a9a1): docs(grafana): redesign Grafana dashboard and update integration guide ([#​2110](0xERR0R/blocky#2110)) ([@​0xERR0R](https://github.com/0xERR0R)) - [`c791e80`](0xERR0R/blocky@c791e80): perf(e2e): probe blocky healthcheck at 250ms during start period ([#​2086](0xERR0R/blocky#2086)) ([@​0xERR0R](https://github.com/0xERR0R)) - [`a0fb375`](0xERR0R/blocky@a0fb375): perf(lists): speed up blocklist loading (cache build + parsing) ([#​2083](0xERR0R/blocky#2083)) ([@​0xERR0R](https://github.com/0xERR0R)) - [`316b073`](0xERR0R/blocky@316b073): perf(resolver): pre-classify client groups to cut per-query allocations ([#​2103](0xERR0R/blocky#2103)) ([@​0xERR0R](https://github.com/0xERR0R)) - [`d502806`](0xERR0R/blocky@d502806): perf(server): let Truncate decide response compression ([#​2102](0xERR0R/blocky#2102)) ([@​0xERR0R](https://github.com/0xERR0R)) - [`8b32512`](0xERR0R/blocky@8b32512): test(e2e): de-flake PROXY protocol and upstream init.strategy specs ([#​2099](0xERR0R/blocky#2099)) ([@​0xERR0R](https://github.com/0xERR0R)) *** #### ❤️ Support Blocky Blocky is free and open source, developed in my spare time — no telemetry, no ads, no hidden filtering. If it's useful to you, please consider supporting its continued development: [GitHub Sponsors](https://github.com/sponsors/0xERR0R) · [thanks.dev](https://thanks.dev/u/gh/0xERR0R) · [Liberapay](https://liberapay.com/spx01) · [Ko-fi](https://ko-fi.com/0xerr0r) · [PayPal](https://paypal.me/spx01) Thank you to everyone supporting Blocky! 🙏 </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMjIuMSIsInVwZGF0ZWRJblZlciI6IjQzLjIyMi4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
Summary
Adds
queryLog.ignore.domains, letting users exclude queries from the query log by domain name. Each entry is an exact domain, a*.wildcard, or a/regex/— the same syntax as blocklists. This complements the existingqueryLog.ignore.sudnflag.Motivation (closes #1390): conditional forwarding makes Apple devices flood the query log with repetitive
*._dns-sd._udp.*and reverse-lookup*.in-addr.arpaqueries. Pi-hole and AdGuard Home already let users suppress such domains; this brings the same capability to Blocky.Implementation
cache/stringcache.ChainedGroupedCache: regex + wildcard + exact) — no new matching logic.nilwhen no domains are configured (zero per-query cost on the common path).QueryLoggingResolver.ignore(), matching the question name normalized viautil.ExtractDomain(lowercase, trailing dot stripped) — consistent with how blocklist entries are stored./regex/entries are pre-validated withregexp.Compileand warned+skipped at startup (the underlying cache otherwise only logs to a global logger), and a lone"/"entry is rejected rather than crashing.Test plan
go build ./...go test ./config/ ./resolver/(Ginkgo) — exact/wildcard/regex matches excluded, non-matching domains still logged, SUDN unaffected, empty list = fast path, invalid-regex and lone-/warn+skip without panicgo vet ./config/ ./resolver/golangci-lint run ./config/... ./resolver/...— 0 issuesdocs/configuration.md: table rows + example)Note for reviewers
While building this I found a pre-existing latent bug in
cache/stringcache:regexCacheFactory.addEntryslicesentry[1:len(entry)-1]without a length guard, so a lone/entry panics. It's reachable from any list source (e.g. a stray/line in a blocklist). I guarded the new query-log path against it here, but did not touch the shared cache (out of scope for this issue) — worth a separate hardening PR.