cmd

package
v2.22.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 17, 2024 License: MIT Imports: 41 Imported by: 0

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// Version is set during release of project during build process.
	Version string
)

Functions

func Execute

func Execute()

Execute starts main logic of command.

Types

type Benchmark

type Benchmark struct {
	// Server represents (plain DNS, DoT, DoH or DoQ) server, which will be benchmarked.
	// Format depends on the DNS protocol, that should be used for DNS benchmark.
	// For plain DNS (either over UDP or TCP) the format is <IP/host>[:port], if port is not provided then port 53 is used.
	// For DoT the format is <IP/host>[:port], if port is not provided then port 853 is used.
	// For DoH the format is https://<IP/host>[:port][/path] or http://<IP/host>[:port][/path], if port is not provided then either 443 or 80 port is used. If no path is provided, then /dns-query is used.
	// For DoQ the format is quic://<IP/host>[:port], if port is not provided then port 853 is used.
	Server string

	// Types is an array of DNS query types, that should be used in benchmark. All domains retrieved from domain data source will be fired with each
	// type specified here.
	Types []string

	// Count specifies how many times each domain from data source is used by each worker. Either Benchmark.Count or Benchmark.Duration must be specified.
	// If Benchmark.Count and Benchmark.Duration is specified at once, it is considered invalid state of Benchmark.
	Count int64

	// Duration specifies for how long the benchmark should be executing, the benchmark will run for the specified time
	// while sending DNS requests in an infinite loop based on the data source. After running for the specified duration, the benchmark is canceled.
	// This option is exclusive with Benchmark.Count.
	Duration time.Duration

	// Concurrency controls how many concurrent queries will be issued at once. Benchmark will spawn Concurrency number of parallel worker goroutines.
	Concurrency uint32

	// Rate configures global rate limit for queries per second. This limit is shared between all the worker goroutines. This means that queries generated by this Benchmark
	// per second will not exceed this limit.
	Rate int
	// RateLimitWorker configures rate limit per worker for queries per second. This means that queries generated by each concurrent worker per second will not exceed this limit.
	RateLimitWorker int

	// QperConn configures how many queries are sent by each connection (socket) before closing it and creating a new one.
	// This is considered only for plain DNS over UDP or TCP and DoT.
	QperConn int64

	// Recurse configures whether the DNS queries generated by this Benchmark have Recursion Desired (RD) flag set.
	Recurse bool

	// Probability is used to bring randomization into Benchmark runs. When Probability is 1 or above, then all the domains passed in Queries field will be used during Benchmark run.
	// When Probability is less than 1 and more than 0, then each domain in Queries has Probability chance to be used during benchmark.
	// When Probability is less than 0, then no domain from Queries is used during benchmark.
	Probability float64

	// EdnsOpt specifies EDNS option with code point code and optionally payload of value as a hexadecimal string in format code[:value].
	// code must be an arbitrary numeric value.
	EdnsOpt string

	// DNSSEC Allow DNSSEC (sets DO bit for all DNS requests to 1)
	DNSSEC bool

	// Edns0 configures EDNS0 usage in DNS requests send by benchmark and configures EDNS0 buffer size to the specified value. When 0 is configured, then EDNS0 is not used.
	Edns0 uint16

	// TCP controls whether plain DNS benchmark uses TCP or UDP. When true, the TCP is used.
	TCP bool

	// DOT controls whether DoT is used for the benchmark.
	DOT bool

	// WriteTimeout configures write timeout for DNS requests generated by Benchmark.
	WriteTimeout time.Duration
	// ReadTimeout configures read timeout for DNS responses.
	ReadTimeout time.Duration
	// ConnectTimeout configures timeout for connection establishment.
	ConnectTimeout time.Duration
	// RequestTimeout configures overall timeout for a single DNS request.
	RequestTimeout time.Duration

	// Rcodes controls whether ResultStats.Codes is filled in Benchmark results.
	Rcodes bool

	// HistDisplay controls whether Benchmark.PrintReport will include histogram.
	HistDisplay bool
	// HistMin controls minimum value of histogram printed by Benchmark.PrintReport.
	HistMin time.Duration
	// HistMax controls maximum value of histogram printed by Benchmark.PrintReport.
	HistMax time.Duration
	// HistPre controls precision of histogram printed by Benchmark.PrintReport.
	HistPre int

	// Csv path to file, where the Benchmark result distribution is written.
	Csv string
	// JSON controls whether the Benchmark.PrintReport prints the Benchmark results in JSON format (option is true).
	JSON bool

	// Silent controls whether the Benchmark.Run and Benchmark.PrintReport writes anything to stdout.
	Silent bool
	// Color controls coloring of std output.
	Color bool

	// PlotDir controls where the generated graphs are exported. If set to empty (""), which is default value. Then no graphs are generated.
	PlotDir string
	// PlotFormat controls the format of generated graphs. Supported values are "svg", "png" and "jpg".
	PlotFormat string

	// DohMethod controls HTTP method used for sending DoH requests. Supported values are "post" and "get". Default is "post".
	DohMethod string
	// DohProtocol controls HTTP protocol version used fo sending DoH requests. Supported values are "1.1", "2" and "3". Default is "1.1".
	DohProtocol string

	// Insecure disables server TLS certificate validation. Applicable for DoT, DoH and DoQ.
	Insecure bool

	// ProgressBar controls whether the progress bar is printed.
	ProgressBar bool

	// Queries list of domains and data sources to be used in Benchmark. It can contain a local file data source referenced using @<file-path>, for example @data/2-domains.
	// It can also be data source file accessible using HTTP, like https://raw.githubusercontent.com/Tantalor93/dnspyre/master/data/1000-domains, in that case the file will be downloaded and saved in-memory.
	// These data sources can be combined, for example "google.com @data/2-domains https://raw.githubusercontent.com/Tantalor93/dnspyre/master/data/2-domains".
	Queries []string
	// contains filtered or unexported fields
}

