google.golang.org/grpc@v1.72.2/channelz/internal/protoconv/channel.go (about) 1 /* 2 * 3 * Copyright 2024 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 protoconv 20 21 import ( 22 "time" 23 24 "google.golang.org/grpc/codes" 25 "google.golang.org/grpc/connectivity" 26 "google.golang.org/grpc/internal/channelz" 27 "google.golang.org/grpc/status" 28 "google.golang.org/protobuf/types/known/timestamppb" 29 30 channelzpb "google.golang.org/grpc/channelz/grpc_channelz_v1" 31 ) 32 33 func connectivityStateToProto(s *connectivity.State) *channelzpb.ChannelConnectivityState { 34 if s == nil { 35 return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_UNKNOWN} 36 } 37 switch *s { 38 case connectivity.Idle: 39 return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_IDLE} 40 case connectivity.Connecting: 41 return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_CONNECTING} 42 case connectivity.Ready: 43 return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_READY} 44 case connectivity.TransientFailure: 45 return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_TRANSIENT_FAILURE} 46 case connectivity.Shutdown: 47 return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_SHUTDOWN} 48 default: 49 return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_UNKNOWN} 50 } 51 } 52 53 func channelTraceToProto(ct *channelz.ChannelTrace) *channelzpb.ChannelTrace { 54 pbt := &channelzpb.ChannelTrace{} 55 if ct == nil { 56 return pbt 57 } 58 pbt.NumEventsLogged = ct.EventNum 59 if ts := timestamppb.New(ct.CreationTime); ts.IsValid() { 60 pbt.CreationTimestamp = ts 61 } 62 events := make([]*channelzpb.ChannelTraceEvent, 0, len(ct.Events)) 63 for _, e := range ct.Events { 64 cte := &channelzpb.ChannelTraceEvent{ 65 Description: e.Desc, 66 Severity: channelzpb.ChannelTraceEvent_Severity(e.Severity), 67 } 68 if ts := timestamppb.New(e.Timestamp); ts.IsValid() { 69 cte.Timestamp = ts 70 } 71 if e.RefID != 0 { 72 switch e.RefType { 73 case channelz.RefChannel: 74 cte.ChildRef = &channelzpb.ChannelTraceEvent_ChannelRef{ChannelRef: &channelzpb.ChannelRef{ChannelId: e.RefID, Name: e.RefName}} 75 case channelz.RefSubChannel: 76 cte.ChildRef = &channelzpb.ChannelTraceEvent_SubchannelRef{SubchannelRef: &channelzpb.SubchannelRef{SubchannelId: e.RefID, Name: e.RefName}} 77 } 78 } 79 events = append(events, cte) 80 } 81 pbt.Events = events 82 return pbt 83 } 84 85 func channelToProto(cm *channelz.Channel) *channelzpb.Channel { 86 c := &channelzpb.Channel{} 87 c.Ref = &channelzpb.ChannelRef{ChannelId: cm.ID, Name: cm.RefName} 88 89 c.Data = &channelzpb.ChannelData{ 90 State: connectivityStateToProto(cm.ChannelMetrics.State.Load()), 91 Target: strFromPointer(cm.ChannelMetrics.Target.Load()), 92 CallsStarted: cm.ChannelMetrics.CallsStarted.Load(), 93 CallsSucceeded: cm.ChannelMetrics.CallsSucceeded.Load(), 94 CallsFailed: cm.ChannelMetrics.CallsFailed.Load(), 95 } 96 if ts := timestamppb.New(time.Unix(0, cm.ChannelMetrics.LastCallStartedTimestamp.Load())); ts.IsValid() { 97 c.Data.LastCallStartedTimestamp = ts 98 } 99 ncs := cm.NestedChans() 100 nestedChans := make([]*channelzpb.ChannelRef, 0, len(ncs)) 101 for id, ref := range ncs { 102 nestedChans = append(nestedChans, &channelzpb.ChannelRef{ChannelId: id, Name: ref}) 103 } 104 c.ChannelRef = nestedChans 105 106 scs := cm.SubChans() 107 subChans := make([]*channelzpb.SubchannelRef, 0, len(scs)) 108 for id, ref := range scs { 109 subChans = append(subChans, &channelzpb.SubchannelRef{SubchannelId: id, Name: ref}) 110 } 111 c.SubchannelRef = subChans 112 113 c.Data.Trace = channelTraceToProto(cm.Trace()) 114 return c 115 } 116 117 // GetTopChannels returns the protobuf representation of the channels starting 118 // at startID (max of len), and returns end=true if no top channels exist with 119 // higher IDs. 120 func GetTopChannels(startID int64, len int) (channels []*channelzpb.Channel, end bool) { 121 chans, end := channelz.GetTopChannels(startID, len) 122 for _, ch := range chans { 123 channels = append(channels, channelToProto(ch)) 124 } 125 return channels, end 126 } 127 128 // GetChannel returns the protobuf representation of the channel with the given 129 // ID. 130 func GetChannel(id int64) (*channelzpb.Channel, error) { 131 ch := channelz.GetChannel(id) 132 if ch == nil { 133 return nil, status.Errorf(codes.NotFound, "requested channel %d not found", id) 134 } 135 return channelToProto(ch), nil 136 }