github.com/tumi8/quic-go@v0.37.4-tum/qlog/event.go (about)

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