funcs.go raw

   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 defines internal APIs for enabling channelz service, entry
  20  // registration/deletion, and accessing channelz data. It also defines channelz
  21  // metric struct formats.
  22  package channelz
  23  
  24  import (
  25  	"sync/atomic"
  26  	"time"
  27  
  28  	"google.golang.org/grpc/internal"
  29  )
  30  
  31  var (
  32  	// IDGen is the global channelz entity ID generator.  It should not be used
  33  	// outside this package except by tests.
  34  	IDGen IDGenerator
  35  
  36  	db = newChannelMap()
  37  	// EntriesPerPage defines the number of channelz entries to be shown on a web page.
  38  	EntriesPerPage = 50
  39  	curState       int32
  40  )
  41  
  42  // TurnOn turns on channelz data collection.
  43  func TurnOn() {
  44  	atomic.StoreInt32(&curState, 1)
  45  }
  46  
  47  func init() {
  48  	internal.ChannelzTurnOffForTesting = func() {
  49  		atomic.StoreInt32(&curState, 0)
  50  	}
  51  }
  52  
  53  // IsOn returns whether channelz data collection is on.
  54  func IsOn() bool {
  55  	return atomic.LoadInt32(&curState) == 1
  56  }
  57  
  58  // GetTopChannels returns a slice of top channel's ChannelMetric, along with a
  59  // boolean indicating whether there's more top channels to be queried for.
  60  //
  61  // The arg id specifies that only top channel with id at or above it will be
  62  // included in the result. The returned slice is up to a length of the arg
  63  // maxResults or EntriesPerPage if maxResults is zero, and is sorted in ascending
  64  // id order.
  65  func GetTopChannels(id int64, maxResults int) ([]*Channel, bool) {
  66  	return db.getTopChannels(id, maxResults)
  67  }
  68  
  69  // GetServers returns a slice of server's ServerMetric, along with a
  70  // boolean indicating whether there's more servers to be queried for.
  71  //
  72  // The arg id specifies that only server with id at or above it will be included
  73  // in the result. The returned slice is up to a length of the arg maxResults or
  74  // EntriesPerPage if maxResults is zero, and is sorted in ascending id order.
  75  func GetServers(id int64, maxResults int) ([]*Server, bool) {
  76  	return db.getServers(id, maxResults)
  77  }
  78  
  79  // GetServerSockets returns a slice of server's (identified by id) normal socket's
  80  // SocketMetrics, along with a boolean indicating whether there's more sockets to
  81  // be queried for.
  82  //
  83  // The arg startID specifies that only sockets with id at or above it will be
  84  // included in the result. The returned slice is up to a length of the arg maxResults
  85  // or EntriesPerPage if maxResults is zero, and is sorted in ascending id order.
  86  func GetServerSockets(id int64, startID int64, maxResults int) ([]*Socket, bool) {
  87  	return db.getServerSockets(id, startID, maxResults)
  88  }
  89  
  90  // GetChannel returns the Channel for the channel (identified by id).
  91  func GetChannel(id int64) *Channel {
  92  	return db.getChannel(id)
  93  }
  94  
  95  // GetSubChannel returns the SubChannel for the subchannel (identified by id).
  96  func GetSubChannel(id int64) *SubChannel {
  97  	return db.getSubChannel(id)
  98  }
  99  
 100  // GetSocket returns the Socket for the socket (identified by id).
 101  func GetSocket(id int64) *Socket {
 102  	return db.getSocket(id)
 103  }
 104  
 105  // GetServer returns the ServerMetric for the server (identified by id).
 106  func GetServer(id int64) *Server {
 107  	return db.getServer(id)
 108  }
 109  
 110  // RegisterChannel registers the given channel c in the channelz database with
 111  // target as its target and reference name, and adds it to the child list of its
 112  // parent.  parent == nil means no parent.
 113  //
 114  // Returns a unique channelz identifier assigned to this channel.
 115  //
 116  // If channelz is not turned ON, the channelz database is not mutated.
 117  func RegisterChannel(parent *Channel, target string) *Channel {
 118  	id := IDGen.genID()
 119  
 120  	if !IsOn() {
 121  		return &Channel{ID: id}
 122  	}
 123  
 124  	isTopChannel := parent == nil
 125  
 126  	cn := &Channel{
 127  		ID:          id,
 128  		RefName:     target,
 129  		nestedChans: make(map[int64]string),
 130  		subChans:    make(map[int64]string),
 131  		Parent:      parent,
 132  		trace:       &ChannelTrace{CreationTime: time.Now(), Events: make([]*traceEvent, 0, getMaxTraceEntry())},
 133  	}
 134  	cn.ChannelMetrics.Target.Store(&target)
 135  	db.addChannel(id, cn, isTopChannel, cn.getParentID())
 136  	return cn
 137  }
 138  
 139  // RegisterSubChannel registers the given subChannel c in the channelz database
 140  // with ref as its reference name, and adds it to the child list of its parent
 141  // (identified by pid).
 142  //
 143  // Returns a unique channelz identifier assigned to this subChannel.
 144  //
 145  // If channelz is not turned ON, the channelz database is not mutated.
 146  func RegisterSubChannel(parent *Channel, ref string) *SubChannel {
 147  	id := IDGen.genID()
 148  	sc := &SubChannel{
 149  		ID:      id,
 150  		RefName: ref,
 151  		parent:  parent,
 152  	}
 153  
 154  	if !IsOn() {
 155  		return sc
 156  	}
 157  
 158  	sc.sockets = make(map[int64]string)
 159  	sc.trace = &ChannelTrace{CreationTime: time.Now(), Events: make([]*traceEvent, 0, getMaxTraceEntry())}
 160  	db.addSubChannel(id, sc, parent.ID)
 161  	return sc
 162  }
 163  
 164  // RegisterServer registers the given server s in channelz database. It returns
 165  // the unique channelz tracking id assigned to this server.
 166  //
 167  // If channelz is not turned ON, the channelz database is not mutated.
 168  func RegisterServer(ref string) *Server {
 169  	id := IDGen.genID()
 170  	if !IsOn() {
 171  		return &Server{ID: id}
 172  	}
 173  
 174  	svr := &Server{
 175  		RefName:       ref,
 176  		sockets:       make(map[int64]string),
 177  		listenSockets: make(map[int64]string),
 178  		ID:            id,
 179  	}
 180  	db.addServer(id, svr)
 181  	return svr
 182  }
 183  
 184  // RegisterSocket registers the given normal socket s in channelz database
 185  // with ref as its reference name, and adds it to the child list of its parent
 186  // (identified by skt.Parent, which must be set). It returns the unique channelz
 187  // tracking id assigned to this normal socket.
 188  //
 189  // If channelz is not turned ON, the channelz database is not mutated.
 190  func RegisterSocket(skt *Socket) *Socket {
 191  	skt.ID = IDGen.genID()
 192  	if IsOn() {
 193  		db.addSocket(skt)
 194  	}
 195  	return skt
 196  }
 197  
 198  // RemoveEntry removes an entry with unique channelz tracking id to be id from
 199  // channelz database.
 200  //
 201  // If channelz is not turned ON, this function is a no-op.
 202  func RemoveEntry(id int64) {
 203  	if !IsOn() {
 204  		return
 205  	}
 206  	db.removeEntry(id)
 207  }
 208  
 209  // IDGenerator is an incrementing atomic that tracks IDs for channelz entities.
 210  type IDGenerator struct {
 211  	id int64
 212  }
 213  
 214  // Reset resets the generated ID back to zero.  Should only be used at
 215  // initialization or by tests sensitive to the ID number.
 216  func (i *IDGenerator) Reset() {
 217  	atomic.StoreInt64(&i.id, 0)
 218  }
 219  
 220  func (i *IDGenerator) genID() int64 {
 221  	return atomic.AddInt64(&i.id, 1)
 222  }
 223  
 224  // Identifier is an opaque channelz identifier used to expose channelz symbols
 225  // outside of grpc.  Currently only implemented by Channel since no other
 226  // types require exposure outside grpc.
 227  type Identifier interface {
 228  	Entity
 229  	channelzIdentifier()
 230  }
 231