import (
"context"
+ "crypto/tls"
"errors"
"fmt"
"io"
gotConn time.Time
responseStart time.Time
end time.Time
+ tlsStart time.Time
+ tlsDone time.Time
}
// transport is a custom transport keeping traces for each HTTP roundtrip.
defer t.mu.Unlock()
t.current.responseStart = time.Now()
}
+func (t *transport) TLSHandshakeStart() {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ t.current.tlsStart = time.Now()
+}
+func (t *transport) TLSHandshakeDone(_ tls.ConnectionState, _ error) {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ t.current.tlsDone = time.Now()
+}
// byteCounter implements an io.ReadCloser that keeps track of the total
// number of bytes it has read.
ConnectDone: tt.ConnectDone,
GotConn: tt.GotConn,
GotFirstResponseByte: tt.GotFirstResponseByte,
+ TLSHandshakeStart: tt.TLSHandshakeStart,
+ TLSHandshakeDone: tt.TLSHandshakeDone,
}
request = request.WithContext(httptrace.WithClientTrace(request.Context(), trace))
"connectDone", trace.connectDone,
"gotConn", trace.gotConn,
"responseStart", trace.responseStart,
+ "tlsStart", trace.tlsStart,
+ "tlsDone", trace.tlsDone,
"end", trace.end,
)
// We get the duration for the first request from chooseProtocol.
continue
}
if trace.tls {
- // dnsDone must be set if gotConn was set.
- durationGaugeVec.WithLabelValues("connect").Add(trace.connectDone.Sub(trace.dnsDone).Seconds())
- durationGaugeVec.WithLabelValues("tls").Add(trace.gotConn.Sub(trace.dnsDone).Seconds())
- } else {
- durationGaugeVec.WithLabelValues("connect").Add(trace.gotConn.Sub(trace.dnsDone).Seconds())
+ durationGaugeVec.WithLabelValues("tls").Add(trace.tlsDone.Sub(trace.tlsStart).Seconds())
}
+ // actual connection - we could add a new phase between connectDone and gotConn
+ durationGaugeVec.WithLabelValues("connect").Add(trace.gotConn.Sub(trace.dnsDone).Seconds())
+
// Continue here if we never got a response from the server.
if trace.responseStart.IsZero() {
continue