google.golang.org/grpc@v1.62.1/internal/channelz/types.go (about)

     1  /*
     2   *
     3   * Copyright 2018 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   */
    18  
    19  package channelz
    20  
    21  import (
    22  	"net"
    23  	"sync"
    24  	"sync/atomic"
    25  	"time"
    26  
    27  	"google.golang.org/grpc/connectivity"
    28  	"google.golang.org/grpc/credentials"
    29  )
    30  
    31  // entry represents a node in the channelz database.
    32  type entry interface {
    33  	// addChild adds a child e, whose channelz id is id to child list
    34  	addChild(id int64, e entry)
    35  	// deleteChild deletes a child with channelz id to be id from child list
    36  	deleteChild(id int64)
    37  	// triggerDelete tries to delete self from channelz database. However, if child
    38  	// list is not empty, then deletion from the database is on hold until the last
    39  	// child is deleted from database.
    40  	triggerDelete()
    41  	// deleteSelfIfReady check whether triggerDelete() has been called before, and whether child
    42  	// list is now empty. If both conditions are met, then delete self from database.
    43  	deleteSelfIfReady()
    44  	// getParentID returns parent ID of the entry. 0 value parent ID means no parent.
    45  	getParentID() int64
    46  }
    47  
    48  // dummyEntry is a fake entry to handle entry not found case.
    49  type dummyEntry struct {
    50  	idNotFound int64
    51  }
    52  
    53  func (d *dummyEntry) addChild(id int64, e entry) {
    54  	// Note: It is possible for a normal program to reach here under race condition.
    55  	// For example, there could be a race between ClientConn.Close() info being propagated
    56  	// to addrConn and http2Client. ClientConn.Close() cancel the context and result
    57  	// in http2Client to error. The error info is then caught by transport monitor
    58  	// and before addrConn.tearDown() is called in side ClientConn.Close(). Therefore,
    59  	// the addrConn will create a new transport. And when registering the new transport in
    60  	// channelz, its parent addrConn could have already been torn down and deleted
    61  	// from channelz tracking, and thus reach the code here.
    62  	logger.Infof("attempt to add child of type %T with id %d to a parent (id=%d) that doesn't currently exist", e, id, d.idNotFound)
    63  }
    64  
    65  func (d *dummyEntry) deleteChild(id int64) {
    66  	// It is possible for a normal program to reach here under race condition.
    67  	// Refer to the example described in addChild().
    68  	logger.Infof("attempt to delete child with id %d from a parent (id=%d) that doesn't currently exist", id, d.idNotFound)
    69  }
    70  
    71  func (d *dummyEntry) triggerDelete() {
    72  	logger.Warningf("attempt to delete an entry (id=%d) that doesn't currently exist", d.idNotFound)
    73  }
    74  
    75  func (*dummyEntry) deleteSelfIfReady() {
    76  	// code should not reach here. deleteSelfIfReady is always called on an existing entry.
    77  }
    78  
    79  func (*dummyEntry) getParentID() int64 {
    80  	return 0
    81  }
    82  
    83  // ChannelMetric defines the info channelz provides for a specific Channel, which
    84  // includes ChannelInternalMetric and channelz-specific data, such as channelz id,
    85  // child list, etc.
    86  type ChannelMetric struct {
    87  	// ID is the channelz id of this channel.
    88  	ID int64
    89  	// RefName is the human readable reference string of this channel.
    90  	RefName string
    91  	// ChannelData contains channel internal metric reported by the channel through
    92  	// ChannelzMetric().
    93  	ChannelData *ChannelInternalMetric
    94  	// NestedChans tracks the nested channel type children of this channel in the format of
    95  	// a map from nested channel channelz id to corresponding reference string.
    96  	NestedChans map[int64]string
    97  	// SubChans tracks the subchannel type children of this channel in the format of a
    98  	// map from subchannel channelz id to corresponding reference string.
    99  	SubChans map[int64]string
   100  	// Sockets tracks the socket type children of this channel in the format of a map
   101  	// from socket channelz id to corresponding reference string.
   102  	// Note current grpc implementation doesn't allow channel having sockets directly,
   103  	// therefore, this is field is unused.
   104  	Sockets map[int64]string
   105  	// Trace contains the most recent traced events.
   106  	Trace *ChannelTrace
   107  }
   108  
   109  // SubChannelMetric defines the info channelz provides for a specific SubChannel,
   110  // which includes ChannelInternalMetric and channelz-specific data, such as
   111  // channelz id, child list, etc.
   112  type SubChannelMetric struct {
   113  	// ID is the channelz id of this subchannel.
   114  	ID int64
   115  	// RefName is the human readable reference string of this subchannel.
   116  	RefName string
   117  	// ChannelData contains subchannel internal metric reported by the subchannel
   118  	// through ChannelzMetric().
   119  	ChannelData *ChannelInternalMetric
   120  	// NestedChans tracks the nested channel type children of this subchannel in the format of
   121  	// a map from nested channel channelz id to corresponding reference string.
   122  	// Note current grpc implementation doesn't allow subchannel to have nested channels
   123  	// as children, therefore, this field is unused.
   124  	NestedChans map[int64]string
   125  	// SubChans tracks the subchannel type children of this subchannel in the format of a
   126  	// map from subchannel channelz id to corresponding reference string.
   127  	// Note current grpc implementation doesn't allow subchannel to have subchannels
   128  	// as children, therefore, this field is unused.
   129  	SubChans map[int64]string
   130  	// Sockets tracks the socket type children of this subchannel in the format of a map
   131  	// from socket channelz id to corresponding reference string.
   132  	Sockets map[int64]string
   133  	// Trace contains the most recent traced events.
   134  	Trace *ChannelTrace
   135  }
   136  
   137  // ChannelInternalMetric defines the struct that the implementor of Channel interface
   138  // should return from ChannelzMetric().
   139  type ChannelInternalMetric struct {
   140  	// current connectivity state of the channel.
   141  	State connectivity.State
   142  	// The target this channel originally tried to connect to.  May be absent
   143  	Target string
   144  	// The number of calls started on the channel.
   145  	CallsStarted int64
   146  	// The number of calls that have completed with an OK status.
   147  	CallsSucceeded int64
   148  	// The number of calls that have a completed with a non-OK status.
   149  	CallsFailed int64
   150  	// The last time a call was started on the channel.
   151  	LastCallStartedTimestamp time.Time
   152  }
   153  
   154  // ChannelTrace stores traced events on a channel/subchannel and related info.
   155  type ChannelTrace struct {
   156  	// EventNum is the number of events that ever got traced (i.e. including those that have been deleted)
   157  	EventNum int64
   158  	// CreationTime is the creation time of the trace.
   159  	CreationTime time.Time
   160  	// Events stores the most recent trace events (up to $maxTraceEntry, newer event will overwrite the
   161  	// oldest one)
   162  	Events []*TraceEvent
   163  }
   164  
   165  // TraceEvent represent a single trace event
   166  type TraceEvent struct {
   167  	// Desc is a simple description of the trace event.
   168  	Desc string
   169  	// Severity states the severity of this trace event.
   170  	Severity Severity
   171  	// Timestamp is the event time.
   172  	Timestamp time.Time
   173  	// RefID is the id of the entity that gets referenced in the event. RefID is 0 if no other entity is
   174  	// involved in this event.
   175  	// e.g. SubChannel (id: 4[]) Created. --> RefID = 4, RefName = "" (inside [])
   176  	RefID int64
   177  	// RefName is the reference name for the entity that gets referenced in the event.
   178  	RefName string
   179  	// RefType indicates the referenced entity type, i.e Channel or SubChannel.
   180  	RefType RefChannelType
   181  }
   182  
   183  // Channel is the interface that should be satisfied in order to be tracked by
   184  // channelz as Channel or SubChannel.
   185  type Channel interface {
   186  	ChannelzMetric() *ChannelInternalMetric
   187  }
   188  
   189  type dummyChannel struct{}
   190  
   191  func (d *dummyChannel) ChannelzMetric() *ChannelInternalMetric {
   192  	return &ChannelInternalMetric{}
   193  }
   194  
   195  type channel struct {
   196  	refName     string
   197  	c           Channel
   198  	closeCalled bool
   199  	nestedChans map[int64]string
   200  	subChans    map[int64]string
   201  	id          int64
   202  	pid         int64
   203  	cm          *channelMap
   204  	trace       *channelTrace
   205  	// traceRefCount is the number of trace events that reference this channel.
   206  	// Non-zero traceRefCount means the trace of this channel cannot be deleted.
   207  	traceRefCount int32
   208  }
   209  
   210  func (c *channel) addChild(id int64, e entry) {
   211  	switch v := e.(type) {
   212  	case *subChannel:
   213  		c.subChans[id] = v.refName
   214  	case *channel:
   215  		c.nestedChans[id] = v.refName
   216  	default:
   217  		logger.Errorf("cannot add a child (id = %d) of type %T to a channel", id, e)
   218  	}
   219  }
   220  
   221  func (c *channel) deleteChild(id int64) {
   222  	delete(c.subChans, id)
   223  	delete(c.nestedChans, id)
   224  	c.deleteSelfIfReady()
   225  }
   226  
   227  func (c *channel) triggerDelete() {
   228  	c.closeCalled = true
   229  	c.deleteSelfIfReady()
   230  }
   231  
   232  func (c *channel) getParentID() int64 {
   233  	return c.pid
   234  }
   235  
   236  // deleteSelfFromTree tries to delete the channel from the channelz entry relation tree, which means
   237  // deleting the channel reference from its parent's child list.
   238  //
   239  // In order for a channel to be deleted from the tree, it must meet the criteria that, removal of the
   240  // corresponding grpc object has been invoked, and the channel does not have any children left.
   241  //
   242  // The returned boolean value indicates whether the channel has been successfully deleted from tree.
   243  func (c *channel) deleteSelfFromTree() (deleted bool) {
   244  	if !c.closeCalled || len(c.subChans)+len(c.nestedChans) != 0 {
   245  		return false
   246  	}
   247  	// not top channel
   248  	if c.pid != 0 {
   249  		c.cm.findEntry(c.pid).deleteChild(c.id)
   250  	}
   251  	return true
   252  }
   253  
   254  // deleteSelfFromMap checks whether it is valid to delete the channel from the map, which means
   255  // deleting the channel from channelz's tracking entirely. Users can no longer use id to query the
   256  // channel, and its memory will be garbage collected.
   257  //
   258  // The trace reference count of the channel must be 0 in order to be deleted from the map. This is
   259  // specified in the channel tracing gRFC that as long as some other trace has reference to an entity,
   260  // the trace of the referenced entity must not be deleted. In order to release the resource allocated
   261  // by grpc, the reference to the grpc object is reset to a dummy object.
   262  //
   263  // deleteSelfFromMap must be called after deleteSelfFromTree returns true.
   264  //
   265  // It returns a bool to indicate whether the channel can be safely deleted from map.
   266  func (c *channel) deleteSelfFromMap() (delete bool) {
   267  	if c.getTraceRefCount() != 0 {
   268  		c.c = &dummyChannel{}
   269  		return false
   270  	}
   271  	return true
   272  }
   273  
   274  // deleteSelfIfReady tries to delete the channel itself from the channelz database.
   275  // The delete process includes two steps:
   276  //  1. delete the channel from the entry relation tree, i.e. delete the channel reference from its
   277  //     parent's child list.
   278  //  2. delete the channel from the map, i.e. delete the channel entirely from channelz. Lookup by id
   279  //     will return entry not found error.
   280  func (c *channel) deleteSelfIfReady() {
   281  	if !c.deleteSelfFromTree() {
   282  		return
   283  	}
   284  	if !c.deleteSelfFromMap() {
   285  		return
   286  	}
   287  	c.cm.deleteEntry(c.id)
   288  	c.trace.clear()
   289  }
   290  
   291  func (c *channel) getChannelTrace() *channelTrace {
   292  	return c.trace
   293  }
   294  
   295  func (c *channel) incrTraceRefCount() {
   296  	atomic.AddInt32(&c.traceRefCount, 1)
   297  }
   298  
   299  func (c *channel) decrTraceRefCount() {
   300  	atomic.AddInt32(&c.traceRefCount, -1)
   301  }
   302  
   303  func (c *channel) getTraceRefCount() int {
   304  	i := atomic.LoadInt32(&c.traceRefCount)
   305  	return int(i)
   306  }
   307  
   308  func (c *channel) getRefName() string {
   309  	return c.refName
   310  }
   311  
   312  type subChannel struct {
   313  	refName       string
   314  	c             Channel
   315  	closeCalled   bool
   316  	sockets       map[int64]string
   317  	id            int64
   318  	pid           int64
   319  	cm            *channelMap
   320  	trace         *channelTrace
   321  	traceRefCount int32
   322  }
   323  
   324  func (sc *subChannel) addChild(id int64, e entry) {
   325  	if v, ok := e.(*normalSocket); ok {
   326  		sc.sockets[id] = v.refName
   327  	} else {
   328  		logger.Errorf("cannot add a child (id = %d) of type %T to a subChannel", id, e)
   329  	}
   330  }
   331  
   332  func (sc *subChannel) deleteChild(id int64) {
   333  	delete(sc.sockets, id)
   334  	sc.deleteSelfIfReady()
   335  }
   336  
   337  func (sc *subChannel) triggerDelete() {
   338  	sc.closeCalled = true
   339  	sc.deleteSelfIfReady()
   340  }
   341  
   342  func (sc *subChannel) getParentID() int64 {
   343  	return sc.pid
   344  }
   345  
   346  // deleteSelfFromTree tries to delete the subchannel from the channelz entry relation tree, which
   347  // means deleting the subchannel reference from its parent's child list.
   348  //
   349  // In order for a subchannel to be deleted from the tree, it must meet the criteria that, removal of
   350  // the corresponding grpc object has been invoked, and the subchannel does not have any children left.
   351  //
   352  // The returned boolean value indicates whether the channel has been successfully deleted from tree.
   353  func (sc *subChannel) deleteSelfFromTree() (deleted bool) {
   354  	if !sc.closeCalled || len(sc.sockets) != 0 {
   355  		return false
   356  	}
   357  	sc.cm.findEntry(sc.pid).deleteChild(sc.id)
   358  	return true
   359  }
   360  
   361  // deleteSelfFromMap checks whether it is valid to delete the subchannel from the map, which means
   362  // deleting the subchannel from channelz's tracking entirely. Users can no longer use id to query
   363  // the subchannel, and its memory will be garbage collected.
   364  //
   365  // The trace reference count of the subchannel must be 0 in order to be deleted from the map. This is
   366  // specified in the channel tracing gRFC that as long as some other trace has reference to an entity,
   367  // the trace of the referenced entity must not be deleted. In order to release the resource allocated
   368  // by grpc, the reference to the grpc object is reset to a dummy object.
   369  //
   370  // deleteSelfFromMap must be called after deleteSelfFromTree returns true.
   371  //
   372  // It returns a bool to indicate whether the channel can be safely deleted from map.
   373  func (sc *subChannel) deleteSelfFromMap() (delete bool) {
   374  	if sc.getTraceRefCount() != 0 {
   375  		// free the grpc struct (i.e. addrConn)
   376  		sc.c = &dummyChannel{}
   377  		return false
   378  	}
   379  	return true
   380  }
   381  
   382  // deleteSelfIfReady tries to delete the subchannel itself from the channelz database.
   383  // The delete process includes two steps:
   384  //  1. delete the subchannel from the entry relation tree, i.e. delete the subchannel reference from
   385  //     its parent's child list.
   386  //  2. delete the subchannel from the map, i.e. delete the subchannel entirely from channelz. Lookup
   387  //     by id will return entry not found error.
   388  func (sc *subChannel) deleteSelfIfReady() {
   389  	if !sc.deleteSelfFromTree() {
   390  		return
   391  	}
   392  	if !sc.deleteSelfFromMap() {
   393  		return
   394  	}
   395  	sc.cm.deleteEntry(sc.id)
   396  	sc.trace.clear()
   397  }
   398  
   399  func (sc *subChannel) getChannelTrace() *channelTrace {
   400  	return sc.trace
   401  }
   402  
   403  func (sc *subChannel) incrTraceRefCount() {
   404  	atomic.AddInt32(&sc.traceRefCount, 1)
   405  }
   406  
   407  func (sc *subChannel) decrTraceRefCount() {
   408  	atomic.AddInt32(&sc.traceRefCount, -1)
   409  }
   410  
   411  func (sc *subChannel) getTraceRefCount() int {
   412  	i := atomic.LoadInt32(&sc.traceRefCount)
   413  	return int(i)
   414  }
   415  
   416  func (sc *subChannel) getRefName() string {
   417  	return sc.refName
   418  }
   419  
   420  // SocketMetric defines the info channelz provides for a specific Socket, which
   421  // includes SocketInternalMetric and channelz-specific data, such as channelz id, etc.
   422  type SocketMetric struct {
   423  	// ID is the channelz id of this socket.
   424  	ID int64
   425  	// RefName is the human readable reference string of this socket.
   426  	RefName string
   427  	// SocketData contains socket internal metric reported by the socket through
   428  	// ChannelzMetric().
   429  	SocketData *SocketInternalMetric
   430  }
   431  
   432  // SocketInternalMetric defines the struct that the implementor of Socket interface
   433  // should return from ChannelzMetric().
   434  type SocketInternalMetric struct {
   435  	// The number of streams that have been started.
   436  	StreamsStarted int64
   437  	// The number of streams that have ended successfully:
   438  	// On client side, receiving frame with eos bit set.
   439  	// On server side, sending frame with eos bit set.
   440  	StreamsSucceeded int64
   441  	// The number of streams that have ended unsuccessfully:
   442  	// On client side, termination without receiving frame with eos bit set.
   443  	// On server side, termination without sending frame with eos bit set.
   444  	StreamsFailed int64
   445  	// The number of messages successfully sent on this socket.
   446  	MessagesSent     int64
   447  	MessagesReceived int64
   448  	// The number of keep alives sent.  This is typically implemented with HTTP/2
   449  	// ping messages.
   450  	KeepAlivesSent int64
   451  	// The last time a stream was created by this endpoint.  Usually unset for
   452  	// servers.
   453  	LastLocalStreamCreatedTimestamp time.Time
   454  	// The last time a stream was created by the remote endpoint.  Usually unset
   455  	// for clients.
   456  	LastRemoteStreamCreatedTimestamp time.Time
   457  	// The last time a message was sent by this endpoint.
   458  	LastMessageSentTimestamp time.Time
   459  	// The last time a message was received by this endpoint.
   460  	LastMessageReceivedTimestamp time.Time
   461  	// The amount of window, granted to the local endpoint by the remote endpoint.
   462  	// This may be slightly out of date due to network latency.  This does NOT
   463  	// include stream level or TCP level flow control info.
   464  	LocalFlowControlWindow int64
   465  	// The amount of window, granted to the remote endpoint by the local endpoint.
   466  	// This may be slightly out of date due to network latency.  This does NOT
   467  	// include stream level or TCP level flow control info.
   468  	RemoteFlowControlWindow int64
   469  	// The locally bound address.
   470  	LocalAddr net.Addr
   471  	// The remote bound address.  May be absent.
   472  	RemoteAddr net.Addr
   473  	// Optional, represents the name of the remote endpoint, if different than
   474  	// the original target name.
   475  	RemoteName    string
   476  	SocketOptions *SocketOptionData
   477  	Security      credentials.ChannelzSecurityValue
   478  }
   479  
   480  // Socket is the interface that should be satisfied in order to be tracked by
   481  // channelz as Socket.
   482  type Socket interface {
   483  	ChannelzMetric() *SocketInternalMetric
   484  }
   485  
   486  type listenSocket struct {
   487  	refName string
   488  	s       Socket
   489  	id      int64
   490  	pid     int64
   491  	cm      *channelMap
   492  }
   493  
   494  func (ls *listenSocket) addChild(id int64, e entry) {
   495  	logger.Errorf("cannot add a child (id = %d) of type %T to a listen socket", id, e)
   496  }
   497  
   498  func (ls *listenSocket) deleteChild(id int64) {
   499  	logger.Errorf("cannot delete a child (id = %d) from a listen socket", id)
   500  }
   501  
   502  func (ls *listenSocket) triggerDelete() {
   503  	ls.cm.deleteEntry(ls.id)
   504  	ls.cm.findEntry(ls.pid).deleteChild(ls.id)
   505  }
   506  
   507  func (ls *listenSocket) deleteSelfIfReady() {
   508  	logger.Errorf("cannot call deleteSelfIfReady on a listen socket")
   509  }
   510  
   511  func (ls *listenSocket) getParentID() int64 {
   512  	return ls.pid
   513  }
   514  
   515  type normalSocket struct {
   516  	refName string
   517  	s       Socket
   518  	id      int64
   519  	pid     int64
   520  	cm      *channelMap
   521  }
   522  
   523  func (ns *normalSocket) addChild(id int64, e entry) {
   524  	logger.Errorf("cannot add a child (id = %d) of type %T to a normal socket", id, e)
   525  }
   526  
   527  func (ns *normalSocket) deleteChild(id int64) {
   528  	logger.Errorf("cannot delete a child (id = %d) from a normal socket", id)
   529  }
   530  
   531  func (ns *normalSocket) triggerDelete() {
   532  	ns.cm.deleteEntry(ns.id)
   533  	ns.cm.findEntry(ns.pid).deleteChild(ns.id)
   534  }
   535  
   536  func (ns *normalSocket) deleteSelfIfReady() {
   537  	logger.Errorf("cannot call deleteSelfIfReady on a normal socket")
   538  }
   539  
   540  func (ns *normalSocket) getParentID() int64 {
   541  	return ns.pid
   542  }
   543  
   544  // ServerMetric defines the info channelz provides for a specific Server, which
   545  // includes ServerInternalMetric and channelz-specific data, such as channelz id,
   546  // child list, etc.
   547  type ServerMetric struct {
   548  	// ID is the channelz id of this server.
   549  	ID int64
   550  	// RefName is the human readable reference string of this server.
   551  	RefName string
   552  	// ServerData contains server internal metric reported by the server through
   553  	// ChannelzMetric().
   554  	ServerData *ServerInternalMetric
   555  	// ListenSockets tracks the listener socket type children of this server in the
   556  	// format of a map from socket channelz id to corresponding reference string.
   557  	ListenSockets map[int64]string
   558  }
   559  
   560  // ServerInternalMetric defines the struct that the implementor of Server interface
   561  // should return from ChannelzMetric().
   562  type ServerInternalMetric struct {
   563  	// The number of incoming calls started on the server.
   564  	CallsStarted int64
   565  	// The number of incoming calls that have completed with an OK status.
   566  	CallsSucceeded int64
   567  	// The number of incoming calls that have a completed with a non-OK status.
   568  	CallsFailed int64
   569  	// The last time a call was started on the server.
   570  	LastCallStartedTimestamp time.Time
   571  }
   572  
   573  // Server is the interface to be satisfied in order to be tracked by channelz as
   574  // Server.
   575  type Server interface {
   576  	ChannelzMetric() *ServerInternalMetric
   577  }
   578  
   579  type server struct {
   580  	refName       string
   581  	s             Server
   582  	closeCalled   bool
   583  	sockets       map[int64]string
   584  	listenSockets map[int64]string
   585  	id            int64
   586  	cm            *channelMap
   587  }
   588  
   589  func (s *server) addChild(id int64, e entry) {
   590  	switch v := e.(type) {
   591  	case *normalSocket:
   592  		s.sockets[id] = v.refName
   593  	case *listenSocket:
   594  		s.listenSockets[id] = v.refName
   595  	default:
   596  		logger.Errorf("cannot add a child (id = %d) of type %T to a server", id, e)
   597  	}
   598  }
   599  
   600  func (s *server) deleteChild(id int64) {
   601  	delete(s.sockets, id)
   602  	delete(s.listenSockets, id)
   603  	s.deleteSelfIfReady()
   604  }
   605  
   606  func (s *server) triggerDelete() {
   607  	s.closeCalled = true
   608  	s.deleteSelfIfReady()
   609  }
   610  
   611  func (s *server) deleteSelfIfReady() {
   612  	if !s.closeCalled || len(s.sockets)+len(s.listenSockets) != 0 {
   613  		return
   614  	}
   615  	s.cm.deleteEntry(s.id)
   616  }
   617  
   618  func (s *server) getParentID() int64 {
   619  	return 0
   620  }
   621  
   622  type tracedChannel interface {
   623  	getChannelTrace() *channelTrace
   624  	incrTraceRefCount()
   625  	decrTraceRefCount()
   626  	getRefName() string
   627  }
   628  
   629  type channelTrace struct {
   630  	cm          *channelMap
   631  	clearCalled bool
   632  	createdTime time.Time
   633  	eventCount  int64
   634  	mu          sync.Mutex
   635  	events      []*TraceEvent
   636  }
   637  
   638  func (c *channelTrace) append(e *TraceEvent) {
   639  	c.mu.Lock()
   640  	if len(c.events) == getMaxTraceEntry() {
   641  		del := c.events[0]
   642  		c.events = c.events[1:]
   643  		if del.RefID != 0 {
   644  			// start recursive cleanup in a goroutine to not block the call originated from grpc.
   645  			go func() {
   646  				// need to acquire c.cm.mu lock to call the unlocked attemptCleanup func.
   647  				c.cm.mu.Lock()
   648  				c.cm.decrTraceRefCount(del.RefID)
   649  				c.cm.mu.Unlock()
   650  			}()
   651  		}
   652  	}
   653  	e.Timestamp = time.Now()
   654  	c.events = append(c.events, e)
   655  	c.eventCount++
   656  	c.mu.Unlock()
   657  }
   658  
   659  func (c *channelTrace) clear() {
   660  	if c.clearCalled {
   661  		return
   662  	}
   663  	c.clearCalled = true
   664  	c.mu.Lock()
   665  	for _, e := range c.events {
   666  		if e.RefID != 0 {
   667  			// caller should have already held the c.cm.mu lock.
   668  			c.cm.decrTraceRefCount(e.RefID)
   669  		}
   670  	}
   671  	c.mu.Unlock()
   672  }
   673  
   674  // Severity is the severity level of a trace event.
   675  // The canonical enumeration of all valid values is here:
   676  // https://github.com/grpc/grpc-proto/blob/9b13d199cc0d4703c7ea26c9c330ba695866eb23/grpc/channelz/v1/channelz.proto#L126.
   677  type Severity int
   678  
   679  const (
   680  	// CtUnknown indicates unknown severity of a trace event.
   681  	CtUnknown Severity = iota
   682  	// CtInfo indicates info level severity of a trace event.
   683  	CtInfo
   684  	// CtWarning indicates warning level severity of a trace event.
   685  	CtWarning
   686  	// CtError indicates error level severity of a trace event.
   687  	CtError
   688  )
   689  
   690  // RefChannelType is the type of the entity being referenced in a trace event.
   691  type RefChannelType int
   692  
   693  const (
   694  	// RefUnknown indicates an unknown entity type, the zero value for this type.
   695  	RefUnknown RefChannelType = iota
   696  	// RefChannel indicates the referenced entity is a Channel.
   697  	RefChannel
   698  	// RefSubChannel indicates the referenced entity is a SubChannel.
   699  	RefSubChannel
   700  	// RefServer indicates the referenced entity is a Server.
   701  	RefServer
   702  	// RefListenSocket indicates the referenced entity is a ListenSocket.
   703  	RefListenSocket
   704  	// RefNormalSocket indicates the referenced entity is a NormalSocket.
   705  	RefNormalSocket
   706  )
   707  
   708  var refChannelTypeToString = map[RefChannelType]string{
   709  	RefUnknown:      "Unknown",
   710  	RefChannel:      "Channel",
   711  	RefSubChannel:   "SubChannel",
   712  	RefServer:       "Server",
   713  	RefListenSocket: "ListenSocket",
   714  	RefNormalSocket: "NormalSocket",
   715  }
   716  
   717  func (r RefChannelType) String() string {
   718  	return refChannelTypeToString[r]
   719  }
   720  
   721  func (c *channelTrace) dumpData() *ChannelTrace {
   722  	c.mu.Lock()
   723  	ct := &ChannelTrace{EventNum: c.eventCount, CreationTime: c.createdTime}
   724  	ct.Events = c.events[:len(c.events)]
   725  	c.mu.Unlock()
   726  	return ct
   727  }