github.com/MerlinKodo/quic-go@v0.39.2/qlog/event.go (about)

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