Update dependencies
This commit is contained in:
19
vendor/github.com/tcnksm/go-httpstat/.travis.yml
generated
vendored
Normal file
19
vendor/github.com/tcnksm/go-httpstat/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.7.5
|
||||
- 1.8
|
||||
- 1.8.1
|
||||
- tip
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
sudo: false
|
||||
|
||||
install:
|
||||
- echo "skipping travis default"
|
||||
|
||||
script:
|
||||
- make test-all
|
||||
21
vendor/github.com/tcnksm/go-httpstat/LICENSE
generated
vendored
Normal file
21
vendor/github.com/tcnksm/go-httpstat/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016 Taichi Nakashima
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
26
vendor/github.com/tcnksm/go-httpstat/Makefile
generated
vendored
Normal file
26
vendor/github.com/tcnksm/go-httpstat/Makefile
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
PACKAGES = $(shell go list ./... | grep -v '/vendor/')
|
||||
|
||||
default: test
|
||||
|
||||
test-all: vet lint test
|
||||
|
||||
test:
|
||||
go test -v -parallel=4 ${PACKAGES}
|
||||
|
||||
test-race:
|
||||
go test -v -race ${PACKAGES}
|
||||
|
||||
vet:
|
||||
go vet ${PACKAGES}
|
||||
|
||||
lint:
|
||||
@go get github.com/golang/lint/golint
|
||||
go list ./... | grep -v vendor | xargs -n1 golint
|
||||
|
||||
cover:
|
||||
@go get golang.org/x/tools/cmd/cover
|
||||
go test -coverprofile=cover.out
|
||||
go tool cover -html cover.out
|
||||
rm cover.out
|
||||
|
||||
.PHONY: test test-race vet lint cover
|
||||
23
vendor/github.com/tcnksm/go-httpstat/README.md
generated
vendored
Normal file
23
vendor/github.com/tcnksm/go-httpstat/README.md
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
# go-httpstat [][godocs] [][travis] [][license]
|
||||
|
||||
[godocs]: http://godoc.org/github.com/tcnksm/go-httpstat
|
||||
[travis]: https://travis-ci.org/tcnksm/go-httpstat
|
||||
[license]: /LICENSE
|
||||
|
||||
`go-httpstat` is a golang package to trace golang HTTP request latency (DNSLookup, TCP Connection and so on). Because it uses [`httptrace`](https://golang.org/pkg/net/http/httptrace/) internally, just creating `go-httpstat` powered `context` and giving it your `http.Request` kicks tracing (no big code modification is required). The original idea came from [`httpstat`](https://github.com/reorx/httpstat) command ( and Dave Cheney's [golang implementation](https://github.com/davecheney/httpstat)) 👏. This package now traces same latency infomation as them.
|
||||
|
||||
See usage and example on [GoDoc][godocs].
|
||||
|
||||
*NOTE*: Since [`httptrace`](https://golang.org/pkg/net/http/httptrace/) was introduced after go1.7, this package may not work with old HTTP client. Especially, if you don't use `net.DialContext` it can not trace DNS and connection.
|
||||
|
||||
## Install
|
||||
|
||||
Use `go get`,
|
||||
|
||||
```bash
|
||||
$ go get github.com/tcnksm/go-httpstat
|
||||
```
|
||||
|
||||
## Author
|
||||
|
||||
[Taichi Nakashima](https://github.com/tcnksm)
|
||||
121
vendor/github.com/tcnksm/go-httpstat/go18.go
generated
vendored
Normal file
121
vendor/github.com/tcnksm/go-httpstat/go18.go
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
// +build go1.8
|
||||
|
||||
package httpstat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net/http/httptrace"
|
||||
"time"
|
||||
)
|
||||
|
||||
// End sets the time when reading response is done.
|
||||
// This must be called after reading response body.
|
||||
func (r *Result) End(t time.Time) {
|
||||
r.trasferDone = t
|
||||
r.t5 = t // for Formatter
|
||||
|
||||
// This means result is empty (it does nothing).
|
||||
// Skip setting value(contentTransfer and total will be zero).
|
||||
if r.dnsStart.IsZero() {
|
||||
return
|
||||
}
|
||||
|
||||
r.contentTransfer = r.trasferDone.Sub(r.transferStart)
|
||||
r.total = r.trasferDone.Sub(r.dnsStart)
|
||||
}
|
||||
|
||||
func withClientTrace(ctx context.Context, r *Result) context.Context {
|
||||
return httptrace.WithClientTrace(ctx, &httptrace.ClientTrace{
|
||||
DNSStart: func(i httptrace.DNSStartInfo) {
|
||||
r.dnsStart = time.Now()
|
||||
},
|
||||
|
||||
DNSDone: func(i httptrace.DNSDoneInfo) {
|
||||
r.dnsDone = time.Now()
|
||||
|
||||
r.DNSLookup = r.dnsDone.Sub(r.dnsStart)
|
||||
r.NameLookup = r.dnsDone.Sub(r.dnsStart)
|
||||
},
|
||||
|
||||
ConnectStart: func(_, _ string) {
|
||||
r.tcpStart = time.Now()
|
||||
|
||||
// When connecting to IP (When no DNS lookup)
|
||||
if r.dnsStart.IsZero() {
|
||||
r.dnsStart = r.tcpStart
|
||||
r.dnsDone = r.tcpStart
|
||||
}
|
||||
},
|
||||
|
||||
ConnectDone: func(network, addr string, err error) {
|
||||
r.tcpDone = time.Now()
|
||||
|
||||
r.TCPConnection = r.tcpDone.Sub(r.tcpStart)
|
||||
r.Connect = r.tcpDone.Sub(r.dnsStart)
|
||||
},
|
||||
|
||||
TLSHandshakeStart: func() {
|
||||
r.isTLS = true
|
||||
r.tlsStart = time.Now()
|
||||
},
|
||||
|
||||
TLSHandshakeDone: func(_ tls.ConnectionState, _ error) {
|
||||
r.tlsDone = time.Now()
|
||||
|
||||
r.TLSHandshake = r.tlsDone.Sub(r.tlsStart)
|
||||
r.Pretransfer = r.tlsDone.Sub(r.dnsStart)
|
||||
},
|
||||
|
||||
GotConn: func(i httptrace.GotConnInfo) {
|
||||
// Handle when keep alive is used and connection is reused.
|
||||
// DNSStart(Done) and ConnectStart(Done) is skipped
|
||||
if i.Reused {
|
||||
r.isReused = true
|
||||
}
|
||||
},
|
||||
|
||||
WroteRequest: func(info httptrace.WroteRequestInfo) {
|
||||
r.serverStart = time.Now()
|
||||
|
||||
// When client doesn't use DialContext or using old (before go1.7) `net`
|
||||
// pakcage, DNS/TCP/TLS hook is not called.
|
||||
if r.dnsStart.IsZero() && r.tcpStart.IsZero() {
|
||||
now := r.serverStart
|
||||
|
||||
r.dnsStart = now
|
||||
r.dnsDone = now
|
||||
r.tcpStart = now
|
||||
r.tcpDone = now
|
||||
}
|
||||
|
||||
// When connection is re-used, DNS/TCP/TLS hook is not called.
|
||||
if r.isReused {
|
||||
now := r.serverStart
|
||||
|
||||
r.dnsStart = now
|
||||
r.dnsDone = now
|
||||
r.tcpStart = now
|
||||
r.tcpDone = now
|
||||
r.tlsStart = now
|
||||
r.tlsDone = now
|
||||
}
|
||||
|
||||
if r.isTLS {
|
||||
return
|
||||
}
|
||||
|
||||
r.TLSHandshake = r.tcpDone.Sub(r.tcpDone)
|
||||
r.Pretransfer = r.Connect
|
||||
},
|
||||
|
||||
GotFirstResponseByte: func() {
|
||||
r.serverDone = time.Now()
|
||||
|
||||
r.ServerProcessing = r.serverDone.Sub(r.serverStart)
|
||||
r.StartTransfer = r.serverDone.Sub(r.dnsStart)
|
||||
|
||||
r.transferStart = r.serverDone
|
||||
},
|
||||
})
|
||||
}
|
||||
147
vendor/github.com/tcnksm/go-httpstat/httpstat.go
generated
vendored
Normal file
147
vendor/github.com/tcnksm/go-httpstat/httpstat.go
generated
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
// Package httpstat traces HTTP latency infomation (DNSLookup, TCP Connection and so on) on any golang HTTP request.
|
||||
// It uses `httptrace` package. Just create `go-httpstat` powered `context.Context` and give it your `http.Request` (no big code modification is required).
|
||||
package httpstat
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Result stores httpstat info.
|
||||
type Result struct {
|
||||
// The following are duration for each phase
|
||||
DNSLookup time.Duration
|
||||
TCPConnection time.Duration
|
||||
TLSHandshake time.Duration
|
||||
ServerProcessing time.Duration
|
||||
contentTransfer time.Duration
|
||||
|
||||
// The followings are timeline of request
|
||||
NameLookup time.Duration
|
||||
Connect time.Duration
|
||||
Pretransfer time.Duration
|
||||
StartTransfer time.Duration
|
||||
total time.Duration
|
||||
|
||||
t0 time.Time
|
||||
t1 time.Time
|
||||
t2 time.Time
|
||||
t3 time.Time
|
||||
t4 time.Time
|
||||
t5 time.Time // need to be provided from outside
|
||||
|
||||
dnsStart time.Time
|
||||
dnsDone time.Time
|
||||
tcpStart time.Time
|
||||
tcpDone time.Time
|
||||
tlsStart time.Time
|
||||
tlsDone time.Time
|
||||
serverStart time.Time
|
||||
serverDone time.Time
|
||||
transferStart time.Time
|
||||
trasferDone time.Time // need to be provided from outside
|
||||
|
||||
// isTLS is true when connection seems to use TLS
|
||||
isTLS bool
|
||||
|
||||
// isReused is true when connection is reused (keep-alive)
|
||||
isReused bool
|
||||
}
|
||||
|
||||
func (r *Result) durations() map[string]time.Duration {
|
||||
return map[string]time.Duration{
|
||||
"DNSLookup": r.DNSLookup,
|
||||
"TCPConnection": r.TCPConnection,
|
||||
"TLSHandshake": r.TLSHandshake,
|
||||
"ServerProcessing": r.ServerProcessing,
|
||||
"ContentTransfer": r.contentTransfer,
|
||||
|
||||
"NameLookup": r.NameLookup,
|
||||
"Connect": r.Connect,
|
||||
"Pretransfer": r.Connect,
|
||||
"StartTransfer": r.StartTransfer,
|
||||
"Total": r.total,
|
||||
}
|
||||
}
|
||||
|
||||
// ContentTransfer returns the duration of content transfer time.
|
||||
// It is from first response byte to the given time. The time must
|
||||
// be time after read body (go-httpstat can not detect that time).
|
||||
func (r *Result) ContentTransfer(t time.Time) time.Duration {
|
||||
return t.Sub(r.t4)
|
||||
}
|
||||
|
||||
// Total returns the duration of total http request.
|
||||
// It is from dns lookup start time to the given time. The
|
||||
// time must be time after read body (go-httpstat can not detect that time).
|
||||
func (r *Result) Total(t time.Time) time.Duration {
|
||||
return t.Sub(r.t0)
|
||||
}
|
||||
|
||||
// Format formats stats result.
|
||||
func (r Result) Format(s fmt.State, verb rune) {
|
||||
switch verb {
|
||||
case 'v':
|
||||
if s.Flag('+') {
|
||||
var buf bytes.Buffer
|
||||
fmt.Fprintf(&buf, "DNS lookup: %4d ms\n",
|
||||
int(r.DNSLookup/time.Millisecond))
|
||||
fmt.Fprintf(&buf, "TCP connection: %4d ms\n",
|
||||
int(r.TCPConnection/time.Millisecond))
|
||||
fmt.Fprintf(&buf, "TLS handshake: %4d ms\n",
|
||||
int(r.TLSHandshake/time.Millisecond))
|
||||
fmt.Fprintf(&buf, "Server processing: %4d ms\n",
|
||||
int(r.ServerProcessing/time.Millisecond))
|
||||
|
||||
if !r.t5.IsZero() {
|
||||
fmt.Fprintf(&buf, "Content transfer: %4d ms\n\n",
|
||||
int(r.contentTransfer/time.Millisecond))
|
||||
} else {
|
||||
fmt.Fprintf(&buf, "Content transfer: %4s ms\n\n", "-")
|
||||
}
|
||||
|
||||
fmt.Fprintf(&buf, "Name Lookup: %4d ms\n",
|
||||
int(r.NameLookup/time.Millisecond))
|
||||
fmt.Fprintf(&buf, "Connect: %4d ms\n",
|
||||
int(r.Connect/time.Millisecond))
|
||||
fmt.Fprintf(&buf, "Pre Transfer: %4d ms\n",
|
||||
int(r.Pretransfer/time.Millisecond))
|
||||
fmt.Fprintf(&buf, "Start Transfer: %4d ms\n",
|
||||
int(r.StartTransfer/time.Millisecond))
|
||||
|
||||
if !r.t5.IsZero() {
|
||||
fmt.Fprintf(&buf, "Total: %4d ms\n",
|
||||
int(r.total/time.Millisecond))
|
||||
} else {
|
||||
fmt.Fprintf(&buf, "Total: %4s ms\n", "-")
|
||||
}
|
||||
io.WriteString(s, buf.String())
|
||||
return
|
||||
}
|
||||
|
||||
fallthrough
|
||||
case 's', 'q':
|
||||
d := r.durations()
|
||||
list := make([]string, 0, len(d))
|
||||
for k, v := range d {
|
||||
// Handle when End function is not called
|
||||
if (k == "ContentTransfer" || k == "Total") && r.t5.IsZero() {
|
||||
list = append(list, fmt.Sprintf("%s: - ms", k))
|
||||
continue
|
||||
}
|
||||
list = append(list, fmt.Sprintf("%s: %d ms", k, v/time.Millisecond))
|
||||
}
|
||||
io.WriteString(s, strings.Join(list, ", "))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// WithHTTPStat is a wrapper of httptrace.WithClientTrace. It records the
|
||||
// time of each httptrace hooks.
|
||||
func WithHTTPStat(ctx context.Context, r *Result) context.Context {
|
||||
return withClientTrace(ctx, r)
|
||||
}
|
||||
114
vendor/github.com/tcnksm/go-httpstat/pre_go18.go
generated
vendored
Normal file
114
vendor/github.com/tcnksm/go-httpstat/pre_go18.go
generated
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
// +build !go1.8
|
||||
|
||||
package httpstat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http/httptrace"
|
||||
"time"
|
||||
)
|
||||
|
||||
// End sets the time when reading response is done.
|
||||
// This must be called after reading response body.
|
||||
func (r *Result) End(t time.Time) {
|
||||
r.t5 = t
|
||||
|
||||
// This means result is empty (it does nothing).
|
||||
// Skip setting value(contentTransfer and total will be zero).
|
||||
if r.t0.IsZero() {
|
||||
return
|
||||
}
|
||||
|
||||
r.contentTransfer = r.t5.Sub(r.t4)
|
||||
r.total = r.t5.Sub(r.t0)
|
||||
}
|
||||
|
||||
func withClientTrace(ctx context.Context, r *Result) context.Context {
|
||||
return httptrace.WithClientTrace(ctx, &httptrace.ClientTrace{
|
||||
GetConn: func(hostPort string) {
|
||||
_, port, err := net.SplitHostPort(hostPort)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Heuristic way to detect
|
||||
if port == "443" {
|
||||
r.isTLS = true
|
||||
}
|
||||
},
|
||||
|
||||
DNSStart: func(i httptrace.DNSStartInfo) {
|
||||
r.t0 = time.Now()
|
||||
},
|
||||
DNSDone: func(i httptrace.DNSDoneInfo) {
|
||||
r.t1 = time.Now()
|
||||
r.DNSLookup = r.t1.Sub(r.t0)
|
||||
r.NameLookup = r.t1.Sub(r.t0)
|
||||
},
|
||||
|
||||
ConnectStart: func(_, _ string) {
|
||||
// When connecting to IP
|
||||
if r.t0.IsZero() {
|
||||
r.t0 = time.Now()
|
||||
r.t1 = r.t0
|
||||
}
|
||||
},
|
||||
|
||||
ConnectDone: func(network, addr string, err error) {
|
||||
r.t2 = time.Now()
|
||||
if r.isTLS {
|
||||
r.TCPConnection = r.t2.Sub(r.t1)
|
||||
r.Connect = r.t2.Sub(r.t0)
|
||||
}
|
||||
},
|
||||
|
||||
GotConn: func(i httptrace.GotConnInfo) {
|
||||
// Handle when keep alive is enabled and connection is reused.
|
||||
// DNSStart(Done) and ConnectStart(Done) is skipped
|
||||
if i.Reused {
|
||||
r.t0 = time.Now()
|
||||
r.t1 = r.t0
|
||||
r.t2 = r.t0
|
||||
|
||||
r.isReused = true
|
||||
}
|
||||
},
|
||||
|
||||
WroteRequest: func(info httptrace.WroteRequestInfo) {
|
||||
r.t3 = time.Now()
|
||||
|
||||
// This means DNSStart, Done and ConnectStart is not
|
||||
// called. This happens if client doesn't use DialContext
|
||||
// or using net package before go1.7.
|
||||
if r.t0.IsZero() && r.t1.IsZero() && r.t2.IsZero() {
|
||||
r.t0 = time.Now()
|
||||
r.t1 = r.t0
|
||||
r.t2 = r.t0
|
||||
r.t3 = r.t0
|
||||
}
|
||||
|
||||
// When connection is reused, TLS handshake is skipped.
|
||||
if r.isReused {
|
||||
r.t3 = r.t0
|
||||
}
|
||||
|
||||
if r.isTLS {
|
||||
r.TLSHandshake = r.t3.Sub(r.t2)
|
||||
r.Pretransfer = r.t3.Sub(r.t0)
|
||||
return
|
||||
}
|
||||
|
||||
r.TCPConnection = r.t3.Sub(r.t1)
|
||||
r.Connect = r.t3.Sub(r.t0)
|
||||
|
||||
r.TLSHandshake = r.t3.Sub(r.t3)
|
||||
r.Pretransfer = r.Connect
|
||||
},
|
||||
GotFirstResponseByte: func() {
|
||||
r.t4 = time.Now()
|
||||
r.ServerProcessing = r.t4.Sub(r.t3)
|
||||
r.StartTransfer = r.t4.Sub(r.t0)
|
||||
},
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user