Benchmark is representation of runnable DNS benchmark scenario. based on domains provided in Benchmark.Queries, it will be firing DNS queries until the desired number of queries have been sent by each concurrent worker (see Benchmark.Count) or the desired benchmark duration have been reached (see Benchmark.Duration).

Benchmark will create Benchmark.Concurrency worker goroutines, where each goroutine will be generating DNS queries with domains defined using Benchmark.Queries and DNS query types defined in Benchmark.Types. Each worker will either generate Benchmark.Types*Benchmark.Count*len(Benchmark.Queries) number of queries if Benchmark.Count is specified, or the worker will be generating arbitrary number of queries until Benchmark.Duration is reached.

func (*Benchmark) PrintReport

func (b *Benchmark) PrintReport(w io.Writer, stats []*ResultStats, benchStart time.Time, benchDuration time.Duration) error

PrintReport prints formatted benchmark result to stdout, exports graphs and generates CSV output if configured. If there is a fatal error while printing report, an error is returned.

Example
b, rs := testReportData()

b.PrintReport(os.Stdout, []*ResultStats{&rs}, time.Now(), time.Second)
Output:

Total requests:		1
Read/Write errors:	3
ID mismatch errors:	6
DNS success codes:	4
Truncated responses:	7

DNS response codes:
	NOERROR:	2

DNS question types:
	A:	2

Time taken for tests:	 1s
Questions per second:	 1.0
DNS timings, 2 datapoints
	 min:		 5ns
	 mean:		 7ns
	 [+/-sd]:	 2ns
	 max:		 10ns
	 p99:		 10ns
	 p95:		 10ns
	 p90:		 10ns
	 p75:		 10ns
	 p50:		 5ns

Total Errors: 6
Top errors:
test2	3 (50.00)%
read udp 8.8.8.8:53	2 (33.33)%
test	1 (16.67)%
Example (Dnssec)
b, rs := testReportData()
b.DNSSEC = true
rs.AuthenticatedDomains = map[string]struct{}{"example.org.": {}}

b.PrintReport(os.Stdout, []*ResultStats{&rs}, time.Now(), time.Second)
Output:

Total requests:		1
Read/Write errors:	3
ID mismatch errors:	6
DNS success codes:	4
Truncated responses:	7

DNS response codes:
	NOERROR:	2

DNS question types:
	A:	2

Number of domains secured using DNSSEC: 1

Time taken for tests:	 1s
Questions per second:	 1.0
DNS timings, 2 datapoints
	 min:		 5ns
	 mean:		 7ns
	 [+/-sd]:	 2ns
	 max:		 10ns
	 p99:		 10ns
	 p95:		 10ns
	 p90:		 10ns
	 p75:		 10ns
	 p50:		 5ns

