snapshot of https://github.com/grpc/grpc-go.git (master, 2026-09-15; blobs > 131072B omitted)
Some checks failed
codecov / upload (push) Failing after 13m59s
CodeQL / Analyze (push) Failing after 1s
Testing / vet-proto (push) Failing after 1s
Testing / tests (arm, latest) (push) Waiting to run
Testing / extras (latest) (push) Failing after 1s
Testing / static checks (latest-1) (push) Failing after 1s
Testing / tests (-race, latest) (push) Failing after 1s
Testing / tests (i386, latest) (push) Failing after 1s
Testing / tests (latest) (push) Failing after 1s
Testing / tests (latest-1) (push) Failing after 1s
Lock Threads / lock (push) Failing after 1s
govulncheck / govulncheck (.) (push) Failing after 1s
govulncheck / govulncheck (./cmd/protoc-gen-go-grpc) (push) Failing after 1s
govulncheck / govulncheck (./gcp/observability) (push) Failing after 1s
govulncheck / govulncheck (./security/advancedtls) (push) Failing after 1s
govulncheck / govulncheck (./stats/opencensus) (push) Failing after 1s
Stale bot / stale (push) Failing after 1s
Some checks failed
codecov / upload (push) Failing after 13m59s
CodeQL / Analyze (push) Failing after 1s
Testing / vet-proto (push) Failing after 1s
Testing / tests (arm, latest) (push) Waiting to run
Testing / extras (latest) (push) Failing after 1s
Testing / static checks (latest-1) (push) Failing after 1s
Testing / tests (-race, latest) (push) Failing after 1s
Testing / tests (i386, latest) (push) Failing after 1s
Testing / tests (latest) (push) Failing after 1s
Testing / tests (latest-1) (push) Failing after 1s
Lock Threads / lock (push) Failing after 1s
govulncheck / govulncheck (.) (push) Failing after 1s
govulncheck / govulncheck (./cmd/protoc-gen-go-grpc) (push) Failing after 1s
govulncheck / govulncheck (./gcp/observability) (push) Failing after 1s
govulncheck / govulncheck (./security/advancedtls) (push) Failing after 1s
govulncheck / govulncheck (./stats/opencensus) (push) Failing after 1s
Stale bot / stale (push) Failing after 1s
This commit is contained in:
36
channelz/channelz.go
Normal file
36
channelz/channelz.go
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2020 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 exports internals of the channelz implementation as required
|
||||
// by other gRPC packages.
|
||||
//
|
||||
// The implementation of the channelz spec as defined in
|
||||
// https://github.com/grpc/proposal/blob/master/A14-channelz.md, is provided by
|
||||
// the `internal/channelz` package.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: All APIs in this package are experimental and may be removed in a
|
||||
// later release.
|
||||
package channelz
|
||||
|
||||
import "google.golang.org/grpc/internal/channelz"
|
||||
|
||||
// Identifier is an opaque identifier which uniquely identifies an entity in the
|
||||
// channelz database.
|
||||
type Identifier = channelz.Identifier
|
||||
3418
channelz/grpc_channelz_v1/channelz.pb.go
Normal file
3418
channelz/grpc_channelz_v1/channelz.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
390
channelz/grpc_channelz_v1/channelz_grpc.pb.go
Normal file
390
channelz/grpc_channelz_v1/channelz_grpc.pb.go
Normal file
@@ -0,0 +1,390 @@
|
||||
// Copyright 2018 The 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.
|
||||
|
||||
// This file defines an interface for exporting monitoring information
|
||||
// out of gRPC servers. See the full design at
|
||||
// https://github.com/grpc/proposal/blob/master/A14-channelz.md
|
||||
//
|
||||
// The canonical version of this proto can be found at
|
||||
// https://github.com/grpc/grpc-proto/blob/master/grpc/channelz/v1/channelz.proto
|
||||
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.6.2
|
||||
// - protoc v5.27.1
|
||||
// source: grpc/channelz/v1/channelz.proto
|
||||
|
||||
package grpc_channelz_v1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
Channelz_GetTopChannels_FullMethodName = "/grpc.channelz.v1.Channelz/GetTopChannels"
|
||||
Channelz_GetServers_FullMethodName = "/grpc.channelz.v1.Channelz/GetServers"
|
||||
Channelz_GetServer_FullMethodName = "/grpc.channelz.v1.Channelz/GetServer"
|
||||
Channelz_GetServerSockets_FullMethodName = "/grpc.channelz.v1.Channelz/GetServerSockets"
|
||||
Channelz_GetChannel_FullMethodName = "/grpc.channelz.v1.Channelz/GetChannel"
|
||||
Channelz_GetSubchannel_FullMethodName = "/grpc.channelz.v1.Channelz/GetSubchannel"
|
||||
Channelz_GetSocket_FullMethodName = "/grpc.channelz.v1.Channelz/GetSocket"
|
||||
)
|
||||
|
||||
// ChannelzClient is the client API for Channelz service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
//
|
||||
// Channelz is a service exposed by gRPC servers that provides detailed debug
|
||||
// information.
|
||||
type ChannelzClient interface {
|
||||
// Gets all root channels (i.e. channels the application has directly
|
||||
// created). This does not include subchannels nor non-top level channels.
|
||||
GetTopChannels(ctx context.Context, in *GetTopChannelsRequest, opts ...grpc.CallOption) (*GetTopChannelsResponse, error)
|
||||
// Gets all servers that exist in the process.
|
||||
GetServers(ctx context.Context, in *GetServersRequest, opts ...grpc.CallOption) (*GetServersResponse, error)
|
||||
// Returns a single Server, or else a NOT_FOUND code.
|
||||
GetServer(ctx context.Context, in *GetServerRequest, opts ...grpc.CallOption) (*GetServerResponse, error)
|
||||
// Gets all server sockets that exist in the process.
|
||||
GetServerSockets(ctx context.Context, in *GetServerSocketsRequest, opts ...grpc.CallOption) (*GetServerSocketsResponse, error)
|
||||
// Returns a single Channel, or else a NOT_FOUND code.
|
||||
GetChannel(ctx context.Context, in *GetChannelRequest, opts ...grpc.CallOption) (*GetChannelResponse, error)
|
||||
// Returns a single Subchannel, or else a NOT_FOUND code.
|
||||
GetSubchannel(ctx context.Context, in *GetSubchannelRequest, opts ...grpc.CallOption) (*GetSubchannelResponse, error)
|
||||
// Returns a single Socket or else a NOT_FOUND code.
|
||||
GetSocket(ctx context.Context, in *GetSocketRequest, opts ...grpc.CallOption) (*GetSocketResponse, error)
|
||||
}
|
||||
|
||||
type channelzClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewChannelzClient(cc grpc.ClientConnInterface) ChannelzClient {
|
||||
return &channelzClient{cc}
|
||||
}
|
||||
|
||||
func (c *channelzClient) GetTopChannels(ctx context.Context, in *GetTopChannelsRequest, opts ...grpc.CallOption) (*GetTopChannelsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetTopChannelsResponse)
|
||||
err := c.cc.Invoke(ctx, Channelz_GetTopChannels_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *channelzClient) GetServers(ctx context.Context, in *GetServersRequest, opts ...grpc.CallOption) (*GetServersResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetServersResponse)
|
||||
err := c.cc.Invoke(ctx, Channelz_GetServers_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *channelzClient) GetServer(ctx context.Context, in *GetServerRequest, opts ...grpc.CallOption) (*GetServerResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetServerResponse)
|
||||
err := c.cc.Invoke(ctx, Channelz_GetServer_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *channelzClient) GetServerSockets(ctx context.Context, in *GetServerSocketsRequest, opts ...grpc.CallOption) (*GetServerSocketsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetServerSocketsResponse)
|
||||
err := c.cc.Invoke(ctx, Channelz_GetServerSockets_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *channelzClient) GetChannel(ctx context.Context, in *GetChannelRequest, opts ...grpc.CallOption) (*GetChannelResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetChannelResponse)
|
||||
err := c.cc.Invoke(ctx, Channelz_GetChannel_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *channelzClient) GetSubchannel(ctx context.Context, in *GetSubchannelRequest, opts ...grpc.CallOption) (*GetSubchannelResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetSubchannelResponse)
|
||||
err := c.cc.Invoke(ctx, Channelz_GetSubchannel_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *channelzClient) GetSocket(ctx context.Context, in *GetSocketRequest, opts ...grpc.CallOption) (*GetSocketResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetSocketResponse)
|
||||
err := c.cc.Invoke(ctx, Channelz_GetSocket_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ChannelzServer is the server API for Channelz service.
|
||||
// All implementations should embed UnimplementedChannelzServer
|
||||
// for forward compatibility.
|
||||
//
|
||||
// Channelz is a service exposed by gRPC servers that provides detailed debug
|
||||
// information.
|
||||
type ChannelzServer interface {
|
||||
// Gets all root channels (i.e. channels the application has directly
|
||||
// created). This does not include subchannels nor non-top level channels.
|
||||
GetTopChannels(context.Context, *GetTopChannelsRequest) (*GetTopChannelsResponse, error)
|
||||
// Gets all servers that exist in the process.
|
||||
GetServers(context.Context, *GetServersRequest) (*GetServersResponse, error)
|
||||
// Returns a single Server, or else a NOT_FOUND code.
|
||||
GetServer(context.Context, *GetServerRequest) (*GetServerResponse, error)
|
||||
// Gets all server sockets that exist in the process.
|
||||
GetServerSockets(context.Context, *GetServerSocketsRequest) (*GetServerSocketsResponse, error)
|
||||
// Returns a single Channel, or else a NOT_FOUND code.
|
||||
GetChannel(context.Context, *GetChannelRequest) (*GetChannelResponse, error)
|
||||
// Returns a single Subchannel, or else a NOT_FOUND code.
|
||||
GetSubchannel(context.Context, *GetSubchannelRequest) (*GetSubchannelResponse, error)
|
||||
// Returns a single Socket or else a NOT_FOUND code.
|
||||
GetSocket(context.Context, *GetSocketRequest) (*GetSocketResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedChannelzServer should be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedChannelzServer struct{}
|
||||
|
||||
func (UnimplementedChannelzServer) GetTopChannels(context.Context, *GetTopChannelsRequest) (*GetTopChannelsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetTopChannels not implemented")
|
||||
}
|
||||
func (UnimplementedChannelzServer) GetServers(context.Context, *GetServersRequest) (*GetServersResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetServers not implemented")
|
||||
}
|
||||
func (UnimplementedChannelzServer) GetServer(context.Context, *GetServerRequest) (*GetServerResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetServer not implemented")
|
||||
}
|
||||
func (UnimplementedChannelzServer) GetServerSockets(context.Context, *GetServerSocketsRequest) (*GetServerSocketsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetServerSockets not implemented")
|
||||
}
|
||||
func (UnimplementedChannelzServer) GetChannel(context.Context, *GetChannelRequest) (*GetChannelResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetChannel not implemented")
|
||||
}
|
||||
func (UnimplementedChannelzServer) GetSubchannel(context.Context, *GetSubchannelRequest) (*GetSubchannelResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetSubchannel not implemented")
|
||||
}
|
||||
func (UnimplementedChannelzServer) GetSocket(context.Context, *GetSocketRequest) (*GetSocketResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetSocket not implemented")
|
||||
}
|
||||
func (UnimplementedChannelzServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeChannelzServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to ChannelzServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeChannelzServer interface {
|
||||
mustEmbedUnimplementedChannelzServer()
|
||||
}
|
||||
|
||||
func RegisterChannelzServer(s grpc.ServiceRegistrar, srv ChannelzServer) {
|
||||
// If the following call panics, it indicates UnimplementedChannelzServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&Channelz_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _Channelz_GetTopChannels_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetTopChannelsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ChannelzServer).GetTopChannels(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Channelz_GetTopChannels_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ChannelzServer).GetTopChannels(ctx, req.(*GetTopChannelsRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Channelz_GetServers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetServersRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ChannelzServer).GetServers(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Channelz_GetServers_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ChannelzServer).GetServers(ctx, req.(*GetServersRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Channelz_GetServer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetServerRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ChannelzServer).GetServer(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Channelz_GetServer_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ChannelzServer).GetServer(ctx, req.(*GetServerRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Channelz_GetServerSockets_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetServerSocketsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ChannelzServer).GetServerSockets(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Channelz_GetServerSockets_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ChannelzServer).GetServerSockets(ctx, req.(*GetServerSocketsRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Channelz_GetChannel_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetChannelRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ChannelzServer).GetChannel(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Channelz_GetChannel_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ChannelzServer).GetChannel(ctx, req.(*GetChannelRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Channelz_GetSubchannel_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetSubchannelRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ChannelzServer).GetSubchannel(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Channelz_GetSubchannel_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ChannelzServer).GetSubchannel(ctx, req.(*GetSubchannelRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Channelz_GetSocket_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetSocketRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ChannelzServer).GetSocket(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Channelz_GetSocket_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ChannelzServer).GetSocket(ctx, req.(*GetSocketRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// Channelz_ServiceDesc is the grpc.ServiceDesc for Channelz service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var Channelz_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "grpc.channelz.v1.Channelz",
|
||||
HandlerType: (*ChannelzServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "GetTopChannels",
|
||||
Handler: _Channelz_GetTopChannels_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetServers",
|
||||
Handler: _Channelz_GetServers_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetServer",
|
||||
Handler: _Channelz_GetServer_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetServerSockets",
|
||||
Handler: _Channelz_GetServerSockets_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetChannel",
|
||||
Handler: _Channelz_GetChannel_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetSubchannel",
|
||||
Handler: _Channelz_GetSubchannel_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetSocket",
|
||||
Handler: _Channelz_GetSocket_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "grpc/channelz/v1/channelz.proto",
|
||||
}
|
||||
136
channelz/internal/protoconv/channel.go
Normal file
136
channelz/internal/protoconv/channel.go
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
*
|
||||
* 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 protoconv
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
channelzpb "google.golang.org/grpc/channelz/grpc_channelz_v1"
|
||||
)
|
||||
|
||||
func connectivityStateToProto(s *connectivity.State) *channelzpb.ChannelConnectivityState {
|
||||
if s == nil {
|
||||
return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_UNKNOWN}
|
||||
}
|
||||
switch *s {
|
||||
case connectivity.Idle:
|
||||
return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_IDLE}
|
||||
case connectivity.Connecting:
|
||||
return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_CONNECTING}
|
||||
case connectivity.Ready:
|
||||
return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_READY}
|
||||
case connectivity.TransientFailure:
|
||||
return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_TRANSIENT_FAILURE}
|
||||
case connectivity.Shutdown:
|
||||
return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_SHUTDOWN}
|
||||
default:
|
||||
return &channelzpb.ChannelConnectivityState{State: channelzpb.ChannelConnectivityState_UNKNOWN}
|
||||
}
|
||||
}
|
||||
|
||||
func channelTraceToProto(ct *channelz.ChannelTrace) *channelzpb.ChannelTrace {
|
||||
pbt := &channelzpb.ChannelTrace{}
|
||||
if ct == nil {
|
||||
return pbt
|
||||
}
|
||||
pbt.NumEventsLogged = ct.EventNum
|
||||
if ts := timestamppb.New(ct.CreationTime); ts.IsValid() {
|
||||
pbt.CreationTimestamp = ts
|
||||
}
|
||||
events := make([]*channelzpb.ChannelTraceEvent, 0, len(ct.Events))
|
||||
for _, e := range ct.Events {
|
||||
cte := &channelzpb.ChannelTraceEvent{
|
||||
Description: e.Desc,
|
||||
Severity: channelzpb.ChannelTraceEvent_Severity(e.Severity),
|
||||
}
|
||||
if ts := timestamppb.New(e.Timestamp); ts.IsValid() {
|
||||
cte.Timestamp = ts
|
||||
}
|
||||
if e.RefID != 0 {
|
||||
switch e.RefType {
|
||||
case channelz.RefChannel:
|
||||
cte.ChildRef = &channelzpb.ChannelTraceEvent_ChannelRef{ChannelRef: &channelzpb.ChannelRef{ChannelId: e.RefID, Name: e.RefName}}
|
||||
case channelz.RefSubChannel:
|
||||
cte.ChildRef = &channelzpb.ChannelTraceEvent_SubchannelRef{SubchannelRef: &channelzpb.SubchannelRef{SubchannelId: e.RefID, Name: e.RefName}}
|
||||
}
|
||||
}
|
||||
events = append(events, cte)
|
||||
}
|
||||
pbt.Events = events
|
||||
return pbt
|
||||
}
|
||||
|
||||
func channelToProto(cm *channelz.Channel) *channelzpb.Channel {
|
||||
c := &channelzpb.Channel{}
|
||||
c.Ref = &channelzpb.ChannelRef{ChannelId: cm.ID, Name: cm.RefName}
|
||||
|
||||
c.Data = &channelzpb.ChannelData{
|
||||
State: connectivityStateToProto(cm.ChannelMetrics.State.Load()),
|
||||
Target: strFromPointer(cm.ChannelMetrics.Target.Load()),
|
||||
CallsStarted: cm.ChannelMetrics.CallsStarted.Load(),
|
||||
CallsSucceeded: cm.ChannelMetrics.CallsSucceeded.Load(),
|
||||
CallsFailed: cm.ChannelMetrics.CallsFailed.Load(),
|
||||
}
|
||||
if ts := timestamppb.New(time.Unix(0, cm.ChannelMetrics.LastCallStartedTimestamp.Load())); ts.IsValid() {
|
||||
c.Data.LastCallStartedTimestamp = ts
|
||||
}
|
||||
ncs := cm.NestedChans()
|
||||
nestedChans := make([]*channelzpb.ChannelRef, 0, len(ncs))
|
||||
for id, ref := range ncs {
|
||||
nestedChans = append(nestedChans, &channelzpb.ChannelRef{ChannelId: id, Name: ref})
|
||||
}
|
||||
c.ChannelRef = nestedChans
|
||||
|
||||
scs := cm.SubChans()
|
||||
subChans := make([]*channelzpb.SubchannelRef, 0, len(scs))
|
||||
for id, ref := range scs {
|
||||
subChans = append(subChans, &channelzpb.SubchannelRef{SubchannelId: id, Name: ref})
|
||||
}
|
||||
c.SubchannelRef = subChans
|
||||
|
||||
c.Data.Trace = channelTraceToProto(cm.Trace())
|
||||
return c
|
||||
}
|
||||
|
||||
// GetTopChannels returns the protobuf representation of the channels starting
|
||||
// at startID (max of len), and returns end=true if no top channels exist with
|
||||
// higher IDs.
|
||||
func GetTopChannels(startID int64, len int) (channels []*channelzpb.Channel, end bool) {
|
||||
chans, end := channelz.GetTopChannels(startID, len)
|
||||
for _, ch := range chans {
|
||||
channels = append(channels, channelToProto(ch))
|
||||
}
|
||||
return channels, end
|
||||
}
|
||||
|
||||
// GetChannel returns the protobuf representation of the channel with the given
|
||||
// ID.
|
||||
func GetChannel(id int64) (*channelzpb.Channel, error) {
|
||||
ch := channelz.GetChannel(id)
|
||||
if ch == nil {
|
||||
return nil, status.Errorf(codes.NotFound, "requested channel %d not found", id)
|
||||
}
|
||||
return channelToProto(ch), nil
|
||||
}
|
||||
73
channelz/internal/protoconv/server.go
Normal file
73
channelz/internal/protoconv/server.go
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
*
|
||||
* 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 protoconv
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
channelzpb "google.golang.org/grpc/channelz/grpc_channelz_v1"
|
||||
)
|
||||
|
||||
func serverToProto(sm *channelz.Server) *channelzpb.Server {
|
||||
s := &channelzpb.Server{}
|
||||
s.Ref = &channelzpb.ServerRef{ServerId: sm.ID, Name: sm.RefName}
|
||||
|
||||
s.Data = &channelzpb.ServerData{
|
||||
CallsStarted: sm.ServerMetrics.CallsStarted.Load(),
|
||||
CallsSucceeded: sm.ServerMetrics.CallsSucceeded.Load(),
|
||||
CallsFailed: sm.ServerMetrics.CallsFailed.Load(),
|
||||
}
|
||||
|
||||
if ts := timestamppb.New(time.Unix(0, sm.ServerMetrics.LastCallStartedTimestamp.Load())); ts.IsValid() {
|
||||
s.Data.LastCallStartedTimestamp = ts
|
||||
}
|
||||
lss := sm.ListenSockets()
|
||||
sockets := make([]*channelzpb.SocketRef, 0, len(lss))
|
||||
for id, ref := range lss {
|
||||
sockets = append(sockets, &channelzpb.SocketRef{SocketId: id, Name: ref})
|
||||
}
|
||||
s.ListenSocket = sockets
|
||||
return s
|
||||
}
|
||||
|
||||
// GetServers returns the protobuf representation of the servers starting at
|
||||
// startID (max of len), and returns end=true if no servers exist with higher
|
||||
// IDs.
|
||||
func GetServers(startID int64, len int) (servers []*channelzpb.Server, end bool) {
|
||||
srvs, end := channelz.GetServers(startID, len)
|
||||
for _, srv := range srvs {
|
||||
servers = append(servers, serverToProto(srv))
|
||||
}
|
||||
return servers, end
|
||||
}
|
||||
|
||||
// GetServer returns the protobuf representation of the server with the given
|
||||
// ID.
|
||||
func GetServer(id int64) (*channelzpb.Server, error) {
|
||||
srv := channelz.GetServer(id)
|
||||
if srv == nil {
|
||||
return nil, status.Errorf(codes.NotFound, "requested server %d not found", id)
|
||||
}
|
||||
return serverToProto(srv), nil
|
||||
}
|
||||
136
channelz/internal/protoconv/socket.go
Normal file
136
channelz/internal/protoconv/socket.go
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
*
|
||||
* 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 protoconv
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
|
||||
channelzpb "google.golang.org/grpc/channelz/grpc_channelz_v1"
|
||||
)
|
||||
|
||||
func securityToProto(se credentials.ChannelzSecurityValue) *channelzpb.Security {
|
||||
switch v := se.(type) {
|
||||
case *credentials.TLSChannelzSecurityValue:
|
||||
return &channelzpb.Security{Model: &channelzpb.Security_Tls_{Tls: &channelzpb.Security_Tls{
|
||||
CipherSuite: &channelzpb.Security_Tls_StandardName{StandardName: v.StandardName},
|
||||
LocalCertificate: v.LocalCertificate,
|
||||
RemoteCertificate: v.RemoteCertificate,
|
||||
}}}
|
||||
case *credentials.OtherChannelzSecurityValue:
|
||||
otherSecurity := &channelzpb.Security_OtherSecurity{
|
||||
Name: v.Name,
|
||||
}
|
||||
if anyval, err := anypb.New(v.Value); err == nil {
|
||||
otherSecurity.Value = anyval
|
||||
}
|
||||
return &channelzpb.Security{Model: &channelzpb.Security_Other{Other: otherSecurity}}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func addrToProto(a net.Addr) *channelzpb.Address {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
switch a.Network() {
|
||||
case "udp":
|
||||
// TODO: Address_OtherAddress{}. Need proto def for Value.
|
||||
case "ip":
|
||||
// Note zone info is discarded through the conversion.
|
||||
return &channelzpb.Address{Address: &channelzpb.Address_TcpipAddress{TcpipAddress: &channelzpb.Address_TcpIpAddress{IpAddress: a.(*net.IPAddr).IP}}}
|
||||
case "ip+net":
|
||||
// Note mask info is discarded through the conversion.
|
||||
return &channelzpb.Address{Address: &channelzpb.Address_TcpipAddress{TcpipAddress: &channelzpb.Address_TcpIpAddress{IpAddress: a.(*net.IPNet).IP}}}
|
||||
case "tcp":
|
||||
// Note zone info is discarded through the conversion.
|
||||
return &channelzpb.Address{Address: &channelzpb.Address_TcpipAddress{TcpipAddress: &channelzpb.Address_TcpIpAddress{IpAddress: a.(*net.TCPAddr).IP, Port: int32(a.(*net.TCPAddr).Port)}}}
|
||||
case "unix", "unixgram", "unixpacket":
|
||||
return &channelzpb.Address{Address: &channelzpb.Address_UdsAddress_{UdsAddress: &channelzpb.Address_UdsAddress{Filename: a.String()}}}
|
||||
default:
|
||||
}
|
||||
return &channelzpb.Address{}
|
||||
}
|
||||
|
||||
func socketToProto(skt *channelz.Socket) *channelzpb.Socket {
|
||||
s := &channelzpb.Socket{}
|
||||
s.Ref = &channelzpb.SocketRef{SocketId: skt.ID, Name: skt.RefName}
|
||||
|
||||
s.Data = &channelzpb.SocketData{
|
||||
StreamsStarted: skt.SocketMetrics.StreamsStarted.Load(),
|
||||
StreamsSucceeded: skt.SocketMetrics.StreamsSucceeded.Load(),
|
||||
StreamsFailed: skt.SocketMetrics.StreamsFailed.Load(),
|
||||
MessagesSent: skt.SocketMetrics.MessagesSent.Load(),
|
||||
MessagesReceived: skt.SocketMetrics.MessagesReceived.Load(),
|
||||
KeepAlivesSent: skt.SocketMetrics.KeepAlivesSent.Load(),
|
||||
}
|
||||
if ts := timestamppb.New(time.Unix(0, skt.SocketMetrics.LastLocalStreamCreatedTimestamp.Load())); ts.IsValid() {
|
||||
s.Data.LastLocalStreamCreatedTimestamp = ts
|
||||
}
|
||||
if ts := timestamppb.New(time.Unix(0, skt.SocketMetrics.LastRemoteStreamCreatedTimestamp.Load())); ts.IsValid() {
|
||||
s.Data.LastRemoteStreamCreatedTimestamp = ts
|
||||
}
|
||||
if ts := timestamppb.New(time.Unix(0, skt.SocketMetrics.LastMessageSentTimestamp.Load())); ts.IsValid() {
|
||||
s.Data.LastMessageSentTimestamp = ts
|
||||
}
|
||||
if ts := timestamppb.New(time.Unix(0, skt.SocketMetrics.LastMessageReceivedTimestamp.Load())); ts.IsValid() {
|
||||
s.Data.LastMessageReceivedTimestamp = ts
|
||||
}
|
||||
if skt.EphemeralMetrics != nil {
|
||||
e := skt.EphemeralMetrics()
|
||||
s.Data.LocalFlowControlWindow = wrapperspb.Int64(e.LocalFlowControlWindow)
|
||||
s.Data.RemoteFlowControlWindow = wrapperspb.Int64(e.RemoteFlowControlWindow)
|
||||
}
|
||||
|
||||
s.Data.Option = sockoptToProto(skt.SocketOptions)
|
||||
s.Security = securityToProto(skt.Security)
|
||||
s.Local = addrToProto(skt.LocalAddr)
|
||||
s.Remote = addrToProto(skt.RemoteAddr)
|
||||
s.RemoteName = skt.RemoteName
|
||||
return s
|
||||
}
|
||||
|
||||
// GetServerSockets returns the protobuf representation of the server (listen)
|
||||
// sockets starting at startID (max of len), and returns end=true if no server
|
||||
// sockets exist with higher IDs.
|
||||
func GetServerSockets(serverID, startID int64, len int) (sockets []*channelzpb.SocketRef, end bool) {
|
||||
skts, end := channelz.GetServerSockets(serverID, startID, len)
|
||||
for _, m := range skts {
|
||||
sockets = append(sockets, &channelzpb.SocketRef{SocketId: m.ID, Name: m.RefName})
|
||||
}
|
||||
return sockets, end
|
||||
}
|
||||
|
||||
// GetSocket returns the protobuf representation of the socket with the given
|
||||
// ID.
|
||||
func GetSocket(id int64) (*channelzpb.Socket, error) {
|
||||
skt := channelz.GetSocket(id)
|
||||
if skt == nil {
|
||||
return nil, status.Errorf(codes.NotFound, "requested socket %d not found", id)
|
||||
}
|
||||
return socketToProto(skt), nil
|
||||
}
|
||||
125
channelz/internal/protoconv/sockopt_linux.go
Normal file
125
channelz/internal/protoconv/sockopt_linux.go
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
*
|
||||
* 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 protoconv
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
|
||||
channelzpb "google.golang.org/grpc/channelz/grpc_channelz_v1"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
)
|
||||
|
||||
var logger = grpclog.Component("channelz")
|
||||
|
||||
func convertToPbDuration(sec int64, usec int64) *durationpb.Duration {
|
||||
return durationpb.New(time.Duration(sec*1e9 + usec*1e3))
|
||||
}
|
||||
|
||||
func sockoptToProto(skopts *channelz.SocketOptionData) []*channelzpb.SocketOption {
|
||||
if skopts == nil {
|
||||
return nil
|
||||
}
|
||||
var opts []*channelzpb.SocketOption
|
||||
if skopts.Linger != nil {
|
||||
additional, err := anypb.New(&channelzpb.SocketOptionLinger{
|
||||
Active: skopts.Linger.Onoff != 0,
|
||||
Duration: convertToPbDuration(int64(skopts.Linger.Linger), 0),
|
||||
})
|
||||
if err == nil {
|
||||
opts = append(opts, &channelzpb.SocketOption{
|
||||
Name: "SO_LINGER",
|
||||
Additional: additional,
|
||||
})
|
||||
} else {
|
||||
logger.Warningf("Failed to marshal socket options linger %+v: %v", skopts.Linger, err)
|
||||
}
|
||||
}
|
||||
if skopts.RecvTimeout != nil {
|
||||
additional, err := anypb.New(&channelzpb.SocketOptionTimeout{
|
||||
Duration: convertToPbDuration(int64(skopts.RecvTimeout.Sec), int64(skopts.RecvTimeout.Usec)),
|
||||
})
|
||||
if err == nil {
|
||||
opts = append(opts, &channelzpb.SocketOption{
|
||||
Name: "SO_RCVTIMEO",
|
||||
Additional: additional,
|
||||
})
|
||||
} else {
|
||||
logger.Warningf("Failed to marshal socket options receive timeout %+v: %v", skopts.RecvTimeout, err)
|
||||
}
|
||||
}
|
||||
if skopts.SendTimeout != nil {
|
||||
additional, err := anypb.New(&channelzpb.SocketOptionTimeout{
|
||||
Duration: convertToPbDuration(int64(skopts.SendTimeout.Sec), int64(skopts.SendTimeout.Usec)),
|
||||
})
|
||||
if err == nil {
|
||||
opts = append(opts, &channelzpb.SocketOption{
|
||||
Name: "SO_SNDTIMEO",
|
||||
Additional: additional,
|
||||
})
|
||||
} else {
|
||||
logger.Warningf("Failed to marshal socket options send timeout %+v: %v", skopts.SendTimeout, err)
|
||||
}
|
||||
}
|
||||
if skopts.TCPInfo != nil {
|
||||
additional, err := anypb.New(&channelzpb.SocketOptionTcpInfo{
|
||||
TcpiState: uint32(skopts.TCPInfo.State),
|
||||
TcpiCaState: uint32(skopts.TCPInfo.Ca_state),
|
||||
TcpiRetransmits: uint32(skopts.TCPInfo.Retransmits),
|
||||
TcpiProbes: uint32(skopts.TCPInfo.Probes),
|
||||
TcpiBackoff: uint32(skopts.TCPInfo.Backoff),
|
||||
TcpiOptions: uint32(skopts.TCPInfo.Options),
|
||||
// https://golang.org/pkg/syscall/#TCPInfo
|
||||
// TCPInfo struct does not contain info about TcpiSndWscale and TcpiRcvWscale.
|
||||
TcpiRto: skopts.TCPInfo.Rto,
|
||||
TcpiAto: skopts.TCPInfo.Ato,
|
||||
TcpiSndMss: skopts.TCPInfo.Snd_mss,
|
||||
TcpiRcvMss: skopts.TCPInfo.Rcv_mss,
|
||||
TcpiUnacked: skopts.TCPInfo.Unacked,
|
||||
TcpiSacked: skopts.TCPInfo.Sacked,
|
||||
TcpiLost: skopts.TCPInfo.Lost,
|
||||
TcpiRetrans: skopts.TCPInfo.Retrans,
|
||||
TcpiFackets: skopts.TCPInfo.Fackets,
|
||||
TcpiLastDataSent: skopts.TCPInfo.Last_data_sent,
|
||||
TcpiLastAckSent: skopts.TCPInfo.Last_ack_sent,
|
||||
TcpiLastDataRecv: skopts.TCPInfo.Last_data_recv,
|
||||
TcpiLastAckRecv: skopts.TCPInfo.Last_ack_recv,
|
||||
TcpiPmtu: skopts.TCPInfo.Pmtu,
|
||||
TcpiRcvSsthresh: skopts.TCPInfo.Rcv_ssthresh,
|
||||
TcpiRtt: skopts.TCPInfo.Rtt,
|
||||
TcpiRttvar: skopts.TCPInfo.Rttvar,
|
||||
TcpiSndSsthresh: skopts.TCPInfo.Snd_ssthresh,
|
||||
TcpiSndCwnd: skopts.TCPInfo.Snd_cwnd,
|
||||
TcpiAdvmss: skopts.TCPInfo.Advmss,
|
||||
TcpiReordering: skopts.TCPInfo.Reordering,
|
||||
})
|
||||
if err == nil {
|
||||
opts = append(opts, &channelzpb.SocketOption{
|
||||
Name: "TCP_INFO",
|
||||
Additional: additional,
|
||||
})
|
||||
} else {
|
||||
logger.Warningf("Failed to marshal socket options TCP info %+v: %v", skopts.TCPInfo, err)
|
||||
}
|
||||
}
|
||||
return opts
|
||||
}
|
||||
31
channelz/internal/protoconv/sockopt_nonlinux.go
Normal file
31
channelz/internal/protoconv/sockopt_nonlinux.go
Normal file
@@ -0,0 +1,31 @@
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
/*
|
||||
*
|
||||
* 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 protoconv
|
||||
|
||||
import (
|
||||
channelzpb "google.golang.org/grpc/channelz/grpc_channelz_v1"
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
)
|
||||
|
||||
func sockoptToProto(_ *channelz.SocketOptionData) []*channelzpb.SocketOption {
|
||||
return nil
|
||||
}
|
||||
65
channelz/internal/protoconv/subchannel.go
Normal file
65
channelz/internal/protoconv/subchannel.go
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
*
|
||||
* 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 protoconv
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
channelzpb "google.golang.org/grpc/channelz/grpc_channelz_v1"
|
||||
)
|
||||
|
||||
func subChannelToProto(cm *channelz.SubChannel) *channelzpb.Subchannel {
|
||||
sc := &channelzpb.Subchannel{}
|
||||
sc.Ref = &channelzpb.SubchannelRef{SubchannelId: cm.ID, Name: cm.RefName}
|
||||
|
||||
sc.Data = &channelzpb.ChannelData{
|
||||
State: connectivityStateToProto(cm.ChannelMetrics.State.Load()),
|
||||
Target: strFromPointer(cm.ChannelMetrics.Target.Load()),
|
||||
CallsStarted: cm.ChannelMetrics.CallsStarted.Load(),
|
||||
CallsSucceeded: cm.ChannelMetrics.CallsSucceeded.Load(),
|
||||
CallsFailed: cm.ChannelMetrics.CallsFailed.Load(),
|
||||
}
|
||||
if ts := timestamppb.New(time.Unix(0, cm.ChannelMetrics.LastCallStartedTimestamp.Load())); ts.IsValid() {
|
||||
sc.Data.LastCallStartedTimestamp = ts
|
||||
}
|
||||
|
||||
skts := cm.Sockets()
|
||||
sockets := make([]*channelzpb.SocketRef, 0, len(skts))
|
||||
for id, ref := range skts {
|
||||
sockets = append(sockets, &channelzpb.SocketRef{SocketId: id, Name: ref})
|
||||
}
|
||||
sc.SocketRef = sockets
|
||||
sc.Data.Trace = channelTraceToProto(cm.Trace())
|
||||
return sc
|
||||
}
|
||||
|
||||
// GetSubChannel returns the protobuf representation of the subchannel with the
|
||||
// given ID.
|
||||
func GetSubChannel(id int64) (*channelzpb.Subchannel, error) {
|
||||
subChan := channelz.GetSubChannel(id)
|
||||
if subChan == nil {
|
||||
return nil, status.Errorf(codes.NotFound, "requested sub channel %d not found", id)
|
||||
}
|
||||
return subChannelToProto(subChan), nil
|
||||
}
|
||||
28
channelz/internal/protoconv/util.go
Normal file
28
channelz/internal/protoconv/util.go
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
*
|
||||
* 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 protoconv supports converting between the internal channelz
|
||||
// implementation and the protobuf representation of all the entities.
|
||||
package protoconv
|
||||
|
||||
func strFromPointer(s *string) string {
|
||||
if s == nil {
|
||||
return ""
|
||||
}
|
||||
return *s
|
||||
}
|
||||
102
channelz/service/service.go
Normal file
102
channelz/service/service.go
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
*
|
||||
* 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 service provides an implementation for channelz service server.
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
channelzgrpc "google.golang.org/grpc/channelz/grpc_channelz_v1"
|
||||
channelzpb "google.golang.org/grpc/channelz/grpc_channelz_v1"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/channelz/internal/protoconv"
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
)
|
||||
|
||||
func init() {
|
||||
channelz.TurnOn()
|
||||
}
|
||||
|
||||
// RegisterChannelzServiceToServer registers the channelz service to the given server.
|
||||
//
|
||||
// Note: it is preferred to use the admin API
|
||||
// (https://pkg.go.dev/google.golang.org/grpc/admin#Register) instead to
|
||||
// register Channelz and other administrative services.
|
||||
func RegisterChannelzServiceToServer(s grpc.ServiceRegistrar) {
|
||||
channelzgrpc.RegisterChannelzServer(s, newCZServer())
|
||||
}
|
||||
|
||||
func newCZServer() channelzgrpc.ChannelzServer {
|
||||
return &serverImpl{}
|
||||
}
|
||||
|
||||
type serverImpl struct {
|
||||
channelzgrpc.UnimplementedChannelzServer
|
||||
}
|
||||
|
||||
func (s *serverImpl) GetChannel(_ context.Context, req *channelzpb.GetChannelRequest) (*channelzpb.GetChannelResponse, error) {
|
||||
ch, err := protoconv.GetChannel(req.GetChannelId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &channelzpb.GetChannelResponse{Channel: ch}, nil
|
||||
}
|
||||
|
||||
func (s *serverImpl) GetTopChannels(_ context.Context, req *channelzpb.GetTopChannelsRequest) (*channelzpb.GetTopChannelsResponse, error) {
|
||||
resp := &channelzpb.GetTopChannelsResponse{}
|
||||
resp.Channel, resp.End = protoconv.GetTopChannels(req.GetStartChannelId(), int(req.GetMaxResults()))
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (s *serverImpl) GetServer(_ context.Context, req *channelzpb.GetServerRequest) (*channelzpb.GetServerResponse, error) {
|
||||
srv, err := protoconv.GetServer(req.GetServerId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &channelzpb.GetServerResponse{Server: srv}, nil
|
||||
}
|
||||
|
||||
func (s *serverImpl) GetServers(_ context.Context, req *channelzpb.GetServersRequest) (*channelzpb.GetServersResponse, error) {
|
||||
resp := &channelzpb.GetServersResponse{}
|
||||
resp.Server, resp.End = protoconv.GetServers(req.GetStartServerId(), int(req.GetMaxResults()))
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (s *serverImpl) GetSubchannel(_ context.Context, req *channelzpb.GetSubchannelRequest) (*channelzpb.GetSubchannelResponse, error) {
|
||||
subChan, err := protoconv.GetSubChannel(req.GetSubchannelId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &channelzpb.GetSubchannelResponse{Subchannel: subChan}, nil
|
||||
}
|
||||
|
||||
func (s *serverImpl) GetServerSockets(_ context.Context, req *channelzpb.GetServerSocketsRequest) (*channelzpb.GetServerSocketsResponse, error) {
|
||||
resp := &channelzpb.GetServerSocketsResponse{}
|
||||
resp.SocketRef, resp.End = protoconv.GetServerSockets(req.GetServerId(), req.GetStartSocketId(), int(req.GetMaxResults()))
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (s *serverImpl) GetSocket(_ context.Context, req *channelzpb.GetSocketRequest) (*channelzpb.GetSocketResponse, error) {
|
||||
socket, err := protoconv.GetSocket(req.GetSocketId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &channelzpb.GetSocketResponse{Socket: socket}, nil
|
||||
}
|
||||
98
channelz/service/service_sktopt_test.go
Normal file
98
channelz/service/service_sktopt_test.go
Normal file
@@ -0,0 +1,98 @@
|
||||
//go:build linux && (386 || amd64)
|
||||
// +build linux
|
||||
// +build 386 amd64
|
||||
|
||||
/*
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
// SocketOptions is only supported on linux system. The functions defined in
|
||||
// this file are to parse the socket option field and the test is specifically
|
||||
// to verify the behavior of socket option parsing.
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"golang.org/x/sys/unix"
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
"google.golang.org/grpc/internal/testutils"
|
||||
"google.golang.org/protobuf/testing/protocmp"
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
|
||||
channelzpb "google.golang.org/grpc/channelz/grpc_channelz_v1"
|
||||
)
|
||||
|
||||
func (s) TestGetSocketOptions(t *testing.T) {
|
||||
ss := &channelz.Socket{
|
||||
SocketOptions: &channelz.SocketOptionData{
|
||||
Linger: &unix.Linger{Onoff: 1, Linger: 2},
|
||||
RecvTimeout: &unix.Timeval{Sec: 10, Usec: 1},
|
||||
SendTimeout: &unix.Timeval{},
|
||||
TCPInfo: &unix.TCPInfo{State: 1},
|
||||
},
|
||||
}
|
||||
svr := newCZServer()
|
||||
czServer := channelz.RegisterServer("test svr")
|
||||
defer channelz.RemoveEntry(czServer.ID)
|
||||
id := channelz.RegisterSocket(&channelz.Socket{SocketType: channelz.SocketTypeNormal, RefName: "0", Parent: czServer, SocketOptions: ss.SocketOptions})
|
||||
defer channelz.RemoveEntry(id.ID)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
|
||||
defer cancel()
|
||||
resp, _ := svr.GetSocket(ctx, &channelzpb.GetSocketRequest{SocketId: id.ID})
|
||||
{
|
||||
got, want := resp.GetSocket().GetRef(), &channelzpb.SocketRef{SocketId: id.ID, Name: "0"}
|
||||
if diff := cmp.Diff(got, want, protocmp.Transform()); diff != "" {
|
||||
t.Fatal("resp.GetSocket() ref (-got +want): ", diff)
|
||||
}
|
||||
}
|
||||
{
|
||||
got := resp.GetSocket().GetData().GetOption()
|
||||
want := []*channelzpb.SocketOption{{
|
||||
Name: "SO_LINGER",
|
||||
Additional: testutils.MarshalAny(
|
||||
t,
|
||||
&channelzpb.SocketOptionLinger{Active: true, Duration: durationpb.New(2 * time.Second)},
|
||||
),
|
||||
}, {
|
||||
Name: "SO_RCVTIMEO",
|
||||
Additional: testutils.MarshalAny(
|
||||
t,
|
||||
&channelzpb.SocketOptionTimeout{Duration: durationpb.New(10*time.Second + time.Microsecond)},
|
||||
),
|
||||
}, {
|
||||
Name: "SO_SNDTIMEO",
|
||||
Additional: testutils.MarshalAny(
|
||||
t,
|
||||
&channelzpb.SocketOptionTimeout{Duration: durationpb.New(0)},
|
||||
),
|
||||
}, {
|
||||
Name: "TCP_INFO",
|
||||
Additional: testutils.MarshalAny(
|
||||
t,
|
||||
&channelzpb.SocketOptionTcpInfo{TcpiState: 1},
|
||||
),
|
||||
}}
|
||||
if diff := cmp.Diff(got, want, protocmp.Transform()); diff != "" {
|
||||
t.Fatal("resp.GetSocket() options (-got +want): ", diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
803
channelz/service/service_test.go
Normal file
803
channelz/service/service_test.go
Normal file
@@ -0,0 +1,803 @@
|
||||
/*
|
||||
*
|
||||
* 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 service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/internal/channelz"
|
||||
"google.golang.org/grpc/internal/grpctest"
|
||||
"google.golang.org/protobuf/encoding/prototext"
|
||||
"google.golang.org/protobuf/reflect/protodesc"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/testing/protocmp"
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
"google.golang.org/protobuf/types/dynamicpb"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
channelzpb "google.golang.org/grpc/channelz/grpc_channelz_v1"
|
||||
)
|
||||
|
||||
func init() {
|
||||
channelz.TurnOn()
|
||||
}
|
||||
|
||||
type s struct {
|
||||
grpctest.Tester
|
||||
}
|
||||
|
||||
func Test(t *testing.T) {
|
||||
grpctest.RunSubTests(t, s{})
|
||||
}
|
||||
|
||||
const defaultTestTimeout = 10 * time.Second
|
||||
|
||||
func channelProtoToStruct(c *channelzpb.Channel) (*channelz.ChannelMetrics, error) {
|
||||
cm := &channelz.ChannelMetrics{}
|
||||
pdata := c.GetData()
|
||||
var s connectivity.State
|
||||
switch pdata.GetState().GetState() {
|
||||
case channelzpb.ChannelConnectivityState_UNKNOWN:
|
||||
// TODO: what should we set here?
|
||||
case channelzpb.ChannelConnectivityState_IDLE:
|
||||
s = connectivity.Idle
|
||||
case channelzpb.ChannelConnectivityState_CONNECTING:
|
||||
s = connectivity.Connecting
|
||||
case channelzpb.ChannelConnectivityState_READY:
|
||||
s = connectivity.Ready
|
||||
case channelzpb.ChannelConnectivityState_TRANSIENT_FAILURE:
|
||||
s = connectivity.TransientFailure
|
||||
case channelzpb.ChannelConnectivityState_SHUTDOWN:
|
||||
s = connectivity.Shutdown
|
||||
}
|
||||
cm.State.Store(&s)
|
||||
tgt := pdata.GetTarget()
|
||||
cm.Target.Store(&tgt)
|
||||
cm.CallsStarted.Store(pdata.CallsStarted)
|
||||
cm.CallsSucceeded.Store(pdata.CallsSucceeded)
|
||||
cm.CallsFailed.Store(pdata.CallsFailed)
|
||||
if err := pdata.GetLastCallStartedTimestamp().CheckValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cm.LastCallStartedTimestamp.Store(int64(pdata.GetLastCallStartedTimestamp().AsTime().UnixNano()))
|
||||
return cm, nil
|
||||
}
|
||||
|
||||
func convertSocketRefSliceToMap(sktRefs []*channelzpb.SocketRef) map[int64]string {
|
||||
m := make(map[int64]string)
|
||||
for _, sr := range sktRefs {
|
||||
m[sr.SocketId] = sr.Name
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func (s) TestGetTopChannels(t *testing.T) {
|
||||
tcs := []*channelz.ChannelMetrics{
|
||||
channelz.NewChannelMetricForTesting(
|
||||
connectivity.Connecting,
|
||||
"test.channelz:1234",
|
||||
6,
|
||||
2,
|
||||
3,
|
||||
time.Now().UTC().UnixNano(),
|
||||
),
|
||||
channelz.NewChannelMetricForTesting(
|
||||
connectivity.Connecting,
|
||||
"test.channelz:1234",
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
time.Now().UTC().UnixNano(),
|
||||
),
|
||||
channelz.NewChannelMetricForTesting(
|
||||
connectivity.Shutdown,
|
||||
"test.channelz:8888",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
),
|
||||
}
|
||||
|
||||
for _, c := range tcs {
|
||||
cz := channelz.RegisterChannel(nil, "test channel")
|
||||
cz.ChannelMetrics.CopyFrom(c)
|
||||
defer channelz.RemoveEntry(cz.ID)
|
||||
}
|
||||
s := newCZServer()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
|
||||
defer cancel()
|
||||
resp, _ := s.GetTopChannels(ctx, &channelzpb.GetTopChannelsRequest{StartChannelId: 0})
|
||||
if !resp.GetEnd() {
|
||||
t.Fatalf("resp.GetEnd() want true, got %v", resp.GetEnd())
|
||||
}
|
||||
for i, c := range resp.GetChannel() {
|
||||
channel, err := channelProtoToStruct(c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if diff := cmp.Diff(tcs[i], channel, protocmp.Transform()); diff != "" {
|
||||
t.Fatalf("unexpected channel, diff (-want +got):\n%s", diff)
|
||||
}
|
||||
}
|
||||
for i := 0; i < 50; i++ {
|
||||
cz := channelz.RegisterChannel(nil, "")
|
||||
defer channelz.RemoveEntry(cz.ID)
|
||||
}
|
||||
resp, _ = s.GetTopChannels(ctx, &channelzpb.GetTopChannelsRequest{StartChannelId: 0})
|
||||
if resp.GetEnd() {
|
||||
t.Fatalf("resp.GetEnd() want false, got %v", resp.GetEnd())
|
||||
}
|
||||
}
|
||||
|
||||
func (s) TestGetServers(t *testing.T) {
|
||||
ss := []*channelz.ServerMetrics{
|
||||
channelz.NewServerMetricsForTesting(
|
||||
6,
|
||||
2,
|
||||
3,
|
||||
time.Now().UnixNano(),
|
||||
),
|
||||
channelz.NewServerMetricsForTesting(
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
time.Now().UnixNano(),
|
||||
),
|
||||
channelz.NewServerMetricsForTesting(
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
time.Now().UnixNano(),
|
||||
),
|
||||
}
|
||||
|
||||
firstID := int64(0)
|
||||
for i, s := range ss {
|
||||
svr := channelz.RegisterServer("")
|
||||
if i == 0 {
|
||||
firstID = svr.ID
|
||||
}
|
||||
svr.ServerMetrics.CopyFrom(s)
|
||||
defer channelz.RemoveEntry(svr.ID)
|
||||
}
|
||||
svr := newCZServer()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
|
||||
defer cancel()
|
||||
resp, _ := svr.GetServers(ctx, &channelzpb.GetServersRequest{StartServerId: 0})
|
||||
if !resp.GetEnd() {
|
||||
t.Fatalf("resp.GetEnd() want true, got %v", resp.GetEnd())
|
||||
}
|
||||
serversWant := []*channelzpb.Server{
|
||||
{
|
||||
Ref: &channelzpb.ServerRef{ServerId: firstID, Name: ""},
|
||||
Data: &channelzpb.ServerData{
|
||||
CallsStarted: 6,
|
||||
CallsSucceeded: 2,
|
||||
CallsFailed: 3,
|
||||
LastCallStartedTimestamp: timestamppb.New(time.Unix(0, ss[0].LastCallStartedTimestamp.Load())),
|
||||
},
|
||||
},
|
||||
{
|
||||
Ref: &channelzpb.ServerRef{ServerId: firstID + 1, Name: ""},
|
||||
Data: &channelzpb.ServerData{
|
||||
CallsStarted: 1,
|
||||
CallsSucceeded: 2,
|
||||
CallsFailed: 3,
|
||||
LastCallStartedTimestamp: timestamppb.New(time.Unix(0, ss[1].LastCallStartedTimestamp.Load())),
|
||||
},
|
||||
},
|
||||
{
|
||||
Ref: &channelzpb.ServerRef{ServerId: firstID + 2, Name: ""},
|
||||
Data: &channelzpb.ServerData{
|
||||
CallsStarted: 1,
|
||||
CallsSucceeded: 0,
|
||||
CallsFailed: 0,
|
||||
LastCallStartedTimestamp: timestamppb.New(time.Unix(0, ss[2].LastCallStartedTimestamp.Load())),
|
||||
},
|
||||
},
|
||||
}
|
||||
if diff := cmp.Diff(serversWant, resp.GetServer(), protocmp.Transform()); diff != "" {
|
||||
t.Fatalf("unexpected server, diff (-want +got):\n%s", diff)
|
||||
}
|
||||
for i := 0; i < 50; i++ {
|
||||
id := channelz.RegisterServer("").ID
|
||||
defer channelz.RemoveEntry(id)
|
||||
}
|
||||
resp, _ = svr.GetServers(ctx, &channelzpb.GetServersRequest{StartServerId: 0})
|
||||
if resp.GetEnd() {
|
||||
t.Fatalf("resp.GetEnd() want false, got %v", resp.GetEnd())
|
||||
}
|
||||
}
|
||||
|
||||
func (s) TestGetServerSockets(t *testing.T) {
|
||||
svrID := channelz.RegisterServer("")
|
||||
defer channelz.RemoveEntry(svrID.ID)
|
||||
refNames := []string{"listen socket 1", "normal socket 1", "normal socket 2"}
|
||||
ids := make([]int64, 3)
|
||||
ids[0] = channelz.RegisterSocket(&channelz.Socket{SocketType: channelz.SocketTypeListen, Parent: svrID, RefName: refNames[0]}).ID
|
||||
ids[1] = channelz.RegisterSocket(&channelz.Socket{SocketType: channelz.SocketTypeNormal, Parent: svrID, RefName: refNames[1]}).ID
|
||||
ids[2] = channelz.RegisterSocket(&channelz.Socket{SocketType: channelz.SocketTypeNormal, Parent: svrID, RefName: refNames[2]}).ID
|
||||
for _, id := range ids {
|
||||
defer channelz.RemoveEntry(id)
|
||||
}
|
||||
svr := newCZServer()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
|
||||
defer cancel()
|
||||
resp, _ := svr.GetServerSockets(ctx, &channelzpb.GetServerSocketsRequest{ServerId: svrID.ID, StartSocketId: 0})
|
||||
if !resp.GetEnd() {
|
||||
t.Fatalf("resp.GetEnd() want: true, got: %v", resp.GetEnd())
|
||||
}
|
||||
// GetServerSockets only return normal sockets.
|
||||
want := map[int64]string{
|
||||
ids[1]: refNames[1],
|
||||
ids[2]: refNames[2],
|
||||
}
|
||||
if got := convertSocketRefSliceToMap(resp.GetSocketRef()); !cmp.Equal(got, want) {
|
||||
t.Fatalf("GetServerSockets want: %#v, got: %#v (resp=%v)", want, got, prototext.Format(resp))
|
||||
}
|
||||
|
||||
for i := 0; i < 50; i++ {
|
||||
id := channelz.RegisterSocket(&channelz.Socket{SocketType: channelz.SocketTypeNormal, Parent: svrID})
|
||||
defer channelz.RemoveEntry(id.ID)
|
||||
}
|
||||
resp, _ = svr.GetServerSockets(ctx, &channelzpb.GetServerSocketsRequest{ServerId: svrID.ID, StartSocketId: 0})
|
||||
if resp.GetEnd() {
|
||||
t.Fatalf("resp.GetEnd() want false, got %v", resp.GetEnd())
|
||||
}
|
||||
}
|
||||
|
||||
// This test makes a GetServerSockets with a non-zero start ID, and expect only
|
||||
// sockets with ID >= the given start ID.
|
||||
func (s) TestGetServerSocketsNonZeroStartID(t *testing.T) {
|
||||
svrID := channelz.RegisterServer("test server")
|
||||
defer channelz.RemoveEntry(svrID.ID)
|
||||
refNames := []string{"listen socket 1", "normal socket 1", "normal socket 2"}
|
||||
ids := make([]int64, 3)
|
||||
ids[0] = channelz.RegisterSocket(&channelz.Socket{SocketType: channelz.SocketTypeListen, Parent: svrID, RefName: refNames[0]}).ID
|
||||
ids[1] = channelz.RegisterSocket(&channelz.Socket{SocketType: channelz.SocketTypeNormal, Parent: svrID, RefName: refNames[1]}).ID
|
||||
ids[2] = channelz.RegisterSocket(&channelz.Socket{SocketType: channelz.SocketTypeNormal, Parent: svrID, RefName: refNames[2]}).ID
|
||||
for _, id := range ids {
|
||||
defer channelz.RemoveEntry(id)
|
||||
}
|
||||
svr := newCZServer()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
|
||||
defer cancel()
|
||||
// Make GetServerSockets with startID = ids[1]+1, so socket-1 won't be
|
||||
// included in the response.
|
||||
resp, _ := svr.GetServerSockets(ctx, &channelzpb.GetServerSocketsRequest{ServerId: svrID.ID, StartSocketId: ids[1] + 1})
|
||||
if !resp.GetEnd() {
|
||||
t.Fatalf("resp.GetEnd() want: true, got: %v", resp.GetEnd())
|
||||
}
|
||||
// GetServerSockets only return normal socket-2, socket-1 should be
|
||||
// filtered by start ID.
|
||||
want := map[int64]string{
|
||||
ids[2]: refNames[2],
|
||||
}
|
||||
if !cmp.Equal(convertSocketRefSliceToMap(resp.GetSocketRef()), want) {
|
||||
t.Fatalf("GetServerSockets want: %#v, got: %#v", want, resp.GetSocketRef())
|
||||
}
|
||||
}
|
||||
|
||||
var logger = grpclog.Component("channelz")
|
||||
|
||||
func (s) TestGetChannel(t *testing.T) {
|
||||
refNames := []string{"top channel 1", "nested channel 1", "sub channel 2", "nested channel 3"}
|
||||
cids := make([]*channelz.Channel, 3)
|
||||
cids[0] = channelz.RegisterChannel(nil, refNames[0])
|
||||
channelz.AddTraceEvent(logger, cids[0], 0, &channelz.TraceEvent{
|
||||
Desc: "Channel Created",
|
||||
Severity: channelz.CtInfo,
|
||||
})
|
||||
|
||||
cids[1] = channelz.RegisterChannel(cids[0], refNames[1])
|
||||
channelz.AddTraceEvent(logger, cids[1], 0, &channelz.TraceEvent{
|
||||
Desc: "Channel Created",
|
||||
Severity: channelz.CtInfo,
|
||||
Parent: &channelz.TraceEvent{
|
||||
Desc: fmt.Sprintf("Nested Channel(id:%d) created", cids[1].ID),
|
||||
Severity: channelz.CtInfo,
|
||||
},
|
||||
})
|
||||
|
||||
subChan := channelz.RegisterSubChannel(cids[0], refNames[2])
|
||||
channelz.AddTraceEvent(logger, subChan, 0, &channelz.TraceEvent{
|
||||
Desc: "SubChannel Created",
|
||||
Severity: channelz.CtInfo,
|
||||
Parent: &channelz.TraceEvent{
|
||||
Desc: fmt.Sprintf("SubChannel(id:%d) created", subChan.ID),
|
||||
Severity: channelz.CtInfo,
|
||||
},
|
||||
})
|
||||
defer channelz.RemoveEntry(subChan.ID)
|
||||
|
||||
cids[2] = channelz.RegisterChannel(cids[1], refNames[3])
|
||||
channelz.AddTraceEvent(logger, cids[2], 0, &channelz.TraceEvent{
|
||||
Desc: "Channel Created",
|
||||
Severity: channelz.CtInfo,
|
||||
Parent: &channelz.TraceEvent{
|
||||
Desc: fmt.Sprintf("Nested Channel(id:%d) created", cids[2].ID),
|
||||
Severity: channelz.CtInfo,
|
||||
},
|
||||
})
|
||||
channelz.AddTraceEvent(logger, cids[0], 0, &channelz.TraceEvent{
|
||||
Desc: fmt.Sprintf("Channel Connectivity change to %v", connectivity.Ready),
|
||||
Severity: channelz.CtInfo,
|
||||
})
|
||||
channelz.AddTraceEvent(logger, cids[0], 0, &channelz.TraceEvent{
|
||||
Desc: "Resolver returns an empty address list",
|
||||
Severity: channelz.CtWarning,
|
||||
})
|
||||
|
||||
for _, id := range cids {
|
||||
defer channelz.RemoveEntry(id.ID)
|
||||
}
|
||||
|
||||
svr := newCZServer()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
|
||||
defer cancel()
|
||||
resp, _ := svr.GetChannel(ctx, &channelzpb.GetChannelRequest{ChannelId: cids[0].ID})
|
||||
metrics := resp.GetChannel()
|
||||
subChans := metrics.GetSubchannelRef()
|
||||
if len(subChans) != 1 || subChans[0].GetName() != refNames[2] || subChans[0].GetSubchannelId() != subChan.ID {
|
||||
t.Fatalf("metrics.GetSubChannelRef() want %#v, got %#v", []*channelzpb.SubchannelRef{{SubchannelId: subChan.ID, Name: refNames[2]}}, subChans)
|
||||
}
|
||||
nestedChans := metrics.GetChannelRef()
|
||||
if len(nestedChans) != 1 || nestedChans[0].GetName() != refNames[1] || nestedChans[0].GetChannelId() != cids[1].ID {
|
||||
t.Fatalf("metrics.GetChannelRef() want %#v, got %#v", []*channelzpb.ChannelRef{{ChannelId: cids[1].ID, Name: refNames[1]}}, nestedChans)
|
||||
}
|
||||
trace := metrics.GetData().GetTrace()
|
||||
want := []struct {
|
||||
desc string
|
||||
severity channelzpb.ChannelTraceEvent_Severity
|
||||
childID int64
|
||||
childRef string
|
||||
}{
|
||||
{desc: "Channel Created", severity: channelzpb.ChannelTraceEvent_CT_INFO},
|
||||
{desc: fmt.Sprintf("Nested Channel(id:%d) created", cids[1].ID), severity: channelzpb.ChannelTraceEvent_CT_INFO, childID: cids[1].ID, childRef: refNames[1]},
|
||||
{desc: fmt.Sprintf("SubChannel(id:%d) created", subChan.ID), severity: channelzpb.ChannelTraceEvent_CT_INFO, childID: subChan.ID, childRef: refNames[2]},
|
||||
{desc: fmt.Sprintf("Channel Connectivity change to %v", connectivity.Ready), severity: channelzpb.ChannelTraceEvent_CT_INFO},
|
||||
{desc: "Resolver returns an empty address list", severity: channelzpb.ChannelTraceEvent_CT_WARNING},
|
||||
}
|
||||
|
||||
for i, e := range trace.Events {
|
||||
if !strings.Contains(e.GetDescription(), want[i].desc) {
|
||||
t.Fatalf("trace: GetDescription want %#v, got %#v", want[i].desc, e.GetDescription())
|
||||
}
|
||||
if e.GetSeverity() != want[i].severity {
|
||||
t.Fatalf("trace: GetSeverity want %#v, got %#v", want[i].severity, e.GetSeverity())
|
||||
}
|
||||
if want[i].childID == 0 && (e.GetChannelRef() != nil || e.GetSubchannelRef() != nil) {
|
||||
t.Fatalf("trace: GetChannelRef() should return nil, as there is no reference")
|
||||
}
|
||||
if e.GetChannelRef().GetChannelId() != want[i].childID || e.GetChannelRef().GetName() != want[i].childRef {
|
||||
if e.GetSubchannelRef().GetSubchannelId() != want[i].childID || e.GetSubchannelRef().GetName() != want[i].childRef {
|
||||
t.Fatalf("trace: GetChannelRef/GetSubchannelRef want (child ID: %d, child name: %q), got %#v and %#v", want[i].childID, want[i].childRef, e.GetChannelRef(), e.GetSubchannelRef())
|
||||
}
|
||||
}
|
||||
}
|
||||
resp, _ = svr.GetChannel(ctx, &channelzpb.GetChannelRequest{ChannelId: cids[1].ID})
|
||||
metrics = resp.GetChannel()
|
||||
nestedChans = metrics.GetChannelRef()
|
||||
if len(nestedChans) != 1 || nestedChans[0].GetName() != refNames[3] || nestedChans[0].GetChannelId() != cids[2].ID {
|
||||
t.Fatalf("metrics.GetChannelRef() want %#v, got %#v", []*channelzpb.ChannelRef{{ChannelId: cids[2].ID, Name: refNames[3]}}, nestedChans)
|
||||
}
|
||||
}
|
||||
|
||||
func (s) TestGetSubChannel(t *testing.T) {
|
||||
var (
|
||||
subchanCreated = "SubChannel Created"
|
||||
subchanConnectivityChange = fmt.Sprintf("Subchannel Connectivity change to %v", connectivity.Ready)
|
||||
subChanPickNewAddress = fmt.Sprintf("Subchannel picks a new address %q to connect", "0.0.0.0")
|
||||
)
|
||||
|
||||
refNames := []string{"top channel 1", "sub channel 1", "socket 1", "socket 2"}
|
||||
chann := channelz.RegisterChannel(nil, refNames[0])
|
||||
defer channelz.RemoveEntry(chann.ID)
|
||||
channelz.AddTraceEvent(logger, chann, 0, &channelz.TraceEvent{
|
||||
Desc: "Channel Created",
|
||||
Severity: channelz.CtInfo,
|
||||
})
|
||||
subChan := channelz.RegisterSubChannel(chann, refNames[1])
|
||||
defer channelz.RemoveEntry(subChan.ID)
|
||||
channelz.AddTraceEvent(logger, subChan, 0, &channelz.TraceEvent{
|
||||
Desc: subchanCreated,
|
||||
Severity: channelz.CtInfo,
|
||||
Parent: &channelz.TraceEvent{
|
||||
Desc: fmt.Sprintf("Nested Channel(id:%d) created", chann.ID),
|
||||
Severity: channelz.CtInfo,
|
||||
},
|
||||
})
|
||||
skt1 := channelz.RegisterSocket(&channelz.Socket{SocketType: channelz.SocketTypeNormal, Parent: subChan, RefName: refNames[2]})
|
||||
defer channelz.RemoveEntry(skt1.ID)
|
||||
skt2 := channelz.RegisterSocket(&channelz.Socket{SocketType: channelz.SocketTypeNormal, Parent: subChan, RefName: refNames[3]})
|
||||
defer channelz.RemoveEntry(skt2.ID)
|
||||
channelz.AddTraceEvent(logger, subChan, 0, &channelz.TraceEvent{
|
||||
Desc: subchanConnectivityChange,
|
||||
Severity: channelz.CtInfo,
|
||||
})
|
||||
channelz.AddTraceEvent(logger, subChan, 0, &channelz.TraceEvent{
|
||||
Desc: subChanPickNewAddress,
|
||||
Severity: channelz.CtInfo,
|
||||
})
|
||||
svr := newCZServer()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
|
||||
defer cancel()
|
||||
resp, _ := svr.GetSubchannel(ctx, &channelzpb.GetSubchannelRequest{SubchannelId: subChan.ID})
|
||||
metrics := resp.GetSubchannel()
|
||||
want := map[int64]string{
|
||||
skt1.ID: refNames[2],
|
||||
skt2.ID: refNames[3],
|
||||
}
|
||||
if !cmp.Equal(convertSocketRefSliceToMap(metrics.GetSocketRef()), want) {
|
||||
t.Fatalf("metrics.GetSocketRef() want %#v: got: %#v", want, metrics.GetSocketRef())
|
||||
}
|
||||
|
||||
trace := metrics.GetData().GetTrace()
|
||||
wantTrace := []struct {
|
||||
desc string
|
||||
severity channelzpb.ChannelTraceEvent_Severity
|
||||
childID int64
|
||||
childRef string
|
||||
}{
|
||||
{desc: subchanCreated, severity: channelzpb.ChannelTraceEvent_CT_INFO},
|
||||
{desc: subchanConnectivityChange, severity: channelzpb.ChannelTraceEvent_CT_INFO},
|
||||
{desc: subChanPickNewAddress, severity: channelzpb.ChannelTraceEvent_CT_INFO},
|
||||
}
|
||||
for i, e := range trace.Events {
|
||||
if e.GetDescription() != wantTrace[i].desc {
|
||||
t.Fatalf("trace: GetDescription want %#v, got %#v", wantTrace[i].desc, e.GetDescription())
|
||||
}
|
||||
if e.GetSeverity() != wantTrace[i].severity {
|
||||
t.Fatalf("trace: GetSeverity want %#v, got %#v", wantTrace[i].severity, e.GetSeverity())
|
||||
}
|
||||
if wantTrace[i].childID == 0 && (e.GetChannelRef() != nil || e.GetSubchannelRef() != nil) {
|
||||
t.Fatalf("trace: GetChannelRef() should return nil, as there is no reference")
|
||||
}
|
||||
if e.GetChannelRef().GetChannelId() != wantTrace[i].childID || e.GetChannelRef().GetName() != wantTrace[i].childRef {
|
||||
if e.GetSubchannelRef().GetSubchannelId() != wantTrace[i].childID || e.GetSubchannelRef().GetName() != wantTrace[i].childRef {
|
||||
t.Fatalf("trace: GetChannelRef/GetSubchannelRef want (child ID: %d, child name: %q), got %#v and %#v", wantTrace[i].childID, wantTrace[i].childRef, e.GetChannelRef(), e.GetSubchannelRef())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type czSocket struct {
|
||||
streamsStarted int64
|
||||
streamsSucceeded int64
|
||||
streamsFailed int64
|
||||
messagesSent int64
|
||||
messagesReceived int64
|
||||
keepAlivesSent int64
|
||||
lastLocalStreamCreatedTimestamp time.Time
|
||||
lastRemoteStreamCreatedTimestamp time.Time
|
||||
lastMessageSentTimestamp time.Time
|
||||
lastMessageReceivedTimestamp time.Time
|
||||
localFlowControlWindow int64
|
||||
remoteFlowControlWindow int64
|
||||
|
||||
localAddr net.Addr
|
||||
remoteAddr net.Addr
|
||||
remoteName string
|
||||
socketOptions *channelz.SocketOptionData
|
||||
security credentials.ChannelzSecurityValue
|
||||
}
|
||||
|
||||
func newSocket(cs czSocket) *channelz.Socket {
|
||||
if cs.lastLocalStreamCreatedTimestamp.IsZero() {
|
||||
cs.lastLocalStreamCreatedTimestamp = time.Unix(0, 0)
|
||||
}
|
||||
if cs.lastRemoteStreamCreatedTimestamp.IsZero() {
|
||||
cs.lastRemoteStreamCreatedTimestamp = time.Unix(0, 0)
|
||||
}
|
||||
if cs.lastMessageSentTimestamp.IsZero() {
|
||||
cs.lastMessageSentTimestamp = time.Unix(0, 0)
|
||||
}
|
||||
if cs.lastMessageReceivedTimestamp.IsZero() {
|
||||
cs.lastMessageReceivedTimestamp = time.Unix(0, 0)
|
||||
}
|
||||
|
||||
s := &channelz.Socket{
|
||||
LocalAddr: cs.localAddr,
|
||||
RemoteAddr: cs.remoteAddr,
|
||||
RemoteName: cs.remoteName,
|
||||
SocketOptions: cs.socketOptions,
|
||||
Security: cs.security,
|
||||
}
|
||||
s.SocketMetrics.StreamsStarted.Store(cs.streamsStarted)
|
||||
s.SocketMetrics.StreamsSucceeded.Store(cs.streamsSucceeded)
|
||||
s.SocketMetrics.StreamsFailed.Store(cs.streamsFailed)
|
||||
s.SocketMetrics.MessagesSent.Store(cs.messagesSent)
|
||||
s.SocketMetrics.MessagesReceived.Store(cs.messagesReceived)
|
||||
s.SocketMetrics.KeepAlivesSent.Store(cs.keepAlivesSent)
|
||||
s.SocketMetrics.LastLocalStreamCreatedTimestamp.Store(cs.lastLocalStreamCreatedTimestamp.UnixNano())
|
||||
s.SocketMetrics.LastRemoteStreamCreatedTimestamp.Store(cs.lastRemoteStreamCreatedTimestamp.UnixNano())
|
||||
s.SocketMetrics.LastMessageSentTimestamp.Store(cs.lastMessageSentTimestamp.UnixNano())
|
||||
s.SocketMetrics.LastMessageReceivedTimestamp.Store(cs.lastMessageReceivedTimestamp.UnixNano())
|
||||
s.EphemeralMetrics = func() *channelz.EphemeralSocketMetrics {
|
||||
return &channelz.EphemeralSocketMetrics{
|
||||
LocalFlowControlWindow: cs.localFlowControlWindow,
|
||||
RemoteFlowControlWindow: cs.remoteFlowControlWindow,
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
type OtherChannelzSecurityValue struct {
|
||||
LocalCertificate []byte `protobuf:"bytes,1,opt,name=local_certificate,json=localCertificate,proto3" json:"local_certificate,omitempty"`
|
||||
RemoteCertificate []byte `protobuf:"bytes,2,opt,name=remote_certificate,json=remoteCertificate,proto3" json:"remote_certificate,omitempty"`
|
||||
}
|
||||
|
||||
func (x *OtherChannelzSecurityValue) Reset() {
|
||||
*x = OtherChannelzSecurityValue{}
|
||||
}
|
||||
|
||||
func (x *OtherChannelzSecurityValue) String() string {
|
||||
return prototext.Format(x)
|
||||
}
|
||||
|
||||
func (*OtherChannelzSecurityValue) ProtoMessage() {}
|
||||
|
||||
func (x OtherChannelzSecurityValue) ProtoReflect() protoreflect.Message {
|
||||
const s = `
|
||||
name: "service_test.proto"
|
||||
syntax: "proto3"
|
||||
package: "grpc.credentials",
|
||||
message_type: [{
|
||||
name: "OtherChannelzSecurityValue"
|
||||
field: [
|
||||
{name:"local_certificate" number:1 type:TYPE_BYTES},
|
||||
{name:"remote_certificate" number:2 type:TYPE_BYTES}
|
||||
]
|
||||
}]
|
||||
`
|
||||
pb := new(descriptorpb.FileDescriptorProto)
|
||||
if err := prototext.Unmarshal([]byte(s), pb); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fd, err := protodesc.NewFile(pb, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
md := fd.Messages().Get(0)
|
||||
mt := dynamicpb.NewMessageType(md)
|
||||
return mt.New()
|
||||
}
|
||||
|
||||
func (s) TestGetSocket(t *testing.T) {
|
||||
ss := []*channelz.Socket{newSocket(czSocket{
|
||||
streamsStarted: 10,
|
||||
streamsSucceeded: 2,
|
||||
streamsFailed: 3,
|
||||
messagesSent: 20,
|
||||
messagesReceived: 10,
|
||||
keepAlivesSent: 2,
|
||||
lastLocalStreamCreatedTimestamp: time.Unix(0, 0),
|
||||
lastRemoteStreamCreatedTimestamp: time.Unix(1, 0),
|
||||
lastMessageSentTimestamp: time.Unix(2, 0),
|
||||
lastMessageReceivedTimestamp: time.Unix(3, 0),
|
||||
localFlowControlWindow: 65536,
|
||||
remoteFlowControlWindow: 1024,
|
||||
localAddr: &net.TCPAddr{IP: netip.MustParseAddr("1.0.0.1").AsSlice(), Port: 10001},
|
||||
remoteAddr: &net.TCPAddr{IP: netip.MustParseAddr("12.0.0.1").AsSlice(), Port: 10002},
|
||||
remoteName: "remote.remote",
|
||||
}), newSocket(czSocket{
|
||||
streamsStarted: 10,
|
||||
streamsSucceeded: 2,
|
||||
streamsFailed: 3,
|
||||
messagesSent: 20,
|
||||
messagesReceived: 10,
|
||||
keepAlivesSent: 2,
|
||||
lastLocalStreamCreatedTimestamp: time.Unix(0, 0),
|
||||
lastRemoteStreamCreatedTimestamp: time.Unix(5, 0),
|
||||
lastMessageSentTimestamp: time.Unix(6, 0),
|
||||
lastMessageReceivedTimestamp: time.Unix(7, 0),
|
||||
localFlowControlWindow: 65536,
|
||||
remoteFlowControlWindow: 1024,
|
||||
localAddr: &net.UnixAddr{Name: "file.path", Net: "unix"},
|
||||
remoteAddr: &net.UnixAddr{Name: "another.path", Net: "unix"},
|
||||
remoteName: "remote.remote",
|
||||
}), newSocket(czSocket{
|
||||
streamsStarted: 5,
|
||||
streamsSucceeded: 2,
|
||||
streamsFailed: 3,
|
||||
messagesSent: 20,
|
||||
messagesReceived: 10,
|
||||
keepAlivesSent: 2,
|
||||
lastLocalStreamCreatedTimestamp: time.Unix(10, 10),
|
||||
lastRemoteStreamCreatedTimestamp: time.Unix(0, 0),
|
||||
lastMessageSentTimestamp: time.Unix(0, 0),
|
||||
lastMessageReceivedTimestamp: time.Unix(0, 0),
|
||||
localFlowControlWindow: 65536,
|
||||
remoteFlowControlWindow: 10240,
|
||||
localAddr: &net.IPAddr{IP: netip.MustParseAddr("1.0.0.1").AsSlice()},
|
||||
remoteAddr: &net.IPAddr{IP: netip.MustParseAddr("9.0.0.1").AsSlice()},
|
||||
remoteName: "",
|
||||
}), newSocket(czSocket{
|
||||
localAddr: &net.TCPAddr{IP: netip.MustParseAddr("127.0.0.1").AsSlice(), Port: 10001},
|
||||
}), newSocket(czSocket{
|
||||
security: &credentials.TLSChannelzSecurityValue{
|
||||
StandardName: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
RemoteCertificate: []byte{48, 130, 2, 156, 48, 130, 2, 5, 160},
|
||||
},
|
||||
}), newSocket(czSocket{
|
||||
security: &credentials.OtherChannelzSecurityValue{
|
||||
Name: "XXXX",
|
||||
},
|
||||
}), newSocket(czSocket{
|
||||
security: &credentials.OtherChannelzSecurityValue{
|
||||
Name: "YYYY",
|
||||
Value: OtherChannelzSecurityValue{
|
||||
LocalCertificate: []byte{1, 2, 3},
|
||||
RemoteCertificate: []byte{4, 5, 6},
|
||||
},
|
||||
},
|
||||
}),
|
||||
}
|
||||
otherSecVal, err := anypb.New(ss[6].Security.(*credentials.OtherChannelzSecurityValue).Value)
|
||||
if err != nil {
|
||||
t.Fatal("Error marshalling proto:", err)
|
||||
}
|
||||
|
||||
svr := newCZServer()
|
||||
skts := make([]*channelz.Socket, len(ss))
|
||||
svrID := channelz.RegisterServer("")
|
||||
defer channelz.RemoveEntry(svrID.ID)
|
||||
for i, s := range ss {
|
||||
s.Parent = svrID
|
||||
s.RefName = strconv.Itoa(i)
|
||||
skts[i] = channelz.RegisterSocket(s)
|
||||
defer channelz.RemoveEntry(skts[i].ID)
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
|
||||
defer cancel()
|
||||
|
||||
emptyData := `data: {
|
||||
last_local_stream_created_timestamp: {seconds: 0 nanos: 0}
|
||||
last_remote_stream_created_timestamp: {seconds: 0 nanos: 0}
|
||||
last_message_sent_timestamp: {seconds: 0 nanos: 0}
|
||||
last_message_received_timestamp: {seconds: 0 nanos: 0}
|
||||
local_flow_control_window: { value: 0 }
|
||||
remote_flow_control_window: { value: 0 }
|
||||
}`
|
||||
want := []string{`
|
||||
ref: {socket_id: ` + fmt.Sprint(skts[0].ID) + ` name: "0" }
|
||||
data: {
|
||||
streams_started: 10
|
||||
streams_succeeded: 2
|
||||
streams_failed: 3
|
||||
messages_sent: 20
|
||||
messages_received: 10
|
||||
keep_alives_sent: 2
|
||||
last_local_stream_created_timestamp: {seconds: 0 nanos: 0}
|
||||
last_remote_stream_created_timestamp: {seconds: 1 nanos: 0}
|
||||
last_message_sent_timestamp: {seconds: 2 nanos: 0}
|
||||
last_message_received_timestamp: {seconds: 3 nanos: 0}
|
||||
local_flow_control_window: { value: 65536 }
|
||||
remote_flow_control_window: { value: 1024 }
|
||||
}
|
||||
local: { tcpip_address: { ip_address: "` + addr(skts[0].LocalAddr) + `" port: 10001 } }
|
||||
remote: { tcpip_address: { ip_address: "` + addr(skts[0].RemoteAddr) + `" port: 10002 } }
|
||||
remote_name: "remote.remote"`,
|
||||
`
|
||||
ref: {socket_id: ` + fmt.Sprint(skts[1].ID) + ` name: "1" }
|
||||
data: {
|
||||
streams_started: 10
|
||||
streams_succeeded: 2
|
||||
streams_failed: 3
|
||||
messages_sent: 20
|
||||
messages_received: 10
|
||||
keep_alives_sent: 2
|
||||
last_local_stream_created_timestamp: {seconds: 0 nanos: 0}
|
||||
last_remote_stream_created_timestamp: {seconds: 5 nanos: 0}
|
||||
last_message_sent_timestamp: {seconds: 6 nanos: 0}
|
||||
last_message_received_timestamp: {seconds: 7 nanos: 0}
|
||||
local_flow_control_window: { value: 65536 }
|
||||
remote_flow_control_window: { value: 1024 }
|
||||
}
|
||||
local: { uds_address { filename: "file.path" } }
|
||||
remote: { uds_address { filename: "another.path" } }
|
||||
remote_name: "remote.remote"`,
|
||||
`
|
||||
ref: {socket_id: ` + fmt.Sprint(skts[2].ID) + ` name: "2" }
|
||||
data: {
|
||||
streams_started: 5
|
||||
streams_succeeded: 2
|
||||
streams_failed: 3
|
||||
messages_sent: 20
|
||||
messages_received: 10
|
||||
keep_alives_sent: 2
|
||||
last_local_stream_created_timestamp: {seconds: 10 nanos: 10}
|
||||
last_remote_stream_created_timestamp: {seconds: 0 nanos: 0}
|
||||
last_message_sent_timestamp: {seconds: 0 nanos: 0}
|
||||
last_message_received_timestamp: {seconds: 0 nanos: 0}
|
||||
local_flow_control_window: { value: 65536 }
|
||||
remote_flow_control_window: { value: 10240 }
|
||||
}
|
||||
local: { tcpip_address: { ip_address: "` + addr(skts[2].LocalAddr) + `" } }
|
||||
remote: { tcpip_address: { ip_address: "` + addr(skts[2].RemoteAddr) + `" } }
|
||||
remote_name: ""`,
|
||||
`
|
||||
ref: {socket_id: ` + fmt.Sprint(skts[3].ID) + ` name: "3" }
|
||||
local: { tcpip_address: { ip_address: "` + addr(skts[3].LocalAddr) + `" port: 10001 } }
|
||||
` + emptyData,
|
||||
`
|
||||
ref: {socket_id: ` + fmt.Sprint(skts[4].ID) + ` name: "4" }
|
||||
security: { tls: {
|
||||
standard_name: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
|
||||
remote_certificate: "\x30\x82\x02\x9c\x30\x82\x02\x05\xa0"
|
||||
} }
|
||||
` + emptyData,
|
||||
`
|
||||
ref: {socket_id: ` + fmt.Sprint(skts[5].ID) + ` name: "5" }
|
||||
security: { other: { name: "XXXX" } }
|
||||
` + emptyData,
|
||||
`
|
||||
ref: {socket_id: ` + fmt.Sprint(skts[6].ID) + ` name: "6" }
|
||||
security: { other: {
|
||||
name: "YYYY"
|
||||
value: {
|
||||
type_url: "type.googleapis.com/grpc.credentials.OtherChannelzSecurityValue"
|
||||
value: "` + escape(otherSecVal.Value) + `"
|
||||
}
|
||||
} }
|
||||
` + emptyData,
|
||||
}
|
||||
|
||||
for i := range ss {
|
||||
resp, _ := svr.GetSocket(ctx, &channelzpb.GetSocketRequest{SocketId: skts[i].ID})
|
||||
w := &channelzpb.Socket{}
|
||||
if err := prototext.Unmarshal([]byte(want[i]), w); err != nil {
|
||||
t.Fatalf("Error unmarshalling %q: %v", want[i], err)
|
||||
}
|
||||
if diff := cmp.Diff(resp.GetSocket(), w, protocmp.Transform()); diff != "" {
|
||||
t.Fatalf("Socket %v did not match expected. -got +want: %v", i, diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func escape(bs []byte) string {
|
||||
ret := ""
|
||||
for _, b := range bs {
|
||||
ret += fmt.Sprintf("\\x%02x", b)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func addr(a net.Addr) string {
|
||||
switch a := a.(type) {
|
||||
case *net.TCPAddr:
|
||||
return escape([]byte(a.IP))
|
||||
case *net.IPAddr:
|
||||
return escape([]byte(a.IP))
|
||||
}
|
||||
return ""
|
||||
}
|
||||
Reference in New Issue
Block a user