diff --git a/internal/ackhandler/sent_packet_handler.go b/internal/ackhandler/sent_packet_handler.go index d731acd9e..b0b565ef0 100644 --- a/internal/ackhandler/sent_packet_handler.go +++ b/internal/ackhandler/sent_packet_handler.go @@ -160,6 +160,9 @@ func (h *sentPacketHandler) dropPackets(encLevel protocol.EncryptionLevel) { } h.setLossDetectionTimer() h.ptoCount = 0 + if h.qlogger != nil { + h.qlogger.UpdatedPTOCount(time.Now(), 0) + } h.ptoMode = SendNone } @@ -286,6 +289,9 @@ func (h *sentPacketHandler) ReceivedAck(ack *wire.AckFrame, encLevel protocol.En } h.ptoCount = 0 + if h.qlogger != nil { + h.qlogger.UpdatedPTOCount(rcvTime, 0) + } h.numProbesToSend = 0 h.setLossDetectionTimer() @@ -531,6 +537,9 @@ func (h *sentPacketHandler) onVerifiedLossDetectionTimeout() error { h.logger.Debugf("Loss detection alarm for %s fired in PTO mode. PTO count: %d", encLevel, h.ptoCount) } h.ptoCount++ + if h.qlogger != nil { + h.qlogger.UpdatedPTOCount(time.Now(), h.ptoCount) + } h.numProbesToSend += 2 switch encLevel { case protocol.EncryptionInitial: diff --git a/qlog/event.go b/qlog/event.go index 0b0b498d9..30a76531a 100644 --- a/qlog/event.go +++ b/qlog/event.go @@ -181,6 +181,18 @@ func (e eventMetricsUpdated) MarshalJSONObject(enc *gojay.Encoder) { enc.Uint64KeyOmitEmpty("packets_in_flight", uint64(e.PacketsInFlight)) } +type eventUpdatedPTO struct { + Value uint32 +} + +func (e eventUpdatedPTO) Category() category { return categoryRecovery } +func (e eventUpdatedPTO) Name() string { return "metrics_updated" } +func (e eventUpdatedPTO) IsNil() bool { return false } + +func (e eventUpdatedPTO) MarshalJSONObject(enc *gojay.Encoder) { + enc.Uint32Key("pto_count", e.Value) +} + type eventPacketLost struct { PacketType packetType PacketNumber protocol.PacketNumber diff --git a/qlog/qlog.go b/qlog/qlog.go index af4105bc1..2d0f20c6f 100644 --- a/qlog/qlog.go +++ b/qlog/qlog.go @@ -21,6 +21,7 @@ type Tracer interface { ReceivedPacket(t time.Time, hdr *wire.ExtendedHeader, packetSize protocol.ByteCount, frames []wire.Frame) UpdatedMetrics(t time.Time, rttStats *congestion.RTTStats, cwnd protocol.ByteCount, bytesInFLight protocol.ByteCount, packetsInFlight int) LostPacket(time.Time, protocol.EncryptionLevel, protocol.PacketNumber, PacketLossReason) + UpdatedPTOCount(time.Time, uint32) UpdatedKeyFromTLS(time.Time, protocol.EncryptionLevel, protocol.Perspective) } @@ -170,3 +171,10 @@ func (t *tracer) UpdatedKeyFromTLS(time time.Time, encLevel protocol.EncryptionL }, }) } + +func (t *tracer) UpdatedPTOCount(time time.Time, value uint32) { + t.events = append(t.events, event{ + Time: time, + eventDetails: eventUpdatedPTO{Value: value}, + }) +} diff --git a/qlog/qlog_test.go b/qlog/qlog_test.go index 7924ac939..03230debf 100644 --- a/qlog/qlog_test.go +++ b/qlog/qlog_test.go @@ -277,5 +277,15 @@ var _ = Describe("Tracer", func() { Expect(ev).ToNot(HaveKey("old")) Expect(ev).ToNot(HaveKey("new")) }) + + It("records PTO changes", func() { + now := time.Now() + tracer.UpdatedPTOCount(now, 42) + t, category, eventName, ev := exportAndParse() + Expect(t).To(BeTemporally("~", now, time.Millisecond)) + Expect(category).To(Equal("recovery")) + Expect(eventName).To(Equal("metrics_updated")) + Expect(ev).To(HaveKeyWithValue("pto_count", float64(42))) + }) }) })