add the packet_sent event

This commit is contained in:
Marten Seemann
2020-01-21 13:21:49 +07:00
parent 4763719051
commit 4d92dd05f9
4 changed files with 132 additions and 0 deletions

View File

@@ -39,3 +39,25 @@ func (e event) MarshalJSONArray(enc *gojay.Encoder) {
enc.String(e.Name())
enc.Object(e.eventDetails)
}
type eventPacketSent struct {
PacketType packetType
Header packetHeader
Frames frames
IsCoalesced bool
Trigger string
}
var _ eventDetails = eventPacketSent{}
func (e eventPacketSent) Category() category { return categoryTransport }
func (e eventPacketSent) Name() string { return "packet_sent" }
func (e eventPacketSent) IsNil() bool { return false }
func (e eventPacketSent) MarshalJSONObject(enc *gojay.Encoder) {
enc.StringKey("packet_type", e.PacketType.String())
enc.ObjectKey("header", e.Header)
enc.ArrayKeyOmitEmpty("frames", e.Frames)
enc.BoolKeyOmitEmpty("is_coalesced", e.IsCoalesced)
enc.StringKeyOmitEmpty("trigger", e.Trigger)
}

View File

@@ -15,6 +15,17 @@ type frame struct {
var _ gojay.MarshalerJSONObject = frame{}
type frames []frame
func (fs frames) IsNil() bool { return fs == nil }
func (fs frames) MarshalJSONArray(enc *gojay.Encoder) {
for _, f := range fs {
enc.Object(f)
}
}
var _ gojay.MarshalerJSONArray = frames{}
type cryptoFrame struct {
Offset protocol.ByteCount
Length protocol.ByteCount

View File

@@ -2,14 +2,17 @@ package qlog
import (
"io"
"time"
"github.com/francoispqt/gojay"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/wire"
)
// A Tracer records events to be exported to a qlog.
type Tracer interface {
Export() error
SentPacket(time.Time, *wire.ExtendedHeader, *wire.AckFrame, []wire.Frame)
}
type tracer struct {
@@ -48,3 +51,25 @@ func (t *tracer) Export() error {
}
return t.w.Close()
}
func (t *tracer) SentPacket(time time.Time, hdr *wire.ExtendedHeader, ack *wire.AckFrame, frames []wire.Frame) {
numFrames := len(frames)
if ack != nil {
numFrames++
}
fs := make([]frame, 0, numFrames)
if ack != nil {
fs = append(fs, *transformFrame(ack))
}
for _, f := range frames {
fs = append(fs, *transformFrame(f))
}
t.events = append(t.events, event{
Time: time,
eventDetails: eventPacketSent{
PacketType: getPacketType(hdr),
Header: *transformHeader(hdr),
Frames: fs,
},
})
}

View File

@@ -4,8 +4,10 @@ import (
"bytes"
"encoding/json"
"io"
"time"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/wire"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -57,4 +59,76 @@ var _ = Describe("Tracer", func() {
vantagePoint := trace["vantage_point"].(map[string]interface{})
Expect(vantagePoint).To(HaveKeyWithValue("type", "server"))
})
Context("Events", func() {
exportAndParse := func() (time.Time, string /* category */, string /* event */, map[string]interface{}) {
Expect(tracer.Export()).To(Succeed())
m := make(map[string]interface{})
Expect(json.Unmarshal(buf.Bytes(), &m)).To(Succeed())
Expect(m).To(HaveKey("traces"))
traces := m["traces"].([]interface{})
Expect(traces).To(HaveLen(1))
trace := traces[0].(map[string]interface{})
Expect(trace).To(HaveKey("events"))
events := trace["events"].([]interface{})
Expect(events).To(HaveLen(1))
ev := events[0].([]interface{})
Expect(ev).To(HaveLen(4))
return time.Unix(0, int64(1e6*ev[0].(float64))), ev[1].(string), ev[2].(string), ev[3].(map[string]interface{})
}
It("records a sent packet, without an ACK", func() {
now := time.Now()
tracer.SentPacket(
now,
&wire.ExtendedHeader{
Header: wire.Header{
IsLongHeader: true,
Type: protocol.PacketTypeHandshake,
DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
SrcConnectionID: protocol.ConnectionID{4, 3, 2, 1},
Version: protocol.VersionTLS,
},
PacketNumber: 1337,
},
nil,
[]wire.Frame{
&wire.MaxStreamDataFrame{StreamID: 42, ByteOffset: 987},
&wire.StreamFrame{StreamID: 123, Offset: 1234, Data: []byte("foobar"), FinBit: true},
},
)
t, category, eventName, ev := exportAndParse()
Expect(t).To(BeTemporally("~", now, time.Millisecond))
Expect(category).To(Equal("transport"))
Expect(eventName).To(Equal("packet_sent"))
Expect(ev).To(HaveKeyWithValue("packet_type", "handshake"))
Expect(ev).To(HaveKey("header"))
Expect(ev).To(HaveKey("frames"))
frames := ev["frames"].([]interface{})
Expect(frames).To(HaveLen(2))
Expect(frames[0].(map[string]interface{})).To(HaveKeyWithValue("frame_type", "max_stream_data"))
Expect(frames[1].(map[string]interface{})).To(HaveKeyWithValue("frame_type", "stream"))
})
It("records a sent packet, without an ACK", func() {
tracer.SentPacket(
time.Now(),
&wire.ExtendedHeader{
Header: wire.Header{DestConnectionID: protocol.ConnectionID{1, 2, 3, 4}},
PacketNumber: 1337,
},
&wire.AckFrame{AckRanges: []wire.AckRange{{Smallest: 1, Largest: 10}}},
[]wire.Frame{&wire.MaxDataFrame{ByteOffset: 987}},
)
_, _, _, ev := exportAndParse()
Expect(ev).To(HaveKeyWithValue("packet_type", "1RTT"))
Expect(ev).To(HaveKey("header"))
Expect(ev).To(HaveKey("frames"))
frames := ev["frames"].([]interface{})
Expect(frames).To(HaveLen(2))
Expect(frames[0].(map[string]interface{})).To(HaveKeyWithValue("frame_type", "ack"))
Expect(frames[1].(map[string]interface{})).To(HaveKeyWithValue("frame_type", "max_data"))
})
})
})