github.com/danielpfeifer02/quic-go-prio-packs@v0.41.0-28/qlog/event.go (about)

     1  package qlog
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"net"
     7  	"net/netip"
     8  	"time"
     9  
    10  	"github.com/danielpfeifer02/quic-go-prio-packs"
    11  	"github.com/danielpfeifer02/quic-go-prio-packs/internal/protocol"
    12  	"github.com/danielpfeifer02/quic-go-prio-packs/internal/utils"
    13  	"github.com/danielpfeifer02/quic-go-prio-packs/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  	ECN           logging.ECN
   163  	Trigger       string
   164  }
   165  
   166  var _ eventDetails = eventPacketSent{}
   167  
   168  func (e eventPacketSent) Category() category { return categoryTransport }
   169  func (e eventPacketSent) Name() string       { return "packet_sent" }
   170  func (e eventPacketSent) IsNil() bool        { return false }
   171  
   172  func (e eventPacketSent) MarshalJSONObject(enc *gojay.Encoder) {
   173  	enc.ObjectKey("header", e.Header)
   174  	enc.ObjectKey("raw", rawInfo{Length: e.Length, PayloadLength: e.PayloadLength})
   175  	enc.ArrayKeyOmitEmpty("frames", e.Frames)
   176  	enc.BoolKeyOmitEmpty("is_coalesced", e.IsCoalesced)
   177  	if e.ECN != logging.ECNUnsupported {
   178  		enc.StringKey("ecn", ecn(e.ECN).String())
   179  	}
   180  	enc.StringKeyOmitEmpty("trigger", e.Trigger)
   181  }
   182  
   183  type eventPacketReceived struct {
   184  	Header        gojay.MarshalerJSONObject // either a shortHeader or a packetHeader
   185  	Length        logging.ByteCount
   186  	PayloadLength logging.ByteCount
   187  	Frames        frames
   188  	ECN           logging.ECN
   189  	IsCoalesced   bool
   190  	Trigger       string
   191  }
   192  
   193  var _ eventDetails = eventPacketReceived{}
   194  
   195  func (e eventPacketReceived) Category() category { return categoryTransport }
   196  func (e eventPacketReceived) Name() string       { return "packet_received" }
   197  func (e eventPacketReceived) IsNil() bool        { return false }
   198  
   199  func (e eventPacketReceived) MarshalJSONObject(enc *gojay.Encoder) {
   200  	enc.ObjectKey("header", e.Header)
   201  	enc.ObjectKey("raw", rawInfo{Length: e.Length, PayloadLength: e.PayloadLength})
   202  	enc.ArrayKeyOmitEmpty("frames", e.Frames)
   203  	enc.BoolKeyOmitEmpty("is_coalesced", e.IsCoalesced)
   204  	if e.ECN != logging.ECNUnsupported {
   205  		enc.StringKey("ecn", ecn(e.ECN).String())
   206  	}
   207  	enc.StringKeyOmitEmpty("trigger", e.Trigger)
   208  }
   209  
   210  type eventRetryReceived struct {
   211  	Header packetHeader
   212  }
   213  
   214  func (e eventRetryReceived) Category() category { return categoryTransport }
   215  func (e eventRetryReceived) Name() string       { return "packet_received" }
   216  func (e eventRetryReceived) IsNil() bool        { return false }
   217  
   218  func (e eventRetryReceived) MarshalJSONObject(enc *gojay.Encoder) {
   219  	enc.ObjectKey("header", e.Header)
   220  }
   221  
   222  type eventVersionNegotiationReceived struct {
   223  	Header            packetHeaderVersionNegotiation
   224  	SupportedVersions []versionNumber
   225  }
   226  
   227  func (e eventVersionNegotiationReceived) Category() category { return categoryTransport }
   228  func (e eventVersionNegotiationReceived) Name() string       { return "packet_received" }
   229  func (e eventVersionNegotiationReceived) IsNil() bool        { return false }
   230  
   231  func (e eventVersionNegotiationReceived) MarshalJSONObject(enc *gojay.Encoder) {
   232  	enc.ObjectKey("header", e.Header)
   233  	enc.ArrayKey("supported_versions", versions(e.SupportedVersions))
   234  }
   235  
   236  type eventPacketBuffered struct {
   237  	PacketType logging.PacketType
   238  	PacketSize protocol.ByteCount
   239  }
   240  
   241  func (e eventPacketBuffered) Category() category { return categoryTransport }
   242  func (e eventPacketBuffered) Name() string       { return "packet_buffered" }
   243  func (e eventPacketBuffered) IsNil() bool        { return false }
   244  
   245  func (e eventPacketBuffered) MarshalJSONObject(enc *gojay.Encoder) {
   246  	//nolint:gosimple
   247  	enc.ObjectKey("header", packetHeaderWithType{PacketType: e.PacketType, PacketNumber: protocol.InvalidPacketNumber})
   248  	enc.ObjectKey("raw", rawInfo{Length: e.PacketSize})
   249  	enc.StringKey("trigger", "keys_unavailable")
   250  }
   251  
   252  type eventPacketDropped struct {
   253  	PacketType   logging.PacketType
   254  	PacketSize   protocol.ByteCount
   255  	PacketNumber logging.PacketNumber
   256  	Trigger      packetDropReason
   257  }
   258  
   259  func (e eventPacketDropped) Category() category { return categoryTransport }
   260  func (e eventPacketDropped) Name() string       { return "packet_dropped" }
   261  func (e eventPacketDropped) IsNil() bool        { return false }
   262  
   263  func (e eventPacketDropped) MarshalJSONObject(enc *gojay.Encoder) {
   264  	enc.ObjectKey("header", packetHeaderWithType{
   265  		PacketType:   e.PacketType,
   266  		PacketNumber: e.PacketNumber,
   267  	})
   268  	enc.ObjectKey("raw", rawInfo{Length: e.PacketSize})
   269  	enc.StringKey("trigger", e.Trigger.String())
   270  }
   271  
   272  type metrics struct {
   273  	MinRTT      time.Duration
   274  	SmoothedRTT time.Duration
   275  	LatestRTT   time.Duration
   276  	RTTVariance time.Duration
   277  
   278  	CongestionWindow protocol.ByteCount
   279  	BytesInFlight    protocol.ByteCount
   280  	PacketsInFlight  int
   281  }
   282  
   283  type eventMetricsUpdated struct {
   284  	Last    *metrics
   285  	Current *metrics
   286  }
   287  
   288  func (e eventMetricsUpdated) Category() category { return categoryRecovery }
   289  func (e eventMetricsUpdated) Name() string       { return "metrics_updated" }
   290  func (e eventMetricsUpdated) IsNil() bool        { return false }
   291  
   292  func (e eventMetricsUpdated) MarshalJSONObject(enc *gojay.Encoder) {
   293  	if e.Last == nil || e.Last.MinRTT != e.Current.MinRTT {
   294  		enc.FloatKey("min_rtt", milliseconds(e.Current.MinRTT))
   295  	}
   296  	if e.Last == nil || e.Last.SmoothedRTT != e.Current.SmoothedRTT {
   297  		enc.FloatKey("smoothed_rtt", milliseconds(e.Current.SmoothedRTT))
   298  	}
   299  	if e.Last == nil || e.Last.LatestRTT != e.Current.LatestRTT {
   300  		enc.FloatKey("latest_rtt", milliseconds(e.Current.LatestRTT))
   301  	}
   302  	if e.Last == nil || e.Last.RTTVariance != e.Current.RTTVariance {
   303  		enc.FloatKey("rtt_variance", milliseconds(e.Current.RTTVariance))
   304  	}
   305  
   306  	if e.Last == nil || e.Last.CongestionWindow != e.Current.CongestionWindow {
   307  		enc.Uint64Key("congestion_window", uint64(e.Current.CongestionWindow))
   308  	}
   309  	if e.Last == nil || e.Last.BytesInFlight != e.Current.BytesInFlight {
   310  		enc.Uint64Key("bytes_in_flight", uint64(e.Current.BytesInFlight))
   311  	}
   312  	if e.Last == nil || e.Last.PacketsInFlight != e.Current.PacketsInFlight {
   313  		enc.Uint64KeyOmitEmpty("packets_in_flight", uint64(e.Current.PacketsInFlight))
   314  	}
   315  }
   316  
   317  type eventUpdatedPTO struct {
   318  	Value uint32
   319  }
   320  
   321  func (e eventUpdatedPTO) Category() category { return categoryRecovery }
   322  func (e eventUpdatedPTO) Name() string       { return "metrics_updated" }
   323  func (e eventUpdatedPTO) IsNil() bool        { return false }
   324  
   325  func (e eventUpdatedPTO) MarshalJSONObject(enc *gojay.Encoder) {
   326  	enc.Uint32Key("pto_count", e.Value)
   327  }
   328  
   329  type eventPacketLost struct {
   330  	PacketType   logging.PacketType
   331  	PacketNumber protocol.PacketNumber
   332  	Trigger      packetLossReason
   333  }
   334  
   335  func (e eventPacketLost) Category() category { return categoryRecovery }
   336  func (e eventPacketLost) Name() string       { return "packet_lost" }
   337  func (e eventPacketLost) IsNil() bool        { return false }
   338  
   339  func (e eventPacketLost) MarshalJSONObject(enc *gojay.Encoder) {
   340  	enc.ObjectKey("header", packetHeaderWithTypeAndPacketNumber{
   341  		PacketType:   e.PacketType,
   342  		PacketNumber: e.PacketNumber,
   343  	})
   344  	enc.StringKey("trigger", e.Trigger.String())
   345  }
   346  
   347  type eventKeyUpdated struct {
   348  	Trigger  keyUpdateTrigger
   349  	KeyType  keyType
   350  	KeyPhase protocol.KeyPhase
   351  	// we don't log the keys here, so we don't need `old` and `new`.
   352  }
   353  
   354  func (e eventKeyUpdated) Category() category { return categorySecurity }
   355  func (e eventKeyUpdated) Name() string       { return "key_updated" }
   356  func (e eventKeyUpdated) IsNil() bool        { return false }
   357  
   358  func (e eventKeyUpdated) MarshalJSONObject(enc *gojay.Encoder) {
   359  	enc.StringKey("trigger", e.Trigger.String())
   360  	enc.StringKey("key_type", e.KeyType.String())
   361  	if e.KeyType == keyTypeClient1RTT || e.KeyType == keyTypeServer1RTT {
   362  		enc.Uint64Key("key_phase", uint64(e.KeyPhase))
   363  	}
   364  }
   365  
   366  type eventKeyDiscarded struct {
   367  	KeyType  keyType
   368  	KeyPhase protocol.KeyPhase
   369  }
   370  
   371  func (e eventKeyDiscarded) Category() category { return categorySecurity }
   372  func (e eventKeyDiscarded) Name() string       { return "key_discarded" }
   373  func (e eventKeyDiscarded) IsNil() bool        { return false }
   374  
   375  func (e eventKeyDiscarded) MarshalJSONObject(enc *gojay.Encoder) {
   376  	if e.KeyType != keyTypeClient1RTT && e.KeyType != keyTypeServer1RTT {
   377  		enc.StringKey("trigger", "tls")
   378  	}
   379  	enc.StringKey("key_type", e.KeyType.String())
   380  	if e.KeyType == keyTypeClient1RTT || e.KeyType == keyTypeServer1RTT {
   381  		enc.Uint64Key("key_phase", uint64(e.KeyPhase))
   382  	}
   383  }
   384  
   385  type eventTransportParameters struct {
   386  	Restore bool
   387  	Owner   owner
   388  	SentBy  protocol.Perspective
   389  
   390  	OriginalDestinationConnectionID protocol.ConnectionID
   391  	InitialSourceConnectionID       protocol.ConnectionID
   392  	RetrySourceConnectionID         *protocol.ConnectionID
   393  
   394  	StatelessResetToken     *protocol.StatelessResetToken
   395  	DisableActiveMigration  bool
   396  	MaxIdleTimeout          time.Duration
   397  	MaxUDPPayloadSize       protocol.ByteCount
   398  	AckDelayExponent        uint8
   399  	MaxAckDelay             time.Duration
   400  	ActiveConnectionIDLimit uint64
   401  
   402  	InitialMaxData                 protocol.ByteCount
   403  	InitialMaxStreamDataBidiLocal  protocol.ByteCount
   404  	InitialMaxStreamDataBidiRemote protocol.ByteCount
   405  	InitialMaxStreamDataUni        protocol.ByteCount
   406  	InitialMaxStreamsBidi          int64
   407  	InitialMaxStreamsUni           int64
   408  
   409  	PreferredAddress *preferredAddress
   410  
   411  	MaxDatagramFrameSize protocol.ByteCount
   412  }
   413  
   414  func (e eventTransportParameters) Category() category { return categoryTransport }
   415  func (e eventTransportParameters) Name() string {
   416  	if e.Restore {
   417  		return "parameters_restored"
   418  	}
   419  	return "parameters_set"
   420  }
   421  func (e eventTransportParameters) IsNil() bool { return false }
   422  
   423  func (e eventTransportParameters) MarshalJSONObject(enc *gojay.Encoder) {
   424  	if !e.Restore {
   425  		enc.StringKey("owner", e.Owner.String())
   426  		if e.SentBy == protocol.PerspectiveServer {
   427  			enc.StringKey("original_destination_connection_id", e.OriginalDestinationConnectionID.String())
   428  			if e.StatelessResetToken != nil {
   429  				enc.StringKey("stateless_reset_token", fmt.Sprintf("%x", e.StatelessResetToken[:]))
   430  			}
   431  			if e.RetrySourceConnectionID != nil {
   432  				enc.StringKey("retry_source_connection_id", (*e.RetrySourceConnectionID).String())
   433  			}
   434  		}
   435  		enc.StringKey("initial_source_connection_id", e.InitialSourceConnectionID.String())
   436  	}
   437  	enc.BoolKey("disable_active_migration", e.DisableActiveMigration)
   438  	enc.FloatKeyOmitEmpty("max_idle_timeout", milliseconds(e.MaxIdleTimeout))
   439  	enc.Int64KeyNullEmpty("max_udp_payload_size", int64(e.MaxUDPPayloadSize))
   440  	enc.Uint8KeyOmitEmpty("ack_delay_exponent", e.AckDelayExponent)
   441  	enc.FloatKeyOmitEmpty("max_ack_delay", milliseconds(e.MaxAckDelay))
   442  	enc.Uint64KeyOmitEmpty("active_connection_id_limit", e.ActiveConnectionIDLimit)
   443  
   444  	enc.Int64KeyOmitEmpty("initial_max_data", int64(e.InitialMaxData))
   445  	enc.Int64KeyOmitEmpty("initial_max_stream_data_bidi_local", int64(e.InitialMaxStreamDataBidiLocal))
   446  	enc.Int64KeyOmitEmpty("initial_max_stream_data_bidi_remote", int64(e.InitialMaxStreamDataBidiRemote))
   447  	enc.Int64KeyOmitEmpty("initial_max_stream_data_uni", int64(e.InitialMaxStreamDataUni))
   448  	enc.Int64KeyOmitEmpty("initial_max_streams_bidi", e.InitialMaxStreamsBidi)
   449  	enc.Int64KeyOmitEmpty("initial_max_streams_uni", e.InitialMaxStreamsUni)
   450  
   451  	if e.PreferredAddress != nil {
   452  		enc.ObjectKey("preferred_address", e.PreferredAddress)
   453  	}
   454  	if e.MaxDatagramFrameSize != protocol.InvalidByteCount {
   455  		enc.Int64Key("max_datagram_frame_size", int64(e.MaxDatagramFrameSize))
   456  	}
   457  }
   458  
   459  type preferredAddress struct {
   460  	IPv4, IPv6          netip.AddrPort
   461  	ConnectionID        protocol.ConnectionID
   462  	StatelessResetToken protocol.StatelessResetToken
   463  }
   464  
   465  var _ gojay.MarshalerJSONObject = &preferredAddress{}
   466  
   467  func (a preferredAddress) IsNil() bool { return false }
   468  func (a preferredAddress) MarshalJSONObject(enc *gojay.Encoder) {
   469  	enc.StringKey("ip_v4", a.IPv4.Addr().String())
   470  	enc.Uint16Key("port_v4", a.IPv4.Port())
   471  	enc.StringKey("ip_v6", a.IPv6.Addr().String())
   472  	enc.Uint16Key("port_v6", a.IPv6.Port())
   473  	enc.StringKey("connection_id", a.ConnectionID.String())
   474  	enc.StringKey("stateless_reset_token", fmt.Sprintf("%x", a.StatelessResetToken))
   475  }
   476  
   477  type eventLossTimerSet struct {
   478  	TimerType timerType
   479  	EncLevel  protocol.EncryptionLevel
   480  	Delta     time.Duration
   481  }
   482  
   483  func (e eventLossTimerSet) Category() category { return categoryRecovery }
   484  func (e eventLossTimerSet) Name() string       { return "loss_timer_updated" }
   485  func (e eventLossTimerSet) IsNil() bool        { return false }
   486  
   487  func (e eventLossTimerSet) MarshalJSONObject(enc *gojay.Encoder) {
   488  	enc.StringKey("event_type", "set")
   489  	enc.StringKey("timer_type", e.TimerType.String())
   490  	enc.StringKey("packet_number_space", encLevelToPacketNumberSpace(e.EncLevel))
   491  	enc.Float64Key("delta", milliseconds(e.Delta))
   492  }
   493  
   494  type eventLossTimerExpired struct {
   495  	TimerType timerType
   496  	EncLevel  protocol.EncryptionLevel
   497  }
   498  
   499  func (e eventLossTimerExpired) Category() category { return categoryRecovery }
   500  func (e eventLossTimerExpired) Name() string       { return "loss_timer_updated" }
   501  func (e eventLossTimerExpired) IsNil() bool        { return false }
   502  
   503  func (e eventLossTimerExpired) MarshalJSONObject(enc *gojay.Encoder) {
   504  	enc.StringKey("event_type", "expired")
   505  	enc.StringKey("timer_type", e.TimerType.String())
   506  	enc.StringKey("packet_number_space", encLevelToPacketNumberSpace(e.EncLevel))
   507  }
   508  
   509  type eventLossTimerCanceled struct{}
   510  
   511  func (e eventLossTimerCanceled) Category() category { return categoryRecovery }
   512  func (e eventLossTimerCanceled) Name() string       { return "loss_timer_updated" }
   513  func (e eventLossTimerCanceled) IsNil() bool        { return false }
   514  
   515  func (e eventLossTimerCanceled) MarshalJSONObject(enc *gojay.Encoder) {
   516  	enc.StringKey("event_type", "cancelled")
   517  }
   518  
   519  type eventCongestionStateUpdated struct {
   520  	state congestionState
   521  }
   522  
   523  func (e eventCongestionStateUpdated) Category() category { return categoryRecovery }
   524  func (e eventCongestionStateUpdated) Name() string       { return "congestion_state_updated" }
   525  func (e eventCongestionStateUpdated) IsNil() bool        { return false }
   526  
   527  func (e eventCongestionStateUpdated) MarshalJSONObject(enc *gojay.Encoder) {
   528  	enc.StringKey("new", e.state.String())
   529  }
   530  
   531  type eventECNStateUpdated struct {
   532  	state   logging.ECNState
   533  	trigger logging.ECNStateTrigger
   534  }
   535  
   536  func (e eventECNStateUpdated) Category() category { return categoryRecovery }
   537  func (e eventECNStateUpdated) Name() string       { return "ecn_state_updated" }
   538  func (e eventECNStateUpdated) IsNil() bool        { return false }
   539  
   540  func (e eventECNStateUpdated) MarshalJSONObject(enc *gojay.Encoder) {
   541  	enc.StringKey("new", ecnState(e.state).String())
   542  	enc.StringKeyOmitEmpty("trigger", ecnStateTrigger(e.trigger).String())
   543  }
   544  
   545  type eventGeneric struct {
   546  	name string
   547  	msg  string
   548  }
   549  
   550  func (e eventGeneric) Category() category { return categoryTransport }
   551  func (e eventGeneric) Name() string       { return e.name }
   552  func (e eventGeneric) IsNil() bool        { return false }
   553  
   554  func (e eventGeneric) MarshalJSONObject(enc *gojay.Encoder) {
   555  	enc.StringKey("details", e.msg)
   556  }
   557  
   558  type eventALPNInformation struct {
   559  	chosenALPN string
   560  }
   561  
   562  func (e eventALPNInformation) Category() category { return categoryTransport }
   563  func (e eventALPNInformation) Name() string       { return "alpn_information" }
   564  func (e eventALPNInformation) IsNil() bool        { return false }
   565  
   566  func (e eventALPNInformation) MarshalJSONObject(enc *gojay.Encoder) {
   567  	enc.StringKey("chosen_alpn", e.chosenALPN)
   568  }