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