google.golang.org/grpc@v1.62.1/channelz/service/service.go (about) 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 service provides an implementation for channelz service server. 20 package service 21 22 import ( 23 "context" 24 "net" 25 26 "github.com/golang/protobuf/ptypes" 27 wrpb "github.com/golang/protobuf/ptypes/wrappers" 28 channelzgrpc "google.golang.org/grpc/channelz/grpc_channelz_v1" 29 channelzpb "google.golang.org/grpc/channelz/grpc_channelz_v1" 30 31 "google.golang.org/grpc" 32 "google.golang.org/grpc/codes" 33 "google.golang.org/grpc/connectivity" 34 "google.golang.org/grpc/credentials" 35 "google.golang.org/grpc/grpclog" 36 "google.golang.org/grpc/internal/channelz" 37 "google.golang.org/grpc/status" 38 "google.golang.org/protobuf/protoadapt" 39 "google.golang.org/protobuf/types/known/anypb" 40 ) 41 42 func init() { 43 channelz.TurnOn() 44 } 45 46 var logger = grpclog.Component("channelz") 47 48 // RegisterChannelzServiceToServer registers the channelz service to the given server. 49 // 50 // Note: it is preferred to use the admin API 51 // (https://pkg.go.dev/google.golang.org/grpc/admin#Register) instead to 52 // register Channelz and other administrative services. 53 func RegisterChannelzServiceToServer(s grpc.ServiceRegistrar) { 54 channelzgrpc.RegisterChannelzServer(s, newCZServer()) 55 } 56 57 func newCZServer() channelzgrpc.ChannelzServer { 58 return &serverImpl{} 59 } 60 61 type serverImpl struct { 62 channelzgrpc.UnimplementedChannelzServer 63 } 64 65 func connectivityStateToProto(s connectivity.State) *channelzpb.ChannelConnectivityState { 66 switch s { 67 case connectivity.Idle: 68 return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_IDLE} 69 case connectivity.Connecting: 70 return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_CONNECTING} 71 case connectivity.Ready: 72 return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_READY} 73 case connectivity.TransientFailure: 74 return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_TRANSIENT_FAILURE} 75 case connectivity.Shutdown: 76 return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_SHUTDOWN} 77 default: 78 return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_UNKNOWN} 79 } 80 } 81 82 func channelTraceToProto(ct *channelz.ChannelTrace) *channelzpb.ChannelTrace { 83 pbt := &channelzpb.ChannelTrace{} 84 pbt.NumEventsLogged = ct.EventNum 85 if ts, err := ptypes.TimestampProto(ct.CreationTime); err == nil { 86 pbt.CreationTimestamp = ts 87 } 88 events := make([]*channelzpb.ChannelTraceEvent, 0, len(ct.Events)) 89 for _, e := range ct.Events { 90 cte := &channelzpb.ChannelTraceEvent{ 91 Description: e.Desc, 92 Severity: channelzpb.ChannelTraceEvent_Severity(e.Severity), 93 } 94 if ts, err := ptypes.TimestampProto(e.Timestamp); err == nil { 95 cte.Timestamp = ts 96 } 97 if e.RefID != 0 { 98 switch e.RefType { 99 case channelz.RefChannel: 100 cte.ChildRef = &channelzpb.ChannelTraceEvent_ChannelRef{ChannelRef: &channelzpb.ChannelRef{ChannelId: e.RefID, Name: e.RefName}} 101 case channelz.RefSubChannel: 102 cte.ChildRef = &channelzpb.ChannelTraceEvent_SubchannelRef{SubchannelRef: &channelzpb.SubchannelRef{SubchannelId: e.RefID, Name: e.RefName}} 103 } 104 } 105 events = append(events, cte) 106 } 107 pbt.Events = events 108 return pbt 109 } 110 111 func channelMetricToProto(cm *channelz.ChannelMetric) *channelzpb.Channel { 112 c := &channelzpb.Channel{} 113 c.Ref = &channelzpb.ChannelRef{ChannelId: cm.ID, Name: cm.RefName} 114 115 c.Data = &channelzpb.ChannelData{ 116 State: connectivityStateToProto(cm.ChannelData.State), 117 Target: cm.ChannelData.Target, 118 CallsStarted: cm.ChannelData.CallsStarted, 119 CallsSucceeded: cm.ChannelData.CallsSucceeded, 120 CallsFailed: cm.ChannelData.CallsFailed, 121 } 122 if ts, err := ptypes.TimestampProto(cm.ChannelData.LastCallStartedTimestamp); err == nil { 123 c.Data.LastCallStartedTimestamp = ts 124 } 125 nestedChans := make([]*channelzpb.ChannelRef, 0, len(cm.NestedChans)) 126 for id, ref := range cm.NestedChans { 127 nestedChans = append(nestedChans, &channelzpb.ChannelRef{ChannelId: id, Name: ref}) 128 } 129 c.ChannelRef = nestedChans 130 131 subChans := make([]*channelzpb.SubchannelRef, 0, len(cm.SubChans)) 132 for id, ref := range cm.SubChans { 133 subChans = append(subChans, &channelzpb.SubchannelRef{SubchannelId: id, Name: ref}) 134 } 135 c.SubchannelRef = subChans 136 137 sockets := make([]*channelzpb.SocketRef, 0, len(cm.Sockets)) 138 for id, ref := range cm.Sockets { 139 sockets = append(sockets, &channelzpb.SocketRef{SocketId: id, Name: ref}) 140 } 141 c.SocketRef = sockets 142 c.Data.Trace = channelTraceToProto(cm.Trace) 143 return c 144 } 145 146 func subChannelMetricToProto(cm *channelz.SubChannelMetric) *channelzpb.Subchannel { 147 sc := &channelzpb.Subchannel{} 148 sc.Ref = &channelzpb.SubchannelRef{SubchannelId: cm.ID, Name: cm.RefName} 149 150 sc.Data = &channelzpb.ChannelData{ 151 State: connectivityStateToProto(cm.ChannelData.State), 152 Target: cm.ChannelData.Target, 153 CallsStarted: cm.ChannelData.CallsStarted, 154 CallsSucceeded: cm.ChannelData.CallsSucceeded, 155 CallsFailed: cm.ChannelData.CallsFailed, 156 } 157 if ts, err := ptypes.TimestampProto(cm.ChannelData.LastCallStartedTimestamp); err == nil { 158 sc.Data.LastCallStartedTimestamp = ts 159 } 160 nestedChans := make([]*channelzpb.ChannelRef, 0, len(cm.NestedChans)) 161 for id, ref := range cm.NestedChans { 162 nestedChans = append(nestedChans, &channelzpb.ChannelRef{ChannelId: id, Name: ref}) 163 } 164 sc.ChannelRef = nestedChans 165 166 subChans := make([]*channelzpb.SubchannelRef, 0, len(cm.SubChans)) 167 for id, ref := range cm.SubChans { 168 subChans = append(subChans, &channelzpb.SubchannelRef{SubchannelId: id, Name: ref}) 169 } 170 sc.SubchannelRef = subChans 171 172 sockets := make([]*channelzpb.SocketRef, 0, len(cm.Sockets)) 173 for id, ref := range cm.Sockets { 174 sockets = append(sockets, &channelzpb.SocketRef{SocketId: id, Name: ref}) 175 } 176 sc.SocketRef = sockets 177 sc.Data.Trace = channelTraceToProto(cm.Trace) 178 return sc 179 } 180 181 func securityToProto(se credentials.ChannelzSecurityValue) *channelzpb.Security { 182 switch v := se.(type) { 183 case *credentials.TLSChannelzSecurityValue: 184 return &channelzpb.Security{Model: &channelzpb.Security_Tls_{Tls: &channelzpb.Security_Tls{ 185 CipherSuite: &channelzpb.Security_Tls_StandardName{StandardName: v.StandardName}, 186 LocalCertificate: v.LocalCertificate, 187 RemoteCertificate: v.RemoteCertificate, 188 }}} 189 case *credentials.OtherChannelzSecurityValue: 190 otherSecurity := &channelzpb.Security_OtherSecurity{ 191 Name: v.Name, 192 } 193 if anyval, err := anypb.New(protoadapt.MessageV2Of(v.Value)); err == nil { 194 otherSecurity.Value = anyval 195 } 196 return &channelzpb.Security{Model: &channelzpb.Security_Other{Other: otherSecurity}} 197 } 198 return nil 199 } 200 201 func addrToProto(a net.Addr) *channelzpb.Address { 202 switch a.Network() { 203 case "udp": 204 // TODO: Address_OtherAddress{}. Need proto def for Value. 205 case "ip": 206 // Note zone info is discarded through the conversion. 207 return &channelzpb.Address{Address: &channelzpb.Address_TcpipAddress{TcpipAddress: &channelzpb.Address_TcpIpAddress{IpAddress: a.(*net.IPAddr).IP}}} 208 case "ip+net": 209 // Note mask info is discarded through the conversion. 210 return &channelzpb.Address{Address: &channelzpb.Address_TcpipAddress{TcpipAddress: &channelzpb.Address_TcpIpAddress{IpAddress: a.(*net.IPNet).IP}}} 211 case "tcp": 212 // Note zone info is discarded through the conversion. 213 return &channelzpb.Address{Address: &channelzpb.Address_TcpipAddress{TcpipAddress: &channelzpb.Address_TcpIpAddress{IpAddress: a.(*net.TCPAddr).IP, Port: int32(a.(*net.TCPAddr).Port)}}} 214 case "unix", "unixgram", "unixpacket": 215 return &channelzpb.Address{Address: &channelzpb.Address_UdsAddress_{UdsAddress: &channelzpb.Address_UdsAddress{Filename: a.String()}}} 216 default: 217 } 218 return &channelzpb.Address{} 219 } 220 221 func socketMetricToProto(sm *channelz.SocketMetric) *channelzpb.Socket { 222 s := &channelzpb.Socket{} 223 s.Ref = &channelzpb.SocketRef{SocketId: sm.ID, Name: sm.RefName} 224 225 s.Data = &channelzpb.SocketData{ 226 StreamsStarted: sm.SocketData.StreamsStarted, 227 StreamsSucceeded: sm.SocketData.StreamsSucceeded, 228 StreamsFailed: sm.SocketData.StreamsFailed, 229 MessagesSent: sm.SocketData.MessagesSent, 230 MessagesReceived: sm.SocketData.MessagesReceived, 231 KeepAlivesSent: sm.SocketData.KeepAlivesSent, 232 } 233 if ts, err := ptypes.TimestampProto(sm.SocketData.LastLocalStreamCreatedTimestamp); err == nil { 234 s.Data.LastLocalStreamCreatedTimestamp = ts 235 } 236 if ts, err := ptypes.TimestampProto(sm.SocketData.LastRemoteStreamCreatedTimestamp); err == nil { 237 s.Data.LastRemoteStreamCreatedTimestamp = ts 238 } 239 if ts, err := ptypes.TimestampProto(sm.SocketData.LastMessageSentTimestamp); err == nil { 240 s.Data.LastMessageSentTimestamp = ts 241 } 242 if ts, err := ptypes.TimestampProto(sm.SocketData.LastMessageReceivedTimestamp); err == nil { 243 s.Data.LastMessageReceivedTimestamp = ts 244 } 245 s.Data.LocalFlowControlWindow = &wrpb.Int64Value{Value: sm.SocketData.LocalFlowControlWindow} 246 s.Data.RemoteFlowControlWindow = &wrpb.Int64Value{Value: sm.SocketData.RemoteFlowControlWindow} 247 248 if sm.SocketData.SocketOptions != nil { 249 s.Data.Option = sockoptToProto(sm.SocketData.SocketOptions) 250 } 251 if sm.SocketData.Security != nil { 252 s.Security = securityToProto(sm.SocketData.Security) 253 } 254 255 if sm.SocketData.LocalAddr != nil { 256 s.Local = addrToProto(sm.SocketData.LocalAddr) 257 } 258 if sm.SocketData.RemoteAddr != nil { 259 s.Remote = addrToProto(sm.SocketData.RemoteAddr) 260 } 261 s.RemoteName = sm.SocketData.RemoteName 262 return s 263 } 264 265 func (s *serverImpl) GetTopChannels(ctx context.Context, req *channelzpb.GetTopChannelsRequest) (*channelzpb.GetTopChannelsResponse, error) { 266 metrics, end := channelz.GetTopChannels(req.GetStartChannelId(), req.GetMaxResults()) 267 resp := &channelzpb.GetTopChannelsResponse{} 268 for _, m := range metrics { 269 resp.Channel = append(resp.Channel, channelMetricToProto(m)) 270 } 271 resp.End = end 272 return resp, nil 273 } 274 275 func serverMetricToProto(sm *channelz.ServerMetric) *channelzpb.Server { 276 s := &channelzpb.Server{} 277 s.Ref = &channelzpb.ServerRef{ServerId: sm.ID, Name: sm.RefName} 278 279 s.Data = &channelzpb.ServerData{ 280 CallsStarted: sm.ServerData.CallsStarted, 281 CallsSucceeded: sm.ServerData.CallsSucceeded, 282 CallsFailed: sm.ServerData.CallsFailed, 283 } 284 285 if ts, err := ptypes.TimestampProto(sm.ServerData.LastCallStartedTimestamp); err == nil { 286 s.Data.LastCallStartedTimestamp = ts 287 } 288 sockets := make([]*channelzpb.SocketRef, 0, len(sm.ListenSockets)) 289 for id, ref := range sm.ListenSockets { 290 sockets = append(sockets, &channelzpb.SocketRef{SocketId: id, Name: ref}) 291 } 292 s.ListenSocket = sockets 293 return s 294 } 295 296 func (s *serverImpl) GetServers(ctx context.Context, req *channelzpb.GetServersRequest) (*channelzpb.GetServersResponse, error) { 297 metrics, end := channelz.GetServers(req.GetStartServerId(), req.GetMaxResults()) 298 resp := &channelzpb.GetServersResponse{} 299 for _, m := range metrics { 300 resp.Server = append(resp.Server, serverMetricToProto(m)) 301 } 302 resp.End = end 303 return resp, nil 304 } 305 306 func (s *serverImpl) GetServerSockets(ctx context.Context, req *channelzpb.GetServerSocketsRequest) (*channelzpb.GetServerSocketsResponse, error) { 307 metrics, end := channelz.GetServerSockets(req.GetServerId(), req.GetStartSocketId(), req.GetMaxResults()) 308 resp := &channelzpb.GetServerSocketsResponse{} 309 for _, m := range metrics { 310 resp.SocketRef = append(resp.SocketRef, &channelzpb.SocketRef{SocketId: m.ID, Name: m.RefName}) 311 } 312 resp.End = end 313 return resp, nil 314 } 315 316 func (s *serverImpl) GetChannel(ctx context.Context, req *channelzpb.GetChannelRequest) (*channelzpb.GetChannelResponse, error) { 317 var metric *channelz.ChannelMetric 318 if metric = channelz.GetChannel(req.GetChannelId()); metric == nil { 319 return nil, status.Errorf(codes.NotFound, "requested channel %d not found", req.GetChannelId()) 320 } 321 resp := &channelzpb.GetChannelResponse{Channel: channelMetricToProto(metric)} 322 return resp, nil 323 } 324 325 func (s *serverImpl) GetSubchannel(ctx context.Context, req *channelzpb.GetSubchannelRequest) (*channelzpb.GetSubchannelResponse, error) { 326 var metric *channelz.SubChannelMetric 327 if metric = channelz.GetSubChannel(req.GetSubchannelId()); metric == nil { 328 return nil, status.Errorf(codes.NotFound, "requested sub channel %d not found", req.GetSubchannelId()) 329 } 330 resp := &channelzpb.GetSubchannelResponse{Subchannel: subChannelMetricToProto(metric)} 331 return resp, nil 332 } 333 334 func (s *serverImpl) GetSocket(ctx context.Context, req *channelzpb.GetSocketRequest) (*channelzpb.GetSocketResponse, error) { 335 var metric *channelz.SocketMetric 336 if metric = channelz.GetSocket(req.GetSocketId()); metric == nil { 337 return nil, status.Errorf(codes.NotFound, "requested socket %d not found", req.GetSocketId()) 338 } 339 resp := &channelzpb.GetSocketResponse{Socket: socketMetricToProto(metric)} 340 return resp, nil 341 } 342 343 func (s *serverImpl) GetServer(ctx context.Context, req *channelzpb.GetServerRequest) (*channelzpb.GetServerResponse, error) { 344 var metric *channelz.ServerMetric 345 if metric = channelz.GetServer(req.GetServerId()); metric == nil { 346 return nil, status.Errorf(codes.NotFound, "requested server %d not found", req.GetServerId()) 347 } 348 resp := &channelzpb.GetServerResponse{Server: serverMetricToProto(metric)} 349 return resp, nil 350 }