funcs.go

  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.
 22package channelz
 23
 24import (
 25	"sync/atomic"
 26	"time"
 27
 28	"google.golang.org/grpc/internal"
 29)
 30
 31var (
 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.
 43func TurnOn() {
 44	atomic.StoreInt32(&curState, 1)
 45}
 46
 47func init() {
 48	internal.ChannelzTurnOffForTesting = func() {
 49		atomic.StoreInt32(&curState, 0)
 50	}
 51}
 52
 53// IsOn returns whether channelz data collection is on.
 54func 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.
 65func 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.
 75func 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.
 86func 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).
 91func GetChannel(id int64) *Channel {
 92	return db.getChannel(id)
 93}
 94
 95// GetSubChannel returns the SubChannel for the subchannel (identified by id).
 96func GetSubChannel(id int64) *SubChannel {
 97	return db.getSubChannel(id)
 98}
 99
100// GetSocket returns the Socket for the socket (identified by id).
101func GetSocket(id int64) *Socket {
102	return db.getSocket(id)
103}
104
105// GetServer returns the ServerMetric for the server (identified by id).
106func 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.
117func 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.
146func 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.
168func 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.
190func 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.
202func 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.
210type 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.
216func (i *IDGenerator) Reset() {
217	atomic.StoreInt64(&i.id, 0)
218}
219
220func (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.
227type Identifier interface {
228	Entity
229	channelzIdentifier()
230}