github.com/tumi8/quic-go@v0.37.4-tum/qlog/event.go (about) 1 package qlog 2 3 import ( 4 "errors" 5 "fmt" 6 "net" 7 "time" 8 9 "github.com/tumi8/quic-go" 10 "github.com/tumi8/quic-go/noninternal/utils" 11 12 "github.com/tumi8/quic-go/noninternal/protocol" 13 "github.com/tumi8/quic-go/logging" 14 15 "github.com/francoispqt/gojay" 16 ) 17 18 func milliseconds(dur time.Duration) float64 { return float64(dur.Nanoseconds()) / 1e6 } 19 20 type eventDetails interface { 21 Category() category 22 Name() string 23 gojay.MarshalerJSONObject 24 } 25 26 type event struct { 27 RelativeTime time.Duration 28 eventDetails 29 } 30 31 var _ gojay.MarshalerJSONObject = event{} 32 33 func (e event) IsNil() bool { return false } 34 func (e event) MarshalJSONObject(enc *gojay.Encoder) { 35 enc.Float64Key("time", milliseconds(e.RelativeTime)) 36 enc.StringKey("name", e.Category().String()+":"+e.Name()) 37 enc.ObjectKey("data", e.eventDetails) 38 } 39 40 type versions []versionNumber 41 42 func (v versions) IsNil() bool { return false } 43 func (v versions) MarshalJSONArray(enc *gojay.Encoder) { 44 for _, e := range v { 45 enc.AddString(e.String()) 46 } 47 } 48 49 type rawInfo struct { 50 Length logging.ByteCount // full packet length, including header and AEAD authentication tag 51 PayloadLength logging.ByteCount // length of the packet payload, excluding AEAD tag 52 } 53 54 func (i rawInfo) IsNil() bool { return false } 55 func (i rawInfo) MarshalJSONObject(enc *gojay.Encoder) { 56 enc.Uint64Key("length", uint64(i.Length)) 57 enc.Uint64KeyOmitEmpty("payload_length", uint64(i.PayloadLength)) 58 } 59 60 type eventConnectionStarted struct { 61 SrcAddr *net.UDPAddr 62 DestAddr *net.UDPAddr 63 64 SrcConnectionID protocol.ConnectionID 65 DestConnectionID protocol.ConnectionID 66 } 67 68 var _ eventDetails = &eventConnectionStarted{} 69 70 func (e eventConnectionStarted) Category() category { return categoryTransport } 71 func (e eventConnectionStarted) Name() string { return "connection_started" } 72 func (e eventConnectionStarted) IsNil() bool { return false } 73 74 func (e eventConnectionStarted) MarshalJSONObject(enc *gojay.Encoder) { 75 if utils.IsIPv4(e.SrcAddr.IP) { 76 enc.StringKey("ip_version", "ipv4") 77 } else { 78 enc.StringKey("ip_version", "ipv6") 79 } 80 enc.StringKey("src_ip", e.SrcAddr.IP.String()) 81 enc.IntKey("src_port", e.SrcAddr.Port) 82 enc.StringKey("dst_ip", e.DestAddr.IP.String()) 83 enc.IntKey("dst_port", e.DestAddr.Port) 84 enc.StringKey("src_cid", e.SrcConnectionID.String()) 85 enc.StringKey("dst_cid", e.DestConnectionID.String()) 86 } 87 88 type eventVersionNegotiated struct { 89 clientVersions, serverVersions []versionNumber 90 chosenVersion versionNumber 91 } 92 93 func (e eventVersionNegotiated) Category() category { return categoryTransport } 94 func (e eventVersionNegotiated) Name() string { return "version_information" } 95 func (e eventVersionNegotiated) IsNil() bool { return false } 96 97 func (e eventVersionNegotiated) MarshalJSONObject(enc *gojay.Encoder) { 98 if len(e.clientVersions) > 0 { 99 enc.ArrayKey("client_versions", versions(e.clientVersions)) 100 } 101 if len(e.serverVersions) > 0 { 102 enc.ArrayKey("server_versions", versions(e.serverVersions)) 103 } 104 enc.StringKey("chosen_version", e.chosenVersion.String()) 105 } 106 107 type eventConnectionClosed struct { 108 e error 109 } 110 111 func (e eventConnectionClosed) Category() category { return categoryTransport } 112 func (e eventConnectionClosed) Name() string { return "connection_closed" } 113 func (e eventConnectionClosed) IsNil() bool { return false } 114 115 func (e eventConnectionClosed) MarshalJSONObject(enc *gojay.Encoder) { 116 var ( 117 statelessResetErr *quic.StatelessResetError 118 handshakeTimeoutErr *quic.HandshakeTimeoutError 119 idleTimeoutErr *quic.IdleTimeoutError 120 applicationErr *quic.ApplicationError 121 transportErr *quic.TransportError 122 versionNegotiationErr *quic.VersionNegotiationError 123 ) 124 switch { 125 case errors.As(e.e, &statelessResetErr): 126 enc.StringKey("owner", ownerRemote.String()) 127 enc.StringKey("trigger", "stateless_reset") 128 enc.StringKey("stateless_reset_token", fmt.Sprintf("%x", statelessResetErr.Token)) 129 case errors.As(e.e, &handshakeTimeoutErr): 130 enc.StringKey("owner", ownerLocal.String()) 131 enc.StringKey("trigger", "handshake_timeout") 132 case errors.As(e.e, &idleTimeoutErr): 133 enc.StringKey("owner", ownerLocal.String()) 134 enc.StringKey("trigger", "idle_timeout") 135 case errors.As(e.e, &applicationErr): 136 owner := ownerLocal 137 if applicationErr.Remote { 138 owner = ownerRemote 139 } 140 enc.StringKey("owner", owner.String()) 141 enc.Uint64Key("application_code", uint64(applicationErr.ErrorCode)) 142 enc.StringKey("reason", applicationErr.ErrorMessage) 143 case errors.As(e.e, &transportErr): 144 owner := ownerLocal 145 if transportErr.Remote { 146 owner = ownerRemote 147 } 148 enc.StringKey("owner", owner.String()) 149 enc.StringKey("connection_code", transportError(transportErr.ErrorCode).String()) 150 enc.StringKey("reason", transportErr.ErrorMessage) 151 case errors.As(e.e, &versionNegotiationErr): 152 enc.StringKey("trigger", "version_mismatch") 153 } 154 } 155 156 type eventPacketSent struct { 157 Header gojay.MarshalerJSONObject // either a shortHeader or a packetHeader 158 Length logging.ByteCount 159 PayloadLength logging.ByteCount 160 Frames frames 161 IsCoalesced bool 162 Trigger string 163 } 164 165 var _ eventDetails = eventPacketSent{} 166 167 func (e eventPacketSent) Category() category { return categoryTransport } 168 func (e eventPacketSent) Name() string { return "packet_sent" } 169 func (e eventPacketSent) IsNil() bool { return false } 170 171 func (e eventPacketSent) MarshalJSONObject(enc *gojay.Encoder) { 172 enc.ObjectKey("header", e.Header) 173 enc.ObjectKey("raw", rawInfo{Length: e.Length, PayloadLength: e.PayloadLength}) 174 enc.ArrayKeyOmitEmpty("frames", e.Frames) 175 enc.BoolKeyOmitEmpty("is_coalesced", e.IsCoalesced) 176 enc.StringKeyOmitEmpty("trigger", e.Trigger) 177 } 178 179 type eventPacketReceived struct { 180 Header gojay.MarshalerJSONObject // either a shortHeader or a packetHeader 181 Length logging.ByteCount 182 PayloadLength logging.ByteCount 183 Frames frames 184 IsCoalesced bool 185 Trigger string 186 } 187 188 var _ eventDetails = eventPacketReceived{} 189 190 func (e eventPacketReceived) Category() category { return categoryTransport } 191 func (e eventPacketReceived) Name() string { return "packet_received" } 192 func (e eventPacketReceived) IsNil() bool { return false } 193 194 func (e eventPacketReceived) MarshalJSONObject(enc *gojay.Encoder) { 195 enc.ObjectKey("header", e.Header) 196 enc.ObjectKey("raw", rawInfo{Length: e.Length, PayloadLength: e.PayloadLength}) 197 enc.ArrayKeyOmitEmpty("frames", e.Frames) 198 enc.BoolKeyOmitEmpty("is_coalesced", e.IsCoalesced) 199 enc.StringKeyOmitEmpty("trigger", e.Trigger) 200 } 201 202 type eventRetryReceived struct { 203 Header packetHeader 204 } 205 206 func (e eventRetryReceived) Category() category { return categoryTransport } 207 func (e eventRetryReceived) Name() string { return "packet_received" } 208 func (e eventRetryReceived) IsNil() bool { return false } 209 210 func (e eventRetryReceived) MarshalJSONObject(enc *gojay.Encoder) { 211 enc.ObjectKey("header", e.Header) 212 } 213 214 type eventVersionNegotiationReceived struct { 215 Header packetHeaderVersionNegotiation 216 SupportedVersions []versionNumber 217 } 218 219 func (e eventVersionNegotiationReceived) Category() category { return categoryTransport } 220 func (e eventVersionNegotiationReceived) Name() string { return "packet_received" } 221 func (e eventVersionNegotiationReceived) IsNil() bool { return false } 222 223 func (e eventVersionNegotiationReceived) MarshalJSONObject(enc *gojay.Encoder) { 224 enc.ObjectKey("header", e.Header) 225 enc.ArrayKey("supported_versions", versions(e.SupportedVersions)) 226 } 227 228 type eventPacketBuffered struct { 229 PacketType logging.PacketType 230 PacketSize protocol.ByteCount 231 } 232 233 func (e eventPacketBuffered) Category() category { return categoryTransport } 234 func (e eventPacketBuffered) Name() string { return "packet_buffered" } 235 func (e eventPacketBuffered) IsNil() bool { return false } 236 237 func (e eventPacketBuffered) MarshalJSONObject(enc *gojay.Encoder) { 238 //nolint:gosimple 239 enc.ObjectKey("header", packetHeaderWithType{PacketType: e.PacketType}) 240 enc.ObjectKey("raw", rawInfo{Length: e.PacketSize}) 241 enc.StringKey("trigger", "keys_unavailable") 242 } 243 244 type eventPacketDropped struct { 245 PacketType logging.PacketType 246 PacketSize protocol.ByteCount 247 Trigger packetDropReason 248 } 249 250 func (e eventPacketDropped) Category() category { return categoryTransport } 251 func (e eventPacketDropped) Name() string { return "packet_dropped" } 252 func (e eventPacketDropped) IsNil() bool { return false } 253 254 func (e eventPacketDropped) MarshalJSONObject(enc *gojay.Encoder) { 255 enc.ObjectKey("header", packetHeaderWithType{PacketType: e.PacketType}) 256 enc.ObjectKey("raw", rawInfo{Length: e.PacketSize}) 257 enc.StringKey("trigger", e.Trigger.String()) 258 } 259 260 type metrics struct { 261 MinRTT time.Duration 262 SmoothedRTT time.Duration 263 LatestRTT time.Duration 264 RTTVariance time.Duration 265 266 CongestionWindow protocol.ByteCount 267 BytesInFlight protocol.ByteCount 268 PacketsInFlight int 269 } 270 271 type eventMetricsUpdated struct { 272 Last *metrics 273 Current *metrics 274 } 275 276 func (e eventMetricsUpdated) Category() category { return categoryRecovery } 277 func (e eventMetricsUpdated) Name() string { return "metrics_updated" } 278 func (e eventMetricsUpdated) IsNil() bool { return false } 279 280 func (e eventMetricsUpdated) MarshalJSONObject(enc *gojay.Encoder) { 281 if e.Last == nil || e.Last.MinRTT != e.Current.MinRTT { 282 enc.FloatKey("min_rtt", milliseconds(e.Current.MinRTT)) 283 } 284 if e.Last == nil || e.Last.SmoothedRTT != e.Current.SmoothedRTT { 285 enc.FloatKey("smoothed_rtt", milliseconds(e.Current.SmoothedRTT)) 286 } 287 if e.Last == nil || e.Last.LatestRTT != e.Current.LatestRTT { 288 enc.FloatKey("latest_rtt", milliseconds(e.Current.LatestRTT)) 289 } 290 if e.Last == nil || e.Last.RTTVariance != e.Current.RTTVariance { 291 enc.FloatKey("rtt_variance", milliseconds(e.Current.RTTVariance)) 292 } 293 294 if e.Last == nil || e.Last.CongestionWindow != e.Current.CongestionWindow { 295 enc.Uint64Key("congestion_window", uint64(e.Current.CongestionWindow)) 296 } 297 if e.Last == nil || e.Last.BytesInFlight != e.Current.BytesInFlight { 298 enc.Uint64Key("bytes_in_flight", uint64(e.Current.BytesInFlight)) 299 } 300 if e.Last == nil || e.Last.PacketsInFlight != e.Current.PacketsInFlight { 301 enc.Uint64KeyOmitEmpty("packets_in_flight", uint64(e.Current.PacketsInFlight)) 302 } 303 } 304 305 type eventUpdatedPTO struct { 306 Value uint32 307 } 308 309 func (e eventUpdatedPTO) Category() category { return categoryRecovery } 310 func (e eventUpdatedPTO) Name() string { return "metrics_updated" } 311 func (e eventUpdatedPTO) IsNil() bool { return false } 312 313 func (e eventUpdatedPTO) MarshalJSONObject(enc *gojay.Encoder) { 314 enc.Uint32Key("pto_count", e.Value) 315 } 316 317 type eventPacketLost struct { 318 PacketType logging.PacketType 319 PacketNumber protocol.PacketNumber 320 Trigger packetLossReason 321 } 322 323 func (e eventPacketLost) Category() category { return categoryRecovery } 324 func (e eventPacketLost) Name() string { return "packet_lost" } 325 func (e eventPacketLost) IsNil() bool { return false } 326 327 func (e eventPacketLost) MarshalJSONObject(enc *gojay.Encoder) { 328 enc.ObjectKey("header", packetHeaderWithTypeAndPacketNumber{ 329 PacketType: e.PacketType, 330 PacketNumber: e.PacketNumber, 331 }) 332 enc.StringKey("trigger", e.Trigger.String()) 333 } 334 335 type eventKeyUpdated struct { 336 Trigger keyUpdateTrigger 337 KeyType keyType 338 Generation protocol.KeyPhase 339 // we don't log the keys here, so we don't need `old` and `new`. 340 } 341 342 func (e eventKeyUpdated) Category() category { return categorySecurity } 343 func (e eventKeyUpdated) Name() string { return "key_updated" } 344 func (e eventKeyUpdated) IsNil() bool { return false } 345 346 func (e eventKeyUpdated) MarshalJSONObject(enc *gojay.Encoder) { 347 enc.StringKey("trigger", e.Trigger.String()) 348 enc.StringKey("key_type", e.KeyType.String()) 349 if e.KeyType == keyTypeClient1RTT || e.KeyType == keyTypeServer1RTT { 350 enc.Uint64Key("generation", uint64(e.Generation)) 351 } 352 } 353 354 type eventKeyDiscarded struct { 355 KeyType keyType 356 Generation protocol.KeyPhase 357 } 358 359 func (e eventKeyDiscarded) Category() category { return categorySecurity } 360 func (e eventKeyDiscarded) Name() string { return "key_discarded" } 361 func (e eventKeyDiscarded) IsNil() bool { return false } 362 363 func (e eventKeyDiscarded) MarshalJSONObject(enc *gojay.Encoder) { 364 if e.KeyType != keyTypeClient1RTT && e.KeyType != keyTypeServer1RTT { 365 enc.StringKey("trigger", "tls") 366 } 367 enc.StringKey("key_type", e.KeyType.String()) 368 if e.KeyType == keyTypeClient1RTT || e.KeyType == keyTypeServer1RTT { 369 enc.Uint64Key("generation", uint64(e.Generation)) 370 } 371 } 372 373 type eventTransportParameters struct { 374 Restore bool 375 Owner owner 376 SentBy protocol.Perspective 377 378 OriginalDestinationConnectionID protocol.ConnectionID 379 InitialSourceConnectionID protocol.ConnectionID 380 RetrySourceConnectionID *protocol.ConnectionID 381 382 StatelessResetToken *protocol.StatelessResetToken 383 DisableActiveMigration bool 384 MaxIdleTimeout time.Duration 385 MaxUDPPayloadSize protocol.ByteCount 386 AckDelayExponent uint8 387 MaxAckDelay time.Duration 388 ActiveConnectionIDLimit uint64 389 390 InitialMaxData protocol.ByteCount 391 InitialMaxStreamDataBidiLocal protocol.ByteCount 392 InitialMaxStreamDataBidiRemote protocol.ByteCount 393 InitialMaxStreamDataUni protocol.ByteCount 394 InitialMaxStreamsBidi int64 395 InitialMaxStreamsUni int64 396 397 PreferredAddress *preferredAddress 398 399 MaxDatagramFrameSize protocol.ByteCount 400 } 401 402 func (e eventTransportParameters) Category() category { return categoryTransport } 403 func (e eventTransportParameters) Name() string { 404 if e.Restore { 405 return "parameters_restored" 406 } 407 return "parameters_set" 408 } 409 func (e eventTransportParameters) IsNil() bool { return false } 410 411 func (e eventTransportParameters) MarshalJSONObject(enc *gojay.Encoder) { 412 if !e.Restore { 413 enc.StringKey("owner", e.Owner.String()) 414 if e.SentBy == protocol.PerspectiveServer { 415 enc.StringKey("original_destination_connection_id", e.OriginalDestinationConnectionID.String()) 416 if e.StatelessResetToken != nil { 417 enc.StringKey("stateless_reset_token", fmt.Sprintf("%x", e.StatelessResetToken[:])) 418 } 419 if e.RetrySourceConnectionID != nil { 420 enc.StringKey("retry_source_connection_id", (*e.RetrySourceConnectionID).String()) 421 } 422 } 423 enc.StringKey("initial_source_connection_id", e.InitialSourceConnectionID.String()) 424 } 425 enc.BoolKey("disable_active_migration", e.DisableActiveMigration) 426 enc.FloatKeyOmitEmpty("max_idle_timeout", milliseconds(e.MaxIdleTimeout)) 427 enc.Int64KeyNullEmpty("max_udp_payload_size", int64(e.MaxUDPPayloadSize)) 428 enc.Uint8KeyOmitEmpty("ack_delay_exponent", e.AckDelayExponent) 429 enc.FloatKeyOmitEmpty("max_ack_delay", milliseconds(e.MaxAckDelay)) 430 enc.Uint64KeyOmitEmpty("active_connection_id_limit", e.ActiveConnectionIDLimit) 431 432 enc.Int64KeyOmitEmpty("initial_max_data", int64(e.InitialMaxData)) 433 enc.Int64KeyOmitEmpty("initial_max_stream_data_bidi_local", int64(e.InitialMaxStreamDataBidiLocal)) 434 enc.Int64KeyOmitEmpty("initial_max_stream_data_bidi_remote", int64(e.InitialMaxStreamDataBidiRemote)) 435 enc.Int64KeyOmitEmpty("initial_max_stream_data_uni", int64(e.InitialMaxStreamDataUni)) 436 enc.Int64KeyOmitEmpty("initial_max_streams_bidi", e.InitialMaxStreamsBidi) 437 enc.Int64KeyOmitEmpty("initial_max_streams_uni", e.InitialMaxStreamsUni) 438 439 if e.PreferredAddress != nil { 440 enc.ObjectKey("preferred_address", e.PreferredAddress) 441 } 442 if e.MaxDatagramFrameSize != protocol.InvalidByteCount { 443 enc.Int64Key("max_datagram_frame_size", int64(e.MaxDatagramFrameSize)) 444 } 445 } 446 447 type preferredAddress struct { 448 IPv4, IPv6 net.IP 449 PortV4, PortV6 uint16 450 ConnectionID protocol.ConnectionID 451 StatelessResetToken protocol.StatelessResetToken 452 } 453 454 var _ gojay.MarshalerJSONObject = &preferredAddress{} 455 456 func (a preferredAddress) IsNil() bool { return false } 457 func (a preferredAddress) MarshalJSONObject(enc *gojay.Encoder) { 458 enc.StringKey("ip_v4", a.IPv4.String()) 459 enc.Uint16Key("port_v4", a.PortV4) 460 enc.StringKey("ip_v6", a.IPv6.String()) 461 enc.Uint16Key("port_v6", a.PortV6) 462 enc.StringKey("connection_id", a.ConnectionID.String()) 463 enc.StringKey("stateless_reset_token", fmt.Sprintf("%x", a.StatelessResetToken)) 464 } 465 466 type eventLossTimerSet struct { 467 TimerType timerType 468 EncLevel protocol.EncryptionLevel 469 Delta time.Duration 470 } 471 472 func (e eventLossTimerSet) Category() category { return categoryRecovery } 473 func (e eventLossTimerSet) Name() string { return "loss_timer_updated" } 474 func (e eventLossTimerSet) IsNil() bool { return false } 475 476 func (e eventLossTimerSet) MarshalJSONObject(enc *gojay.Encoder) { 477 enc.StringKey("event_type", "set") 478 enc.StringKey("timer_type", e.TimerType.String()) 479 enc.StringKey("packet_number_space", encLevelToPacketNumberSpace(e.EncLevel)) 480 enc.Float64Key("delta", milliseconds(e.Delta)) 481 } 482 483 type eventLossTimerExpired struct { 484 TimerType timerType 485 EncLevel protocol.EncryptionLevel 486 } 487 488 func (e eventLossTimerExpired) Category() category { return categoryRecovery } 489 func (e eventLossTimerExpired) Name() string { return "loss_timer_updated" } 490 func (e eventLossTimerExpired) IsNil() bool { return false } 491 492 func (e eventLossTimerExpired) MarshalJSONObject(enc *gojay.Encoder) { 493 enc.StringKey("event_type", "expired") 494 enc.StringKey("timer_type", e.TimerType.String()) 495 enc.StringKey("packet_number_space", encLevelToPacketNumberSpace(e.EncLevel)) 496 } 497 498 type eventLossTimerCanceled struct{} 499 500 func (e eventLossTimerCanceled) Category() category { return categoryRecovery } 501 func (e eventLossTimerCanceled) Name() string { return "loss_timer_updated" } 502 func (e eventLossTimerCanceled) IsNil() bool { return false } 503 504 func (e eventLossTimerCanceled) MarshalJSONObject(enc *gojay.Encoder) { 505 enc.StringKey("event_type", "cancelled") 506 } 507 508 type eventCongestionStateUpdated struct { 509 state congestionState 510 } 511 512 func (e eventCongestionStateUpdated) Category() category { return categoryRecovery } 513 func (e eventCongestionStateUpdated) Name() string { return "congestion_state_updated" } 514 func (e eventCongestionStateUpdated) IsNil() bool { return false } 515 516 func (e eventCongestionStateUpdated) MarshalJSONObject(enc *gojay.Encoder) { 517 enc.StringKey("new", e.state.String()) 518 } 519 520 type eventGeneric struct { 521 name string 522 msg string 523 } 524 525 func (e eventGeneric) Category() category { return categoryTransport } 526 func (e eventGeneric) Name() string { return e.name } 527 func (e eventGeneric) IsNil() bool { return false } 528 529 func (e eventGeneric) MarshalJSONObject(enc *gojay.Encoder) { 530 enc.StringKey("details", e.msg) 531 }