Skip to content

Commit

Permalink
Merge pull request Tantalor93#139 from Tantalor93/godoc
Browse files Browse the repository at this point in the history
add godoc
  • Loading branch information
Ondřej Benkovský authored Aug 30, 2023
2 parents 9cc45b2 + 3446df6 commit 4760497
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 39 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ jobs:
build:
working_directory: ~/repo
docker:
- image: cimg/go:1.20
- image: cimg/go:1.21
steps:
- checkout
- restore_cache:
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![codecov](https://codecov.io/gh/Tantalor93/dnspyre/branch/master/graph/badge.svg?token=MC6PK2OLMK)](https://codecov.io/gh/Tantalor93/dnspyre)
[![lint](https://github.com/Tantalor93/dnspyre/actions/workflows/lint.yml/badge.svg?branch=master)](https://github.com/Tantalor93/dnspyre/actions/workflows/lint.yml)
[![](https://godoc.org/github.com/Tantalor93/dnspyre/v2/cmd?status.svg)](https://godoc.org/github.com/tantalor93/dnspyre/v2/cmd)

![dnspyre logo](./docs/assets/logo.png)

Expand Down
98 changes: 79 additions & 19 deletions cmd/benchmark.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,57 +29,117 @@ var client = http.Client{
Timeout: 120 * time.Second,
}

// Benchmark is representation of benchmark scenario.
// 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.
type Benchmark struct {
Server string
Types []string
Count int64
// 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:port, if port is not provided then port 53 is used.
// for DoT the format is <IP>:[port], if port is not provided then port 853 is used.
// for DoH the format is https://<hostname>:[port] or http://<hostname>:[port], if port is not provided then either 443 or 80 port is used.
// for DoQ the format is quic://<hostname>:[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 int
// 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 int64

// 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

UDPSize uint16
// 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

// 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 time.Duration
ReadTimeout time.Duration
// 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 time.Duration
HistMax time.Duration
HistPre int

Csv string
// 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 bool
// Color controls coloring of std output.
Color bool

PlotDir string
// 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 "png" and "jpg".
PlotFormat string

DohMethod 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

// 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

Duration time.Duration

// internal variable so we do not have to parse the address with each request.
useDoH bool
useQuic bool
Expand Down
3 changes: 2 additions & 1 deletion cmd/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ type orderedMap struct {
order []string
}

// PrintReport print formatted benchmark results to stdout. If there is a fatal error while printing report, an error is returned.
// 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.
func (b *Benchmark) PrintReport(w io.Writer, stats []*ResultStats, t time.Duration) error {
// merge all the stats here
timings := hdrhistogram.New(b.HistMin.Nanoseconds(), b.HistMax.Nanoseconds(), b.HistPre)
Expand Down
6 changes: 3 additions & 3 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ func init() {
pApp.Flag("probability", "Each provided hostname will be used with provided probability. Value 1 and above means that each hostname will be used by each concurrent benchmark goroutine. Useful for randomizing queries across benchmark goroutines.").
Default("1").Float64Var(&benchmark.Probability)

pApp.Flag("edns0", "Enable EDNS0 with specified size.").Default("0").Uint16Var(&benchmark.UDPSize)

pApp.Flag("ednsopt", "code[:value], Specify EDNS option with code point code and optionally payload of value as a hexadecimal string. code must be an arbitrary numeric value.").
Default("").StringVar(&benchmark.EdnsOpt)

Expand Down Expand Up @@ -118,7 +116,9 @@ func init() {

pApp.Arg("queries", "Queries to issue. It can be a local file referenced using @<file-path>, for example @data/2-domains. "+
"It can also be resource 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.").Required().StringsVar(&benchmark.Queries)
"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\"").
Required().StringsVar(&benchmark.Queries)
}

// Execute starts main logic of command.
Expand Down
12 changes: 7 additions & 5 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ A high QPS DNS benchmark.
Flags:
--[no-]help Show context-sensitive help (also try --help-long and --help-man).
-s, --server="127.0.0.1" DNS server IP:port to test. IPv6 is also supported, for example '[fddd:dddd::]:53'. DoH (DNS over HTTPS) servers are supported such as `https://1.1.1.1/dns-query`, when such server is provided, the benchmark automatically switches to the use of DoH. Note that path on which the DoH server handles requests (like `/dns-query`) has to be provided as well. DoQ (DNS over QUIC) servers are also supported, such as `quic://dns.adguard-dns.com`, when such server is
provided the benchmark switches to the use of DoQ.
-s, --server="127.0.0.1" DNS server IP:port to test. IPv6 is also supported, for example '[fddd:dddd::]:53'. DoH (DNS over HTTPS) servers are supported such as `https://1.1.1.1/dns-query`, when such server is provided, the benchmark automatically
switches to the use of DoH. Note that path on which the DoH server handles requests (like `/dns-query`) has to be provided as well. DoQ (DNS over QUIC) servers are also supported, such as `quic://dns.adguard-dns.com`,
when such server is provided the benchmark switches to the use of DoQ.
-t, --type=A ... Query type. Repeatable flag. If multiple query types are specified then each query will be duplicated for each type.
-n, --number=NUMBER How many times the provided queries are repeated. Note that the total number of queries issued = types*number*concurrency*len(queries).
-c, --concurrency=1 Number of concurrent queries to issue.
Expand All @@ -40,7 +41,6 @@ Flags:
--query-per-conn=0 Queries on a connection before creating a new one. 0: unlimited. Applicable for plain DNS and DoT, this option is not considered for DoH or DoQ.
-r, --[no-]recurse Allow DNS recursion. Enabled by default.
--probability=1 Each provided hostname will be used with provided probability. Value 1 and above means that each hostname will be used by each concurrent benchmark goroutine. Useful for randomizing queries across benchmark goroutines.
--edns0=0 Enable EDNS0 with specified size.
--ednsopt="" code[:value], Specify EDNS option with code point code and optionally payload of value as a hexadecimal string. code must be an arbitrary numeric value.
--[no-]tcp Use TCP for DNS requests.
--[no-]dot Use DoT (DNS over TLS) for DNS requests.
Expand All @@ -62,9 +62,11 @@ Flags:
--doh-method=post HTTP method to use for DoH requests. Supported values: get, post.
--doh-protocol=1.1 HTTP protocol to use for DoH requests. Supported values: 1.1, 2 and 3.
--[no-]insecure Disables server TLS certificate validation. Applicable for DoT, DoH and DoQ.
-d, --duration=1m 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 --number option. The duration is specified in GO duration format e.g. 10s, 15m, 1h.
-d, --duration=1m 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 --number option. The duration is specified in GO duration format e.g. 10s, 15m, 1h.
--[no-]version Show application version.
Args:
<queries> Queries to issue. It can be a local file referenced using @<file-path>, for example @data/2-domains. It can also be resource 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.
<queries> Queries to issue. It can be a local file referenced using @<file-path>, for example @data/2-domains. It can also be resource 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"
```
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/tantalor93/dnspyre/v2

go 1.20
go 1.21

require (
github.com/HdrHistogram/hdrhistogram-go v1.1.2
Expand All @@ -9,10 +9,10 @@ require (
github.com/miekg/dns v1.1.55
github.com/montanaflynn/stats v0.7.1
github.com/olekukonko/tablewriter v0.0.5
github.com/quic-go/quic-go v0.37.0
github.com/quic-go/quic-go v0.38.1
github.com/stretchr/testify v1.8.4
github.com/tantalor93/doh-go v0.1.0
github.com/tantalor93/doq-go v0.7.1
github.com/tantalor93/doq-go v0.8.0
go-hep.org/x/hep v0.33.0
go.uber.org/ratelimit v0.3.0
golang.org/x/net v0.14.0
Expand Down Expand Up @@ -40,7 +40,7 @@ require (
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-20 v0.3.0 // indirect
github.com/quic-go/qtls-go1-20 v0.3.3 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
golang.org/x/crypto v0.12.0 // indirect
Expand Down
Loading

0 comments on commit 4760497

Please sign in to comment.