qlog: split the PTO count updates ouf of the MetricsUpdated event (#5421)

* qlog: split the PTO count updates ouf of the MetricsUpdated event

This allows us to not use pointers for all member variables of both
events.

* ackhandler: avoid spurious call to GetCongestionWindow
This commit is contained in:
Marten Seemann
2025-11-04 12:13:06 -05:00
committed by GitHub
parent 4930f90307
commit eb7fcf5637
5 changed files with 88 additions and 95 deletions

View File

@@ -57,20 +57,14 @@ func BenchmarkConnectionTracing(b *testing.B) {
},
})
minRTT := rttStats.MinRTT()
smoothedRTT := rttStats.SmoothedRTT()
latestRTT := rttStats.LatestRTT()
rttVariance := rttStats.MeanDeviation()
cwndInt := int(12345 + protocol.ByteCount(2*i))
bytesInt := int(12345 + protocol.ByteCount(i))
tracer.RecordEvent(&MetricsUpdated{
MinRTT: &minRTT,
SmoothedRTT: &smoothedRTT,
LatestRTT: &latestRTT,
RTTVariance: &rttVariance,
CongestionWindow: &cwndInt,
BytesInFlight: &bytesInt,
PacketsInFlight: &i,
MinRTT: rttStats.MinRTT(),
SmoothedRTT: rttStats.SmoothedRTT(),
LatestRTT: rttStats.LatestRTT(),
RTTVariance: rttStats.MeanDeviation(),
CongestionWindow: int(12345 + protocol.ByteCount(2*i)),
BytesInFlight: int(12345 + protocol.ByteCount(i)),
PacketsInFlight: i,
})
if i%2 == 0 {

View File

@@ -412,15 +412,17 @@ func (e MTUUpdated) Encode(enc *jsontext.Encoder, _ time.Time) error {
return h.err
}
// MetricsUpdated logs RTT and congestion metrics as defined in the
// recovery:metrics_updated event.
// The PTO count is logged via PTOCountUpdated.
type MetricsUpdated struct {
MinRTT *time.Duration
SmoothedRTT *time.Duration
LatestRTT *time.Duration
RTTVariance *time.Duration
CongestionWindow *int
BytesInFlight *int
PacketsInFlight *int
PTOCount *uint32
MinRTT time.Duration
SmoothedRTT time.Duration
LatestRTT time.Duration
RTTVariance time.Duration
CongestionWindow int
BytesInFlight int
PacketsInFlight int
}
func (e MetricsUpdated) Name() string { return "recovery:metrics_updated" }
@@ -428,42 +430,55 @@ func (e MetricsUpdated) Name() string { return "recovery:metrics_updated" }
func (e MetricsUpdated) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
if e.MinRTT != nil {
if e.MinRTT != 0 {
h.WriteToken(jsontext.String("min_rtt"))
h.WriteToken(jsontext.Float(milliseconds(*e.MinRTT)))
h.WriteToken(jsontext.Float(milliseconds(e.MinRTT)))
}
if e.SmoothedRTT != nil {
if e.SmoothedRTT != 0 {
h.WriteToken(jsontext.String("smoothed_rtt"))
h.WriteToken(jsontext.Float(milliseconds(*e.SmoothedRTT)))
h.WriteToken(jsontext.Float(milliseconds(e.SmoothedRTT)))
}
if e.LatestRTT != nil {
if e.LatestRTT != 0 {
h.WriteToken(jsontext.String("latest_rtt"))
h.WriteToken(jsontext.Float(milliseconds(*e.LatestRTT)))
h.WriteToken(jsontext.Float(milliseconds(e.LatestRTT)))
}
if e.RTTVariance != nil {
if e.RTTVariance != 0 {
h.WriteToken(jsontext.String("rtt_variance"))
h.WriteToken(jsontext.Float(milliseconds(*e.RTTVariance)))
h.WriteToken(jsontext.Float(milliseconds(e.RTTVariance)))
}
if e.CongestionWindow != nil {
if e.CongestionWindow != 0 {
h.WriteToken(jsontext.String("congestion_window"))
h.WriteToken(jsontext.Uint(uint64(*e.CongestionWindow)))
h.WriteToken(jsontext.Uint(uint64(e.CongestionWindow)))
}
if e.BytesInFlight != nil {
if e.BytesInFlight != 0 {
h.WriteToken(jsontext.String("bytes_in_flight"))
h.WriteToken(jsontext.Uint(uint64(*e.BytesInFlight)))
h.WriteToken(jsontext.Uint(uint64(e.BytesInFlight)))
}
if e.PacketsInFlight != nil {
if e.PacketsInFlight != 0 {
h.WriteToken(jsontext.String("packets_in_flight"))
h.WriteToken(jsontext.Uint(uint64(*e.PacketsInFlight)))
}
if e.PTOCount != nil {
h.WriteToken(jsontext.String("pto_count"))
h.WriteToken(jsontext.Uint(uint64(*e.PTOCount)))
h.WriteToken(jsontext.Uint(uint64(e.PacketsInFlight)))
}
h.WriteToken(jsontext.EndObject)
return h.err
}
// PTOCountUpdated logs the pto_count value of the
// recovery:metrics_updated event.
type PTOCountUpdated struct {
PTOCount uint32
}
func (e PTOCountUpdated) Name() string { return "recovery:metrics_updated" }
func (e PTOCountUpdated) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("pto_count"))
h.WriteToken(jsontext.Uint(uint64(e.PTOCount)))
h.WriteToken(jsontext.EndObject)
return h.err
}
type PacketLost struct {
Header PacketHeader
Trigger PacketLossReason

View File

@@ -606,21 +606,14 @@ func TestMetricsUpdated(t *testing.T) {
rttStats.UpdateRTT(15*time.Millisecond, 0)
rttStats.UpdateRTT(20*time.Millisecond, 0)
rttStats.UpdateRTT(25*time.Millisecond, 0)
minRTT := rttStats.MinRTT()
smoothedRTT := rttStats.SmoothedRTT()
latestRTT := rttStats.LatestRTT()
rttVariance := rttStats.MeanDeviation()
cwndInt := 4321
bytesInt := 1234
packetsInt := 42
name, ev := testEventEncoding(t, &MetricsUpdated{
MinRTT: &minRTT,
SmoothedRTT: &smoothedRTT,
LatestRTT: &latestRTT,
RTTVariance: &rttVariance,
CongestionWindow: &cwndInt,
BytesInFlight: &bytesInt,
PacketsInFlight: &packetsInt,
MinRTT: rttStats.MinRTT(),
SmoothedRTT: rttStats.SmoothedRTT(),
LatestRTT: rttStats.LatestRTT(),
RTTVariance: rttStats.MeanDeviation(),
CongestionWindow: 4321,
BytesInFlight: 1234,
PacketsInFlight: 42,
})
require.Equal(t, "recovery:metrics_updated", name)
@@ -683,9 +676,8 @@ func TestCongestionStateUpdated(t *testing.T) {
require.Equal(t, "congestion_avoidance", ev["new"])
}
func TestMetricsUpdatedPTO(t *testing.T) {
value := uint32(42)
name, ev := testEventEncoding(t, &MetricsUpdated{PTOCount: &value})
func TestPTOCountUpdated(t *testing.T) {
name, ev := testEventEncoding(t, &PTOCountUpdated{PTOCount: 42})
require.Equal(t, "recovery:metrics_updated", name)
require.Equal(t, float64(42), ev["pto_count"])