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