Total Errors: 6
Top errors:
test2	3 (50.00)%
read udp 8.8.8.8:53	2 (33.33)%
test	1 (16.67)%
Example (Doh)
b, rs := testReportData()
rs.DoHStatusCodes = map[int]int64{
	200: 2,
	500: 1,
}

b.PrintReport(os.Stdout, []*ResultStats{&rs}, time.Now(), time.Second)
Output:

Total requests:		1
Read/Write errors:	3
ID mismatch errors:	6
DNS success codes:	4
Truncated responses:	7

DNS response codes:
	NOERROR:	2

DoH HTTP response status codes:
	200:	2
	500:	1

DNS question types:
	A:	2

Time taken for tests:	 1s
Questions per second:	 1.0
DNS timings, 2 datapoints
	 min:		 5ns
	 mean:		 7ns
	 [+/-sd]:	 2ns
	 max:		 10ns
	 p99:		 10ns
	 p95:		 10ns
	 p90:		 10ns
	 p75:		 10ns
	 p50:		 5ns

Total Errors: 6
Top errors:
test2	3 (50.00)%
read udp 8.8.8.8:53	2 (33.33)%
test	1 (16.67)%
Example (Json)
b, rs := testReportData()
b.JSON = true
b.Rcodes = true
b.HistDisplay = true

b.PrintReport(os.Stdout, []*ResultStats{&rs}, time.Now(), time.Second)
Output:

{"totalRequests":1,"totalSuccessCodes":4,"totalErrors":6,"TotalIDmismatch":6,"totalTruncatedResponses":7,"responseRcodes":{"NOERROR":2},"questionTypes":{"A":2},"queriesPerSecond":1,"benchmarkDurationSeconds":1,"latencyStats":{"minMs":0,"meanMs":0,"stdMs":0,"maxMs":0,"p99Ms":0,"p95Ms":0,"p90Ms":0,"p75Ms":0,"p50Ms":0},"latencyDistribution":[{"latencyMs":0,"count":0},{"latencyMs":0,"count":0},{"latencyMs":0,"count":0},{"latencyMs":0,"count":0},{"latencyMs":0,"count":0},{"latencyMs":0,"count":1},{"latencyMs":0,"count":0},{"latencyMs":0,"count":0},{"latencyMs":0,"count":0},{"latencyMs":0,"count":0},{"latencyMs":0,"count":1}]}
Example (Json_dnssec)
b, rs := testReportData()
b.JSON = true
b.Rcodes = true
b.HistDisplay = true
b.DNSSEC = true
rs.AuthenticatedDomains = map[string]struct{}{"example.org.": {}}

b.PrintReport(os.Stdout, []*ResultStats{&rs}, time.Now(), time.Second)
Output:

{"totalRequests":1,"totalSuccessCodes":4,"totalErrors":6,"TotalIDmismatch":6,"totalTruncatedResponses":7,"responseRcodes":{"NOERROR":2},"questionTypes":{"A":2},"queriesPerSecond":1,"benchmarkDurationSeconds":1,"latencyStats":{"minMs":0,"meanMs":0,"stdMs":0,"maxMs":0,"p99Ms":0,"p95Ms":0,"p90Ms":0,"p75Ms":0,"p50Ms":0},"latencyDistribution":[{"latencyMs":0,"count":0},{"latencyMs":0,"count":0},{"latencyMs":0,"count":0},{"latencyMs":0,"count":0},{"latencyMs":0,"count":0},{"latencyMs":0,"count":1},{"latencyMs":0,"count":0},{"latencyMs":0,"count":0},{"latencyMs":0,"count":0},{"latencyMs":0,"count":0},{"latencyMs":0,"count":1}],"totalDNSSECSecuredDomains":1}
Example (Json_doh)
b, rs := testReportData()
b.JSON = true
b.Rcodes = true
b.HistDisplay = true
rs.DoHStatusCodes = map[int]int64{
	200: 2,
}

b.PrintReport(os.Stdout, []*ResultStats{&rs}, time.Now(), time.Second)
Output:

