github.com/metacubex/quic-go@v0.44.1-0.20240520163451-20b689a59136/qlog/connection_tracer.go (about) 1 package qlog 2 3 import ( 4 "io" 5 "net" 6 "time" 7 8 "github.com/metacubex/quic-go/internal/protocol" 9 "github.com/metacubex/quic-go/internal/utils" 10 "github.com/metacubex/quic-go/internal/wire" 11 "github.com/metacubex/quic-go/logging" 12 13 "github.com/francoispqt/gojay" 14 ) 15 16 type connectionTracer struct { 17 w writer 18 lastMetrics *metrics 19 20 perspective logging.Perspective 21 } 22 23 // NewConnectionTracer creates a new tracer to record a qlog for a connection. 24 func NewConnectionTracer(w io.WriteCloser, p logging.Perspective, odcid protocol.ConnectionID) *logging.ConnectionTracer { 25 tr := &trace{ 26 VantagePoint: vantagePoint{Type: p.String()}, 27 CommonFields: commonFields{ 28 ODCID: &odcid, 29 GroupID: &odcid, 30 ReferenceTime: time.Now(), 31 }, 32 } 33 t := connectionTracer{ 34 w: *newWriter(w, tr), 35 perspective: p, 36 } 37 go t.w.Run() 38 return &logging.ConnectionTracer{ 39 StartedConnection: func(local, remote net.Addr, srcConnID, destConnID logging.ConnectionID) { 40 t.StartedConnection(local, remote, srcConnID, destConnID) 41 }, 42 NegotiatedVersion: func(chosen logging.VersionNumber, clientVersions, serverVersions []logging.VersionNumber) { 43 t.NegotiatedVersion(chosen, clientVersions, serverVersions) 44 }, 45 ClosedConnection: func(e error) { t.ClosedConnection(e) }, 46 SentTransportParameters: func(tp *wire.TransportParameters) { t.SentTransportParameters(tp) }, 47 ReceivedTransportParameters: func(tp *wire.TransportParameters) { t.ReceivedTransportParameters(tp) }, 48 RestoredTransportParameters: func(tp *wire.TransportParameters) { t.RestoredTransportParameters(tp) }, 49 SentLongHeaderPacket: func(hdr *logging.ExtendedHeader, size logging.ByteCount, ecn logging.ECN, ack *logging.AckFrame, frames []logging.Frame) { 50 t.SentLongHeaderPacket(hdr, size, ecn, ack, frames) 51 }, 52 SentShortHeaderPacket: func(hdr *logging.ShortHeader, size logging.ByteCount, ecn logging.ECN, ack *logging.AckFrame, frames []logging.Frame) { 53 t.SentShortHeaderPacket(hdr, size, ecn, ack, frames) 54 }, 55 ReceivedLongHeaderPacket: func(hdr *logging.ExtendedHeader, size logging.ByteCount, ecn logging.ECN, frames []logging.Frame) { 56 t.ReceivedLongHeaderPacket(hdr, size, ecn, frames) 57 }, 58 ReceivedShortHeaderPacket: func(hdr *logging.ShortHeader, size logging.ByteCount, ecn logging.ECN, frames []logging.Frame) { 59 t.ReceivedShortHeaderPacket(hdr, size, ecn, frames) 60 }, 61 ReceivedRetry: func(hdr *wire.Header) { 62 t.ReceivedRetry(hdr) 63 }, 64 ReceivedVersionNegotiationPacket: func(dest, src logging.ArbitraryLenConnectionID, versions []logging.VersionNumber) { 65 t.ReceivedVersionNegotiationPacket(dest, src, versions) 66 }, 67 BufferedPacket: func(pt logging.PacketType, size protocol.ByteCount) { 68 t.BufferedPacket(pt, size) 69 }, 70 DroppedPacket: func(pt logging.PacketType, pn logging.PacketNumber, size logging.ByteCount, reason logging.PacketDropReason) { 71 t.DroppedPacket(pt, pn, size, reason) 72 }, 73 UpdatedMetrics: func(rttStats *utils.RTTStats, cwnd, bytesInFlight protocol.ByteCount, packetsInFlight int) { 74 t.UpdatedMetrics(rttStats, cwnd, bytesInFlight, packetsInFlight) 75 }, 76 LostPacket: func(encLevel protocol.EncryptionLevel, pn protocol.PacketNumber, lossReason logging.PacketLossReason) { 77 t.LostPacket(encLevel, pn, lossReason) 78 }, 79 UpdatedMTU: func(mtu logging.ByteCount, done bool) { 80 t.UpdatedMTU(mtu, done) 81 }, 82 UpdatedCongestionState: func(state logging.CongestionState) { 83 t.UpdatedCongestionState(state) 84 }, 85 UpdatedPTOCount: func(value uint32) { 86 t.UpdatedPTOCount(value) 87 }, 88 UpdatedKeyFromTLS: func(encLevel protocol.EncryptionLevel, pers protocol.Perspective) { 89 t.UpdatedKeyFromTLS(encLevel, pers) 90 }, 91 UpdatedKey: func(keyPhase protocol.KeyPhase, remote bool) { 92 t.UpdatedKey(keyPhase, remote) 93 }, 94 DroppedEncryptionLevel: func(encLevel protocol.EncryptionLevel) { 95 t.DroppedEncryptionLevel(encLevel) 96 }, 97 DroppedKey: func(keyPhase protocol.KeyPhase) { 98 t.DroppedKey(keyPhase) 99 }, 100 SetLossTimer: func(tt logging.TimerType, encLevel protocol.EncryptionLevel, timeout time.Time) { 101 t.SetLossTimer(tt, encLevel, timeout) 102 }, 103 LossTimerExpired: func(tt logging.TimerType, encLevel protocol.EncryptionLevel) { 104 t.LossTimerExpired(tt, encLevel) 105 }, 106 LossTimerCanceled: func() { 107 t.LossTimerCanceled() 108 }, 109 ECNStateUpdated: func(state logging.ECNState, trigger logging.ECNStateTrigger) { 110 t.ECNStateUpdated(state, trigger) 111 }, 112 ChoseALPN: func(protocol string) { 113 t.recordEvent(time.Now(), eventALPNInformation{chosenALPN: protocol}) 114 }, 115 Debug: func(name, msg string) { 116 t.Debug(name, msg) 117 }, 118 Close: func() { 119 t.Close() 120 }, 121 } 122 } 123 124 func (t *connectionTracer) recordEvent(eventTime time.Time, details eventDetails) { 125 t.w.RecordEvent(eventTime, details) 126 } 127 128 func (t *connectionTracer) Close() { 129 t.w.Close() 130 } 131 132 func (t *connectionTracer) StartedConnection(local, remote net.Addr, srcConnID, destConnID protocol.ConnectionID) { 133 // ignore this event if we're not dealing with UDP addresses here 134 localAddr, ok := local.(*net.UDPAddr) 135 if !ok { 136 return 137 } 138 remoteAddr, ok := remote.(*net.UDPAddr) 139 if !ok { 140 return 141 } 142 t.recordEvent(time.Now(), &eventConnectionStarted{ 143 SrcAddr: localAddr, 144 DestAddr: remoteAddr, 145 SrcConnectionID: srcConnID, 146 DestConnectionID: destConnID, 147 }) 148 } 149 150 func (t *connectionTracer) NegotiatedVersion(chosen logging.VersionNumber, client, server []logging.VersionNumber) { 151 var clientVersions, serverVersions []versionNumber 152 if len(client) > 0 { 153 clientVersions = make([]versionNumber, len(client)) 154 for i, v := range client { 155 clientVersions[i] = versionNumber(v) 156 } 157 } 158 if len(server) > 0 { 159 serverVersions = make([]versionNumber, len(server)) 160 for i, v := range server { 161 serverVersions[i] = versionNumber(v) 162 } 163 } 164 t.recordEvent(time.Now(), &eventVersionNegotiated{ 165 clientVersions: clientVersions, 166 serverVersions: serverVersions, 167 chosenVersion: versionNumber(chosen), 168 }) 169 } 170 171 func (t *connectionTracer) ClosedConnection(e error) { 172 t.recordEvent(time.Now(), &eventConnectionClosed{e: e}) 173 } 174 175 func (t *connectionTracer) SentTransportParameters(tp *wire.TransportParameters) { 176 t.recordTransportParameters(t.perspective, tp) 177 } 178 179 func (t *connectionTracer) ReceivedTransportParameters(tp *wire.TransportParameters) { 180 t.recordTransportParameters(t.perspective.Opposite(), tp) 181 } 182 183 func (t *connectionTracer) RestoredTransportParameters(tp *wire.TransportParameters) { 184 ev := t.toTransportParameters(tp) 185 ev.Restore = true 186 187 t.recordEvent(time.Now(), ev) 188 } 189 190 func (t *connectionTracer) recordTransportParameters(sentBy protocol.Perspective, tp *wire.TransportParameters) { 191 ev := t.toTransportParameters(tp) 192 ev.Owner = ownerLocal 193 if sentBy != t.perspective { 194 ev.Owner = ownerRemote 195 } 196 ev.SentBy = sentBy 197 198 t.recordEvent(time.Now(), ev) 199 } 200 201 func (t *connectionTracer) toTransportParameters(tp *wire.TransportParameters) *eventTransportParameters { 202 var pa *preferredAddress 203 if tp.PreferredAddress != nil { 204 pa = &preferredAddress{ 205 IPv4: tp.PreferredAddress.IPv4, 206 IPv6: tp.PreferredAddress.IPv6, 207 ConnectionID: tp.PreferredAddress.ConnectionID, 208 StatelessResetToken: tp.PreferredAddress.StatelessResetToken, 209 } 210 } 211 return &eventTransportParameters{ 212 OriginalDestinationConnectionID: tp.OriginalDestinationConnectionID, 213 InitialSourceConnectionID: tp.InitialSourceConnectionID, 214 RetrySourceConnectionID: tp.RetrySourceConnectionID, 215 StatelessResetToken: tp.StatelessResetToken, 216 DisableActiveMigration: tp.DisableActiveMigration, 217 MaxIdleTimeout: tp.MaxIdleTimeout, 218 MaxUDPPayloadSize: tp.MaxUDPPayloadSize, 219 AckDelayExponent: tp.AckDelayExponent, 220 MaxAckDelay: tp.MaxAckDelay, 221 ActiveConnectionIDLimit: tp.ActiveConnectionIDLimit, 222 InitialMaxData: tp.InitialMaxData, 223 InitialMaxStreamDataBidiLocal: tp.InitialMaxStreamDataBidiLocal, 224 InitialMaxStreamDataBidiRemote: tp.InitialMaxStreamDataBidiRemote, 225 InitialMaxStreamDataUni: tp.InitialMaxStreamDataUni, 226 InitialMaxStreamsBidi: int64(tp.MaxBidiStreamNum), 227 InitialMaxStreamsUni: int64(tp.MaxUniStreamNum), 228 PreferredAddress: pa, 229 MaxDatagramFrameSize: tp.MaxDatagramFrameSize, 230 } 231 } 232 233 func (t *connectionTracer) SentLongHeaderPacket( 234 hdr *logging.ExtendedHeader, 235 size logging.ByteCount, 236 ecn logging.ECN, 237 ack *logging.AckFrame, 238 frames []logging.Frame, 239 ) { 240 t.sentPacket(*transformLongHeader(hdr), size, hdr.Length, ecn, ack, frames) 241 } 242 243 func (t *connectionTracer) SentShortHeaderPacket( 244 hdr *logging.ShortHeader, 245 size logging.ByteCount, 246 ecn logging.ECN, 247 ack *logging.AckFrame, 248 frames []logging.Frame, 249 ) { 250 t.sentPacket(*transformShortHeader(hdr), size, 0, ecn, ack, frames) 251 } 252 253 func (t *connectionTracer) sentPacket( 254 hdr gojay.MarshalerJSONObject, 255 size, payloadLen logging.ByteCount, 256 ecn logging.ECN, 257 ack *logging.AckFrame, 258 frames []logging.Frame, 259 ) { 260 numFrames := len(frames) 261 if ack != nil { 262 numFrames++ 263 } 264 fs := make([]frame, 0, numFrames) 265 if ack != nil { 266 fs = append(fs, frame{Frame: ack}) 267 } 268 for _, f := range frames { 269 fs = append(fs, frame{Frame: f}) 270 } 271 t.recordEvent(time.Now(), &eventPacketSent{ 272 Header: hdr, 273 Length: size, 274 PayloadLength: payloadLen, 275 ECN: ecn, 276 Frames: fs, 277 }) 278 } 279 280 func (t *connectionTracer) ReceivedLongHeaderPacket(hdr *logging.ExtendedHeader, size logging.ByteCount, ecn logging.ECN, frames []logging.Frame) { 281 fs := make([]frame, len(frames)) 282 for i, f := range frames { 283 fs[i] = frame{Frame: f} 284 } 285 header := *transformLongHeader(hdr) 286 t.recordEvent(time.Now(), &eventPacketReceived{ 287 Header: header, 288 Length: size, 289 PayloadLength: hdr.Length, 290 ECN: ecn, 291 Frames: fs, 292 }) 293 } 294 295 func (t *connectionTracer) ReceivedShortHeaderPacket(hdr *logging.ShortHeader, size logging.ByteCount, ecn logging.ECN, frames []logging.Frame) { 296 fs := make([]frame, len(frames)) 297 for i, f := range frames { 298 fs[i] = frame{Frame: f} 299 } 300 header := *transformShortHeader(hdr) 301 t.recordEvent(time.Now(), &eventPacketReceived{ 302 Header: header, 303 Length: size, 304 PayloadLength: size - wire.ShortHeaderLen(hdr.DestConnectionID, hdr.PacketNumberLen), 305 ECN: ecn, 306 Frames: fs, 307 }) 308 } 309 310 func (t *connectionTracer) ReceivedRetry(hdr *wire.Header) { 311 t.recordEvent(time.Now(), &eventRetryReceived{ 312 Header: *transformHeader(hdr), 313 }) 314 } 315 316 func (t *connectionTracer) ReceivedVersionNegotiationPacket(dest, src logging.ArbitraryLenConnectionID, versions []logging.VersionNumber) { 317 ver := make([]versionNumber, len(versions)) 318 for i, v := range versions { 319 ver[i] = versionNumber(v) 320 } 321 t.recordEvent(time.Now(), &eventVersionNegotiationReceived{ 322 Header: packetHeaderVersionNegotiation{ 323 SrcConnectionID: src, 324 DestConnectionID: dest, 325 }, 326 SupportedVersions: ver, 327 }) 328 } 329 330 func (t *connectionTracer) BufferedPacket(pt logging.PacketType, size protocol.ByteCount) { 331 t.recordEvent(time.Now(), &eventPacketBuffered{ 332 PacketType: pt, 333 PacketSize: size, 334 }) 335 } 336 337 func (t *connectionTracer) DroppedPacket(pt logging.PacketType, pn logging.PacketNumber, size protocol.ByteCount, reason logging.PacketDropReason) { 338 t.recordEvent(time.Now(), &eventPacketDropped{ 339 PacketType: pt, 340 PacketNumber: pn, 341 PacketSize: size, 342 Trigger: packetDropReason(reason), 343 }) 344 } 345 346 func (t *connectionTracer) UpdatedMetrics(rttStats *utils.RTTStats, cwnd, bytesInFlight protocol.ByteCount, packetsInFlight int) { 347 m := &metrics{ 348 MinRTT: rttStats.MinRTT(), 349 SmoothedRTT: rttStats.SmoothedRTT(), 350 LatestRTT: rttStats.LatestRTT(), 351 RTTVariance: rttStats.MeanDeviation(), 352 CongestionWindow: cwnd, 353 BytesInFlight: bytesInFlight, 354 PacketsInFlight: packetsInFlight, 355 } 356 t.recordEvent(time.Now(), &eventMetricsUpdated{ 357 Last: t.lastMetrics, 358 Current: m, 359 }) 360 t.lastMetrics = m 361 } 362 363 func (t *connectionTracer) AcknowledgedPacket(protocol.EncryptionLevel, protocol.PacketNumber) {} 364 365 func (t *connectionTracer) LostPacket(encLevel protocol.EncryptionLevel, pn protocol.PacketNumber, lossReason logging.PacketLossReason) { 366 t.recordEvent(time.Now(), &eventPacketLost{ 367 PacketType: getPacketTypeFromEncryptionLevel(encLevel), 368 PacketNumber: pn, 369 Trigger: packetLossReason(lossReason), 370 }) 371 } 372 373 func (t *connectionTracer) UpdatedMTU(mtu protocol.ByteCount, done bool) { 374 t.recordEvent(time.Now(), &eventMTUUpdated{mtu: mtu, done: done}) 375 } 376 377 func (t *connectionTracer) UpdatedCongestionState(state logging.CongestionState) { 378 t.recordEvent(time.Now(), &eventCongestionStateUpdated{state: congestionState(state)}) 379 } 380 381 func (t *connectionTracer) UpdatedPTOCount(value uint32) { 382 t.recordEvent(time.Now(), &eventUpdatedPTO{Value: value}) 383 } 384 385 func (t *connectionTracer) UpdatedKeyFromTLS(encLevel protocol.EncryptionLevel, pers protocol.Perspective) { 386 t.recordEvent(time.Now(), &eventKeyUpdated{ 387 Trigger: keyUpdateTLS, 388 KeyType: encLevelToKeyType(encLevel, pers), 389 }) 390 } 391 392 func (t *connectionTracer) UpdatedKey(generation protocol.KeyPhase, remote bool) { 393 trigger := keyUpdateLocal 394 if remote { 395 trigger = keyUpdateRemote 396 } 397 now := time.Now() 398 t.recordEvent(now, &eventKeyUpdated{ 399 Trigger: trigger, 400 KeyType: keyTypeClient1RTT, 401 KeyPhase: generation, 402 }) 403 t.recordEvent(now, &eventKeyUpdated{ 404 Trigger: trigger, 405 KeyType: keyTypeServer1RTT, 406 KeyPhase: generation, 407 }) 408 } 409 410 func (t *connectionTracer) DroppedEncryptionLevel(encLevel protocol.EncryptionLevel) { 411 now := time.Now() 412 if encLevel == protocol.Encryption0RTT { 413 t.recordEvent(now, &eventKeyDiscarded{KeyType: encLevelToKeyType(encLevel, t.perspective)}) 414 } else { 415 t.recordEvent(now, &eventKeyDiscarded{KeyType: encLevelToKeyType(encLevel, protocol.PerspectiveServer)}) 416 t.recordEvent(now, &eventKeyDiscarded{KeyType: encLevelToKeyType(encLevel, protocol.PerspectiveClient)}) 417 } 418 } 419 420 func (t *connectionTracer) DroppedKey(generation protocol.KeyPhase) { 421 now := time.Now() 422 t.recordEvent(now, &eventKeyDiscarded{ 423 KeyType: encLevelToKeyType(protocol.Encryption1RTT, protocol.PerspectiveServer), 424 KeyPhase: generation, 425 }) 426 t.recordEvent(now, &eventKeyDiscarded{ 427 KeyType: encLevelToKeyType(protocol.Encryption1RTT, protocol.PerspectiveClient), 428 KeyPhase: generation, 429 }) 430 } 431 432 func (t *connectionTracer) SetLossTimer(tt logging.TimerType, encLevel protocol.EncryptionLevel, timeout time.Time) { 433 now := time.Now() 434 t.recordEvent(now, &eventLossTimerSet{ 435 TimerType: timerType(tt), 436 EncLevel: encLevel, 437 Delta: timeout.Sub(now), 438 }) 439 } 440 441 func (t *connectionTracer) LossTimerExpired(tt logging.TimerType, encLevel protocol.EncryptionLevel) { 442 t.recordEvent(time.Now(), &eventLossTimerExpired{ 443 TimerType: timerType(tt), 444 EncLevel: encLevel, 445 }) 446 } 447 448 func (t *connectionTracer) LossTimerCanceled() { 449 t.recordEvent(time.Now(), &eventLossTimerCanceled{}) 450 } 451 452 func (t *connectionTracer) ECNStateUpdated(state logging.ECNState, trigger logging.ECNStateTrigger) { 453 t.recordEvent(time.Now(), &eventECNStateUpdated{state: state, trigger: trigger}) 454 } 455 456 func (t *connectionTracer) Debug(name, msg string) { 457 t.recordEvent(time.Now(), &eventGeneric{ 458 name: name, 459 msg: msg, 460 }) 461 }