improve qlogging of transport errors

This commit is contained in:
Marten Seemann
2020-03-28 14:39:40 +07:00
parent b9ab1d172d
commit cc737b4b11
4 changed files with 96 additions and 5 deletions

View File

@@ -236,8 +236,12 @@ func marshalConnectionCloseFrame(enc *gojay.Encoder, f *wire.ConnectionCloseFram
}
enc.StringKey("frame_type", "connection_close")
enc.StringKey("error_space", errorSpace)
enc.Int64Key("error_code", int64(f.ErrorCode))
enc.Int64Key("raw_error_code", int64(f.ErrorCode))
if errName := transportError(f.ErrorCode).String(); len(errName) > 0 {
enc.StringKey("error_code", errName)
} else {
enc.Uint64Key("error_code", uint64(f.ErrorCode))
}
enc.Uint64Key("raw_error_code", uint64(f.ErrorCode))
enc.StringKey("reason", f.ReasonPhrase)
}

View File

@@ -5,6 +5,8 @@ import (
"encoding/json"
"time"
"github.com/lucas-clemente/quic-go/internal/qerr"
"github.com/francoispqt/gojay"
"github.com/lucas-clemente/quic-go/internal/protocol"
@@ -325,14 +327,14 @@ var _ = Describe("Frames", func() {
It("marshals CONNECTION_CLOSE frames, for transport error codes", func() {
check(
&wire.ConnectionCloseFrame{
ErrorCode: 1337,
ErrorCode: qerr.FlowControlError,
ReasonPhrase: "lorem ipsum",
},
map[string]interface{}{
"frame_type": "connection_close",
"error_space": "transport",
"error_code": 1337,
"raw_error_code": 1337,
"error_code": "flow_control_error",
"raw_error_code": int(qerr.FlowControlError),
"reason": "lorem ipsum",
},
)

View File

@@ -4,6 +4,7 @@ import (
"fmt"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/qerr"
)
type owner uint8
@@ -264,3 +265,40 @@ func (r PacketDropReason) String() string {
panic("unknown packet drop reason")
}
}
type transportError uint64
func (e transportError) String() string {
switch qerr.ErrorCode(e) {
case qerr.NoError:
return "no_error"
case qerr.InternalError:
return "internal_error"
case qerr.ServerBusy:
return "server_busy"
case qerr.FlowControlError:
return "flow_control_error"
case qerr.StreamLimitError:
return "stream_limit_error"
case qerr.StreamStateError:
return "stream_state_error"
case qerr.FinalSizeError:
return "final_size_error"
case qerr.FrameEncodingError:
return "frame_encoding_error"
case qerr.TransportParameterError:
return "transport_parameter_error"
case qerr.ConnectionIDLimitError:
return "connection_id_limit_error"
case qerr.ProtocolViolation:
return "protocol_violation"
case qerr.InvalidToken:
return "invalid_token"
case qerr.ApplicationError:
return "application_error"
case qerr.CryptoBufferExceeded:
return "crypto_buffer_exceeded"
default:
return ""
}
}

View File

@@ -1,7 +1,16 @@
package qlog
import (
"go/ast"
"go/parser"
"go/token"
"path"
"runtime"
"strconv"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/qerr"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -56,4 +65,42 @@ var _ = Describe("Types", func() {
Expect(PacketDropDOSPrevention.String()).To(Equal("dos_prevention"))
Expect(PacketDropUnsupportedVersion.String()).To(Equal("unsupported_version"))
})
Context("transport errors", func() {
It("has a string representation for every error code", func() {
// We parse the error code file, extract all constants, and verify that
// each of them has a string version. Go FTW!
_, thisfile, _, ok := runtime.Caller(0)
if !ok {
panic("Failed to get current frame")
}
filename := path.Join(path.Dir(thisfile), "../internal/qerr/error_codes.go")
fileAst, err := parser.ParseFile(token.NewFileSet(), filename, nil, 0)
Expect(err).NotTo(HaveOccurred())
constSpecs := fileAst.Decls[2].(*ast.GenDecl).Specs
Expect(len(constSpecs)).To(BeNumerically(">", 4)) // at time of writing
for _, c := range constSpecs {
valString := c.(*ast.ValueSpec).Values[0].(*ast.BasicLit).Value
val, err := strconv.ParseInt(valString, 0, 64)
Expect(err).NotTo(HaveOccurred())
Expect(transportError(val).String()).ToNot(BeEmpty())
}
})
It("has a string representation for transport errors", func() {
Expect(transportError(qerr.NoError).String()).To(Equal("no_error"))
Expect(transportError(qerr.InternalError).String()).To(Equal("internal_error"))
Expect(transportError(qerr.ServerBusy).String()).To(Equal("server_busy"))
Expect(transportError(qerr.FlowControlError).String()).To(Equal("flow_control_error"))
Expect(transportError(qerr.StreamLimitError).String()).To(Equal("stream_limit_error"))
Expect(transportError(qerr.StreamStateError).String()).To(Equal("stream_state_error"))
Expect(transportError(qerr.FrameEncodingError).String()).To(Equal("frame_encoding_error"))
Expect(transportError(qerr.ConnectionIDLimitError).String()).To(Equal("connection_id_limit_error"))
Expect(transportError(qerr.ProtocolViolation).String()).To(Equal("protocol_violation"))
Expect(transportError(qerr.InvalidToken).String()).To(Equal("invalid_token"))
Expect(transportError(qerr.ApplicationError).String()).To(Equal("application_error"))
Expect(transportError(qerr.CryptoBufferExceeded).String()).To(Equal("crypto_buffer_exceeded"))
Expect(transportError(1337).String()).To(BeEmpty())
})
})
})