...

Source file src/google.golang.org/grpc/internal/channelz/trace.go

Documentation: google.golang.org/grpc/internal/channelz

     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  	"fmt"
    23  	"sync"
    24  	"sync/atomic"
    25  	"time"
    26  
    27  	"google.golang.org/grpc/grpclog"
    28  )
    29  
    30  const (
    31  	defaultMaxTraceEntry int32 = 30
    32  )
    33  
    34  var maxTraceEntry = defaultMaxTraceEntry
    35  
    36  // SetMaxTraceEntry sets maximum number of trace entries per entity (i.e.
    37  // channel/subchannel).  Setting it to 0 will disable channel tracing.
    38  func SetMaxTraceEntry(i int32) {
    39  	atomic.StoreInt32(&maxTraceEntry, i)
    40  }
    41  
    42  // ResetMaxTraceEntryToDefault resets the maximum number of trace entries per
    43  // entity to default.
    44  func ResetMaxTraceEntryToDefault() {
    45  	atomic.StoreInt32(&maxTraceEntry, defaultMaxTraceEntry)
    46  }
    47  
    48  func getMaxTraceEntry() int {
    49  	i := atomic.LoadInt32(&maxTraceEntry)
    50  	return int(i)
    51  }
    52  
    53  // traceEvent is an internal representation of a single trace event
    54  type traceEvent struct {
    55  	// Desc is a simple description of the trace event.
    56  	Desc string
    57  	// Severity states the severity of this trace event.
    58  	Severity Severity
    59  	// Timestamp is the event time.
    60  	Timestamp time.Time
    61  	// RefID is the id of the entity that gets referenced in the event. RefID is 0 if no other entity is
    62  	// involved in this event.
    63  	// e.g. SubChannel (id: 4[]) Created. --> RefID = 4, RefName = "" (inside [])
    64  	RefID int64
    65  	// RefName is the reference name for the entity that gets referenced in the event.
    66  	RefName string
    67  	// RefType indicates the referenced entity type, i.e Channel or SubChannel.
    68  	RefType RefChannelType
    69  }
    70  
    71  // TraceEvent is what the caller of AddTraceEvent should provide to describe the
    72  // event to be added to the channel trace.
    73  //
    74  // The Parent field is optional. It is used for an event that will be recorded
    75  // in the entity's parent trace.
    76  type TraceEvent struct {
    77  	Desc     string
    78  	Severity Severity
    79  	Parent   *TraceEvent
    80  }
    81  
    82  type ChannelTrace struct {
    83  	cm           *channelMap
    84  	clearCalled  bool
    85  	CreationTime time.Time
    86  	EventNum     int64
    87  	mu           sync.Mutex
    88  	Events       []*traceEvent
    89  }
    90  
    91  func (c *ChannelTrace) copy() *ChannelTrace {
    92  	return &ChannelTrace{
    93  		CreationTime: c.CreationTime,
    94  		EventNum:     c.EventNum,
    95  		Events:       append(([]*traceEvent)(nil), c.Events...),
    96  	}
    97  }
    98  
    99  func (c *ChannelTrace) append(e *traceEvent) {
   100  	c.mu.Lock()
   101  	if len(c.Events) == getMaxTraceEntry() {
   102  		del := c.Events[0]
   103  		c.Events = c.Events[1:]
   104  		if del.RefID != 0 {
   105  			// start recursive cleanup in a goroutine to not block the call originated from grpc.
   106  			go func() {
   107  				// need to acquire c.cm.mu lock to call the unlocked attemptCleanup func.
   108  				c.cm.mu.Lock()
   109  				c.cm.decrTraceRefCount(del.RefID)
   110  				c.cm.mu.Unlock()
   111  			}()
   112  		}
   113  	}
   114  	e.Timestamp = time.Now()
   115  	c.Events = append(c.Events, e)
   116  	c.EventNum++
   117  	c.mu.Unlock()
   118  }
   119  
   120  func (c *ChannelTrace) clear() {
   121  	if c.clearCalled {
   122  		return
   123  	}
   124  	c.clearCalled = true
   125  	c.mu.Lock()
   126  	for _, e := range c.Events {
   127  		if e.RefID != 0 {
   128  			// caller should have already held the c.cm.mu lock.
   129  			c.cm.decrTraceRefCount(e.RefID)
   130  		}
   131  	}
   132  	c.mu.Unlock()
   133  }
   134  
   135  // Severity is the severity level of a trace event.
   136  // The canonical enumeration of all valid values is here:
   137  // https://github.com/grpc/grpc-proto/blob/9b13d199cc0d4703c7ea26c9c330ba695866eb23/grpc/channelz/v1/channelz.proto#L126.
   138  type Severity int
   139  
   140  const (
   141  	// CtUnknown indicates unknown severity of a trace event.
   142  	CtUnknown Severity = iota
   143  	// CtInfo indicates info level severity of a trace event.
   144  	CtInfo
   145  	// CtWarning indicates warning level severity of a trace event.
   146  	CtWarning
   147  	// CtError indicates error level severity of a trace event.
   148  	CtError
   149  )
   150  
   151  // RefChannelType is the type of the entity being referenced in a trace event.
   152  type RefChannelType int
   153  
   154  const (
   155  	// RefUnknown indicates an unknown entity type, the zero value for this type.
   156  	RefUnknown RefChannelType = iota
   157  	// RefChannel indicates the referenced entity is a Channel.
   158  	RefChannel
   159  	// RefSubChannel indicates the referenced entity is a SubChannel.
   160  	RefSubChannel
   161  	// RefServer indicates the referenced entity is a Server.
   162  	RefServer
   163  	// RefListenSocket indicates the referenced entity is a ListenSocket.
   164  	RefListenSocket
   165  	// RefNormalSocket indicates the referenced entity is a NormalSocket.
   166  	RefNormalSocket
   167  )
   168  
   169  var refChannelTypeToString = map[RefChannelType]string{
   170  	RefUnknown:      "Unknown",
   171  	RefChannel:      "Channel",
   172  	RefSubChannel:   "SubChannel",
   173  	RefServer:       "Server",
   174  	RefListenSocket: "ListenSocket",
   175  	RefNormalSocket: "NormalSocket",
   176  }
   177  
   178  func (r RefChannelType) String() string {
   179  	return refChannelTypeToString[r]
   180  }
   181  
   182  // AddTraceEvent adds trace related to the entity with specified id, using the
   183  // provided TraceEventDesc.
   184  //
   185  // If channelz is not turned ON, this will simply log the event descriptions.
   186  func AddTraceEvent(l grpclog.DepthLoggerV2, e Entity, depth int, desc *TraceEvent) {
   187  	// Log only the trace description associated with the bottom most entity.
   188  	d := fmt.Sprintf("[%s]%s", e, desc.Desc)
   189  	switch desc.Severity {
   190  	case CtUnknown, CtInfo:
   191  		l.InfoDepth(depth+1, d)
   192  	case CtWarning:
   193  		l.WarningDepth(depth+1, d)
   194  	case CtError:
   195  		l.ErrorDepth(depth+1, d)
   196  	}
   197  
   198  	if getMaxTraceEntry() == 0 {
   199  		return
   200  	}
   201  	if IsOn() {
   202  		db.traceEvent(e.id(), desc)
   203  	}
   204  }
   205  

View as plain text