github.com/mikelsr/quic-go@v0.36.1-0.20230701132136-1d9415b66898/qlog/event.go (about)

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