| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | /* | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright 2018 gRPC authors. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  * You may obtain a copy of the License at | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     http://www.apache.org/licenses/LICENSE-2.0 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  * limitations under the License. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | // Package channelz defines internal APIs for enabling channelz service, entry | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | // registration/deletion, and accessing channelz data. It also defines channelz | 
					
						
							|  |  |  | // metric struct formats. | 
					
						
							|  |  |  | package channelz | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"sync/atomic" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-11 15:34:34 +01:00
										 |  |  | 	"google.golang.org/grpc/internal" | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							| 
									
										
										
										
											2023-09-18 13:47:28 +01:00
										 |  |  | 	// IDGen is the global channelz entity ID generator.  It should not be used | 
					
						
							|  |  |  | 	// outside this package except by tests. | 
					
						
							|  |  |  | 	IDGen IDGenerator | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-06 12:14:37 +01:00
										 |  |  | 	db = newChannelMap() | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | 	// EntriesPerPage defines the number of channelz entries to be shown on a web page. | 
					
						
							|  |  |  | 	EntriesPerPage = 50 | 
					
						
							|  |  |  | 	curState       int32 | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TurnOn turns on channelz data collection. | 
					
						
							|  |  |  | func TurnOn() { | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | 	atomic.StoreInt32(&curState, 1) | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-11 15:34:34 +01:00
										 |  |  | func init() { | 
					
						
							|  |  |  | 	internal.ChannelzTurnOffForTesting = func() { | 
					
						
							|  |  |  | 		atomic.StoreInt32(&curState, 0) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | // IsOn returns whether channelz data collection is on. | 
					
						
							|  |  |  | func IsOn() bool { | 
					
						
							| 
									
										
										
										
											2023-09-18 13:47:28 +01:00
										 |  |  | 	return atomic.LoadInt32(&curState) == 1 | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GetTopChannels returns a slice of top channel's ChannelMetric, along with a | 
					
						
							|  |  |  | // boolean indicating whether there's more top channels to be queried for. | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | // The arg id specifies that only top channel with id at or above it will be | 
					
						
							|  |  |  | // included in the result. The returned slice is up to a length of the arg | 
					
						
							|  |  |  | // maxResults or EntriesPerPage if maxResults is zero, and is sorted in ascending | 
					
						
							|  |  |  | // id order. | 
					
						
							|  |  |  | func GetTopChannels(id int64, maxResults int) ([]*Channel, bool) { | 
					
						
							|  |  |  | 	return db.getTopChannels(id, maxResults) | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GetServers returns a slice of server's ServerMetric, along with a | 
					
						
							|  |  |  | // boolean indicating whether there's more servers to be queried for. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The arg id specifies that only server with id at or above it will be included | 
					
						
							|  |  |  | // in the result. The returned slice is up to a length of the arg maxResults or | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | // EntriesPerPage if maxResults is zero, and is sorted in ascending id order. | 
					
						
							|  |  |  | func GetServers(id int64, maxResults int) ([]*Server, bool) { | 
					
						
							|  |  |  | 	return db.getServers(id, maxResults) | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GetServerSockets returns a slice of server's (identified by id) normal socket's | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | // SocketMetrics, along with a boolean indicating whether there's more sockets to | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | // be queried for. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The arg startID specifies that only sockets with id at or above it will be | 
					
						
							|  |  |  | // included in the result. The returned slice is up to a length of the arg maxResults | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | // or EntriesPerPage if maxResults is zero, and is sorted in ascending id order. | 
					
						
							|  |  |  | func GetServerSockets(id int64, startID int64, maxResults int) ([]*Socket, bool) { | 
					
						
							|  |  |  | 	return db.getServerSockets(id, startID, maxResults) | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | // GetChannel returns the Channel for the channel (identified by id). | 
					
						
							|  |  |  | func GetChannel(id int64) *Channel { | 
					
						
							|  |  |  | 	return db.getChannel(id) | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | // GetSubChannel returns the SubChannel for the subchannel (identified by id). | 
					
						
							|  |  |  | func GetSubChannel(id int64) *SubChannel { | 
					
						
							|  |  |  | 	return db.getSubChannel(id) | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | // GetSocket returns the Socket for the socket (identified by id). | 
					
						
							|  |  |  | func GetSocket(id int64) *Socket { | 
					
						
							|  |  |  | 	return db.getSocket(id) | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GetServer returns the ServerMetric for the server (identified by id). | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | func GetServer(id int64) *Server { | 
					
						
							|  |  |  | 	return db.getServer(id) | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // RegisterChannel registers the given channel c in the channelz database with | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | // target as its target and reference name, and adds it to the child list of its | 
					
						
							|  |  |  | // parent.  parent == nil means no parent. | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | // | 
					
						
							|  |  |  | // Returns a unique channelz identifier assigned to this channel. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // If channelz is not turned ON, the channelz database is not mutated. | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | func RegisterChannel(parent *Channel, target string) *Channel { | 
					
						
							| 
									
										
										
										
											2023-09-18 13:47:28 +01:00
										 |  |  | 	id := IDGen.genID() | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if !IsOn() { | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | 		return &Channel{ID: id} | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | 	isTopChannel := parent == nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cn := &Channel{ | 
					
						
							|  |  |  | 		ID:          id, | 
					
						
							|  |  |  | 		RefName:     target, | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | 		nestedChans: make(map[int64]string), | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | 		subChans:    make(map[int64]string), | 
					
						
							|  |  |  | 		Parent:      parent, | 
					
						
							|  |  |  | 		trace:       &ChannelTrace{CreationTime: time.Now(), Events: make([]*traceEvent, 0, getMaxTraceEntry())}, | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | 	cn.ChannelMetrics.Target.Store(&target) | 
					
						
							|  |  |  | 	db.addChannel(id, cn, isTopChannel, cn.getParentID()) | 
					
						
							|  |  |  | 	return cn | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // RegisterSubChannel registers the given subChannel c in the channelz database | 
					
						
							|  |  |  | // with ref as its reference name, and adds it to the child list of its parent | 
					
						
							|  |  |  | // (identified by pid). | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Returns a unique channelz identifier assigned to this subChannel. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // If channelz is not turned ON, the channelz database is not mutated. | 
					
						
							| 
									
										
										
										
											2024-04-29 09:18:16 +00:00
										 |  |  | func RegisterSubChannel(parent *Channel, ref string) *SubChannel { | 
					
						
							| 
									
										
										
										
											2023-09-18 13:47:28 +01:00
										 |  |  | 	id := IDGen.genID() | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | 	sc := &SubChannel{ | 
					
						
							|  |  |  | 		ID:      id, | 
					
						
							| 
									
										
										
										
											2024-04-29 09:18:16 +00:00
										 |  |  | 		RefName: ref, | 
					
						
							|  |  |  | 		parent:  parent, | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-04-29 09:18:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if !IsOn() { | 
					
						
							|  |  |  | 		return sc | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc.sockets = make(map[int64]string) | 
					
						
							|  |  |  | 	sc.trace = &ChannelTrace{CreationTime: time.Now(), Events: make([]*traceEvent, 0, getMaxTraceEntry())} | 
					
						
							|  |  |  | 	db.addSubChannel(id, sc, parent.ID) | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | 	return sc | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // RegisterServer registers the given server s in channelz database. It returns | 
					
						
							|  |  |  | // the unique channelz tracking id assigned to this server. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // If channelz is not turned ON, the channelz database is not mutated. | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | func RegisterServer(ref string) *Server { | 
					
						
							| 
									
										
										
										
											2023-09-18 13:47:28 +01:00
										 |  |  | 	id := IDGen.genID() | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | 	if !IsOn() { | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | 		return &Server{ID: id} | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | 	svr := &Server{ | 
					
						
							|  |  |  | 		RefName:       ref, | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | 		sockets:       make(map[int64]string), | 
					
						
							|  |  |  | 		listenSockets: make(map[int64]string), | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | 		ID:            id, | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | 	db.addServer(id, svr) | 
					
						
							|  |  |  | 	return svr | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | // RegisterSocket registers the given normal socket s in channelz database | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | // with ref as its reference name, and adds it to the child list of its parent | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | // (identified by skt.Parent, which must be set). It returns the unique channelz | 
					
						
							|  |  |  | // tracking id assigned to this normal socket. | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | // | 
					
						
							|  |  |  | // If channelz is not turned ON, the channelz database is not mutated. | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | func RegisterSocket(skt *Socket) *Socket { | 
					
						
							|  |  |  | 	skt.ID = IDGen.genID() | 
					
						
							|  |  |  | 	if IsOn() { | 
					
						
							|  |  |  | 		db.addSocket(skt) | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | 	return skt | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // RemoveEntry removes an entry with unique channelz tracking id to be id from | 
					
						
							|  |  |  | // channelz database. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // If channelz is not turned ON, this function is a no-op. | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | func RemoveEntry(id int64) { | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | 	if !IsOn() { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | 	db.removeEntry(id) | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-18 13:47:28 +01:00
										 |  |  | // IDGenerator is an incrementing atomic that tracks IDs for channelz entities. | 
					
						
							|  |  |  | type IDGenerator struct { | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | 	id int64 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-18 13:47:28 +01:00
										 |  |  | // Reset resets the generated ID back to zero.  Should only be used at | 
					
						
							|  |  |  | // initialization or by tests sensitive to the ID number. | 
					
						
							|  |  |  | func (i *IDGenerator) Reset() { | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | 	atomic.StoreInt64(&i.id, 0) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-18 13:47:28 +01:00
										 |  |  | func (i *IDGenerator) genID() int64 { | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | 	return atomic.AddInt64(&i.id, 1) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Identifier is an opaque channelz identifier used to expose channelz symbols | 
					
						
							|  |  |  | // outside of grpc.  Currently only implemented by Channel since no other | 
					
						
							|  |  |  | // types require exposure outside grpc. | 
					
						
							|  |  |  | type Identifier interface { | 
					
						
							|  |  |  | 	Entity | 
					
						
							|  |  |  | 	channelzIdentifier() | 
					
						
							|  |  |  | } |