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