/* * * Copyright 2024 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 channelzimport ()// Channel represents a channel within channelz, which includes metrics and// internal channelz data, such as channelz id, child list, etc.typeChannelstruct {Entity// ID is the channelz id of this channel. ID int64// RefName is the human readable reference string of this channel. RefName string closeCalled bool nestedChans map[int64]string subChans map[int64]string Parent *Channel trace *ChannelTrace// traceRefCount is the number of trace events that reference this channel. // Non-zero traceRefCount means the trace of this channel cannot be deleted. traceRefCount int32// ChannelMetrics holds connectivity state, target and call metrics for the // channel within channelz. ChannelMetrics ChannelMetrics}// Implemented to make Channel implement the Identifier interface used for// nesting.func ( *Channel) () {}// String returns a string representation of the Channel, including its parent// entity and ID.func ( *Channel) () string {if .Parent == nil {returnfmt.Sprintf("Channel #%d", .ID) }returnfmt.Sprintf("%s Channel #%d", .Parent, .ID)}func ( *Channel) () int64 {return .ID}// SubChans returns a copy of the map of sub-channels associated with the// Channel.func ( *Channel) () map[int64]string {db.mu.RLock()deferdb.mu.RUnlock()returncopyMap(.subChans)}// NestedChans returns a copy of the map of nested channels associated with the// Channel.func ( *Channel) () map[int64]string {db.mu.RLock()deferdb.mu.RUnlock()returncopyMap(.nestedChans)}// Trace returns a copy of the Channel's trace data.func ( *Channel) () *ChannelTrace {db.mu.RLock()deferdb.mu.RUnlock()return .trace.copy()}// ChannelMetrics holds connectivity state, target and call metrics for the// channel within channelz.typeChannelMetricsstruct {// The current connectivity state of the channel. State atomic.Pointer[connectivity.State]// The target this channel originally tried to connect to. May be absent Target atomic.Pointer[string]// The number of calls started on the channel. CallsStarted atomic.Int64// The number of calls that have completed with an OK status. CallsSucceeded atomic.Int64// The number of calls that have a completed with a non-OK status. CallsFailed atomic.Int64// The last time a call was started on the channel. LastCallStartedTimestamp atomic.Int64}// CopyFrom copies the metrics in o to c. For testing only.func ( *ChannelMetrics) ( *ChannelMetrics) { .State.Store(.State.Load()) .Target.Store(.Target.Load()) .CallsStarted.Store(.CallsStarted.Load()) .CallsSucceeded.Store(.CallsSucceeded.Load()) .CallsFailed.Store(.CallsFailed.Load()) .LastCallStartedTimestamp.Store(.LastCallStartedTimestamp.Load())}// Equal returns true iff the metrics of c are the same as the metrics of o.// For testing only.func ( *ChannelMetrics) ( any) bool { , := .(*ChannelMetrics)if ! {returnfalse }if (.State.Load() == nil) != (.State.Load() == nil) {returnfalse }if .State.Load() != nil && *.State.Load() != *.State.Load() {returnfalse }if (.Target.Load() == nil) != (.Target.Load() == nil) {returnfalse }if .Target.Load() != nil && *.Target.Load() != *.Target.Load() {returnfalse }return .CallsStarted.Load() == .CallsStarted.Load() && .CallsFailed.Load() == .CallsFailed.Load() && .CallsSucceeded.Load() == .CallsSucceeded.Load() && .LastCallStartedTimestamp.Load() == .LastCallStartedTimestamp.Load()}func strFromPointer( *string) string {if == nil {return"" }return *}// String returns a string representation of the ChannelMetrics, including its// state, target, and call metrics.func ( *ChannelMetrics) () string {returnfmt.Sprintf("State: %v, Target: %s, CallsStarted: %v, CallsSucceeded: %v, CallsFailed: %v, LastCallStartedTimestamp: %v", .State.Load(), strFromPointer(.Target.Load()), .CallsStarted.Load(), .CallsSucceeded.Load(), .CallsFailed.Load(), .LastCallStartedTimestamp.Load(), )}// NewChannelMetricForTesting creates a new instance of ChannelMetrics with// specified initial values for testing purposes.func ( connectivity.State, string, , , , int64) *ChannelMetrics { := &ChannelMetrics{} .State.Store(&) .Target.Store(&) .CallsStarted.Store() .CallsSucceeded.Store() .CallsFailed.Store() .LastCallStartedTimestamp.Store()return}func ( *Channel) ( int64, entry) {switch v := .(type) {case *SubChannel: .subChans[] = .RefNamecase *Channel: .nestedChans[] = .RefNamedefault:logger.Errorf("cannot add a child (id = %d) of type %T to a channel", , ) }}func ( *Channel) ( int64) {delete(.subChans, )delete(.nestedChans, ) .deleteSelfIfReady()}func ( *Channel) () { .closeCalled = true .deleteSelfIfReady()}func ( *Channel) () int64 {if .Parent == nil {return -1 }return .Parent.ID}// deleteSelfFromTree tries to delete the channel from the channelz entry relation tree, which means// deleting the channel reference from its parent's child list.//// In order for a channel to be deleted from the tree, it must meet the criteria that, removal of the// corresponding grpc object has been invoked, and the channel does not have any children left.//// The returned boolean value indicates whether the channel has been successfully deleted from tree.func ( *Channel) () ( bool) {if !.closeCalled || len(.subChans)+len(.nestedChans) != 0 {returnfalse }// not top channelif .Parent != nil { .Parent.deleteChild(.ID) }returntrue}// deleteSelfFromMap checks whether it is valid to delete the channel from the map, which means// deleting the channel from channelz's tracking entirely. Users can no longer use id to query the// channel, and its memory will be garbage collected.//// The trace reference count of the channel must be 0 in order to be deleted from the map. This is// specified in the channel tracing gRFC that as long as some other trace has reference to an entity,// the trace of the referenced entity must not be deleted. In order to release the resource allocated// by grpc, the reference to the grpc object is reset to a dummy object.//// deleteSelfFromMap must be called after deleteSelfFromTree returns true.//// It returns a bool to indicate whether the channel can be safely deleted from map.func ( *Channel) () ( bool) {return .getTraceRefCount() == 0}// deleteSelfIfReady tries to delete the channel itself from the channelz database.// The delete process includes two steps:// 1. delete the channel from the entry relation tree, i.e. delete the channel reference from its// parent's child list.// 2. delete the channel from the map, i.e. delete the channel entirely from channelz. Lookup by id// will return entry not found error.func ( *Channel) () {if !.deleteSelfFromTree() {return }if !.deleteSelfFromMap() {return }db.deleteEntry(.ID) .trace.clear()}func ( *Channel) () *ChannelTrace {return .trace}func ( *Channel) () {atomic.AddInt32(&.traceRefCount, 1)}func ( *Channel) () {atomic.AddInt32(&.traceRefCount, -1)}func ( *Channel) () int { := atomic.LoadInt32(&.traceRefCount)returnint()}func ( *Channel) () string {return .RefName}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.