/*
 *
 * 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.
 *
 */

// Package channelz defines internal APIs for enabling channelz service, entry // registration/deletion, and accessing channelz data. It also defines channelz // metric struct formats.
package channelz import ( ) var ( // IDGen is the global channelz entity ID generator. It should not be used // outside this package except by tests. IDGen IDGenerator db = newChannelMap() // EntriesPerPage defines the number of channelz entries to be shown on a web page. EntriesPerPage = 50 curState int32 ) // TurnOn turns on channelz data collection. func () { atomic.StoreInt32(&curState, 1) } func () { internal.ChannelzTurnOffForTesting = func() { atomic.StoreInt32(&curState, 0) } } // IsOn returns whether channelz data collection is on. func () bool { return atomic.LoadInt32(&curState) == 1 } // GetTopChannels returns a slice of top channel's ChannelMetric, along with a // boolean indicating whether there's more top channels to be queried for. // // 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 ( int64, int) ([]*Channel, bool) { return db.getTopChannels(, ) } // 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 // EntriesPerPage if maxResults is zero, and is sorted in ascending id order. func ( int64, int) ([]*Server, bool) { return db.getServers(, ) } // GetServerSockets returns a slice of server's (identified by id) normal socket's // SocketMetrics, along with a boolean indicating whether there's more sockets to // 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 // or EntriesPerPage if maxResults is zero, and is sorted in ascending id order. func ( int64, int64, int) ([]*Socket, bool) { return db.getServerSockets(, , ) } // GetChannel returns the Channel for the channel (identified by id). func ( int64) *Channel { return db.getChannel() } // GetSubChannel returns the SubChannel for the subchannel (identified by id). func ( int64) *SubChannel { return db.getSubChannel() } // GetSocket returns the Socket for the socket (identified by id). func ( int64) *Socket { return db.getSocket() } // GetServer returns the ServerMetric for the server (identified by id). func ( int64) *Server { return db.getServer() } // RegisterChannel registers the given channel c in the channelz database with // target as its target and reference name, and adds it to the child list of its // parent. parent == nil means no parent. // // Returns a unique channelz identifier assigned to this channel. // // If channelz is not turned ON, the channelz database is not mutated. func ( *Channel, string) *Channel { := IDGen.genID() if !IsOn() { return &Channel{ID: } } := == nil := &Channel{ ID: , RefName: , nestedChans: make(map[int64]string), subChans: make(map[int64]string), Parent: , trace: &ChannelTrace{CreationTime: time.Now(), Events: make([]*traceEvent, 0, getMaxTraceEntry())}, } .ChannelMetrics.Target.Store(&) db.addChannel(, , , .getParentID()) return } // 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. func ( *Channel, string) *SubChannel { := IDGen.genID() := &SubChannel{ ID: , RefName: , parent: , } if !IsOn() { return } .sockets = make(map[int64]string) .trace = &ChannelTrace{CreationTime: time.Now(), Events: make([]*traceEvent, 0, getMaxTraceEntry())} db.addSubChannel(, , .ID) return } // 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. func ( string) *Server { := IDGen.genID() if !IsOn() { return &Server{ID: } } := &Server{ RefName: , sockets: make(map[int64]string), listenSockets: make(map[int64]string), ID: , } db.addServer(, ) return } // RegisterSocket registers the given normal socket s in channelz database // with ref as its reference name, and adds it to the child list of its parent // (identified by skt.Parent, which must be set). It returns the unique channelz // tracking id assigned to this normal socket. // // If channelz is not turned ON, the channelz database is not mutated. func ( *Socket) *Socket { .ID = IDGen.genID() if IsOn() { db.addSocket() } return } // 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. func ( int64) { if !IsOn() { return } db.removeEntry() } // IDGenerator is an incrementing atomic that tracks IDs for channelz entities. type IDGenerator struct { id int64 } // Reset resets the generated ID back to zero. Should only be used at // initialization or by tests sensitive to the ID number. func ( *IDGenerator) () { atomic.StoreInt64(&.id, 0) } func ( *IDGenerator) () int64 { return atomic.AddInt64(&.id, 1) } // 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() }