1
1
package main
2
2
3
3
import (
4
+ "context"
5
+ "crypto/tls"
4
6
"fmt"
5
7
"io"
6
8
"io/ioutil"
9
+ "log"
7
10
"net/http"
8
11
"net/http/httptrace"
9
12
"strconv"
@@ -25,31 +28,42 @@ type durationMetrics struct {
25
28
26
29
func (c * cassowary ) runLoadTest (outPutChan chan <- durationMetrics , workerChan chan string ) {
27
30
for item := range workerChan {
28
- tt := newTransport (c .client .Transport )
29
- c .client .Transport = tt
31
+
30
32
fmt .Println (item )
31
- fmt .Println (c )
32
33
33
34
request , err := http .NewRequest ("GET" , c .baseURL , nil )
34
35
if err != nil {
35
36
panic (err )
36
37
}
38
+ var t0 , t1 , t2 , t3 , t4 , t5 , t6 time.Time
37
39
38
40
trace := & httptrace.ClientTrace {
39
- DNSStart : tt .DNSStart ,
40
- DNSDone : tt .DNSDone ,
41
- ConnectStart : tt .ConnectStart ,
42
- ConnectDone : tt .ConnectDone ,
43
- GotConn : tt .GotConn ,
44
- GotFirstResponseByte : tt .GotFirstResponseByte ,
41
+ DNSStart : func (_ httptrace.DNSStartInfo ) { t0 = time .Now () },
42
+ DNSDone : func (_ httptrace.DNSDoneInfo ) { t1 = time .Now () },
43
+ ConnectStart : func (_ , _ string ) {
44
+ if t1 .IsZero () {
45
+ // connecting directly to IP
46
+ t1 = time .Now ()
47
+ }
48
+ },
49
+ ConnectDone : func (net , addr string , err error ) {
50
+ if err != nil {
51
+ log .Fatalf ("unable to connect to host %v: %v" , addr , err )
52
+ }
53
+ t2 = time .Now ()
54
+
55
+ },
56
+ GotConn : func (_ httptrace.GotConnInfo ) { t3 = time .Now () },
57
+ GotFirstResponseByte : func () { t4 = time .Now () },
58
+ TLSHandshakeStart : func () { t5 = time .Now () },
59
+ TLSHandshakeDone : func (_ tls.ConnectionState , _ error ) { t6 = time .Now () },
45
60
}
46
61
47
- request = request .WithContext (httptrace .WithClientTrace (request . Context (), trace ))
62
+ request = request .WithContext (httptrace .WithClientTrace (context . Background (), trace ))
48
63
resp , err := c .client .Do (request )
49
64
if err != nil {
50
65
panic (err )
51
66
}
52
-
53
67
if resp != nil {
54
68
_ , err = io .Copy (ioutil .Discard , resp .Body )
55
69
if err != nil {
@@ -60,22 +74,25 @@ func (c *cassowary) runLoadTest(outPutChan chan<- durationMetrics, workerChan ch
60
74
c .bar .Add (1 )
61
75
62
76
// Body fully read here
63
- tt .current .end = time .Now ()
64
- for _ , trace := range tt .traces {
65
- out := durationMetrics {}
66
-
67
- out .DNSLookup = trace .dnsDone .Sub (trace .start ).Seconds ()
68
- out .TCPConn = trace .gotConn .Sub (trace .dnsDone ).Seconds ()
69
- out .ServerProcessing = trace .responseStart .Sub (trace .gotConn ).Seconds ()
70
- out .ContentTransfer = trace .end .Sub (trace .responseStart ).Seconds ()
71
- out .StatusCode = resp .StatusCode
72
-
73
- if trace .tls {
74
- out .TLSHandshake = trace .gotConn .Sub (trace .dnsDone ).Seconds ()
75
- }
77
+ t7 := time .Now ()
78
+ if t0 .IsZero () {
79
+ // we skipped DNS
80
+ t0 = t1
81
+ }
76
82
77
- outPutChan <- out
83
+ out := durationMetrics {
84
+ DNSLookup : float64 (t1 .Sub (t0 ) / time .Millisecond ), // dns lookup
85
+ TCPConn : float64 (t3 .Sub (t1 ) / time .Millisecond ), // tcp connection
86
+ ServerProcessing : float64 (t4 .Sub (t3 ) / time .Millisecond ), // server processing
87
+ ContentTransfer : float64 (t7 .Sub (t4 ) / time .Millisecond ), // content transfer
88
+ StatusCode : resp .StatusCode ,
78
89
}
90
+
91
+ if c .isTLS {
92
+ out .TLSHandshake = float64 (t6 .Sub (t5 ) / time .Millisecond ) // tls handshake
93
+ }
94
+
95
+ outPutChan <- out
79
96
}
80
97
}
81
98
0 commit comments