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  }