{"totalRequests":1,"totalSuccessCodes":4,"totalErrors":6,"TotalIDmismatch":6,"totalTruncatedResponses":7,"responseRcodes":{"NOERROR":2},"questionTypes":{"A":2},"queriesPerSecond":1,"benchmarkDurationSeconds":1,"latencyStats":{"minMs":0,"meanMs":0,"stdMs":0,"maxMs":0,"p99Ms":0,"p95Ms":0,"p90Ms":0,"p75Ms":0,"p50Ms":0},"latencyDistribution":[{"latencyMs":0,"count":0},{"latencyMs":0,"count":0},{"latencyMs":0,"count":0},{"latencyMs":0,"count":0},{"latencyMs":0,"count":0},{"latencyMs":0,"count":1},{"latencyMs":0,"count":0},{"latencyMs":0,"count":0},{"latencyMs":0,"count":0},{"latencyMs":0,"count":0},{"latencyMs":0,"count":1}],"dohHTTPResponseStatusCodes":{"200":2}}
Example (Server_dns_errors)
b, rs := testReportDataWithServerDNSErrors()

b.PrintReport(os.Stdout, []*ResultStats{&rs}, time.Now(), time.Second)
Output:

Total requests:		3
Read/Write errors:	3

DNS question types:
	A:	3

Time taken for tests:	 1s
Questions per second:	 3.0

Total Errors: 3
Top errors:
no such host unknown.host.com	3 (100.00)%

func (*Benchmark) Run

func (b *Benchmark) Run(ctx context.Context) ([]*ResultStats, error)

Run executes benchmark, if benchmark is unable to start the error is returned, otherwise array of results from parallel benchmark goroutines is returned.

Example (Doh)
bench := createBenchmark("https://1.1.1.1", true, 1)

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
bench.Run(ctx)
Output:

Using 1 hostnames
Benchmarking https://1.1.1.1/dns-query via https/1.1 (POST) with 2 concurrent requests
Example (Doh_get)
bench := createBenchmark("https://1.1.1.1", true, 1)
bench.DohMethod = getMethod

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
bench.Run(ctx)
Output:

Using 1 hostnames
Benchmarking https://1.1.1.1/dns-query via https/1.1 (GET) with 2 concurrent requests
Example (Doh_http2)
bench := createBenchmark("https://1.1.1.1", true, 1)
bench.DohProtocol = http2Proto

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
bench.Run(ctx)
Output:

Using 1 hostnames
Benchmarking https://1.1.1.1/dns-query via https/2 (POST) with 2 concurrent requests
Example (Doh_http3)
bench := createBenchmark("https://1.1.1.1", true, 1)
bench.DohProtocol = http3Proto

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
bench.Run(ctx)
Output:

Using 1 hostnames
Benchmarking https://1.1.1.1/dns-query via https/3 (POST) with 2 concurrent requests
Example (Doq)
bench := createBenchmark("quic://dns.adguard-dns.com", true, 1)

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
bench.Run(ctx)
Output:

Using 1 hostnames
Benchmarking dns.adguard-dns.com:853 via quic with 2 concurrent requests
Example (Dot)
bench := createBenchmark("8.8.8.8", true, 1)
bench.DOT = true

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
bench.Run(ctx)
Output:

Using 1 hostnames
Benchmarking 8.8.8.8:853 via tcp-tls with 2 concurrent requests
Example (PlainDNS_tcp)
bench := createBenchmark("8.8.8.8", true, 1)

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
bench.Run(ctx)
Output:

Using 1 hostnames
Benchmarking 8.8.8.8:53 via tcp with 2 concurrent requests
Example (PlainDNS_udp)
bench := createBenchmark("8.8.8.8", false, 1)

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
bench.Run(ctx)
Output:

Using 1 hostnames
Benchmarking 8.8.8.8:53 via udp with 2 concurrent requests

type Counters

type Counters struct {
	Total      int64
	IOError    int64
	Success    int64
	IDmismatch int64
	Truncated  int64
}

Counters represents various counters of benchmark results.

type Datapoint

type Datapoint struct {
	Duration time.Duration
	Start    time.Time
}

Datapoint one datapoint of benchmark (single DNS request).

type ErrorDatapoint added in v2.20.0

type ErrorDatapoint struct {
	Start time.Time
	Err   error
}

ErrorDatapoint one datapoint representing single IO error of benchmark. Datapoint one datapoint of benchmark (single DNS request).

type ResultStats

type ResultStats struct {
	Codes                map[int]int64
	Qtypes               map[string]int64
	Hist                 *hdrhistogram.Histogram
	Timings              []Datapoint
	Counters             *Counters
	Errors               []ErrorDatapoint
	AuthenticatedDomains map[string]struct{}
	DoHStatusCodes       map[int]int64
}

ResultStats is a representation of benchmark results of single concurrent thread.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL