Skip to content

Commit 81403a6

Browse files
flaviostutztsenart
authored andcommitted
Prometheus Exporter in attack (#534)
Closes #477, #534 Signed-off-by: Flávio Stutz <flaviostutz@gmail.com> Signed-off-by: Tomás Senart <tsenart@gmail.com>
1 parent 73d929f commit 81403a6

File tree

11 files changed

+1185
-7
lines changed

11 files changed

+1185
-7
lines changed

Dockerfile

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
FROM golang:1.20-alpine3.18 AS BUILD
2+
3+
RUN apk add make build-base git
4+
5+
WORKDIR /vegeta
6+
7+
# cache dependencies
8+
ADD go.mod /vegeta
9+
ADD go.sum /vegeta
10+
RUN go mod download
11+
12+
ADD . /vegeta
13+
14+
RUN make generate
15+
RUN make vegeta
16+
17+
FROM alpine:3.18.0
18+
19+
COPY --from=BUILD /vegeta/vegeta /bin/vegeta
20+
21+
ENTRYPOINT ["vegeta"]

README.md

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ Usage: vegeta [global flags] <command> [command flags]
7979

8080
global flags:
8181
-cpus int
82-
Number of CPUs to use (defaults to the number of CPUs you have)
82+
Number of CPUs to use (default = number of cpus)
8383
-profile string
8484
Enable profiling of [cpu, heap]
8585
-version
@@ -126,6 +126,8 @@ attack command:
126126
Attack name
127127
-output string
128128
Output file (default "stdout")
129+
-prometheus-addr string
130+
Prometheus exporter listen address [empty = disabled]. Example: 0.0.0.0:8880
129131
-proxy-header value
130132
Proxy CONNECT header
131133
-rate value
@@ -137,7 +139,7 @@ attack command:
137139
-root-certs value
138140
TLS root certificate files (comma separated list)
139141
-session-tickets
140-
Enable TLS session resumption support using session tickets (default false)
142+
Enable TLS session resumption using session tickets
141143
-targets string
142144
Targets file (default "stdin")
143145
-timeout duration
@@ -176,6 +178,7 @@ examples:
176178
vegeta report -type=json results.bin > metrics.json
177179
cat results.bin | vegeta plot > plot.html
178180
cat results.bin | vegeta report -type="hist[0,100ms,200ms,300ms]"
181+
179182
```
180183

181184
#### `-cpus`
@@ -783,6 +786,8 @@ It'll read and sort them by timestamp before generating reports.
783786
vegeta report *.bin
784787
```
785788

789+
Another way to gather results in distributed tests is to use the built-in Prometheus Exporter and configure a Prometheus Server to get test results from all Vegeta instances. See `attack` option "prometheus-addr" for more details and a complete example in the section "Prometheus Support".
790+
786791
## Usage: Real-time Analysis
787792

788793
If you are a happy user of iTerm, you can integrate vegeta with [jplot](https://github.com/rs/jplot) using [jaggr](https://github.com/rs/jaggr) to plot a vegeta report in real-time in the comfort of your terminal:
@@ -802,7 +807,7 @@ echo 'GET http://localhost:8080' | \
802807

803808
![](https://i.imgur.com/ttBDsQS.gif)
804809

805-
## Usage (Library)
810+
## Usage: Library
806811

807812
The library versioning follows [SemVer v2.0.0](https://semver.org/spec/v2.0.0.html).
808813
Since [lib/v9.0.0](https://github.com/tsenart/vegeta/tree/lib/v9.0.0), the library and cli
@@ -859,6 +864,67 @@ $ ulimit -u # processes / threads
859864

860865
Just pass a new number as the argument to change it.
861866

867+
## Prometheus Support
868+
869+
Vegeta has a built-in Prometheus Exporter that may be enabled during attacks so that you can point any Prometheus instance to Vegeta instances and get some metrics about http requests performance and about the Vegeta process itself.
870+
871+
To enable the Prometheus Exporter on the command line, use the "prometheus-addr" flag.
872+
873+
A Prometheus HTTP endpoint will be available only during the lifespan of an attack and will be closed right after the attack is finished.
874+
875+
The following metrics are exposed:
876+
877+
* `request_bytes_in` - bytes count received from targeted servers by "url", "method" and "status"
878+
* `request_bytes_out` - bytes count sent to targeted server by "url", "method" and "status"
879+
* `request_seconds` - histogram with request latency and counters by "url", "method" and "status"
880+
881+
<image src="prometheus-sample.png" width="500" />
882+
883+
Check file [lib/prom/grafana.json](lib/prom/grafana.json) with the source of this sample dashboard in Grafana.
884+
885+
### Samples
886+
887+
If you want to query P90 quantiles, for example, use "histogram_quantile(0.90, sum(rate(request_seconds_bucket[1m])) by (le, status))"
888+
889+
### Prometheus Exporter example
890+
891+
* Create a docker-compose.yml
892+
893+
```
894+
version: '3.5'
895+
services:
896+
vegeta:
897+
image: tsenart/vegeta
898+
ports:
899+
- 8880:8880
900+
command: sh -c 'echo "GET https://www.yahoo.com" | vegeta attack -duration=30s -rate=5 -prometheus-addr=0.0.0.0:8880'
901+
902+
prometheus:
903+
image: flaviostutz/prometheus:2.19.2.0
904+
ports:
905+
- 9090:9090
906+
environment:
907+
- SCRAPE_INTERVAL=10s
908+
- SCRAPE_TIMEOUT=10s
909+
- STATIC_SCRAPE_TARGETS=vegeta@vegeta:8880
910+
```
911+
912+
* Run `docker-compose up -d`
913+
914+
* Run `curl localhost:8880` to see plain Prometheus Exporter endpoint contents
915+
916+
* Open Prometheus server instance with your browser at http://localhost:9090
917+
918+
* Go to "Graph" and execute query `rate(request_seconds_sum[1m])` and then select the "Graph" tab to see a graph with latency over time
919+
920+
#### More resources
921+
922+
* See https://prometheus.io/docs/prometheus/latest/querying/basics/ for query details
923+
924+
* Use Grafana for creating stateful dashboards. Get a sample dashboard for Vegeta [here](grafana.json)
925+
926+
* For more elaborated scenarios, see https://github.com/flaviostutz/promster so that you can automatically register new Vegeta Prometheus Exporter instances to Prometheus in elastic scenarios.
927+
862928
## License
863929

864930
See [LICENSE](LICENSE).

attack.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ import (
1515
"syscall"
1616
"time"
1717

18+
"github.com/prometheus/client_golang/prometheus"
1819
"github.com/tsenart/vegeta/v12/internal/resolver"
1920
vegeta "github.com/tsenart/vegeta/v12/lib"
21+
prom "github.com/tsenart/vegeta/v12/lib/prom"
2022
)
2123

2224
func attackCmd() command {
@@ -27,6 +29,7 @@ func attackCmd() command {
2729
laddr: localAddr{&vegeta.DefaultLocalAddr},
2830
rate: vegeta.Rate{Freq: 50, Per: time.Second},
2931
maxBody: vegeta.DefaultMaxBody,
32+
promAddr: "0.0.0.0:8880",
3033
}
3134
fs.StringVar(&opts.name, "name", "", "Attack name")
3235
fs.StringVar(&opts.targetsf, "targets", "stdin", "Targets file")
@@ -56,6 +59,7 @@ func attackCmd() command {
5659
fs.Var(&opts.laddr, "laddr", "Local IP address")
5760
fs.BoolVar(&opts.keepalive, "keepalive", true, "Use persistent connections")
5861
fs.StringVar(&opts.unixSocket, "unix-socket", "", "Connect over a unix socket. This overrides the host address in target URLs")
62+
fs.StringVar(&opts.promAddr, "prometheus-addr", "", "Prometheus exporter listen address [empty = disabled]. Example: 0.0.0.0:8880")
5963
fs.Var(&dnsTTLFlag{&opts.dnsTTL}, "dns-ttl", "Cache DNS lookups for the given duration [-1 = disabled, 0 = forever]")
6064
fs.BoolVar(&opts.sessionTickets, "session-tickets", false, "Enable TLS session resumption using session tickets")
6165
systemSpecificFlags(fs, opts)
@@ -101,6 +105,7 @@ type attackOpts struct {
101105
keepalive bool
102106
resolvers csl
103107
unixSocket string
108+
promAddr string
104109
dnsTTL time.Duration
105110
sessionTickets bool
106111
}
@@ -178,6 +183,22 @@ func attack(opts *attackOpts) (err error) {
178183
return err
179184
}
180185

186+
// Start Prometheus Metrics and Server
187+
var pm *prom.Metrics
188+
if opts.promAddr != "" {
189+
r := prometheus.NewRegistry()
190+
pm, err = prom.NewMetrics(r)
191+
if err != nil {
192+
return err
193+
}
194+
srv, err := prom.StartPromServer(opts.promAddr, r)
195+
if err != nil {
196+
return err
197+
}
198+
199+
defer srv.Close()
200+
}
201+
181202
atk := vegeta.NewAttacker(
182203
vegeta.Redirects(opts.redirects),
183204
vegeta.Timeout(opts.timeout),
@@ -203,14 +224,15 @@ func attack(opts *attackOpts) (err error) {
203224
sig := make(chan os.Signal, 1)
204225
signal.Notify(sig, os.Interrupt, syscall.SIGTERM)
205226

206-
return processAttack(atk, res, enc, sig)
227+
return processAttack(atk, res, enc, sig, pm)
207228
}
208229

209230
func processAttack(
210231
atk *vegeta.Attacker,
211232
res <-chan *vegeta.Result,
212233
enc vegeta.Encoder,
213234
sig <-chan os.Signal,
235+
pm *prom.Metrics,
214236
) error {
215237
for {
216238
select {
@@ -223,6 +245,9 @@ func processAttack(
223245
if !ok {
224246
return nil
225247
}
248+
if pm != nil {
249+
pm.Observe(r)
250+
}
226251
if err := enc.Encode(r); err != nil {
227252
return err
228253
}

attack_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func TestAttackSignalOnce(t *testing.T) {
8686
wg.Add(1)
8787
go func() {
8888
defer wg.Done()
89-
processAttack(atk, res, enc, sig)
89+
processAttack(atk, res, enc, sig, nil)
9090
}()
9191

9292
// Allow more than one request to have started before stopping.
@@ -139,7 +139,7 @@ func TestAttackSignalTwice(t *testing.T) {
139139
wg.Add(1)
140140
go func() {
141141
defer wg.Done()
142-
processAttack(atk, res, enc, sig)
142+
processAttack(atk, res, enc, sig, nil)
143143
}()
144144

145145
// Exit as soon as possible.

docker-compose.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
version: '3.5'
2+
3+
services:
4+
5+
vegeta:
6+
build: .
7+
image: tsenart/vegeta
8+
ports:
9+
- 8880:8880
10+
command: sh -c 'echo "GET https://www.yahoo.com" | vegeta attack -duration=300s -rate=5 -prometheus-addr=0.0.0.0:8880 | vegeta report --type=text'
11+
12+
prometheus:
13+
image: flaviostutz/prometheus
14+
ports:
15+
- 9090:9090
16+
environment:
17+
- SCRAPE_INTERVAL=10s
18+
- SCRAPE_TIMEOUT=10s
19+
- STATIC_SCRAPE_TARGETS=vegeta@vegeta:8880
20+
21+
grafana:
22+
image: flaviostutz/grafana:5.2.4
23+
ports:
24+
- 3000:3000
25+
environment:
26+
- GF_SECURITY_ADMIN_PASSWORD=mypass
27+

go.mod

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ require (
1212
github.com/influxdata/tdigest v0.0.1
1313
github.com/mailru/easyjson v0.7.7
1414
github.com/miekg/dns v1.1.55
15+
github.com/prometheus/client_golang v1.16.0
1516
github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417
1617
github.com/streadway/quantile v0.0.0-20220407130108-4246515d968d
1718
github.com/tsenart/go-tsz v0.0.0-20180814235614-0bd30b3df1c3
@@ -20,12 +21,20 @@ require (
2021
)
2122

2223
require (
24+
github.com/beorn7/perks v1.0.1 // indirect
25+
github.com/cespare/xxhash/v2 v2.2.0 // indirect
26+
github.com/golang/protobuf v1.5.3 // indirect
2327
github.com/iancoleman/orderedmap v0.3.0 // indirect
2428
github.com/josharian/intern v1.0.0 // indirect
29+
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
30+
github.com/prometheus/client_model v0.3.0 // indirect
31+
github.com/prometheus/common v0.42.0 // indirect
32+
github.com/prometheus/procfs v0.10.1 // indirect
2533
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect
2634
golang.org/x/mod v0.12.0 // indirect
2735
golang.org/x/sync v0.3.0 // indirect
2836
golang.org/x/sys v0.10.0 // indirect
2937
golang.org/x/text v0.11.0 // indirect
3038
golang.org/x/tools v0.11.0 // indirect
39+
google.golang.org/protobuf v1.30.0 // indirect
3140
)

go.sum

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,28 @@
11
github.com/alecthomas/jsonschema v0.0.0-20220216202328-9eeeec9d044b h1:doCpXjVwui6HUN+xgNsNS3SZ0/jUZ68Eb+mJRNOZfog=
22
github.com/alecthomas/jsonschema v0.0.0-20220216202328-9eeeec9d044b/go.mod h1:/n6+1/DWPltRLWL/VKyUxg6tzsl5kHUCcraimt4vr60=
3+
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
4+
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
35
github.com/bmizerany/perks v0.0.0-20230307044200-03f9df79da1e h1:mWOqoK5jV13ChKf/aF3plwQ96laasTJgZi4f1aSOu+M=
46
github.com/bmizerany/perks v0.0.0-20230307044200-03f9df79da1e/go.mod h1:ac9efd0D1fsDb3EJvhqgXRbFx7bs2wqZ10HQPeU8U/Q=
57
github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b h1:6+ZFm0flnudZzdSE0JxlhR2hKnGPcNB35BjQf4RYQDY=
68
github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
9+
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
10+
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
711
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
812
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
13+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
914
github.com/dgryski/go-gk v0.0.0-20200319235926-a69029f61654 h1:XOPLOMn/zT4jIgxfxSsoXPxkrzz0FaCHwp33x5POJ+Q=
1015
github.com/dgryski/go-gk v0.0.0-20200319235926-a69029f61654/go.mod h1:qm+vckxRlDt0aOla0RYJJVeqHZlWfOm2UIxHaqPB46E=
1116
github.com/dgryski/go-lttb v0.0.0-20230207170358-f8fc36cdbff1 h1:dxwR3CStJdJamsIoMPCmxuIfBAPTgmzvFax+MvFav3M=
1217
github.com/dgryski/go-lttb v0.0.0-20230207170358-f8fc36cdbff1/go.mod h1:UwftcHUI/qTYvLAxrWmANuRckf8+08O3C3hwStvkhDU=
18+
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
19+
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
20+
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
21+
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
22+
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
23+
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
1324
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
25+
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
1426
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
1527
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
1628
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA=
@@ -20,18 +32,33 @@ github.com/influxdata/tdigest v0.0.1 h1:XpFptwYmnEKUqmkcDjrzffswZ3nvNeevbUSLPP/Z
2032
github.com/influxdata/tdigest v0.0.1/go.mod h1:Z0kXnxzbTC2qrx4NaIzYkE1k66+6oEDQTvL95hQFh5Y=
2133
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
2234
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
35+
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
36+
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
37+
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
2338
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
2439
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
40+
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
41+
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
2542
github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
2643
github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
44+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
45+
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
46+
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
2747
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
2848
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
49+
github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
50+
github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
51+
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
52+
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
53+
github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
54+
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
55+
github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
56+
github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
2957
github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417 h1:Lt9DzQALzHoDwMBGJ6v8ObDPR0dzr2a6sXTB1Fq7IHs=
3058
github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417/go.mod h1:qe5TWALJ8/a1Lqznoc5BDHpYX/8HU60Hm2AwRmqzxqA=
3159
github.com/streadway/quantile v0.0.0-20220407130108-4246515d968d h1:X4+kt6zM/OVO6gbJdAfJR60MGPsqCzbtXNnjoGqdfAs=
3260
github.com/streadway/quantile v0.0.0-20220407130108-4246515d968d/go.mod h1:lbP8tGiBjZ5YWIc2fzuRpTaz0b/53vT6PEs3QuAWzuU=
3361
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
34-
github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709 h1:Ko2LQMrRU+Oy/+EDBwX7eZ2jp3C47eDBB8EIhKTun+I=
3562
github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
3663
github.com/tsenart/go-tsz v0.0.0-20180814235614-0bd30b3df1c3 h1:pcQGQzTwCg//7FgVywqge1sW9Yf8VMsMdG58MI5kd8s=
3764
github.com/tsenart/go-tsz v0.0.0-20180814235614-0bd30b3df1c3/go.mod h1:SWZznP1z5Ki7hDT2ioqiFKEse8K9tU2OUvaRI0NeGQo=
@@ -42,6 +69,7 @@ golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
4269
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
4370
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
4471
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
72+
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
4573
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
4674
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
4775
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
@@ -52,8 +80,14 @@ golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
5280
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
5381
golang.org/x/tools v0.11.0 h1:EMCa6U9S2LtZXLAMoWiR/R8dAQFRqbAitmbJ2UKhoi8=
5482
golang.org/x/tools v0.11.0/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8=
83+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
5584
gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca h1:PupagGYwj8+I4ubCxcmcBRk3VlUWtTg5huQpZR9flmE=
5685
gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
5786
gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
87+
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
88+
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
89+
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
90+
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
91+
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
5892
pgregory.net/rapid v1.0.0 h1:iQaM2w5PZ6xvt6x7hbd7tiDS+nk7YPp5uCaEba+T/F4=
5993
pgregory.net/rapid v1.0.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=

0 commit comments

Comments
 (0)