This repository was archived by the owner on May 9, 2026. It is now read-only.
Release/0.3.5#52
Merged
Merged
Conversation
…ocol/DNSSEC handling - Add _doh_clients dict (AsyncClient per resolver) and _get_doh_client() so DoH queries reuse HTTP/2 connections instead of opening a new TLS handshake per query. Measured improvement: ~350ms avg down to ~170ms avg on mobile. - Add _dot_connections dict (StreamReader/Writer per resolver) and _get_dot_connection() so DoT queries reuse TLS connections instead of handshaking on every query. Measured improvement: 795-1759ms avg down to 200-460ms avg on mobile hotspot. - Add close() to drain both pools. Must be awaited after run_benchmark. Used via single _run() coroutine in CLI to avoid closed event loop errors. - Add TLS_ERROR to QueryStatus enum for ssl.SSLError in query_single_dot. Previously mapped to CONNECTION_REFUSED which was misleading. - Evict pooled DoT connection on timeout, SSL error, and unknown errors so retries always get a clean connection. - Fix double time.time() calls in DoH/DoT timeout and exception handlers. Two consecutive calls produced inconsistent end_time and latency_ms values. Capture end_time once at the top of each handler. - Add httpx.HTTPStatusError handler in query_single_doh mapped to SERVFAIL with HTTP status code in error_message. Previously fell through to the generic Exception handler and returned UNKNOWN_ERROR. - Pass protocol and doh_urls to _run_warmup and _run_fast_warmup so warmup queries use the same protocol as the benchmark. Previously always used plain UDP, meaning DoH/DoT warmup did not prime the right connections. - Validate DoH URL presence early in run_benchmark before dispatching tasks so a missing URL raises a clear ValueError upfront instead of mid-benchmark. - Change enable_dnssec=True hardcoded to enable_dnssec=dnssec_validate so the DO bit and RRSIG overhead only apply when --dnssec-validate is passed. Plain benchmarks no longer pay the extra latency unconditionally. - Add Tuple to typing imports required by _dot_connections type annotation. - Remove dead commented-out import dns.query.
…y stats and fix typo - Add completed column to _create_dataframe that is True for both SUCCESS and DNSSEC_FAILED. A DNSSEC_FAILED query completed successfully at the network level — only the AD flag validation failed client-side — so its latency is valid and should be included in all latency statistics. - Switch all latency filters from success==True to completed==True across get_resolver_statistics, get_overall_statistics, get_domain_statistics, get_record_type_statistics, and get_protocol_statistics. Success rate reporting remains on success only so the two metrics stay separate. Before this fix, using --dnssec-validate against unsigned domains caused all queries to return DNSSEC_FAILED, making avg/median/p95 show 0.0 and fastest/slowest resolver show N/A in the summary. - Fix typo: "interation" -> "iteration" in _create_dataframe. The wrong column name silently produced NaN in all downstream CSV and Excel exports for the iteration column.
…tion cleanup, and UX fixes
benchmark:
- Move _resolve_protocol_and_doh_urls before benchmark_started flag so bad
--doh/--dot flag combos fail before any output or side effects.
- Add explicit except click.UsageError: raise so Click formats usage errors
cleanly without triggering the feedback prompt or error message.
- Merge two asyncio.run calls into single _run() coroutine to fix
RuntimeError: Event loop is closed from calling asyncio.run(engine.close())
after asyncio.run(run_benchmark()) had already closed the loop.
- Skip DNSSEC signed-domain warning for custom domain files. The check
compared user domains against DOMAINS_DATABASE which has no knowledge of
user-supplied domains, producing near-constant false positive warnings.
Warning now only shown with --use-defaults where signed status is known.
- Fix PDF export catching RuntimeError with wrong error message. Changed to
broad Exception with "PDF export failed" message. Progress bar now advances
even on PDF failure to keep the bar consistent.
- Remove redundant bare print() showing DNSSEC ENABLED/DISABLED. Duplicated
the config block line, used print instead of click.echo, and ignored --quiet.
- Update DNSSEC config message to reflect enable_dnssec=dnssec_validate:
off means no DO bit and no collection; enforced means DO bit set with a
note that success rate and DNSSEC outcome are separate metrics.
- Rename summary line from "DNSSEC validated" to "DNSSEC AD validated" so
users understand this is specifically the AD flag count, not query success.
- Update enable_dnssec comment to reflect that DO bit is only set when
--dnssec-validate is passed, not unconditionally.
top:
- Wire doh, dot, doh_url, dnssec_validate into _resolve_protocol_and_doh_urls,
DNSQueryEngine, and run_benchmark. Flags were declared but silently ignored.
- Switch domain loading from load_domains_from_file to parse_domains_input
so --domains accepts both file paths and inline comma-separated lists.
- Merge asyncio.run and engine.close into single _run() coroutine.
- Add except click.UsageError: raise to let Click handle usage errors cleanly.
compare:
- Same protocol/DNSSEC wiring as top.
- Same parse_domains_input fix as top.
- Same _run() coroutine fix as top.
- Guard sorted() against nan avg_latency using math.isnan check with
float("inf") fallback. Resolvers with zero successes produce nan which
raises TypeError in Python 3.12 comparisons.
- Add protocol field to JSON export output.
monitoring:
- Same protocol/DNSSEC wiring as top and compare.
- Move DNSQueryEngine construction outside the while loop. Previously a new
engine was created every check interval, discarding the connection pool and
paying full TLS handshake cost on every check.
- Fix RuntimeError: Event loop is closed on Ctrl+C. asyncio.run() closes the
loop on each iteration. The finally block called asyncio.run(engine.close())
on the already-closed loop and printed a full traceback. Fixed by creating
a fresh event loop in finally specifically for cleanup, wrapped in
try/except to suppress residual errors on exit.
- Remove bare raise from except Exception so all errors show a clean click
error message instead of a traceback to the user.
- Switch resolver loading from load_resolvers_from_file to
parse_resolvers_input so --resolvers accepts names, IPs, and file paths.
… new protocol and dnssec changes - Update tests to reflect enable_dnssec=dnssec_validate (no longer hardcoded True). - Add coverage for TLS_ERROR status returned on ssl.SSLError in query_single_dot. - Add coverage for httpx.HTTPStatusError mapped to SERVFAIL in query_single_doh. - Add coverage for completed column in BenchmarkAnalyzer including DNSSEC_FAILED queries in latency statistics. - Update warmup tests to verify protocol is passed through to _run_warmup and _run_fast_warmup.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.