Skip to content

Commit 95888ee

Browse files
committed
http2: add Transport.CountErrors
Like the earlier Server.CountErrors. This lets people observe hook up an http2.Transport to monitoring (expvar/Prometheus/etc) and spot pattern changes over time. Change-Id: I12a4d0b3499fb0be75d5a56342ced0719c00654d Reviewed-on: https://go-review.googlesource.com/c/net/+/350709 Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Damien Neil <[email protected]> Trust: Brad Fitzpatrick <[email protected]>
1 parent 3c21e5b commit 95888ee

File tree

2 files changed

+51
-3
lines changed

2 files changed

+51
-3
lines changed

http2/errors.go

+7
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ func (e ErrCode) String() string {
5353
return fmt.Sprintf("unknown error code 0x%x", uint32(e))
5454
}
5555

56+
func (e ErrCode) stringToken() string {
57+
if s, ok := errCodeName[e]; ok {
58+
return s
59+
}
60+
return fmt.Sprintf("ERR_UNKNOWN_%d", uint32(e))
61+
}
62+
5663
// ConnectionError is an error that results in the termination of the
5764
// entire connection.
5865
type ConnectionError ErrCode

http2/transport.go

+44-3
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,12 @@ type Transport struct {
130130
// Defaults to 15s.
131131
PingTimeout time.Duration
132132

133+
// CountError, if non-nil, is called on HTTP/2 transport errors.
134+
// It's intended to increment a metric for monitoring, such
135+
// as an expvar or Prometheus metric.
136+
// The errType consists of only ASCII word characters.
137+
CountError func(errType string)
138+
133139
// t1, if non-nil, is the standard library Transport using
134140
// this transport. Its settings are used (but not its
135141
// RoundTrip method, etc).
@@ -943,6 +949,9 @@ func (cc *ClientConn) Close() error {
943949
// closes the client connection immediately. In-flight requests are interrupted.
944950
func (cc *ClientConn) closeForLostPing() error {
945951
err := errors.New("http2: client connection lost")
952+
if f := cc.t.CountError; f != nil {
953+
f("conn_close_lost_ping")
954+
}
946955
return cc.closeForError(err)
947956
}
948957

@@ -1830,6 +1839,33 @@ func (rl *clientConnReadLoop) cleanup() {
18301839
cc.mu.Unlock()
18311840
}
18321841

1842+
// countReadFrameError calls Transport.CountError with a string
1843+
// representing err.
1844+
func (cc *ClientConn) countReadFrameError(err error) {
1845+
f := cc.t.CountError
1846+
if f == nil || err == nil {
1847+
return
1848+
}
1849+
if ce, ok := err.(ConnectionError); ok {
1850+
errCode := ErrCode(ce)
1851+
f(fmt.Sprintf("read_frame_conn_error_%s", errCode.stringToken()))
1852+
return
1853+
}
1854+
if errors.Is(err, io.EOF) {
1855+
f("read_frame_eof")
1856+
return
1857+
}
1858+
if errors.Is(err, io.ErrUnexpectedEOF) {
1859+
f("read_frame_unexpected_eof")
1860+
return
1861+
}
1862+
if errors.Is(err, ErrFrameTooLarge) {
1863+
f("read_frame_too_large")
1864+
return
1865+
}
1866+
f("read_frame_other")
1867+
}
1868+
18331869
func (rl *clientConnReadLoop) run() error {
18341870
cc := rl.cc
18351871
rl.closeWhenIdle = cc.t.disableKeepAlives() || cc.singleUse
@@ -1860,6 +1896,7 @@ func (rl *clientConnReadLoop) run() error {
18601896
}
18611897
continue
18621898
} else if err != nil {
1899+
cc.countReadFrameError(err)
18631900
return err
18641901
}
18651902
if VerboseLogs {
@@ -2352,6 +2389,10 @@ func (rl *clientConnReadLoop) processGoAway(f *GoAwayFrame) error {
23522389
if f.ErrCode != 0 {
23532390
// TODO: deal with GOAWAY more. particularly the error code
23542391
cc.vlogf("transport got GOAWAY with error code = %v", f.ErrCode)
2392+
if fn := cc.t.CountError; fn != nil {
2393+
fn("recv_goaway_" + f.ErrCode.stringToken())
2394+
}
2395+
23552396
}
23562397
cc.setGoAway(f)
23572398
return nil
@@ -2466,9 +2507,9 @@ func (rl *clientConnReadLoop) processResetStream(f *RSTStreamFrame) error {
24662507
if f.ErrCode == ErrCodeProtocol {
24672508
rl.cc.SetDoNotReuse()
24682509
serr.Cause = errFromPeer
2469-
// TODO(bradfitz): increment a varz here, once Transport
2470-
// takes an optional interface-typed field that expvar.Map.Add
2471-
// implements.
2510+
}
2511+
if fn := cs.cc.t.CountError; fn != nil {
2512+
fn("recv_rststream_" + f.ErrCode.stringToken())
24722513
}
24732514
cs.resetErr = serr
24742515
close(cs.peerReset)

0 commit comments

Comments
 (0)