mirror of https://github.com/grpc/grpc-node.git
Merge pull request #1926 from grpc/master
Merge master into 1.4.x (i.e. backport channelz to 1.4.x)
This commit is contained in:
commit
c4fc1dbe8a
|
@ -4,7 +4,7 @@ This guide is for troubleshooting the `grpc-js` library for Node.js
|
|||
|
||||
## Enabling extra logging and tracing
|
||||
|
||||
Extra logging can be very useful for diagnosing problems. `grpc-js` supporst
|
||||
Extra logging can be very useful for diagnosing problems. `grpc-js` supports
|
||||
the `GRPC_VERBOSITY` and `GRPC_TRACE` environment variables that can be used to increase the amount of information
|
||||
that gets printed to stderr.
|
||||
|
||||
|
|
|
@ -185,14 +185,7 @@ export class EdsLoadBalancer implements LoadBalancer {
|
|||
private concurrentRequests: number = 0;
|
||||
|
||||
constructor(private readonly channelControlHelper: ChannelControlHelper) {
|
||||
this.childBalancer = new ChildLoadBalancerHandler({
|
||||
createSubchannel: (subchannelAddress, subchannelArgs) =>
|
||||
this.channelControlHelper.createSubchannel(
|
||||
subchannelAddress,
|
||||
subchannelArgs
|
||||
),
|
||||
requestReresolution: () =>
|
||||
this.channelControlHelper.requestReresolution(),
|
||||
this.childBalancer = new ChildLoadBalancerHandler(experimental.createChildChannelControlHelper(this.channelControlHelper, {
|
||||
updateState: (connectivityState, originalPicker) => {
|
||||
if (this.latestEdsUpdate === null) {
|
||||
return;
|
||||
|
@ -243,7 +236,7 @@ export class EdsLoadBalancer implements LoadBalancer {
|
|||
};
|
||||
this.channelControlHelper.updateState(connectivityState, edsPicker);
|
||||
},
|
||||
});
|
||||
}));
|
||||
this.watcher = {
|
||||
onValidUpdate: (update) => {
|
||||
trace('Received EDS update for ' + this.edsServiceName + ': ' + JSON.stringify(update, undefined, 2));
|
||||
|
|
|
@ -174,20 +174,14 @@ export class LrsLoadBalancer implements LoadBalancer {
|
|||
private localityStatsReporter: XdsClusterLocalityStats | null = null;
|
||||
|
||||
constructor(private channelControlHelper: ChannelControlHelper) {
|
||||
this.childBalancer = new ChildLoadBalancerHandler({
|
||||
createSubchannel: (subchannelAddress, subchannelArgs) =>
|
||||
channelControlHelper.createSubchannel(
|
||||
subchannelAddress,
|
||||
subchannelArgs
|
||||
),
|
||||
requestReresolution: () => channelControlHelper.requestReresolution(),
|
||||
this.childBalancer = new ChildLoadBalancerHandler(experimental.createChildChannelControlHelper(channelControlHelper, {
|
||||
updateState: (connectivityState: ConnectivityState, picker: Picker) => {
|
||||
if (this.localityStatsReporter !== null) {
|
||||
picker = new LoadReportingPicker(picker, this.localityStatsReporter);
|
||||
}
|
||||
channelControlHelper.updateState(connectivityState, picker);
|
||||
},
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
updateAddressList(
|
||||
|
|
|
@ -139,23 +139,11 @@ export class PriorityLoadBalancer implements LoadBalancer {
|
|||
private failoverTimer: NodeJS.Timer | null = null;
|
||||
private deactivationTimer: NodeJS.Timer | null = null;
|
||||
constructor(private parent: PriorityLoadBalancer, private name: string) {
|
||||
this.childBalancer = new ChildLoadBalancerHandler({
|
||||
createSubchannel: (
|
||||
subchannelAddress: SubchannelAddress,
|
||||
subchannelArgs: ChannelOptions
|
||||
) => {
|
||||
return this.parent.channelControlHelper.createSubchannel(
|
||||
subchannelAddress,
|
||||
subchannelArgs
|
||||
);
|
||||
},
|
||||
this.childBalancer = new ChildLoadBalancerHandler(experimental.createChildChannelControlHelper(this.parent.channelControlHelper, {
|
||||
updateState: (connectivityState: ConnectivityState, picker: Picker) => {
|
||||
this.updateState(connectivityState, picker);
|
||||
},
|
||||
requestReresolution: () => {
|
||||
this.parent.channelControlHelper.requestReresolution();
|
||||
},
|
||||
});
|
||||
}));
|
||||
this.picker = new QueuePicker(this.childBalancer);
|
||||
}
|
||||
|
||||
|
|
|
@ -168,17 +168,11 @@ export class WeightedTargetLoadBalancer implements LoadBalancer {
|
|||
private weight: number = 0;
|
||||
|
||||
constructor(private parent: WeightedTargetLoadBalancer, private name: string) {
|
||||
this.childBalancer = new ChildLoadBalancerHandler({
|
||||
createSubchannel: (subchannelAddress, subchannelOptions) => {
|
||||
return this.parent.channelControlHelper.createSubchannel(subchannelAddress, subchannelOptions);
|
||||
},
|
||||
updateState: (connectivityState, picker) => {
|
||||
this.childBalancer = new ChildLoadBalancerHandler(experimental.createChildChannelControlHelper(this.parent.channelControlHelper, {
|
||||
updateState: (connectivityState: ConnectivityState, picker: Picker) => {
|
||||
this.updateState(connectivityState, picker);
|
||||
},
|
||||
requestReresolution: () => {
|
||||
this.parent.channelControlHelper.requestReresolution();
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
this.picker = new QueuePicker(this.childBalancer);
|
||||
}
|
||||
|
|
|
@ -131,17 +131,11 @@ class XdsClusterManager implements LoadBalancer {
|
|||
private childBalancer: ChildLoadBalancerHandler;
|
||||
|
||||
constructor(private parent: XdsClusterManager, private name: string) {
|
||||
this.childBalancer = new ChildLoadBalancerHandler({
|
||||
createSubchannel: (subchannelAddress, subchannelOptions) => {
|
||||
return this.parent.channelControlHelper.createSubchannel(subchannelAddress, subchannelOptions);
|
||||
},
|
||||
updateState: (connectivityState, picker) => {
|
||||
this.childBalancer = new ChildLoadBalancerHandler(experimental.createChildChannelControlHelper(this.parent.channelControlHelper, {
|
||||
updateState: (connectivityState: ConnectivityState, picker: Picker) => {
|
||||
this.updateState(connectivityState, picker);
|
||||
},
|
||||
requestReresolution: () => {
|
||||
this.parent.channelControlHelper.requestReresolution();
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
this.picker = new QueuePicker(this.childBalancer);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
"types": "build/src/index.d.ts",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@grpc/proto-loader": "^0.5.5",
|
||||
"@types/gulp": "^4.0.6",
|
||||
"@types/gulp-mocha": "0.0.32",
|
||||
"@types/lodash": "^4.14.108",
|
||||
|
@ -54,9 +53,11 @@
|
|||
"check": "gts check src/**/*.ts",
|
||||
"fix": "gts fix src/*.ts",
|
||||
"pretest": "npm run compile",
|
||||
"posttest": "npm run check && madge -c ./build/src"
|
||||
"posttest": "npm run check && madge -c ./build/src",
|
||||
"generate-types": "proto-loader-gen-types --keepCase --longs String --enums String --defaults --oneofs --includeComments --includeDirs proto/ -O src/generated/ --grpcLib ../index channelz.proto"
|
||||
},
|
||||
"dependencies": {
|
||||
"@grpc/proto-loader": "^0.6.4",
|
||||
"@types/node": ">=12.12.47"
|
||||
},
|
||||
"files": [
|
||||
|
|
|
@ -0,0 +1,564 @@
|
|||
// 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
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package grpc.channelz.v1;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/duration.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "google/protobuf/wrappers.proto";
|
||||
|
||||
option go_package = "google.golang.org/grpc/channelz/grpc_channelz_v1";
|
||||
option java_multiple_files = true;
|
||||
option java_package = "io.grpc.channelz.v1";
|
||||
option java_outer_classname = "ChannelzProto";
|
||||
|
||||
// Channel is a logical grouping of channels, subchannels, and sockets.
|
||||
message Channel {
|
||||
// The identifier for this channel. This should bet set.
|
||||
ChannelRef ref = 1;
|
||||
// Data specific to this channel.
|
||||
ChannelData data = 2;
|
||||
// At most one of 'channel_ref+subchannel_ref' and 'socket' is set.
|
||||
|
||||
// There are no ordering guarantees on the order of channel refs.
|
||||
// There may not be cycles in the ref graph.
|
||||
// A channel ref may be present in more than one channel or subchannel.
|
||||
repeated ChannelRef channel_ref = 3;
|
||||
|
||||
// At most one of 'channel_ref+subchannel_ref' and 'socket' is set.
|
||||
// There are no ordering guarantees on the order of subchannel refs.
|
||||
// There may not be cycles in the ref graph.
|
||||
// A sub channel ref may be present in more than one channel or subchannel.
|
||||
repeated SubchannelRef subchannel_ref = 4;
|
||||
|
||||
// There are no ordering guarantees on the order of sockets.
|
||||
repeated SocketRef socket_ref = 5;
|
||||
}
|
||||
|
||||
// Subchannel is a logical grouping of channels, subchannels, and sockets.
|
||||
// A subchannel is load balanced over by it's ancestor
|
||||
message Subchannel {
|
||||
// The identifier for this channel.
|
||||
SubchannelRef ref = 1;
|
||||
// Data specific to this channel.
|
||||
ChannelData data = 2;
|
||||
// At most one of 'channel_ref+subchannel_ref' and 'socket' is set.
|
||||
|
||||
// There are no ordering guarantees on the order of channel refs.
|
||||
// There may not be cycles in the ref graph.
|
||||
// A channel ref may be present in more than one channel or subchannel.
|
||||
repeated ChannelRef channel_ref = 3;
|
||||
|
||||
// At most one of 'channel_ref+subchannel_ref' and 'socket' is set.
|
||||
// There are no ordering guarantees on the order of subchannel refs.
|
||||
// There may not be cycles in the ref graph.
|
||||
// A sub channel ref may be present in more than one channel or subchannel.
|
||||
repeated SubchannelRef subchannel_ref = 4;
|
||||
|
||||
// There are no ordering guarantees on the order of sockets.
|
||||
repeated SocketRef socket_ref = 5;
|
||||
}
|
||||
|
||||
// These come from the specified states in this document:
|
||||
// https://github.com/grpc/grpc/blob/master/doc/connectivity-semantics-and-api.md
|
||||
message ChannelConnectivityState {
|
||||
enum State {
|
||||
UNKNOWN = 0;
|
||||
IDLE = 1;
|
||||
CONNECTING = 2;
|
||||
READY = 3;
|
||||
TRANSIENT_FAILURE = 4;
|
||||
SHUTDOWN = 5;
|
||||
}
|
||||
State state = 1;
|
||||
}
|
||||
|
||||
// Channel data is data related to a specific Channel or Subchannel.
|
||||
message ChannelData {
|
||||
// The connectivity state of the channel or subchannel. Implementations
|
||||
// should always set this.
|
||||
ChannelConnectivityState state = 1;
|
||||
|
||||
// The target this channel originally tried to connect to. May be absent
|
||||
string target = 2;
|
||||
|
||||
// A trace of recent events on the channel. May be absent.
|
||||
ChannelTrace trace = 3;
|
||||
|
||||
// The number of calls started on the channel
|
||||
int64 calls_started = 4;
|
||||
// The number of calls that have completed with an OK status
|
||||
int64 calls_succeeded = 5;
|
||||
// The number of calls that have completed with a non-OK status
|
||||
int64 calls_failed = 6;
|
||||
|
||||
// The last time a call was started on the channel.
|
||||
google.protobuf.Timestamp last_call_started_timestamp = 7;
|
||||
}
|
||||
|
||||
// A trace event is an interesting thing that happened to a channel or
|
||||
// subchannel, such as creation, address resolution, subchannel creation, etc.
|
||||
message ChannelTraceEvent {
|
||||
// High level description of the event.
|
||||
string description = 1;
|
||||
// The supported severity levels of trace events.
|
||||
enum Severity {
|
||||
CT_UNKNOWN = 0;
|
||||
CT_INFO = 1;
|
||||
CT_WARNING = 2;
|
||||
CT_ERROR = 3;
|
||||
}
|
||||
// the severity of the trace event
|
||||
Severity severity = 2;
|
||||
// When this event occurred.
|
||||
google.protobuf.Timestamp timestamp = 3;
|
||||
// ref of referenced channel or subchannel.
|
||||
// Optional, only present if this event refers to a child object. For example,
|
||||
// this field would be filled if this trace event was for a subchannel being
|
||||
// created.
|
||||
oneof child_ref {
|
||||
ChannelRef channel_ref = 4;
|
||||
SubchannelRef subchannel_ref = 5;
|
||||
}
|
||||
}
|
||||
|
||||
// ChannelTrace represents the recent events that have occurred on the channel.
|
||||
message ChannelTrace {
|
||||
// Number of events ever logged in this tracing object. This can differ from
|
||||
// events.size() because events can be overwritten or garbage collected by
|
||||
// implementations.
|
||||
int64 num_events_logged = 1;
|
||||
// Time that this channel was created.
|
||||
google.protobuf.Timestamp creation_timestamp = 2;
|
||||
// List of events that have occurred on this channel.
|
||||
repeated ChannelTraceEvent events = 3;
|
||||
}
|
||||
|
||||
// ChannelRef is a reference to a Channel.
|
||||
message ChannelRef {
|
||||
// The globally unique id for this channel. Must be a positive number.
|
||||
int64 channel_id = 1;
|
||||
// An optional name associated with the channel.
|
||||
string name = 2;
|
||||
// Intentionally don't use field numbers from other refs.
|
||||
reserved 3, 4, 5, 6, 7, 8;
|
||||
}
|
||||
|
||||
// SubchannelRef is a reference to a Subchannel.
|
||||
message SubchannelRef {
|
||||
// The globally unique id for this subchannel. Must be a positive number.
|
||||
int64 subchannel_id = 7;
|
||||
// An optional name associated with the subchannel.
|
||||
string name = 8;
|
||||
// Intentionally don't use field numbers from other refs.
|
||||
reserved 1, 2, 3, 4, 5, 6;
|
||||
}
|
||||
|
||||
// SocketRef is a reference to a Socket.
|
||||
message SocketRef {
|
||||
// The globally unique id for this socket. Must be a positive number.
|
||||
int64 socket_id = 3;
|
||||
// An optional name associated with the socket.
|
||||
string name = 4;
|
||||
// Intentionally don't use field numbers from other refs.
|
||||
reserved 1, 2, 5, 6, 7, 8;
|
||||
}
|
||||
|
||||
// ServerRef is a reference to a Server.
|
||||
message ServerRef {
|
||||
// A globally unique identifier for this server. Must be a positive number.
|
||||
int64 server_id = 5;
|
||||
// An optional name associated with the server.
|
||||
string name = 6;
|
||||
// Intentionally don't use field numbers from other refs.
|
||||
reserved 1, 2, 3, 4, 7, 8;
|
||||
}
|
||||
|
||||
// Server represents a single server. There may be multiple servers in a single
|
||||
// program.
|
||||
message Server {
|
||||
// The identifier for a Server. This should be set.
|
||||
ServerRef ref = 1;
|
||||
// The associated data of the Server.
|
||||
ServerData data = 2;
|
||||
|
||||
// The sockets that the server is listening on. There are no ordering
|
||||
// guarantees. This may be absent.
|
||||
repeated SocketRef listen_socket = 3;
|
||||
}
|
||||
|
||||
// ServerData is data for a specific Server.
|
||||
message ServerData {
|
||||
// A trace of recent events on the server. May be absent.
|
||||
ChannelTrace trace = 1;
|
||||
|
||||
// The number of incoming calls started on the server
|
||||
int64 calls_started = 2;
|
||||
// The number of incoming calls that have completed with an OK status
|
||||
int64 calls_succeeded = 3;
|
||||
// The number of incoming calls that have a completed with a non-OK status
|
||||
int64 calls_failed = 4;
|
||||
|
||||
// The last time a call was started on the server.
|
||||
google.protobuf.Timestamp last_call_started_timestamp = 5;
|
||||
}
|
||||
|
||||
// Information about an actual connection. Pronounced "sock-ay".
|
||||
message Socket {
|
||||
// The identifier for the Socket.
|
||||
SocketRef ref = 1;
|
||||
|
||||
// Data specific to this Socket.
|
||||
SocketData data = 2;
|
||||
// The locally bound address.
|
||||
Address local = 3;
|
||||
// The remote bound address. May be absent.
|
||||
Address remote = 4;
|
||||
// Security details for this socket. May be absent if not available, or
|
||||
// there is no security on the socket.
|
||||
Security security = 5;
|
||||
|
||||
// Optional, represents the name of the remote endpoint, if different than
|
||||
// the original target name.
|
||||
string remote_name = 6;
|
||||
}
|
||||
|
||||
// SocketData is data associated for a specific Socket. The fields present
|
||||
// are specific to the implementation, so there may be minor differences in
|
||||
// the semantics. (e.g. flow control windows)
|
||||
message SocketData {
|
||||
// The number of streams that have been started.
|
||||
int64 streams_started = 1;
|
||||
// The number of streams that have ended successfully:
|
||||
// On client side, received frame with eos bit set;
|
||||
// On server side, sent frame with eos bit set.
|
||||
int64 streams_succeeded = 2;
|
||||
// The number of streams that have ended unsuccessfully:
|
||||
// On client side, ended without receiving frame with eos bit set;
|
||||
// On server side, ended without sending frame with eos bit set.
|
||||
int64 streams_failed = 3;
|
||||
// The number of grpc messages successfully sent on this socket.
|
||||
int64 messages_sent = 4;
|
||||
// The number of grpc messages received on this socket.
|
||||
int64 messages_received = 5;
|
||||
|
||||
// The number of keep alives sent. This is typically implemented with HTTP/2
|
||||
// ping messages.
|
||||
int64 keep_alives_sent = 6;
|
||||
|
||||
// The last time a stream was created by this endpoint. Usually unset for
|
||||
// servers.
|
||||
google.protobuf.Timestamp last_local_stream_created_timestamp = 7;
|
||||
// The last time a stream was created by the remote endpoint. Usually unset
|
||||
// for clients.
|
||||
google.protobuf.Timestamp last_remote_stream_created_timestamp = 8;
|
||||
|
||||
// The last time a message was sent by this endpoint.
|
||||
google.protobuf.Timestamp last_message_sent_timestamp = 9;
|
||||
// The last time a message was received by this endpoint.
|
||||
google.protobuf.Timestamp last_message_received_timestamp = 10;
|
||||
|
||||
// The amount of window, granted to the local endpoint by the remote endpoint.
|
||||
// This may be slightly out of date due to network latency. This does NOT
|
||||
// include stream level or TCP level flow control info.
|
||||
google.protobuf.Int64Value local_flow_control_window = 11;
|
||||
|
||||
// The amount of window, granted to the remote endpoint by the local endpoint.
|
||||
// This may be slightly out of date due to network latency. This does NOT
|
||||
// include stream level or TCP level flow control info.
|
||||
google.protobuf.Int64Value remote_flow_control_window = 12;
|
||||
|
||||
// Socket options set on this socket. May be absent if 'summary' is set
|
||||
// on GetSocketRequest.
|
||||
repeated SocketOption option = 13;
|
||||
}
|
||||
|
||||
// Address represents the address used to create the socket.
|
||||
message Address {
|
||||
message TcpIpAddress {
|
||||
// Either the IPv4 or IPv6 address in bytes. Will be either 4 bytes or 16
|
||||
// bytes in length.
|
||||
bytes ip_address = 1;
|
||||
// 0-64k, or -1 if not appropriate.
|
||||
int32 port = 2;
|
||||
}
|
||||
// A Unix Domain Socket address.
|
||||
message UdsAddress {
|
||||
string filename = 1;
|
||||
}
|
||||
// An address type not included above.
|
||||
message OtherAddress {
|
||||
// The human readable version of the value. This value should be set.
|
||||
string name = 1;
|
||||
// The actual address message.
|
||||
google.protobuf.Any value = 2;
|
||||
}
|
||||
|
||||
oneof address {
|
||||
TcpIpAddress tcpip_address = 1;
|
||||
UdsAddress uds_address = 2;
|
||||
OtherAddress other_address = 3;
|
||||
}
|
||||
}
|
||||
|
||||
// Security represents details about how secure the socket is.
|
||||
message Security {
|
||||
message Tls {
|
||||
oneof cipher_suite {
|
||||
// The cipher suite name in the RFC 4346 format:
|
||||
// https://tools.ietf.org/html/rfc4346#appendix-C
|
||||
string standard_name = 1;
|
||||
// Some other way to describe the cipher suite if
|
||||
// the RFC 4346 name is not available.
|
||||
string other_name = 2;
|
||||
}
|
||||
// the certificate used by this endpoint.
|
||||
bytes local_certificate = 3;
|
||||
// the certificate used by the remote endpoint.
|
||||
bytes remote_certificate = 4;
|
||||
}
|
||||
message OtherSecurity {
|
||||
// The human readable version of the value.
|
||||
string name = 1;
|
||||
// The actual security details message.
|
||||
google.protobuf.Any value = 2;
|
||||
}
|
||||
oneof model {
|
||||
Tls tls = 1;
|
||||
OtherSecurity other = 2;
|
||||
}
|
||||
}
|
||||
|
||||
// SocketOption represents socket options for a socket. Specifically, these
|
||||
// are the options returned by getsockopt().
|
||||
message SocketOption {
|
||||
// The full name of the socket option. Typically this will be the upper case
|
||||
// name, such as "SO_REUSEPORT".
|
||||
string name = 1;
|
||||
// The human readable value of this socket option. At least one of value or
|
||||
// additional will be set.
|
||||
string value = 2;
|
||||
// Additional data associated with the socket option. At least one of value
|
||||
// or additional will be set.
|
||||
google.protobuf.Any additional = 3;
|
||||
}
|
||||
|
||||
// For use with SocketOption's additional field. This is primarily used for
|
||||
// SO_RCVTIMEO and SO_SNDTIMEO
|
||||
message SocketOptionTimeout {
|
||||
google.protobuf.Duration duration = 1;
|
||||
}
|
||||
|
||||
// For use with SocketOption's additional field. This is primarily used for
|
||||
// SO_LINGER.
|
||||
message SocketOptionLinger {
|
||||
// active maps to `struct linger.l_onoff`
|
||||
bool active = 1;
|
||||
// duration maps to `struct linger.l_linger`
|
||||
google.protobuf.Duration duration = 2;
|
||||
}
|
||||
|
||||
// For use with SocketOption's additional field. Tcp info for
|
||||
// SOL_TCP and TCP_INFO.
|
||||
message SocketOptionTcpInfo {
|
||||
uint32 tcpi_state = 1;
|
||||
|
||||
uint32 tcpi_ca_state = 2;
|
||||
uint32 tcpi_retransmits = 3;
|
||||
uint32 tcpi_probes = 4;
|
||||
uint32 tcpi_backoff = 5;
|
||||
uint32 tcpi_options = 6;
|
||||
uint32 tcpi_snd_wscale = 7;
|
||||
uint32 tcpi_rcv_wscale = 8;
|
||||
|
||||
uint32 tcpi_rto = 9;
|
||||
uint32 tcpi_ato = 10;
|
||||
uint32 tcpi_snd_mss = 11;
|
||||
uint32 tcpi_rcv_mss = 12;
|
||||
|
||||
uint32 tcpi_unacked = 13;
|
||||
uint32 tcpi_sacked = 14;
|
||||
uint32 tcpi_lost = 15;
|
||||
uint32 tcpi_retrans = 16;
|
||||
uint32 tcpi_fackets = 17;
|
||||
|
||||
uint32 tcpi_last_data_sent = 18;
|
||||
uint32 tcpi_last_ack_sent = 19;
|
||||
uint32 tcpi_last_data_recv = 20;
|
||||
uint32 tcpi_last_ack_recv = 21;
|
||||
|
||||
uint32 tcpi_pmtu = 22;
|
||||
uint32 tcpi_rcv_ssthresh = 23;
|
||||
uint32 tcpi_rtt = 24;
|
||||
uint32 tcpi_rttvar = 25;
|
||||
uint32 tcpi_snd_ssthresh = 26;
|
||||
uint32 tcpi_snd_cwnd = 27;
|
||||
uint32 tcpi_advmss = 28;
|
||||
uint32 tcpi_reordering = 29;
|
||||
}
|
||||
|
||||
// Channelz is a service exposed by gRPC servers that provides detailed debug
|
||||
// information.
|
||||
service Channelz {
|
||||
// Gets all root channels (i.e. channels the application has directly
|
||||
// created). This does not include subchannels nor non-top level channels.
|
||||
rpc GetTopChannels(GetTopChannelsRequest) returns (GetTopChannelsResponse);
|
||||
// Gets all servers that exist in the process.
|
||||
rpc GetServers(GetServersRequest) returns (GetServersResponse);
|
||||
// Returns a single Server, or else a NOT_FOUND code.
|
||||
rpc GetServer(GetServerRequest) returns (GetServerResponse);
|
||||
// Gets all server sockets that exist in the process.
|
||||
rpc GetServerSockets(GetServerSocketsRequest) returns (GetServerSocketsResponse);
|
||||
// Returns a single Channel, or else a NOT_FOUND code.
|
||||
rpc GetChannel(GetChannelRequest) returns (GetChannelResponse);
|
||||
// Returns a single Subchannel, or else a NOT_FOUND code.
|
||||
rpc GetSubchannel(GetSubchannelRequest) returns (GetSubchannelResponse);
|
||||
// Returns a single Socket or else a NOT_FOUND code.
|
||||
rpc GetSocket(GetSocketRequest) returns (GetSocketResponse);
|
||||
}
|
||||
|
||||
message GetTopChannelsRequest {
|
||||
// start_channel_id indicates that only channels at or above this id should be
|
||||
// included in the results.
|
||||
// To request the first page, this should be set to 0. To request
|
||||
// subsequent pages, the client generates this value by adding 1 to
|
||||
// the highest seen result ID.
|
||||
int64 start_channel_id = 1;
|
||||
|
||||
// If non-zero, the server will return a page of results containing
|
||||
// at most this many items. If zero, the server will choose a
|
||||
// reasonable page size. Must never be negative.
|
||||
int64 max_results = 2;
|
||||
}
|
||||
|
||||
message GetTopChannelsResponse {
|
||||
// list of channels that the connection detail service knows about. Sorted in
|
||||
// ascending channel_id order.
|
||||
// Must contain at least 1 result, otherwise 'end' must be true.
|
||||
repeated Channel channel = 1;
|
||||
// If set, indicates that the list of channels is the final list. Requesting
|
||||
// more channels can only return more if they are created after this RPC
|
||||
// completes.
|
||||
bool end = 2;
|
||||
}
|
||||
|
||||
message GetServersRequest {
|
||||
// start_server_id indicates that only servers at or above this id should be
|
||||
// included in the results.
|
||||
// To request the first page, this must be set to 0. To request
|
||||
// subsequent pages, the client generates this value by adding 1 to
|
||||
// the highest seen result ID.
|
||||
int64 start_server_id = 1;
|
||||
|
||||
// If non-zero, the server will return a page of results containing
|
||||
// at most this many items. If zero, the server will choose a
|
||||
// reasonable page size. Must never be negative.
|
||||
int64 max_results = 2;
|
||||
}
|
||||
|
||||
message GetServersResponse {
|
||||
// list of servers that the connection detail service knows about. Sorted in
|
||||
// ascending server_id order.
|
||||
// Must contain at least 1 result, otherwise 'end' must be true.
|
||||
repeated Server server = 1;
|
||||
// If set, indicates that the list of servers is the final list. Requesting
|
||||
// more servers will only return more if they are created after this RPC
|
||||
// completes.
|
||||
bool end = 2;
|
||||
}
|
||||
|
||||
message GetServerRequest {
|
||||
// server_id is the identifier of the specific server to get.
|
||||
int64 server_id = 1;
|
||||
}
|
||||
|
||||
message GetServerResponse {
|
||||
// The Server that corresponds to the requested server_id. This field
|
||||
// should be set.
|
||||
Server server = 1;
|
||||
}
|
||||
|
||||
message GetServerSocketsRequest {
|
||||
int64 server_id = 1;
|
||||
// start_socket_id indicates that only sockets at or above this id should be
|
||||
// included in the results.
|
||||
// To request the first page, this must be set to 0. To request
|
||||
// subsequent pages, the client generates this value by adding 1 to
|
||||
// the highest seen result ID.
|
||||
int64 start_socket_id = 2;
|
||||
|
||||
// If non-zero, the server will return a page of results containing
|
||||
// at most this many items. If zero, the server will choose a
|
||||
// reasonable page size. Must never be negative.
|
||||
int64 max_results = 3;
|
||||
}
|
||||
|
||||
message GetServerSocketsResponse {
|
||||
// list of socket refs that the connection detail service knows about. Sorted in
|
||||
// ascending socket_id order.
|
||||
// Must contain at least 1 result, otherwise 'end' must be true.
|
||||
repeated SocketRef socket_ref = 1;
|
||||
// If set, indicates that the list of sockets is the final list. Requesting
|
||||
// more sockets will only return more if they are created after this RPC
|
||||
// completes.
|
||||
bool end = 2;
|
||||
}
|
||||
|
||||
message GetChannelRequest {
|
||||
// channel_id is the identifier of the specific channel to get.
|
||||
int64 channel_id = 1;
|
||||
}
|
||||
|
||||
message GetChannelResponse {
|
||||
// The Channel that corresponds to the requested channel_id. This field
|
||||
// should be set.
|
||||
Channel channel = 1;
|
||||
}
|
||||
|
||||
message GetSubchannelRequest {
|
||||
// subchannel_id is the identifier of the specific subchannel to get.
|
||||
int64 subchannel_id = 1;
|
||||
}
|
||||
|
||||
message GetSubchannelResponse {
|
||||
// The Subchannel that corresponds to the requested subchannel_id. This
|
||||
// field should be set.
|
||||
Subchannel subchannel = 1;
|
||||
}
|
||||
|
||||
message GetSocketRequest {
|
||||
// socket_id is the identifier of the specific socket to get.
|
||||
int64 socket_id = 1;
|
||||
|
||||
// If true, the response will contain only high level information
|
||||
// that is inexpensive to obtain. Fields thay may be omitted are
|
||||
// documented.
|
||||
bool summary = 2;
|
||||
}
|
||||
|
||||
message GetSocketResponse {
|
||||
// The Socket that corresponds to the requested socket_id. This field
|
||||
// should be set.
|
||||
Socket socket = 1;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright 2021 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.
|
||||
*
|
||||
*/
|
||||
|
||||
import { ServiceDefinition } from "./make-client";
|
||||
import { Server, UntypedServiceImplementation } from "./server";
|
||||
|
||||
interface GetServiceDefinition {
|
||||
(): ServiceDefinition;
|
||||
}
|
||||
|
||||
interface GetHandlers {
|
||||
(): UntypedServiceImplementation;
|
||||
}
|
||||
|
||||
const registeredAdminServices: {getServiceDefinition: GetServiceDefinition, getHandlers: GetHandlers}[] = [];
|
||||
|
||||
export function registerAdminService(getServiceDefinition: GetServiceDefinition, getHandlers: GetHandlers) {
|
||||
registeredAdminServices.push({getServiceDefinition, getHandlers});
|
||||
}
|
||||
|
||||
export function addAdminServicesToServer(server: Server): void {
|
||||
for (const {getServiceDefinition, getHandlers} of registeredAdminServices) {
|
||||
server.addService(getServiceDefinition(), getHandlers());
|
||||
}
|
||||
}
|
|
@ -25,7 +25,7 @@ import { FilterStackFactory, FilterStack } from './filter-stack';
|
|||
import { Metadata } from './metadata';
|
||||
import { StreamDecoder } from './stream-decoder';
|
||||
import { ChannelImplementation } from './channel';
|
||||
import { Subchannel } from './subchannel';
|
||||
import { SubchannelCallStatsTracker, Subchannel } from './subchannel';
|
||||
import * as logging from './logging';
|
||||
import { LogVerbosity } from './constants';
|
||||
import { ServerSurfaceCall } from './server-call';
|
||||
|
@ -249,6 +249,11 @@ export class Http2CallStream implements Call {
|
|||
|
||||
private configDeadline: Deadline = Infinity;
|
||||
|
||||
private statusWatchers: ((status: StatusObject) => void)[] = [];
|
||||
private streamEndWatchers: ((success: boolean) => void)[] = [];
|
||||
|
||||
private callStatsTracker: SubchannelCallStatsTracker | null = null;
|
||||
|
||||
constructor(
|
||||
private readonly methodName: string,
|
||||
private readonly channel: ChannelImplementation,
|
||||
|
@ -283,6 +288,7 @@ export class Http2CallStream implements Call {
|
|||
const filteredStatus = this.filterStack.receiveTrailers(
|
||||
this.finalStatus!
|
||||
);
|
||||
this.statusWatchers.forEach(watcher => watcher(filteredStatus));
|
||||
/* We delay the actual action of bubbling up the status to insulate the
|
||||
* cleanup code in this class from any errors that may be thrown in the
|
||||
* upper layers as a result of bubbling up the status. In particular,
|
||||
|
@ -426,6 +432,7 @@ export class Http2CallStream implements Call {
|
|||
}
|
||||
|
||||
private handleTrailers(headers: http2.IncomingHttpHeaders) {
|
||||
this.streamEndWatchers.forEach(watcher => watcher(true));
|
||||
let headersString = '';
|
||||
for (const header of Object.keys(headers)) {
|
||||
headersString += '\t\t' + header + ': ' + headers[header] + '\n';
|
||||
|
@ -463,10 +470,16 @@ export class Http2CallStream implements Call {
|
|||
this.endCall(status);
|
||||
}
|
||||
|
||||
private writeMessageToStream(message: Buffer, callback: WriteCallback) {
|
||||
this.callStatsTracker?.addMessageSent();
|
||||
this.http2Stream!.write(message, callback);
|
||||
}
|
||||
|
||||
attachHttp2Stream(
|
||||
stream: http2.ClientHttp2Stream,
|
||||
subchannel: Subchannel,
|
||||
extraFilters: Filter[]
|
||||
extraFilters: Filter[],
|
||||
callStatsTracker: SubchannelCallStatsTracker
|
||||
): void {
|
||||
this.filterStack.push(extraFilters);
|
||||
if (this.finalStatus !== null) {
|
||||
|
@ -477,6 +490,7 @@ export class Http2CallStream implements Call {
|
|||
);
|
||||
this.http2Stream = stream;
|
||||
this.subchannel = subchannel;
|
||||
this.callStatsTracker = callStatsTracker;
|
||||
subchannel.addDisconnectListener(this.disconnectListener);
|
||||
subchannel.callRef();
|
||||
stream.on('response', (headers, flags) => {
|
||||
|
@ -542,6 +556,7 @@ export class Http2CallStream implements Call {
|
|||
|
||||
for (const message of messages) {
|
||||
this.trace('parsed message of length ' + message.length);
|
||||
this.callStatsTracker!.addMessageReceived();
|
||||
this.tryPush(message);
|
||||
}
|
||||
});
|
||||
|
@ -645,6 +660,7 @@ export class Http2CallStream implements Call {
|
|||
);
|
||||
this.internalError = err;
|
||||
}
|
||||
this.streamEndWatchers.forEach(watcher => watcher(false));
|
||||
});
|
||||
if (!this.pendingRead) {
|
||||
stream.pause();
|
||||
|
@ -659,7 +675,7 @@ export class Http2CallStream implements Call {
|
|||
' (deferred)'
|
||||
);
|
||||
try {
|
||||
stream.write(this.pendingWrite, this.pendingWriteCallback);
|
||||
this.writeMessageToStream(this.pendingWrite, this.pendingWriteCallback);
|
||||
} catch (error) {
|
||||
this.endCall({
|
||||
code: Status.UNAVAILABLE,
|
||||
|
@ -742,6 +758,14 @@ export class Http2CallStream implements Call {
|
|||
this.configDeadline = configDeadline;
|
||||
}
|
||||
|
||||
addStatusWatcher(watcher: (status: StatusObject) => void) {
|
||||
this.statusWatchers.push(watcher);
|
||||
}
|
||||
|
||||
addStreamEndWatcher(watcher: (success: boolean) => void) {
|
||||
this.streamEndWatchers.push(watcher);
|
||||
}
|
||||
|
||||
addFilters(extraFilters: Filter[]) {
|
||||
this.filterStack.push(extraFilters);
|
||||
}
|
||||
|
@ -799,7 +823,7 @@ export class Http2CallStream implements Call {
|
|||
} else {
|
||||
this.trace('sending data chunk of length ' + message.message.length);
|
||||
try {
|
||||
this.http2Stream.write(message.message, cb);
|
||||
this.writeMessageToStream(message.message, cb);
|
||||
} catch (error) {
|
||||
this.endCall({
|
||||
code: Status.UNAVAILABLE,
|
||||
|
|
|
@ -49,6 +49,7 @@ import { SurfaceCall } from './call';
|
|||
import { Filter } from './filter';
|
||||
|
||||
import { ConnectivityState } from './connectivity-state';
|
||||
import { ChannelInfo, ChannelRef, ChannelzCallTracker, ChannelzChildrenTracker, ChannelzTrace, registerChannelzChannel, SubchannelRef, unregisterChannelzRef } from './channelz';
|
||||
|
||||
/**
|
||||
* See https://nodejs.org/api/timers.html#timers_setinterval_callback_delay_args
|
||||
|
@ -104,6 +105,12 @@ export interface Channel {
|
|||
deadline: Date | number,
|
||||
callback: (error?: Error) => void
|
||||
): void;
|
||||
/**
|
||||
* Get the channelz reference object for this channel. A request to the
|
||||
* channelz service for the id in this object will provide information
|
||||
* about this channel.
|
||||
*/
|
||||
getChannelzRef(): ChannelRef;
|
||||
/**
|
||||
* Create a call object. Call is an opaque type that is used by the Client
|
||||
* class. This function is called by the gRPC library when starting a
|
||||
|
@ -163,6 +170,14 @@ export class ChannelImplementation implements Channel {
|
|||
*/
|
||||
private callRefTimer: NodeJS.Timer;
|
||||
private configSelector: ConfigSelector | null = null;
|
||||
|
||||
// Channelz info
|
||||
private originalTarget: string;
|
||||
private channelzRef: ChannelRef;
|
||||
private channelzTrace: ChannelzTrace;
|
||||
private callTracker = new ChannelzCallTracker();
|
||||
private childrenTracker = new ChannelzChildrenTracker();
|
||||
|
||||
constructor(
|
||||
target: string,
|
||||
private readonly credentials: ChannelCredentials,
|
||||
|
@ -181,6 +196,7 @@ export class ChannelImplementation implements Channel {
|
|||
throw new TypeError('Channel options must be an object');
|
||||
}
|
||||
}
|
||||
this.originalTarget = target;
|
||||
const originalTargetUri = parseUri(target);
|
||||
if (originalTargetUri === null) {
|
||||
throw new Error(`Could not parse target name "${target}"`);
|
||||
|
@ -197,6 +213,10 @@ export class ChannelImplementation implements Channel {
|
|||
this.callRefTimer = setInterval(() => {}, MAX_TIMEOUT_TIME);
|
||||
this.callRefTimer.unref?.();
|
||||
|
||||
this.channelzRef = registerChannelzChannel(target, () => this.getChannelzInfo());
|
||||
this.channelzTrace = new ChannelzTrace();
|
||||
this.channelzTrace.addTrace('CT_INFO', 'Channel created');
|
||||
|
||||
if (this.options['grpc.default_authority']) {
|
||||
this.defaultAuthority = this.options['grpc.default_authority'] as string;
|
||||
} else {
|
||||
|
@ -216,12 +236,14 @@ export class ChannelImplementation implements Channel {
|
|||
subchannelAddress: SubchannelAddress,
|
||||
subchannelArgs: ChannelOptions
|
||||
) => {
|
||||
return this.subchannelPool.getOrCreateSubchannel(
|
||||
const subchannel = this.subchannelPool.getOrCreateSubchannel(
|
||||
this.target,
|
||||
subchannelAddress,
|
||||
Object.assign({}, this.options, subchannelArgs),
|
||||
this.credentials
|
||||
);
|
||||
this.channelzTrace.addTrace('CT_INFO', 'Created subchannel or used existing subchannel', subchannel.getChannelzRef());
|
||||
return subchannel;
|
||||
},
|
||||
updateState: (connectivityState: ConnectivityState, picker: Picker) => {
|
||||
this.currentPicker = picker;
|
||||
|
@ -239,12 +261,19 @@ export class ChannelImplementation implements Channel {
|
|||
'Resolving load balancer should never call requestReresolution'
|
||||
);
|
||||
},
|
||||
addChannelzChild: (child: ChannelRef | SubchannelRef) => {
|
||||
this.childrenTracker.refChild(child);
|
||||
},
|
||||
removeChannelzChild: (child: ChannelRef | SubchannelRef) => {
|
||||
this.childrenTracker.unrefChild(child);
|
||||
}
|
||||
};
|
||||
this.resolvingLoadBalancer = new ResolvingLoadBalancer(
|
||||
this.target,
|
||||
channelControlHelper,
|
||||
options,
|
||||
(configSelector) => {
|
||||
this.channelzTrace.addTrace('CT_INFO', 'Address resolution succeeded');
|
||||
this.configSelector = configSelector;
|
||||
/* We process the queue asynchronously to ensure that the corresponding
|
||||
* load balancer update has completed. */
|
||||
|
@ -259,14 +288,9 @@ export class ChannelImplementation implements Channel {
|
|||
});
|
||||
},
|
||||
(status) => {
|
||||
this.channelzTrace.addTrace('CT_WARNING', 'Address resolution failed with code ' + status.code + ' and details "' + status.details + '"');
|
||||
if (this.configSelectionQueue.length > 0) {
|
||||
trace(
|
||||
LogVerbosity.DEBUG,
|
||||
'channel',
|
||||
'Name resolution failed for target ' +
|
||||
uriToString(this.target) +
|
||||
' with calls queued for config selection'
|
||||
);
|
||||
this.trace('Name resolution failed with calls queued for config selection');
|
||||
}
|
||||
const localQueue = this.configSelectionQueue;
|
||||
this.configSelectionQueue = [];
|
||||
|
@ -287,14 +311,27 @@ export class ChannelImplementation implements Channel {
|
|||
new MaxMessageSizeFilterFactory(this.options),
|
||||
new CompressionFilterFactory(this),
|
||||
]);
|
||||
this.trace('Constructed channel');
|
||||
}
|
||||
|
||||
private getChannelzInfo(): ChannelInfo {
|
||||
return {
|
||||
target: this.originalTarget,
|
||||
state: this.connectivityState,
|
||||
trace: this.channelzTrace,
|
||||
callTracker: this.callTracker,
|
||||
children: this.childrenTracker.getChildLists()
|
||||
};
|
||||
}
|
||||
|
||||
private trace(text: string, verbosityOverride?: LogVerbosity) {
|
||||
trace(verbosityOverride ?? LogVerbosity.DEBUG, 'channel', '(' + this.channelzRef.id + ') ' + uriToString(this.target) + ' ' + text);
|
||||
}
|
||||
|
||||
private callRefTimerRef() {
|
||||
// If the hasRef function does not exist, always run the code
|
||||
if (!this.callRefTimer.hasRef?.()) {
|
||||
trace(
|
||||
LogVerbosity.DEBUG,
|
||||
'channel',
|
||||
this.trace(
|
||||
'callRefTimer.ref | configSelectionQueue.length=' +
|
||||
this.configSelectionQueue.length +
|
||||
' pickQueue.length=' +
|
||||
|
@ -307,9 +344,7 @@ export class ChannelImplementation implements Channel {
|
|||
private callRefTimerUnref() {
|
||||
// If the hasRef function does not exist, always run the code
|
||||
if (!this.callRefTimer.hasRef || this.callRefTimer.hasRef()) {
|
||||
trace(
|
||||
LogVerbosity.DEBUG,
|
||||
'channel',
|
||||
this.trace(
|
||||
'callRefTimer.unref | configSelectionQueue.length=' +
|
||||
this.configSelectionQueue.length +
|
||||
' pickQueue.length=' +
|
||||
|
@ -346,9 +381,7 @@ export class ChannelImplementation implements Channel {
|
|||
metadata: callMetadata,
|
||||
extraPickInfo: callConfig.pickInformation,
|
||||
});
|
||||
trace(
|
||||
LogVerbosity.DEBUG,
|
||||
'channel',
|
||||
this.trace(
|
||||
'Pick result: ' +
|
||||
PickResultType[pickResult.pickResultType] +
|
||||
' subchannel: ' +
|
||||
|
@ -422,25 +455,23 @@ export class ChannelImplementation implements Channel {
|
|||
* the stream because the correct behavior may be
|
||||
* re-queueing instead, based on the logic in the rest of
|
||||
* tryPick */
|
||||
trace(
|
||||
LogVerbosity.INFO,
|
||||
'channel',
|
||||
this.trace(
|
||||
'Failed to start call on picked subchannel ' +
|
||||
pickResult.subchannel!.getAddress() +
|
||||
' with error ' +
|
||||
(error as Error).message +
|
||||
'. Retrying pick'
|
||||
'. Retrying pick',
|
||||
LogVerbosity.INFO
|
||||
);
|
||||
this.tryPick(callStream, callMetadata, callConfig, dynamicFilters);
|
||||
} else {
|
||||
trace(
|
||||
LogVerbosity.INFO,
|
||||
'channel',
|
||||
this.trace(
|
||||
'Failed to start call on picked subchanel ' +
|
||||
pickResult.subchannel!.getAddress() +
|
||||
' with error ' +
|
||||
(error as Error).message +
|
||||
'. Ending call'
|
||||
'. Ending call',
|
||||
LogVerbosity.INFO
|
||||
);
|
||||
callStream.cancelWithStatus(
|
||||
Status.INTERNAL,
|
||||
|
@ -453,14 +484,13 @@ export class ChannelImplementation implements Channel {
|
|||
} else {
|
||||
/* The logic for doing this here is the same as in the catch
|
||||
* block above */
|
||||
trace(
|
||||
LogVerbosity.INFO,
|
||||
'channel',
|
||||
this.trace(
|
||||
'Picked subchannel ' +
|
||||
pickResult.subchannel!.getAddress() +
|
||||
' has state ' +
|
||||
ConnectivityState[subchannelState] +
|
||||
' after metadata filters. Retrying pick'
|
||||
' after metadata filters. Retrying pick',
|
||||
LogVerbosity.INFO
|
||||
);
|
||||
this.tryPick(callStream, callMetadata, callConfig, dynamicFilters);
|
||||
}
|
||||
|
@ -516,12 +546,14 @@ export class ChannelImplementation implements Channel {
|
|||
trace(
|
||||
LogVerbosity.DEBUG,
|
||||
'connectivity_state',
|
||||
'(' + this.channelzRef.id + ') ' +
|
||||
uriToString(this.target) +
|
||||
' ' +
|
||||
ConnectivityState[this.connectivityState] +
|
||||
' -> ' +
|
||||
ConnectivityState[newState]
|
||||
);
|
||||
this.channelzTrace.addTrace('CT_INFO', ConnectivityState[this.connectivityState] + ' -> ' + ConnectivityState[newState]);
|
||||
this.connectivityState = newState;
|
||||
const watchersCopy = this.connectivityStateWatchers.slice();
|
||||
for (const watcherObject of watchersCopy) {
|
||||
|
@ -606,6 +638,7 @@ export class ChannelImplementation implements Channel {
|
|||
this.resolvingLoadBalancer.destroy();
|
||||
this.updateState(ConnectivityState.SHUTDOWN);
|
||||
clearInterval(this.callRefTimer);
|
||||
unregisterChannelzRef(this.channelzRef);
|
||||
|
||||
this.subchannelPool.unrefUnusedSubchannels();
|
||||
}
|
||||
|
@ -657,6 +690,10 @@ export class ChannelImplementation implements Channel {
|
|||
this.connectivityStateWatchers.push(watcherObject);
|
||||
}
|
||||
|
||||
getChannelzRef() {
|
||||
return this.channelzRef;
|
||||
}
|
||||
|
||||
createCall(
|
||||
method: string,
|
||||
deadline: Deadline,
|
||||
|
@ -676,11 +713,8 @@ export class ChannelImplementation implements Channel {
|
|||
throw new Error('Channel has been shut down');
|
||||
}
|
||||
const callNumber = getNewCallNumber();
|
||||
trace(
|
||||
LogVerbosity.DEBUG,
|
||||
'channel',
|
||||
uriToString(this.target) +
|
||||
' createCall [' +
|
||||
this.trace(
|
||||
'createCall [' +
|
||||
callNumber +
|
||||
'] method="' +
|
||||
method +
|
||||
|
@ -701,6 +735,14 @@ export class ChannelImplementation implements Channel {
|
|||
this.credentials._getCallCredentials(),
|
||||
callNumber
|
||||
);
|
||||
this.callTracker.addCallStarted();
|
||||
stream.addStatusWatcher(status => {
|
||||
if (status.code === Status.OK) {
|
||||
this.callTracker.addCallSucceeded();
|
||||
} else {
|
||||
this.callTracker.addCallFailed();
|
||||
}
|
||||
});
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,727 @@
|
|||
/*
|
||||
* Copyright 2021 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.
|
||||
*
|
||||
*/
|
||||
|
||||
import { isIPv4, isIPv6 } from "net";
|
||||
import { ConnectivityState } from "./connectivity-state";
|
||||
import { Status } from "./constants";
|
||||
import { Timestamp } from "./generated/google/protobuf/Timestamp";
|
||||
import { Channel as ChannelMessage } from "./generated/grpc/channelz/v1/Channel";
|
||||
import { ChannelConnectivityState__Output } from "./generated/grpc/channelz/v1/ChannelConnectivityState";
|
||||
import { ChannelRef as ChannelRefMessage } from "./generated/grpc/channelz/v1/ChannelRef";
|
||||
import { ChannelTrace } from "./generated/grpc/channelz/v1/ChannelTrace";
|
||||
import { GetChannelRequest__Output } from "./generated/grpc/channelz/v1/GetChannelRequest";
|
||||
import { GetChannelResponse } from "./generated/grpc/channelz/v1/GetChannelResponse";
|
||||
import { sendUnaryData, ServerUnaryCall } from "./server-call";
|
||||
import { ServerRef as ServerRefMessage } from "./generated/grpc/channelz/v1/ServerRef";
|
||||
import { SocketRef as SocketRefMessage } from "./generated/grpc/channelz/v1/SocketRef";
|
||||
import { isTcpSubchannelAddress, SubchannelAddress } from "./subchannel-address";
|
||||
import { SubchannelRef as SubchannelRefMessage } from "./generated/grpc/channelz/v1/SubchannelRef";
|
||||
import { GetServerRequest__Output } from "./generated/grpc/channelz/v1/GetServerRequest";
|
||||
import { GetServerResponse } from "./generated/grpc/channelz/v1/GetServerResponse";
|
||||
import { Server as ServerMessage } from "./generated/grpc/channelz/v1/Server";
|
||||
import { GetServersRequest__Output } from "./generated/grpc/channelz/v1/GetServersRequest";
|
||||
import { GetServersResponse } from "./generated/grpc/channelz/v1/GetServersResponse";
|
||||
import { GetTopChannelsRequest__Output } from "./generated/grpc/channelz/v1/GetTopChannelsRequest";
|
||||
import { GetTopChannelsResponse } from "./generated/grpc/channelz/v1/GetTopChannelsResponse";
|
||||
import { GetSubchannelRequest__Output } from "./generated/grpc/channelz/v1/GetSubchannelRequest";
|
||||
import { GetSubchannelResponse } from "./generated/grpc/channelz/v1/GetSubchannelResponse";
|
||||
import { Subchannel as SubchannelMessage } from "./generated/grpc/channelz/v1/Subchannel";
|
||||
import { GetSocketRequest__Output } from "./generated/grpc/channelz/v1/GetSocketRequest";
|
||||
import { GetSocketResponse } from "./generated/grpc/channelz/v1/GetSocketResponse";
|
||||
import { Socket as SocketMessage } from "./generated/grpc/channelz/v1/Socket";
|
||||
import { Address } from "./generated/grpc/channelz/v1/Address";
|
||||
import { Security } from "./generated/grpc/channelz/v1/Security";
|
||||
import { GetServerSocketsRequest__Output } from "./generated/grpc/channelz/v1/GetServerSocketsRequest";
|
||||
import { GetServerSocketsResponse } from "./generated/grpc/channelz/v1/GetServerSocketsResponse";
|
||||
import { ChannelzDefinition, ChannelzHandlers } from "./generated/grpc/channelz/v1/Channelz";
|
||||
import { ProtoGrpcType as ChannelzProtoGrpcType } from "./generated/channelz";
|
||||
import type { loadSync } from '@grpc/proto-loader';
|
||||
import { registerAdminService } from "./admin";
|
||||
import { loadPackageDefinition } from "./make-client";
|
||||
|
||||
export type TraceSeverity = 'CT_UNKNOWN' | 'CT_INFO' | 'CT_WARNING' | 'CT_ERROR';
|
||||
|
||||
export interface ChannelRef {
|
||||
kind: 'channel';
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface SubchannelRef {
|
||||
kind: 'subchannel';
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface ServerRef {
|
||||
kind: 'server';
|
||||
id: number;
|
||||
}
|
||||
|
||||
export interface SocketRef {
|
||||
kind: 'socket';
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
function channelRefToMessage(ref: ChannelRef): ChannelRefMessage {
|
||||
return {
|
||||
channel_id: ref.id,
|
||||
name: ref.name
|
||||
};
|
||||
}
|
||||
|
||||
function subchannelRefToMessage(ref: SubchannelRef): SubchannelRefMessage {
|
||||
return {
|
||||
subchannel_id: ref.id,
|
||||
name: ref.name
|
||||
}
|
||||
}
|
||||
|
||||
function serverRefToMessage(ref: ServerRef): ServerRefMessage {
|
||||
return {
|
||||
server_id: ref.id
|
||||
}
|
||||
}
|
||||
|
||||
function socketRefToMessage(ref: SocketRef): SocketRefMessage {
|
||||
return {
|
||||
socket_id: ref.id,
|
||||
name: ref.name
|
||||
}
|
||||
}
|
||||
|
||||
interface TraceEvent {
|
||||
description: string;
|
||||
severity: TraceSeverity;
|
||||
timestamp: Date;
|
||||
childChannel?: ChannelRef;
|
||||
childSubchannel?: SubchannelRef;
|
||||
}
|
||||
|
||||
export class ChannelzTrace {
|
||||
events: TraceEvent[] = [];
|
||||
creationTimestamp: Date;
|
||||
eventsLogged: number = 0;
|
||||
|
||||
constructor() {
|
||||
this.creationTimestamp = new Date();
|
||||
}
|
||||
|
||||
addTrace(severity: TraceSeverity, description: string, child?: ChannelRef | SubchannelRef) {
|
||||
const timestamp = new Date();
|
||||
this.events.push({
|
||||
description: description,
|
||||
severity: severity,
|
||||
timestamp: timestamp,
|
||||
childChannel: child?.kind === 'channel' ? child : undefined,
|
||||
childSubchannel: child?.kind === 'subchannel' ? child : undefined
|
||||
});
|
||||
this.eventsLogged += 1;
|
||||
}
|
||||
|
||||
getTraceMessage(): ChannelTrace {
|
||||
return {
|
||||
creation_timestamp: dateToProtoTimestamp(this.creationTimestamp),
|
||||
num_events_logged: this.eventsLogged,
|
||||
events: this.events.map(event => {
|
||||
return {
|
||||
description: event.description,
|
||||
severity: event.severity,
|
||||
timestamp: dateToProtoTimestamp(event.timestamp),
|
||||
channel_ref: event.childChannel ? channelRefToMessage(event.childChannel) : null,
|
||||
subchannel_ref: event.childSubchannel ? subchannelRefToMessage(event.childSubchannel) : null
|
||||
}
|
||||
})
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class ChannelzChildrenTracker {
|
||||
private channelChildren: Map<number, {ref: ChannelRef, count: number}> = new Map<number, {ref: ChannelRef, count: number}>();
|
||||
private subchannelChildren: Map<number, {ref: SubchannelRef, count: number}> = new Map<number, {ref: SubchannelRef, count: number}>();
|
||||
private socketChildren: Map<number, {ref: SocketRef, count: number}> = new Map<number, {ref: SocketRef, count: number}>();
|
||||
|
||||
refChild(child: ChannelRef | SubchannelRef | SocketRef) {
|
||||
switch (child.kind) {
|
||||
case 'channel': {
|
||||
let trackedChild = this.channelChildren.get(child.id) ?? {ref: child, count: 0};
|
||||
trackedChild.count += 1;
|
||||
this.channelChildren.set(child.id, trackedChild);
|
||||
break;
|
||||
}
|
||||
case 'subchannel':{
|
||||
let trackedChild = this.subchannelChildren.get(child.id) ?? {ref: child, count: 0};
|
||||
trackedChild.count += 1;
|
||||
this.subchannelChildren.set(child.id, trackedChild);
|
||||
break;
|
||||
}
|
||||
case 'socket':{
|
||||
let trackedChild = this.socketChildren.get(child.id) ?? {ref: child, count: 0};
|
||||
trackedChild.count += 1;
|
||||
this.socketChildren.set(child.id, trackedChild);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unrefChild(child: ChannelRef | SubchannelRef | SocketRef) {
|
||||
switch (child.kind) {
|
||||
case 'channel': {
|
||||
let trackedChild = this.channelChildren.get(child.id);
|
||||
if (trackedChild !== undefined) {
|
||||
trackedChild.count -= 1;
|
||||
if (trackedChild.count === 0) {
|
||||
this.channelChildren.delete(child.id);
|
||||
} else {
|
||||
this.channelChildren.set(child.id, trackedChild);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'subchannel': {
|
||||
let trackedChild = this.subchannelChildren.get(child.id);
|
||||
if (trackedChild !== undefined) {
|
||||
trackedChild.count -= 1;
|
||||
if (trackedChild.count === 0) {
|
||||
this.subchannelChildren.delete(child.id);
|
||||
} else {
|
||||
this.subchannelChildren.set(child.id, trackedChild);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'socket': {
|
||||
let trackedChild = this.socketChildren.get(child.id);
|
||||
if (trackedChild !== undefined) {
|
||||
trackedChild.count -= 1;
|
||||
if (trackedChild.count === 0) {
|
||||
this.socketChildren.delete(child.id);
|
||||
} else {
|
||||
this.socketChildren.set(child.id, trackedChild);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getChildLists(): ChannelzChildren {
|
||||
const channels: ChannelRef[] = [];
|
||||
for (const {ref} of this.channelChildren.values()) {
|
||||
channels.push(ref);
|
||||
}
|
||||
const subchannels: SubchannelRef[] = [];
|
||||
for (const {ref} of this.subchannelChildren.values()) {
|
||||
subchannels.push(ref);
|
||||
}
|
||||
const sockets: SocketRef[] = [];
|
||||
for (const {ref} of this.socketChildren.values()) {
|
||||
sockets.push(ref);
|
||||
}
|
||||
return {channels, subchannels, sockets};
|
||||
}
|
||||
}
|
||||
|
||||
export class ChannelzCallTracker {
|
||||
callsStarted: number = 0;
|
||||
callsSucceeded: number = 0;
|
||||
callsFailed: number = 0;
|
||||
lastCallStartedTimestamp: Date | null = null;
|
||||
|
||||
addCallStarted() {
|
||||
this.callsStarted += 1;
|
||||
this.lastCallStartedTimestamp = new Date();
|
||||
}
|
||||
addCallSucceeded() {
|
||||
this.callsSucceeded += 1;
|
||||
}
|
||||
addCallFailed() {
|
||||
this.callsFailed += 1;
|
||||
}
|
||||
}
|
||||
|
||||
export interface ChannelzChildren {
|
||||
channels: ChannelRef[];
|
||||
subchannels: SubchannelRef[];
|
||||
sockets: SocketRef[];
|
||||
}
|
||||
|
||||
export interface ChannelInfo {
|
||||
target: string;
|
||||
state: ConnectivityState;
|
||||
trace: ChannelzTrace;
|
||||
callTracker: ChannelzCallTracker;
|
||||
children: ChannelzChildren;
|
||||
}
|
||||
|
||||
export interface SubchannelInfo extends ChannelInfo {}
|
||||
|
||||
export interface ServerInfo {
|
||||
trace: ChannelzTrace;
|
||||
callTracker: ChannelzCallTracker;
|
||||
listenerChildren: ChannelzChildren;
|
||||
sessionChildren: ChannelzChildren;
|
||||
}
|
||||
|
||||
export interface TlsInfo {
|
||||
cipherSuiteStandardName: string | null;
|
||||
cipherSuiteOtherName: string | null;
|
||||
localCertificate: Buffer | null;
|
||||
remoteCertificate: Buffer | null;
|
||||
}
|
||||
|
||||
export interface SocketInfo {
|
||||
localAddress: SubchannelAddress;
|
||||
remoteAddress: SubchannelAddress | null;
|
||||
security: TlsInfo | null;
|
||||
remoteName: string | null;
|
||||
streamsStarted: number;
|
||||
streamsSucceeded: number;
|
||||
streamsFailed: number;
|
||||
messagesSent: number;
|
||||
messagesReceived: number;
|
||||
keepAlivesSent: number;
|
||||
lastLocalStreamCreatedTimestamp: Date | null;
|
||||
lastRemoteStreamCreatedTimestamp: Date | null;
|
||||
lastMessageSentTimestamp: Date | null;
|
||||
lastMessageReceivedTimestamp: Date | null;
|
||||
localFlowControlWindow: number | null;
|
||||
remoteFlowControlWindow: number | null;
|
||||
}
|
||||
|
||||
interface ChannelEntry {
|
||||
ref: ChannelRef;
|
||||
getInfo(): ChannelInfo;
|
||||
}
|
||||
|
||||
interface SubchannelEntry {
|
||||
ref: SubchannelRef;
|
||||
getInfo(): SubchannelInfo;
|
||||
}
|
||||
|
||||
interface ServerEntry {
|
||||
ref: ServerRef;
|
||||
getInfo(): ServerInfo;
|
||||
}
|
||||
|
||||
interface SocketEntry {
|
||||
ref: SocketRef;
|
||||
getInfo(): SocketInfo;
|
||||
}
|
||||
|
||||
let nextId = 1;
|
||||
|
||||
function getNextId(): number {
|
||||
return nextId++;
|
||||
}
|
||||
|
||||
const channels: (ChannelEntry | undefined)[] = [];
|
||||
const subchannels: (SubchannelEntry | undefined)[] = [];
|
||||
const servers: (ServerEntry | undefined)[] = [];
|
||||
const sockets: (SocketEntry | undefined)[] = [];
|
||||
|
||||
export function registerChannelzChannel(name: string, getInfo: () => ChannelInfo): ChannelRef {
|
||||
const id = getNextId();
|
||||
const ref: ChannelRef = {id, name, kind: 'channel'};
|
||||
channels[id] = { ref, getInfo };
|
||||
return ref;
|
||||
}
|
||||
|
||||
export function registerChannelzSubchannel(name: string, getInfo:() => SubchannelInfo): SubchannelRef {
|
||||
const id = getNextId();
|
||||
const ref: SubchannelRef = {id, name, kind: 'subchannel'};
|
||||
subchannels[id] = { ref, getInfo };
|
||||
return ref;
|
||||
}
|
||||
|
||||
export function registerChannelzServer(getInfo: () => ServerInfo): ServerRef {
|
||||
const id = getNextId();
|
||||
const ref: ServerRef = {id, kind: 'server'};
|
||||
servers[id] = { ref, getInfo };
|
||||
return ref;
|
||||
}
|
||||
|
||||
export function registerChannelzSocket(name: string, getInfo: () => SocketInfo): SocketRef {
|
||||
const id = getNextId();
|
||||
const ref: SocketRef = {id, name, kind: 'socket'};
|
||||
sockets[id] = { ref, getInfo};
|
||||
return ref;
|
||||
}
|
||||
|
||||
export function unregisterChannelzRef(ref: ChannelRef | SubchannelRef | ServerRef | SocketRef) {
|
||||
switch (ref.kind) {
|
||||
case 'channel':
|
||||
delete channels[ref.id];
|
||||
return;
|
||||
case 'subchannel':
|
||||
delete subchannels[ref.id];
|
||||
return;
|
||||
case 'server':
|
||||
delete servers[ref.id];
|
||||
return;
|
||||
case 'socket':
|
||||
delete sockets[ref.id];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
export interface ChannelzClientView {
|
||||
updateState(connectivityState: ConnectivityState): void;
|
||||
addTrace(severity: TraceSeverity, description: string, child?: ChannelRef | SubchannelRef): void;
|
||||
addCallStarted(): void;
|
||||
addCallSucceeded(): void;
|
||||
addCallFailed(): void;
|
||||
addChild(child: ChannelRef | SubchannelRef): void;
|
||||
removeChild(child: ChannelRef | SubchannelRef): void;
|
||||
}
|
||||
|
||||
export interface ChannelzSubchannelView extends ChannelzClientView {
|
||||
getRef(): SubchannelRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an IPv4 or IPv6 address from string representation to binary
|
||||
* representation
|
||||
* @param ipAddress an IP address in standard IPv4 or IPv6 text format
|
||||
* @returns
|
||||
*/
|
||||
function ipAddressStringToBuffer(ipAddress: string): Buffer | null {
|
||||
if (isIPv4(ipAddress)) {
|
||||
return Buffer.from(Uint8Array.from(ipAddress.split('.').map(segment => Number.parseInt(segment))));
|
||||
} else if (isIPv6(ipAddress)) {
|
||||
let leftSection: string;
|
||||
let rightSection: string | null;
|
||||
const doubleColonIndex = ipAddress.indexOf('::');
|
||||
if (doubleColonIndex === -1) {
|
||||
leftSection = ipAddress;
|
||||
rightSection = null;
|
||||
} else {
|
||||
leftSection = ipAddress.substring(0, doubleColonIndex);
|
||||
rightSection = ipAddress.substring(doubleColonIndex + 2);
|
||||
}
|
||||
const leftBuffer = Uint8Array.from(leftSection.split(':').map(segment => Number.parseInt(segment, 16)));
|
||||
const rightBuffer = rightSection ? Uint8Array.from(rightSection.split(':').map(segment => Number.parseInt(segment, 16))) : new Uint8Array();
|
||||
const middleBuffer = Buffer.alloc(16 - leftBuffer.length - rightBuffer.length, 0);
|
||||
return Buffer.concat([leftBuffer, middleBuffer, rightBuffer]);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function connectivityStateToMessage(state: ConnectivityState): ChannelConnectivityState__Output {
|
||||
switch (state) {
|
||||
case ConnectivityState.CONNECTING:
|
||||
return {
|
||||
state: 'CONNECTING'
|
||||
};
|
||||
case ConnectivityState.IDLE:
|
||||
return {
|
||||
state: 'IDLE'
|
||||
};
|
||||
case ConnectivityState.READY:
|
||||
return {
|
||||
state: 'READY'
|
||||
};
|
||||
case ConnectivityState.SHUTDOWN:
|
||||
return {
|
||||
state: 'SHUTDOWN'
|
||||
};
|
||||
case ConnectivityState.TRANSIENT_FAILURE:
|
||||
return {
|
||||
state: 'TRANSIENT_FAILURE'
|
||||
};
|
||||
default:
|
||||
return {
|
||||
state: 'UNKNOWN'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function dateToProtoTimestamp(date?: Date | null): Timestamp | null {
|
||||
if (!date) {
|
||||
return null;
|
||||
}
|
||||
const millisSinceEpoch = date.getTime();
|
||||
return {
|
||||
seconds: (millisSinceEpoch / 1000) | 0,
|
||||
nanos: (millisSinceEpoch % 1000) * 1_000_000
|
||||
}
|
||||
}
|
||||
|
||||
function getChannelMessage(channelEntry: ChannelEntry): ChannelMessage {
|
||||
const resolvedInfo = channelEntry.getInfo();
|
||||
return {
|
||||
ref: channelRefToMessage(channelEntry.ref),
|
||||
data: {
|
||||
target: resolvedInfo.target,
|
||||
state: connectivityStateToMessage(resolvedInfo.state),
|
||||
calls_started: resolvedInfo.callTracker.callsStarted,
|
||||
calls_succeeded: resolvedInfo.callTracker.callsSucceeded,
|
||||
calls_failed: resolvedInfo.callTracker.callsFailed,
|
||||
last_call_started_timestamp: dateToProtoTimestamp(resolvedInfo.callTracker.lastCallStartedTimestamp),
|
||||
trace: resolvedInfo.trace.getTraceMessage()
|
||||
},
|
||||
channel_ref: resolvedInfo.children.channels.map(ref => channelRefToMessage(ref)),
|
||||
subchannel_ref: resolvedInfo.children.subchannels.map(ref => subchannelRefToMessage(ref))
|
||||
};
|
||||
}
|
||||
|
||||
function GetChannel(call: ServerUnaryCall<GetChannelRequest__Output, GetChannelResponse>, callback: sendUnaryData<GetChannelResponse>): void {
|
||||
const channelId = Number.parseInt(call.request.channel_id);
|
||||
const channelEntry = channels[channelId];
|
||||
if (channelEntry === undefined) {
|
||||
callback({
|
||||
'code': Status.NOT_FOUND,
|
||||
'details': 'No channel data found for id ' + channelId
|
||||
});
|
||||
return;
|
||||
}
|
||||
callback(null, {channel: getChannelMessage(channelEntry)});
|
||||
}
|
||||
|
||||
function GetTopChannels(call: ServerUnaryCall<GetTopChannelsRequest__Output, GetTopChannelsResponse>, callback: sendUnaryData<GetTopChannelsResponse>): void {
|
||||
const maxResults = Number.parseInt(call.request.max_results);
|
||||
const resultList: ChannelMessage[] = [];
|
||||
let i = Number.parseInt(call.request.start_channel_id);
|
||||
for (; i < channels.length; i++) {
|
||||
const channelEntry = channels[i];
|
||||
if (channelEntry === undefined) {
|
||||
continue;
|
||||
}
|
||||
resultList.push(getChannelMessage(channelEntry));
|
||||
if (resultList.length >= maxResults) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
callback(null, {
|
||||
channel: resultList,
|
||||
end: i >= servers.length
|
||||
});
|
||||
}
|
||||
|
||||
function getServerMessage(serverEntry: ServerEntry): ServerMessage {
|
||||
const resolvedInfo = serverEntry.getInfo();
|
||||
return {
|
||||
ref: serverRefToMessage(serverEntry.ref),
|
||||
data: {
|
||||
calls_started: resolvedInfo.callTracker.callsStarted,
|
||||
calls_succeeded: resolvedInfo.callTracker.callsSucceeded,
|
||||
calls_failed: resolvedInfo.callTracker.callsFailed,
|
||||
last_call_started_timestamp: dateToProtoTimestamp(resolvedInfo.callTracker.lastCallStartedTimestamp),
|
||||
trace: resolvedInfo.trace.getTraceMessage()
|
||||
},
|
||||
listen_socket: resolvedInfo.listenerChildren.sockets.map(ref => socketRefToMessage(ref))
|
||||
};
|
||||
}
|
||||
|
||||
function GetServer(call: ServerUnaryCall<GetServerRequest__Output, GetServerResponse>, callback: sendUnaryData<GetServerResponse>): void {
|
||||
const serverId = Number.parseInt(call.request.server_id);
|
||||
const serverEntry = servers[serverId];
|
||||
if (serverEntry === undefined) {
|
||||
callback({
|
||||
'code': Status.NOT_FOUND,
|
||||
'details': 'No server data found for id ' + serverId
|
||||
});
|
||||
return;
|
||||
}
|
||||
callback(null, {server: getServerMessage(serverEntry)});
|
||||
}
|
||||
|
||||
function GetServers(call: ServerUnaryCall<GetServersRequest__Output, GetServersResponse>, callback: sendUnaryData<GetServersResponse>): void {
|
||||
const maxResults = Number.parseInt(call.request.max_results);
|
||||
const resultList: ServerMessage[] = [];
|
||||
let i = Number.parseInt(call.request.start_server_id);
|
||||
for (; i < servers.length; i++) {
|
||||
const serverEntry = servers[i];
|
||||
if (serverEntry === undefined) {
|
||||
continue;
|
||||
}
|
||||
resultList.push(getServerMessage(serverEntry));
|
||||
if (resultList.length >= maxResults) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
callback(null, {
|
||||
server: resultList,
|
||||
end: i >= servers.length
|
||||
});
|
||||
}
|
||||
|
||||
function GetSubchannel(call: ServerUnaryCall<GetSubchannelRequest__Output, GetSubchannelResponse>, callback: sendUnaryData<GetSubchannelResponse>): void {
|
||||
const subchannelId = Number.parseInt(call.request.subchannel_id);
|
||||
const subchannelEntry = subchannels[subchannelId];
|
||||
if (subchannelEntry === undefined) {
|
||||
callback({
|
||||
'code': Status.NOT_FOUND,
|
||||
'details': 'No subchannel data found for id ' + subchannelId
|
||||
});
|
||||
return;
|
||||
}
|
||||
const resolvedInfo = subchannelEntry.getInfo();
|
||||
const subchannelMessage: SubchannelMessage = {
|
||||
ref: subchannelRefToMessage(subchannelEntry.ref),
|
||||
data: {
|
||||
target: resolvedInfo.target,
|
||||
state: connectivityStateToMessage(resolvedInfo.state),
|
||||
calls_started: resolvedInfo.callTracker.callsStarted,
|
||||
calls_succeeded: resolvedInfo.callTracker.callsSucceeded,
|
||||
calls_failed: resolvedInfo.callTracker.callsFailed,
|
||||
last_call_started_timestamp: dateToProtoTimestamp(resolvedInfo.callTracker.lastCallStartedTimestamp),
|
||||
trace: resolvedInfo.trace.getTraceMessage()
|
||||
},
|
||||
socket_ref: resolvedInfo.children.sockets.map(ref => socketRefToMessage(ref))
|
||||
};
|
||||
callback(null, {subchannel: subchannelMessage});
|
||||
}
|
||||
|
||||
function subchannelAddressToAddressMessage(subchannelAddress: SubchannelAddress): Address {
|
||||
if (isTcpSubchannelAddress(subchannelAddress)) {
|
||||
return {
|
||||
address: 'tcpip_address',
|
||||
tcpip_address: {
|
||||
ip_address: ipAddressStringToBuffer(subchannelAddress.host) ?? undefined,
|
||||
port: subchannelAddress.port
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
address: 'uds_address',
|
||||
uds_address: {
|
||||
filename: subchannelAddress.path
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function GetSocket(call: ServerUnaryCall<GetSocketRequest__Output, GetSocketResponse>, callback: sendUnaryData<GetSocketResponse>): void {
|
||||
const socketId = Number.parseInt(call.request.socket_id);
|
||||
const socketEntry = sockets[socketId];
|
||||
if (socketEntry === undefined) {
|
||||
callback({
|
||||
'code': Status.NOT_FOUND,
|
||||
'details': 'No socket data found for id ' + socketId
|
||||
});
|
||||
return;
|
||||
}
|
||||
const resolvedInfo = socketEntry.getInfo();
|
||||
const securityMessage: Security | null = resolvedInfo.security ? {
|
||||
model: 'tls',
|
||||
tls: {
|
||||
cipher_suite: resolvedInfo.security.cipherSuiteStandardName ? 'standard_name' : 'other_name',
|
||||
standard_name: resolvedInfo.security.cipherSuiteStandardName ?? undefined,
|
||||
other_name: resolvedInfo.security.cipherSuiteOtherName ?? undefined,
|
||||
local_certificate: resolvedInfo.security.localCertificate ?? undefined,
|
||||
remote_certificate: resolvedInfo.security.remoteCertificate ?? undefined
|
||||
}
|
||||
} : null;
|
||||
const socketMessage: SocketMessage = {
|
||||
ref: socketRefToMessage(socketEntry.ref),
|
||||
local: subchannelAddressToAddressMessage(resolvedInfo.localAddress),
|
||||
remote: resolvedInfo.remoteAddress ? subchannelAddressToAddressMessage(resolvedInfo.remoteAddress) : null,
|
||||
remote_name: resolvedInfo.remoteName ?? undefined,
|
||||
security: securityMessage,
|
||||
data: {
|
||||
keep_alives_sent: resolvedInfo.keepAlivesSent,
|
||||
streams_started: resolvedInfo.streamsStarted,
|
||||
streams_succeeded: resolvedInfo.streamsSucceeded,
|
||||
streams_failed: resolvedInfo.streamsFailed,
|
||||
last_local_stream_created_timestamp: dateToProtoTimestamp(resolvedInfo.lastLocalStreamCreatedTimestamp),
|
||||
last_remote_stream_created_timestamp: dateToProtoTimestamp(resolvedInfo.lastRemoteStreamCreatedTimestamp),
|
||||
messages_received: resolvedInfo.messagesReceived,
|
||||
messages_sent: resolvedInfo.messagesSent,
|
||||
last_message_received_timestamp: dateToProtoTimestamp(resolvedInfo.lastMessageReceivedTimestamp),
|
||||
last_message_sent_timestamp: dateToProtoTimestamp(resolvedInfo.lastMessageSentTimestamp),
|
||||
local_flow_control_window: resolvedInfo.localFlowControlWindow ? { value: resolvedInfo.localFlowControlWindow } : null,
|
||||
remote_flow_control_window: resolvedInfo.remoteFlowControlWindow ? { value: resolvedInfo.remoteFlowControlWindow } : null,
|
||||
}
|
||||
};
|
||||
callback(null, {socket: socketMessage});
|
||||
}
|
||||
|
||||
function GetServerSockets(call: ServerUnaryCall<GetServerSocketsRequest__Output, GetServerSocketsResponse>, callback: sendUnaryData<GetServerSocketsResponse>): void {
|
||||
const serverId = Number.parseInt(call.request.server_id);
|
||||
const serverEntry = servers[serverId];
|
||||
if (serverEntry === undefined) {
|
||||
callback({
|
||||
'code': Status.NOT_FOUND,
|
||||
'details': 'No server data found for id ' + serverId
|
||||
});
|
||||
return;
|
||||
}
|
||||
const startId = Number.parseInt(call.request.start_socket_id);
|
||||
const maxResults = Number.parseInt(call.request.max_results);
|
||||
const resolvedInfo = serverEntry.getInfo();
|
||||
// If we wanted to include listener sockets in the result, this line would
|
||||
// instead say
|
||||
// const allSockets = resolvedInfo.listenerChildren.sockets.concat(resolvedInfo.sessionChildren.sockets).sort((ref1, ref2) => ref1.id - ref2.id);
|
||||
const allSockets = resolvedInfo.sessionChildren.sockets.sort((ref1, ref2) => ref1.id - ref2.id);
|
||||
const resultList: SocketRefMessage[] = [];
|
||||
let i = 0;
|
||||
for (; i < allSockets.length; i++) {
|
||||
if (allSockets[i].id >= startId) {
|
||||
resultList.push(socketRefToMessage(allSockets[i]));
|
||||
if (resultList.length >= maxResults) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
callback(null, {
|
||||
socket_ref: resultList,
|
||||
end: i >= allSockets.length
|
||||
});
|
||||
}
|
||||
|
||||
export function getChannelzHandlers(): ChannelzHandlers {
|
||||
return {
|
||||
GetChannel,
|
||||
GetTopChannels,
|
||||
GetServer,
|
||||
GetServers,
|
||||
GetSubchannel,
|
||||
GetSocket,
|
||||
GetServerSockets
|
||||
};
|
||||
}
|
||||
|
||||
let loadedChannelzDefinition: ChannelzDefinition | null = null;
|
||||
|
||||
export function getChannelzServiceDefinition(): ChannelzDefinition {
|
||||
if (loadedChannelzDefinition) {
|
||||
return loadedChannelzDefinition;
|
||||
}
|
||||
/* The purpose of this complexity is to avoid loading @grpc/proto-loader at
|
||||
* runtime for users who will not use/enable channelz. */
|
||||
const loaderLoadSync = require('@grpc/proto-loader').loadSync as typeof loadSync;
|
||||
const loadedProto = loaderLoadSync('channelz.proto', {
|
||||
keepCase: true,
|
||||
longs: String,
|
||||
enums: String,
|
||||
defaults: true,
|
||||
oneofs: true,
|
||||
includeDirs: [
|
||||
`${__dirname}/../../proto`
|
||||
]
|
||||
});
|
||||
const channelzGrpcObject = loadPackageDefinition(loadedProto) as unknown as ChannelzProtoGrpcType;
|
||||
loadedChannelzDefinition = channelzGrpcObject.grpc.channelz.v1.Channelz.service;
|
||||
return loadedChannelzDefinition;
|
||||
}
|
||||
|
||||
export function setup() {
|
||||
registerAdminService(getChannelzServiceDefinition, getChannelzHandlers);
|
||||
}
|
|
@ -12,6 +12,7 @@ export {
|
|||
LoadBalancer,
|
||||
LoadBalancingConfig,
|
||||
ChannelControlHelper,
|
||||
createChildChannelControlHelper,
|
||||
registerLoadBalancerType,
|
||||
getFirstUsableConfig,
|
||||
validateLoadBalancingConfig,
|
||||
|
@ -32,3 +33,4 @@ export {
|
|||
export { Call as CallStream } from './call-stream';
|
||||
export { Filter, BaseFilter, FilterFactory } from './filter';
|
||||
export { FilterStackFactory } from './filter-stack';
|
||||
export { registerAdminService } from './admin';
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
import type * as grpc from '../index';
|
||||
import type { MessageTypeDefinition } from '@grpc/proto-loader';
|
||||
|
||||
import type { ChannelzClient as _grpc_channelz_v1_ChannelzClient, ChannelzDefinition as _grpc_channelz_v1_ChannelzDefinition } from './grpc/channelz/v1/Channelz';
|
||||
|
||||
type SubtypeConstructor<Constructor extends new (...args: any) => any, Subtype> = {
|
||||
new(...args: ConstructorParameters<Constructor>): Subtype;
|
||||
};
|
||||
|
||||
export interface ProtoGrpcType {
|
||||
google: {
|
||||
protobuf: {
|
||||
Any: MessageTypeDefinition
|
||||
BoolValue: MessageTypeDefinition
|
||||
BytesValue: MessageTypeDefinition
|
||||
DoubleValue: MessageTypeDefinition
|
||||
Duration: MessageTypeDefinition
|
||||
FloatValue: MessageTypeDefinition
|
||||
Int32Value: MessageTypeDefinition
|
||||
Int64Value: MessageTypeDefinition
|
||||
StringValue: MessageTypeDefinition
|
||||
Timestamp: MessageTypeDefinition
|
||||
UInt32Value: MessageTypeDefinition
|
||||
UInt64Value: MessageTypeDefinition
|
||||
}
|
||||
}
|
||||
grpc: {
|
||||
channelz: {
|
||||
v1: {
|
||||
Address: MessageTypeDefinition
|
||||
Channel: MessageTypeDefinition
|
||||
ChannelConnectivityState: MessageTypeDefinition
|
||||
ChannelData: MessageTypeDefinition
|
||||
ChannelRef: MessageTypeDefinition
|
||||
ChannelTrace: MessageTypeDefinition
|
||||
ChannelTraceEvent: MessageTypeDefinition
|
||||
/**
|
||||
* Channelz is a service exposed by gRPC servers that provides detailed debug
|
||||
* information.
|
||||
*/
|
||||
Channelz: SubtypeConstructor<typeof grpc.Client, _grpc_channelz_v1_ChannelzClient> & { service: _grpc_channelz_v1_ChannelzDefinition }
|
||||
GetChannelRequest: MessageTypeDefinition
|
||||
GetChannelResponse: MessageTypeDefinition
|
||||
GetServerRequest: MessageTypeDefinition
|
||||
GetServerResponse: MessageTypeDefinition
|
||||
GetServerSocketsRequest: MessageTypeDefinition
|
||||
GetServerSocketsResponse: MessageTypeDefinition
|
||||
GetServersRequest: MessageTypeDefinition
|
||||
GetServersResponse: MessageTypeDefinition
|
||||
GetSocketRequest: MessageTypeDefinition
|
||||
GetSocketResponse: MessageTypeDefinition
|
||||
GetSubchannelRequest: MessageTypeDefinition
|
||||
GetSubchannelResponse: MessageTypeDefinition
|
||||
GetTopChannelsRequest: MessageTypeDefinition
|
||||
GetTopChannelsResponse: MessageTypeDefinition
|
||||
Security: MessageTypeDefinition
|
||||
Server: MessageTypeDefinition
|
||||
ServerData: MessageTypeDefinition
|
||||
ServerRef: MessageTypeDefinition
|
||||
Socket: MessageTypeDefinition
|
||||
SocketData: MessageTypeDefinition
|
||||
SocketOption: MessageTypeDefinition
|
||||
SocketOptionLinger: MessageTypeDefinition
|
||||
SocketOptionTcpInfo: MessageTypeDefinition
|
||||
SocketOptionTimeout: MessageTypeDefinition
|
||||
SocketRef: MessageTypeDefinition
|
||||
Subchannel: MessageTypeDefinition
|
||||
SubchannelRef: MessageTypeDefinition
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// Original file: null
|
||||
|
||||
import type { AnyExtension } from '@grpc/proto-loader';
|
||||
|
||||
export type Any = AnyExtension | {
|
||||
type_url: string;
|
||||
value: Buffer | Uint8Array | string;
|
||||
}
|
||||
|
||||
export interface Any__Output {
|
||||
'type_url': (string);
|
||||
'value': (Buffer);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// Original file: null
|
||||
|
||||
|
||||
export interface BoolValue {
|
||||
'value'?: (boolean);
|
||||
}
|
||||
|
||||
export interface BoolValue__Output {
|
||||
'value': (boolean);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// Original file: null
|
||||
|
||||
|
||||
export interface BytesValue {
|
||||
'value'?: (Buffer | Uint8Array | string);
|
||||
}
|
||||
|
||||
export interface BytesValue__Output {
|
||||
'value': (Buffer);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// Original file: null
|
||||
|
||||
|
||||
export interface DoubleValue {
|
||||
'value'?: (number | string);
|
||||
}
|
||||
|
||||
export interface DoubleValue__Output {
|
||||
'value': (number);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// Original file: null
|
||||
|
||||
import type { Long } from '@grpc/proto-loader';
|
||||
|
||||
export interface Duration {
|
||||
'seconds'?: (number | string | Long);
|
||||
'nanos'?: (number);
|
||||
}
|
||||
|
||||
export interface Duration__Output {
|
||||
'seconds': (string);
|
||||
'nanos': (number);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// Original file: null
|
||||
|
||||
|
||||
export interface FloatValue {
|
||||
'value'?: (number | string);
|
||||
}
|
||||
|
||||
export interface FloatValue__Output {
|
||||
'value': (number);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// Original file: null
|
||||
|
||||
|
||||
export interface Int32Value {
|
||||
'value'?: (number);
|
||||
}
|
||||
|
||||
export interface Int32Value__Output {
|
||||
'value': (number);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
// Original file: null
|
||||
|
||||
import type { Long } from '@grpc/proto-loader';
|
||||
|
||||
export interface Int64Value {
|
||||
'value'?: (number | string | Long);
|
||||
}
|
||||
|
||||
export interface Int64Value__Output {
|
||||
'value': (string);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// Original file: null
|
||||
|
||||
|
||||
export interface StringValue {
|
||||
'value'?: (string);
|
||||
}
|
||||
|
||||
export interface StringValue__Output {
|
||||
'value': (string);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// Original file: null
|
||||
|
||||
import type { Long } from '@grpc/proto-loader';
|
||||
|
||||
export interface Timestamp {
|
||||
'seconds'?: (number | string | Long);
|
||||
'nanos'?: (number);
|
||||
}
|
||||
|
||||
export interface Timestamp__Output {
|
||||
'seconds': (string);
|
||||
'nanos': (number);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// Original file: null
|
||||
|
||||
|
||||
export interface UInt32Value {
|
||||
'value'?: (number);
|
||||
}
|
||||
|
||||
export interface UInt32Value__Output {
|
||||
'value': (number);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
// Original file: null
|
||||
|
||||
import type { Long } from '@grpc/proto-loader';
|
||||
|
||||
export interface UInt64Value {
|
||||
'value'?: (number | string | Long);
|
||||
}
|
||||
|
||||
export interface UInt64Value__Output {
|
||||
'value': (string);
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../google/protobuf/Any';
|
||||
|
||||
/**
|
||||
* An address type not included above.
|
||||
*/
|
||||
export interface _grpc_channelz_v1_Address_OtherAddress {
|
||||
/**
|
||||
* The human readable version of the value. This value should be set.
|
||||
*/
|
||||
'name'?: (string);
|
||||
/**
|
||||
* The actual address message.
|
||||
*/
|
||||
'value'?: (_google_protobuf_Any | null);
|
||||
}
|
||||
|
||||
/**
|
||||
* An address type not included above.
|
||||
*/
|
||||
export interface _grpc_channelz_v1_Address_OtherAddress__Output {
|
||||
/**
|
||||
* The human readable version of the value. This value should be set.
|
||||
*/
|
||||
'name': (string);
|
||||
/**
|
||||
* The actual address message.
|
||||
*/
|
||||
'value': (_google_protobuf_Any__Output | null);
|
||||
}
|
||||
|
||||
export interface _grpc_channelz_v1_Address_TcpIpAddress {
|
||||
/**
|
||||
* Either the IPv4 or IPv6 address in bytes. Will be either 4 bytes or 16
|
||||
* bytes in length.
|
||||
*/
|
||||
'ip_address'?: (Buffer | Uint8Array | string);
|
||||
/**
|
||||
* 0-64k, or -1 if not appropriate.
|
||||
*/
|
||||
'port'?: (number);
|
||||
}
|
||||
|
||||
export interface _grpc_channelz_v1_Address_TcpIpAddress__Output {
|
||||
/**
|
||||
* Either the IPv4 or IPv6 address in bytes. Will be either 4 bytes or 16
|
||||
* bytes in length.
|
||||
*/
|
||||
'ip_address': (Buffer);
|
||||
/**
|
||||
* 0-64k, or -1 if not appropriate.
|
||||
*/
|
||||
'port': (number);
|
||||
}
|
||||
|
||||
/**
|
||||
* A Unix Domain Socket address.
|
||||
*/
|
||||
export interface _grpc_channelz_v1_Address_UdsAddress {
|
||||
'filename'?: (string);
|
||||
}
|
||||
|
||||
/**
|
||||
* A Unix Domain Socket address.
|
||||
*/
|
||||
export interface _grpc_channelz_v1_Address_UdsAddress__Output {
|
||||
'filename': (string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Address represents the address used to create the socket.
|
||||
*/
|
||||
export interface Address {
|
||||
'tcpip_address'?: (_grpc_channelz_v1_Address_TcpIpAddress | null);
|
||||
'uds_address'?: (_grpc_channelz_v1_Address_UdsAddress | null);
|
||||
'other_address'?: (_grpc_channelz_v1_Address_OtherAddress | null);
|
||||
'address'?: "tcpip_address"|"uds_address"|"other_address";
|
||||
}
|
||||
|
||||
/**
|
||||
* Address represents the address used to create the socket.
|
||||
*/
|
||||
export interface Address__Output {
|
||||
'tcpip_address'?: (_grpc_channelz_v1_Address_TcpIpAddress__Output | null);
|
||||
'uds_address'?: (_grpc_channelz_v1_Address_UdsAddress__Output | null);
|
||||
'other_address'?: (_grpc_channelz_v1_Address_OtherAddress__Output | null);
|
||||
'address': "tcpip_address"|"uds_address"|"other_address";
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { ChannelRef as _grpc_channelz_v1_ChannelRef, ChannelRef__Output as _grpc_channelz_v1_ChannelRef__Output } from '../../../grpc/channelz/v1/ChannelRef';
|
||||
import type { ChannelData as _grpc_channelz_v1_ChannelData, ChannelData__Output as _grpc_channelz_v1_ChannelData__Output } from '../../../grpc/channelz/v1/ChannelData';
|
||||
import type { SubchannelRef as _grpc_channelz_v1_SubchannelRef, SubchannelRef__Output as _grpc_channelz_v1_SubchannelRef__Output } from '../../../grpc/channelz/v1/SubchannelRef';
|
||||
import type { SocketRef as _grpc_channelz_v1_SocketRef, SocketRef__Output as _grpc_channelz_v1_SocketRef__Output } from '../../../grpc/channelz/v1/SocketRef';
|
||||
|
||||
/**
|
||||
* Channel is a logical grouping of channels, subchannels, and sockets.
|
||||
*/
|
||||
export interface Channel {
|
||||
/**
|
||||
* The identifier for this channel. This should bet set.
|
||||
*/
|
||||
'ref'?: (_grpc_channelz_v1_ChannelRef | null);
|
||||
/**
|
||||
* Data specific to this channel.
|
||||
*/
|
||||
'data'?: (_grpc_channelz_v1_ChannelData | null);
|
||||
/**
|
||||
* There are no ordering guarantees on the order of channel refs.
|
||||
* There may not be cycles in the ref graph.
|
||||
* A channel ref may be present in more than one channel or subchannel.
|
||||
*/
|
||||
'channel_ref'?: (_grpc_channelz_v1_ChannelRef)[];
|
||||
/**
|
||||
* At most one of 'channel_ref+subchannel_ref' and 'socket' is set.
|
||||
* There are no ordering guarantees on the order of subchannel refs.
|
||||
* There may not be cycles in the ref graph.
|
||||
* A sub channel ref may be present in more than one channel or subchannel.
|
||||
*/
|
||||
'subchannel_ref'?: (_grpc_channelz_v1_SubchannelRef)[];
|
||||
/**
|
||||
* There are no ordering guarantees on the order of sockets.
|
||||
*/
|
||||
'socket_ref'?: (_grpc_channelz_v1_SocketRef)[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel is a logical grouping of channels, subchannels, and sockets.
|
||||
*/
|
||||
export interface Channel__Output {
|
||||
/**
|
||||
* The identifier for this channel. This should bet set.
|
||||
*/
|
||||
'ref': (_grpc_channelz_v1_ChannelRef__Output | null);
|
||||
/**
|
||||
* Data specific to this channel.
|
||||
*/
|
||||
'data': (_grpc_channelz_v1_ChannelData__Output | null);
|
||||
/**
|
||||
* There are no ordering guarantees on the order of channel refs.
|
||||
* There may not be cycles in the ref graph.
|
||||
* A channel ref may be present in more than one channel or subchannel.
|
||||
*/
|
||||
'channel_ref': (_grpc_channelz_v1_ChannelRef__Output)[];
|
||||
/**
|
||||
* At most one of 'channel_ref+subchannel_ref' and 'socket' is set.
|
||||
* There are no ordering guarantees on the order of subchannel refs.
|
||||
* There may not be cycles in the ref graph.
|
||||
* A sub channel ref may be present in more than one channel or subchannel.
|
||||
*/
|
||||
'subchannel_ref': (_grpc_channelz_v1_SubchannelRef__Output)[];
|
||||
/**
|
||||
* There are no ordering guarantees on the order of sockets.
|
||||
*/
|
||||
'socket_ref': (_grpc_channelz_v1_SocketRef__Output)[];
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
|
||||
// Original file: proto/channelz.proto
|
||||
|
||||
export enum _grpc_channelz_v1_ChannelConnectivityState_State {
|
||||
UNKNOWN = 0,
|
||||
IDLE = 1,
|
||||
CONNECTING = 2,
|
||||
READY = 3,
|
||||
TRANSIENT_FAILURE = 4,
|
||||
SHUTDOWN = 5,
|
||||
}
|
||||
|
||||
/**
|
||||
* These come from the specified states in this document:
|
||||
* https://github.com/grpc/grpc/blob/master/doc/connectivity-semantics-and-api.md
|
||||
*/
|
||||
export interface ChannelConnectivityState {
|
||||
'state'?: (_grpc_channelz_v1_ChannelConnectivityState_State | keyof typeof _grpc_channelz_v1_ChannelConnectivityState_State);
|
||||
}
|
||||
|
||||
/**
|
||||
* These come from the specified states in this document:
|
||||
* https://github.com/grpc/grpc/blob/master/doc/connectivity-semantics-and-api.md
|
||||
*/
|
||||
export interface ChannelConnectivityState__Output {
|
||||
'state': (keyof typeof _grpc_channelz_v1_ChannelConnectivityState_State);
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { ChannelConnectivityState as _grpc_channelz_v1_ChannelConnectivityState, ChannelConnectivityState__Output as _grpc_channelz_v1_ChannelConnectivityState__Output } from '../../../grpc/channelz/v1/ChannelConnectivityState';
|
||||
import type { ChannelTrace as _grpc_channelz_v1_ChannelTrace, ChannelTrace__Output as _grpc_channelz_v1_ChannelTrace__Output } from '../../../grpc/channelz/v1/ChannelTrace';
|
||||
import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp';
|
||||
import type { Long } from '@grpc/proto-loader';
|
||||
|
||||
/**
|
||||
* Channel data is data related to a specific Channel or Subchannel.
|
||||
*/
|
||||
export interface ChannelData {
|
||||
/**
|
||||
* The connectivity state of the channel or subchannel. Implementations
|
||||
* should always set this.
|
||||
*/
|
||||
'state'?: (_grpc_channelz_v1_ChannelConnectivityState | null);
|
||||
/**
|
||||
* The target this channel originally tried to connect to. May be absent
|
||||
*/
|
||||
'target'?: (string);
|
||||
/**
|
||||
* A trace of recent events on the channel. May be absent.
|
||||
*/
|
||||
'trace'?: (_grpc_channelz_v1_ChannelTrace | null);
|
||||
/**
|
||||
* The number of calls started on the channel
|
||||
*/
|
||||
'calls_started'?: (number | string | Long);
|
||||
/**
|
||||
* The number of calls that have completed with an OK status
|
||||
*/
|
||||
'calls_succeeded'?: (number | string | Long);
|
||||
/**
|
||||
* The number of calls that have completed with a non-OK status
|
||||
*/
|
||||
'calls_failed'?: (number | string | Long);
|
||||
/**
|
||||
* The last time a call was started on the channel.
|
||||
*/
|
||||
'last_call_started_timestamp'?: (_google_protobuf_Timestamp | null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel data is data related to a specific Channel or Subchannel.
|
||||
*/
|
||||
export interface ChannelData__Output {
|
||||
/**
|
||||
* The connectivity state of the channel or subchannel. Implementations
|
||||
* should always set this.
|
||||
*/
|
||||
'state': (_grpc_channelz_v1_ChannelConnectivityState__Output | null);
|
||||
/**
|
||||
* The target this channel originally tried to connect to. May be absent
|
||||
*/
|
||||
'target': (string);
|
||||
/**
|
||||
* A trace of recent events on the channel. May be absent.
|
||||
*/
|
||||
'trace': (_grpc_channelz_v1_ChannelTrace__Output | null);
|
||||
/**
|
||||
* The number of calls started on the channel
|
||||
*/
|
||||
'calls_started': (string);
|
||||
/**
|
||||
* The number of calls that have completed with an OK status
|
||||
*/
|
||||
'calls_succeeded': (string);
|
||||
/**
|
||||
* The number of calls that have completed with a non-OK status
|
||||
*/
|
||||
'calls_failed': (string);
|
||||
/**
|
||||
* The last time a call was started on the channel.
|
||||
*/
|
||||
'last_call_started_timestamp': (_google_protobuf_Timestamp__Output | null);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Long } from '@grpc/proto-loader';
|
||||
|
||||
/**
|
||||
* ChannelRef is a reference to a Channel.
|
||||
*/
|
||||
export interface ChannelRef {
|
||||
/**
|
||||
* The globally unique id for this channel. Must be a positive number.
|
||||
*/
|
||||
'channel_id'?: (number | string | Long);
|
||||
/**
|
||||
* An optional name associated with the channel.
|
||||
*/
|
||||
'name'?: (string);
|
||||
}
|
||||
|
||||
/**
|
||||
* ChannelRef is a reference to a Channel.
|
||||
*/
|
||||
export interface ChannelRef__Output {
|
||||
/**
|
||||
* The globally unique id for this channel. Must be a positive number.
|
||||
*/
|
||||
'channel_id': (string);
|
||||
/**
|
||||
* An optional name associated with the channel.
|
||||
*/
|
||||
'name': (string);
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp';
|
||||
import type { ChannelTraceEvent as _grpc_channelz_v1_ChannelTraceEvent, ChannelTraceEvent__Output as _grpc_channelz_v1_ChannelTraceEvent__Output } from '../../../grpc/channelz/v1/ChannelTraceEvent';
|
||||
import type { Long } from '@grpc/proto-loader';
|
||||
|
||||
/**
|
||||
* ChannelTrace represents the recent events that have occurred on the channel.
|
||||
*/
|
||||
export interface ChannelTrace {
|
||||
/**
|
||||
* Number of events ever logged in this tracing object. This can differ from
|
||||
* events.size() because events can be overwritten or garbage collected by
|
||||
* implementations.
|
||||
*/
|
||||
'num_events_logged'?: (number | string | Long);
|
||||
/**
|
||||
* Time that this channel was created.
|
||||
*/
|
||||
'creation_timestamp'?: (_google_protobuf_Timestamp | null);
|
||||
/**
|
||||
* List of events that have occurred on this channel.
|
||||
*/
|
||||
'events'?: (_grpc_channelz_v1_ChannelTraceEvent)[];
|
||||
}
|
||||
|
||||
/**
|
||||
* ChannelTrace represents the recent events that have occurred on the channel.
|
||||
*/
|
||||
export interface ChannelTrace__Output {
|
||||
/**
|
||||
* Number of events ever logged in this tracing object. This can differ from
|
||||
* events.size() because events can be overwritten or garbage collected by
|
||||
* implementations.
|
||||
*/
|
||||
'num_events_logged': (string);
|
||||
/**
|
||||
* Time that this channel was created.
|
||||
*/
|
||||
'creation_timestamp': (_google_protobuf_Timestamp__Output | null);
|
||||
/**
|
||||
* List of events that have occurred on this channel.
|
||||
*/
|
||||
'events': (_grpc_channelz_v1_ChannelTraceEvent__Output)[];
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp';
|
||||
import type { ChannelRef as _grpc_channelz_v1_ChannelRef, ChannelRef__Output as _grpc_channelz_v1_ChannelRef__Output } from '../../../grpc/channelz/v1/ChannelRef';
|
||||
import type { SubchannelRef as _grpc_channelz_v1_SubchannelRef, SubchannelRef__Output as _grpc_channelz_v1_SubchannelRef__Output } from '../../../grpc/channelz/v1/SubchannelRef';
|
||||
|
||||
// Original file: proto/channelz.proto
|
||||
|
||||
/**
|
||||
* The supported severity levels of trace events.
|
||||
*/
|
||||
export enum _grpc_channelz_v1_ChannelTraceEvent_Severity {
|
||||
CT_UNKNOWN = 0,
|
||||
CT_INFO = 1,
|
||||
CT_WARNING = 2,
|
||||
CT_ERROR = 3,
|
||||
}
|
||||
|
||||
/**
|
||||
* A trace event is an interesting thing that happened to a channel or
|
||||
* subchannel, such as creation, address resolution, subchannel creation, etc.
|
||||
*/
|
||||
export interface ChannelTraceEvent {
|
||||
/**
|
||||
* High level description of the event.
|
||||
*/
|
||||
'description'?: (string);
|
||||
/**
|
||||
* the severity of the trace event
|
||||
*/
|
||||
'severity'?: (_grpc_channelz_v1_ChannelTraceEvent_Severity | keyof typeof _grpc_channelz_v1_ChannelTraceEvent_Severity);
|
||||
/**
|
||||
* When this event occurred.
|
||||
*/
|
||||
'timestamp'?: (_google_protobuf_Timestamp | null);
|
||||
'channel_ref'?: (_grpc_channelz_v1_ChannelRef | null);
|
||||
'subchannel_ref'?: (_grpc_channelz_v1_SubchannelRef | null);
|
||||
/**
|
||||
* ref of referenced channel or subchannel.
|
||||
* Optional, only present if this event refers to a child object. For example,
|
||||
* this field would be filled if this trace event was for a subchannel being
|
||||
* created.
|
||||
*/
|
||||
'child_ref'?: "channel_ref"|"subchannel_ref";
|
||||
}
|
||||
|
||||
/**
|
||||
* A trace event is an interesting thing that happened to a channel or
|
||||
* subchannel, such as creation, address resolution, subchannel creation, etc.
|
||||
*/
|
||||
export interface ChannelTraceEvent__Output {
|
||||
/**
|
||||
* High level description of the event.
|
||||
*/
|
||||
'description': (string);
|
||||
/**
|
||||
* the severity of the trace event
|
||||
*/
|
||||
'severity': (keyof typeof _grpc_channelz_v1_ChannelTraceEvent_Severity);
|
||||
/**
|
||||
* When this event occurred.
|
||||
*/
|
||||
'timestamp': (_google_protobuf_Timestamp__Output | null);
|
||||
'channel_ref'?: (_grpc_channelz_v1_ChannelRef__Output | null);
|
||||
'subchannel_ref'?: (_grpc_channelz_v1_SubchannelRef__Output | null);
|
||||
/**
|
||||
* ref of referenced channel or subchannel.
|
||||
* Optional, only present if this event refers to a child object. For example,
|
||||
* this field would be filled if this trace event was for a subchannel being
|
||||
* created.
|
||||
*/
|
||||
'child_ref': "channel_ref"|"subchannel_ref";
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type * as grpc from '../../../../index'
|
||||
import type { MethodDefinition } from '@grpc/proto-loader'
|
||||
import type { GetChannelRequest as _grpc_channelz_v1_GetChannelRequest, GetChannelRequest__Output as _grpc_channelz_v1_GetChannelRequest__Output } from '../../../grpc/channelz/v1/GetChannelRequest';
|
||||
import type { GetChannelResponse as _grpc_channelz_v1_GetChannelResponse, GetChannelResponse__Output as _grpc_channelz_v1_GetChannelResponse__Output } from '../../../grpc/channelz/v1/GetChannelResponse';
|
||||
import type { GetServerRequest as _grpc_channelz_v1_GetServerRequest, GetServerRequest__Output as _grpc_channelz_v1_GetServerRequest__Output } from '../../../grpc/channelz/v1/GetServerRequest';
|
||||
import type { GetServerResponse as _grpc_channelz_v1_GetServerResponse, GetServerResponse__Output as _grpc_channelz_v1_GetServerResponse__Output } from '../../../grpc/channelz/v1/GetServerResponse';
|
||||
import type { GetServerSocketsRequest as _grpc_channelz_v1_GetServerSocketsRequest, GetServerSocketsRequest__Output as _grpc_channelz_v1_GetServerSocketsRequest__Output } from '../../../grpc/channelz/v1/GetServerSocketsRequest';
|
||||
import type { GetServerSocketsResponse as _grpc_channelz_v1_GetServerSocketsResponse, GetServerSocketsResponse__Output as _grpc_channelz_v1_GetServerSocketsResponse__Output } from '../../../grpc/channelz/v1/GetServerSocketsResponse';
|
||||
import type { GetServersRequest as _grpc_channelz_v1_GetServersRequest, GetServersRequest__Output as _grpc_channelz_v1_GetServersRequest__Output } from '../../../grpc/channelz/v1/GetServersRequest';
|
||||
import type { GetServersResponse as _grpc_channelz_v1_GetServersResponse, GetServersResponse__Output as _grpc_channelz_v1_GetServersResponse__Output } from '../../../grpc/channelz/v1/GetServersResponse';
|
||||
import type { GetSocketRequest as _grpc_channelz_v1_GetSocketRequest, GetSocketRequest__Output as _grpc_channelz_v1_GetSocketRequest__Output } from '../../../grpc/channelz/v1/GetSocketRequest';
|
||||
import type { GetSocketResponse as _grpc_channelz_v1_GetSocketResponse, GetSocketResponse__Output as _grpc_channelz_v1_GetSocketResponse__Output } from '../../../grpc/channelz/v1/GetSocketResponse';
|
||||
import type { GetSubchannelRequest as _grpc_channelz_v1_GetSubchannelRequest, GetSubchannelRequest__Output as _grpc_channelz_v1_GetSubchannelRequest__Output } from '../../../grpc/channelz/v1/GetSubchannelRequest';
|
||||
import type { GetSubchannelResponse as _grpc_channelz_v1_GetSubchannelResponse, GetSubchannelResponse__Output as _grpc_channelz_v1_GetSubchannelResponse__Output } from '../../../grpc/channelz/v1/GetSubchannelResponse';
|
||||
import type { GetTopChannelsRequest as _grpc_channelz_v1_GetTopChannelsRequest, GetTopChannelsRequest__Output as _grpc_channelz_v1_GetTopChannelsRequest__Output } from '../../../grpc/channelz/v1/GetTopChannelsRequest';
|
||||
import type { GetTopChannelsResponse as _grpc_channelz_v1_GetTopChannelsResponse, GetTopChannelsResponse__Output as _grpc_channelz_v1_GetTopChannelsResponse__Output } from '../../../grpc/channelz/v1/GetTopChannelsResponse';
|
||||
|
||||
/**
|
||||
* Channelz is a service exposed by gRPC servers that provides detailed debug
|
||||
* information.
|
||||
*/
|
||||
export interface ChannelzClient extends grpc.Client {
|
||||
/**
|
||||
* Returns a single Channel, or else a NOT_FOUND code.
|
||||
*/
|
||||
GetChannel(argument: _grpc_channelz_v1_GetChannelRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetChannelResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
GetChannel(argument: _grpc_channelz_v1_GetChannelRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetChannelResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
GetChannel(argument: _grpc_channelz_v1_GetChannelRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetChannelResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
GetChannel(argument: _grpc_channelz_v1_GetChannelRequest, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetChannelResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
|
||||
/**
|
||||
* Returns a single Server, or else a NOT_FOUND code.
|
||||
*/
|
||||
GetServer(argument: _grpc_channelz_v1_GetServerRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServerResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
GetServer(argument: _grpc_channelz_v1_GetServerRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServerResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
GetServer(argument: _grpc_channelz_v1_GetServerRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServerResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
GetServer(argument: _grpc_channelz_v1_GetServerRequest, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServerResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
/**
|
||||
* Returns a single Server, or else a NOT_FOUND code.
|
||||
*/
|
||||
getServer(argument: _grpc_channelz_v1_GetServerRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServerResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
getServer(argument: _grpc_channelz_v1_GetServerRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServerResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
getServer(argument: _grpc_channelz_v1_GetServerRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServerResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
getServer(argument: _grpc_channelz_v1_GetServerRequest, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServerResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
|
||||
/**
|
||||
* Gets all server sockets that exist in the process.
|
||||
*/
|
||||
GetServerSockets(argument: _grpc_channelz_v1_GetServerSocketsRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServerSocketsResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
GetServerSockets(argument: _grpc_channelz_v1_GetServerSocketsRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServerSocketsResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
GetServerSockets(argument: _grpc_channelz_v1_GetServerSocketsRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServerSocketsResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
GetServerSockets(argument: _grpc_channelz_v1_GetServerSocketsRequest, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServerSocketsResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
/**
|
||||
* Gets all server sockets that exist in the process.
|
||||
*/
|
||||
getServerSockets(argument: _grpc_channelz_v1_GetServerSocketsRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServerSocketsResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
getServerSockets(argument: _grpc_channelz_v1_GetServerSocketsRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServerSocketsResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
getServerSockets(argument: _grpc_channelz_v1_GetServerSocketsRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServerSocketsResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
getServerSockets(argument: _grpc_channelz_v1_GetServerSocketsRequest, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServerSocketsResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
|
||||
/**
|
||||
* Gets all servers that exist in the process.
|
||||
*/
|
||||
GetServers(argument: _grpc_channelz_v1_GetServersRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServersResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
GetServers(argument: _grpc_channelz_v1_GetServersRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServersResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
GetServers(argument: _grpc_channelz_v1_GetServersRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServersResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
GetServers(argument: _grpc_channelz_v1_GetServersRequest, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServersResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
/**
|
||||
* Gets all servers that exist in the process.
|
||||
*/
|
||||
getServers(argument: _grpc_channelz_v1_GetServersRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServersResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
getServers(argument: _grpc_channelz_v1_GetServersRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServersResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
getServers(argument: _grpc_channelz_v1_GetServersRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServersResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
getServers(argument: _grpc_channelz_v1_GetServersRequest, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetServersResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
|
||||
/**
|
||||
* Returns a single Socket or else a NOT_FOUND code.
|
||||
*/
|
||||
GetSocket(argument: _grpc_channelz_v1_GetSocketRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetSocketResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
GetSocket(argument: _grpc_channelz_v1_GetSocketRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetSocketResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
GetSocket(argument: _grpc_channelz_v1_GetSocketRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetSocketResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
GetSocket(argument: _grpc_channelz_v1_GetSocketRequest, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetSocketResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
/**
|
||||
* Returns a single Socket or else a NOT_FOUND code.
|
||||
*/
|
||||
getSocket(argument: _grpc_channelz_v1_GetSocketRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetSocketResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
getSocket(argument: _grpc_channelz_v1_GetSocketRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetSocketResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
getSocket(argument: _grpc_channelz_v1_GetSocketRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetSocketResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
getSocket(argument: _grpc_channelz_v1_GetSocketRequest, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetSocketResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
|
||||
/**
|
||||
* Returns a single Subchannel, or else a NOT_FOUND code.
|
||||
*/
|
||||
GetSubchannel(argument: _grpc_channelz_v1_GetSubchannelRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetSubchannelResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
GetSubchannel(argument: _grpc_channelz_v1_GetSubchannelRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetSubchannelResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
GetSubchannel(argument: _grpc_channelz_v1_GetSubchannelRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetSubchannelResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
GetSubchannel(argument: _grpc_channelz_v1_GetSubchannelRequest, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetSubchannelResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
/**
|
||||
* Returns a single Subchannel, or else a NOT_FOUND code.
|
||||
*/
|
||||
getSubchannel(argument: _grpc_channelz_v1_GetSubchannelRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetSubchannelResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
getSubchannel(argument: _grpc_channelz_v1_GetSubchannelRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetSubchannelResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
getSubchannel(argument: _grpc_channelz_v1_GetSubchannelRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetSubchannelResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
getSubchannel(argument: _grpc_channelz_v1_GetSubchannelRequest, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetSubchannelResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
|
||||
/**
|
||||
* Gets all root channels (i.e. channels the application has directly
|
||||
* created). This does not include subchannels nor non-top level channels.
|
||||
*/
|
||||
GetTopChannels(argument: _grpc_channelz_v1_GetTopChannelsRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetTopChannelsResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
GetTopChannels(argument: _grpc_channelz_v1_GetTopChannelsRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetTopChannelsResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
GetTopChannels(argument: _grpc_channelz_v1_GetTopChannelsRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetTopChannelsResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
GetTopChannels(argument: _grpc_channelz_v1_GetTopChannelsRequest, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetTopChannelsResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
/**
|
||||
* Gets all root channels (i.e. channels the application has directly
|
||||
* created). This does not include subchannels nor non-top level channels.
|
||||
*/
|
||||
getTopChannels(argument: _grpc_channelz_v1_GetTopChannelsRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetTopChannelsResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
getTopChannels(argument: _grpc_channelz_v1_GetTopChannelsRequest, metadata: grpc.Metadata, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetTopChannelsResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
getTopChannels(argument: _grpc_channelz_v1_GetTopChannelsRequest, options: grpc.CallOptions, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetTopChannelsResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
getTopChannels(argument: _grpc_channelz_v1_GetTopChannelsRequest, callback: (error?: grpc.ServiceError, result?: _grpc_channelz_v1_GetTopChannelsResponse__Output) => void): grpc.ClientUnaryCall;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Channelz is a service exposed by gRPC servers that provides detailed debug
|
||||
* information.
|
||||
*/
|
||||
export interface ChannelzHandlers extends grpc.UntypedServiceImplementation {
|
||||
/**
|
||||
* Returns a single Channel, or else a NOT_FOUND code.
|
||||
*/
|
||||
GetChannel: grpc.handleUnaryCall<_grpc_channelz_v1_GetChannelRequest__Output, _grpc_channelz_v1_GetChannelResponse>;
|
||||
|
||||
/**
|
||||
* Returns a single Server, or else a NOT_FOUND code.
|
||||
*/
|
||||
GetServer: grpc.handleUnaryCall<_grpc_channelz_v1_GetServerRequest__Output, _grpc_channelz_v1_GetServerResponse>;
|
||||
|
||||
/**
|
||||
* Gets all server sockets that exist in the process.
|
||||
*/
|
||||
GetServerSockets: grpc.handleUnaryCall<_grpc_channelz_v1_GetServerSocketsRequest__Output, _grpc_channelz_v1_GetServerSocketsResponse>;
|
||||
|
||||
/**
|
||||
* Gets all servers that exist in the process.
|
||||
*/
|
||||
GetServers: grpc.handleUnaryCall<_grpc_channelz_v1_GetServersRequest__Output, _grpc_channelz_v1_GetServersResponse>;
|
||||
|
||||
/**
|
||||
* Returns a single Socket or else a NOT_FOUND code.
|
||||
*/
|
||||
GetSocket: grpc.handleUnaryCall<_grpc_channelz_v1_GetSocketRequest__Output, _grpc_channelz_v1_GetSocketResponse>;
|
||||
|
||||
/**
|
||||
* Returns a single Subchannel, or else a NOT_FOUND code.
|
||||
*/
|
||||
GetSubchannel: grpc.handleUnaryCall<_grpc_channelz_v1_GetSubchannelRequest__Output, _grpc_channelz_v1_GetSubchannelResponse>;
|
||||
|
||||
/**
|
||||
* Gets all root channels (i.e. channels the application has directly
|
||||
* created). This does not include subchannels nor non-top level channels.
|
||||
*/
|
||||
GetTopChannels: grpc.handleUnaryCall<_grpc_channelz_v1_GetTopChannelsRequest__Output, _grpc_channelz_v1_GetTopChannelsResponse>;
|
||||
|
||||
}
|
||||
|
||||
export interface ChannelzDefinition extends grpc.ServiceDefinition {
|
||||
GetChannel: MethodDefinition<_grpc_channelz_v1_GetChannelRequest, _grpc_channelz_v1_GetChannelResponse, _grpc_channelz_v1_GetChannelRequest__Output, _grpc_channelz_v1_GetChannelResponse__Output>
|
||||
GetServer: MethodDefinition<_grpc_channelz_v1_GetServerRequest, _grpc_channelz_v1_GetServerResponse, _grpc_channelz_v1_GetServerRequest__Output, _grpc_channelz_v1_GetServerResponse__Output>
|
||||
GetServerSockets: MethodDefinition<_grpc_channelz_v1_GetServerSocketsRequest, _grpc_channelz_v1_GetServerSocketsResponse, _grpc_channelz_v1_GetServerSocketsRequest__Output, _grpc_channelz_v1_GetServerSocketsResponse__Output>
|
||||
GetServers: MethodDefinition<_grpc_channelz_v1_GetServersRequest, _grpc_channelz_v1_GetServersResponse, _grpc_channelz_v1_GetServersRequest__Output, _grpc_channelz_v1_GetServersResponse__Output>
|
||||
GetSocket: MethodDefinition<_grpc_channelz_v1_GetSocketRequest, _grpc_channelz_v1_GetSocketResponse, _grpc_channelz_v1_GetSocketRequest__Output, _grpc_channelz_v1_GetSocketResponse__Output>
|
||||
GetSubchannel: MethodDefinition<_grpc_channelz_v1_GetSubchannelRequest, _grpc_channelz_v1_GetSubchannelResponse, _grpc_channelz_v1_GetSubchannelRequest__Output, _grpc_channelz_v1_GetSubchannelResponse__Output>
|
||||
GetTopChannels: MethodDefinition<_grpc_channelz_v1_GetTopChannelsRequest, _grpc_channelz_v1_GetTopChannelsResponse, _grpc_channelz_v1_GetTopChannelsRequest__Output, _grpc_channelz_v1_GetTopChannelsResponse__Output>
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Long } from '@grpc/proto-loader';
|
||||
|
||||
export interface GetChannelRequest {
|
||||
/**
|
||||
* channel_id is the identifier of the specific channel to get.
|
||||
*/
|
||||
'channel_id'?: (number | string | Long);
|
||||
}
|
||||
|
||||
export interface GetChannelRequest__Output {
|
||||
/**
|
||||
* channel_id is the identifier of the specific channel to get.
|
||||
*/
|
||||
'channel_id': (string);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Channel as _grpc_channelz_v1_Channel, Channel__Output as _grpc_channelz_v1_Channel__Output } from '../../../grpc/channelz/v1/Channel';
|
||||
|
||||
export interface GetChannelResponse {
|
||||
/**
|
||||
* The Channel that corresponds to the requested channel_id. This field
|
||||
* should be set.
|
||||
*/
|
||||
'channel'?: (_grpc_channelz_v1_Channel | null);
|
||||
}
|
||||
|
||||
export interface GetChannelResponse__Output {
|
||||
/**
|
||||
* The Channel that corresponds to the requested channel_id. This field
|
||||
* should be set.
|
||||
*/
|
||||
'channel': (_grpc_channelz_v1_Channel__Output | null);
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Long } from '@grpc/proto-loader';
|
||||
|
||||
export interface GetServerRequest {
|
||||
/**
|
||||
* server_id is the identifier of the specific server to get.
|
||||
*/
|
||||
'server_id'?: (number | string | Long);
|
||||
}
|
||||
|
||||
export interface GetServerRequest__Output {
|
||||
/**
|
||||
* server_id is the identifier of the specific server to get.
|
||||
*/
|
||||
'server_id': (string);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Server as _grpc_channelz_v1_Server, Server__Output as _grpc_channelz_v1_Server__Output } from '../../../grpc/channelz/v1/Server';
|
||||
|
||||
export interface GetServerResponse {
|
||||
/**
|
||||
* The Server that corresponds to the requested server_id. This field
|
||||
* should be set.
|
||||
*/
|
||||
'server'?: (_grpc_channelz_v1_Server | null);
|
||||
}
|
||||
|
||||
export interface GetServerResponse__Output {
|
||||
/**
|
||||
* The Server that corresponds to the requested server_id. This field
|
||||
* should be set.
|
||||
*/
|
||||
'server': (_grpc_channelz_v1_Server__Output | null);
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Long } from '@grpc/proto-loader';
|
||||
|
||||
export interface GetServerSocketsRequest {
|
||||
'server_id'?: (number | string | Long);
|
||||
/**
|
||||
* start_socket_id indicates that only sockets at or above this id should be
|
||||
* included in the results.
|
||||
* To request the first page, this must be set to 0. To request
|
||||
* subsequent pages, the client generates this value by adding 1 to
|
||||
* the highest seen result ID.
|
||||
*/
|
||||
'start_socket_id'?: (number | string | Long);
|
||||
/**
|
||||
* If non-zero, the server will return a page of results containing
|
||||
* at most this many items. If zero, the server will choose a
|
||||
* reasonable page size. Must never be negative.
|
||||
*/
|
||||
'max_results'?: (number | string | Long);
|
||||
}
|
||||
|
||||
export interface GetServerSocketsRequest__Output {
|
||||
'server_id': (string);
|
||||
/**
|
||||
* start_socket_id indicates that only sockets at or above this id should be
|
||||
* included in the results.
|
||||
* To request the first page, this must be set to 0. To request
|
||||
* subsequent pages, the client generates this value by adding 1 to
|
||||
* the highest seen result ID.
|
||||
*/
|
||||
'start_socket_id': (string);
|
||||
/**
|
||||
* If non-zero, the server will return a page of results containing
|
||||
* at most this many items. If zero, the server will choose a
|
||||
* reasonable page size. Must never be negative.
|
||||
*/
|
||||
'max_results': (string);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { SocketRef as _grpc_channelz_v1_SocketRef, SocketRef__Output as _grpc_channelz_v1_SocketRef__Output } from '../../../grpc/channelz/v1/SocketRef';
|
||||
|
||||
export interface GetServerSocketsResponse {
|
||||
/**
|
||||
* list of socket refs that the connection detail service knows about. Sorted in
|
||||
* ascending socket_id order.
|
||||
* Must contain at least 1 result, otherwise 'end' must be true.
|
||||
*/
|
||||
'socket_ref'?: (_grpc_channelz_v1_SocketRef)[];
|
||||
/**
|
||||
* If set, indicates that the list of sockets is the final list. Requesting
|
||||
* more sockets will only return more if they are created after this RPC
|
||||
* completes.
|
||||
*/
|
||||
'end'?: (boolean);
|
||||
}
|
||||
|
||||
export interface GetServerSocketsResponse__Output {
|
||||
/**
|
||||
* list of socket refs that the connection detail service knows about. Sorted in
|
||||
* ascending socket_id order.
|
||||
* Must contain at least 1 result, otherwise 'end' must be true.
|
||||
*/
|
||||
'socket_ref': (_grpc_channelz_v1_SocketRef__Output)[];
|
||||
/**
|
||||
* If set, indicates that the list of sockets is the final list. Requesting
|
||||
* more sockets will only return more if they are created after this RPC
|
||||
* completes.
|
||||
*/
|
||||
'end': (boolean);
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Long } from '@grpc/proto-loader';
|
||||
|
||||
export interface GetServersRequest {
|
||||
/**
|
||||
* start_server_id indicates that only servers at or above this id should be
|
||||
* included in the results.
|
||||
* To request the first page, this must be set to 0. To request
|
||||
* subsequent pages, the client generates this value by adding 1 to
|
||||
* the highest seen result ID.
|
||||
*/
|
||||
'start_server_id'?: (number | string | Long);
|
||||
/**
|
||||
* If non-zero, the server will return a page of results containing
|
||||
* at most this many items. If zero, the server will choose a
|
||||
* reasonable page size. Must never be negative.
|
||||
*/
|
||||
'max_results'?: (number | string | Long);
|
||||
}
|
||||
|
||||
export interface GetServersRequest__Output {
|
||||
/**
|
||||
* start_server_id indicates that only servers at or above this id should be
|
||||
* included in the results.
|
||||
* To request the first page, this must be set to 0. To request
|
||||
* subsequent pages, the client generates this value by adding 1 to
|
||||
* the highest seen result ID.
|
||||
*/
|
||||
'start_server_id': (string);
|
||||
/**
|
||||
* If non-zero, the server will return a page of results containing
|
||||
* at most this many items. If zero, the server will choose a
|
||||
* reasonable page size. Must never be negative.
|
||||
*/
|
||||
'max_results': (string);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Server as _grpc_channelz_v1_Server, Server__Output as _grpc_channelz_v1_Server__Output } from '../../../grpc/channelz/v1/Server';
|
||||
|
||||
export interface GetServersResponse {
|
||||
/**
|
||||
* list of servers that the connection detail service knows about. Sorted in
|
||||
* ascending server_id order.
|
||||
* Must contain at least 1 result, otherwise 'end' must be true.
|
||||
*/
|
||||
'server'?: (_grpc_channelz_v1_Server)[];
|
||||
/**
|
||||
* If set, indicates that the list of servers is the final list. Requesting
|
||||
* more servers will only return more if they are created after this RPC
|
||||
* completes.
|
||||
*/
|
||||
'end'?: (boolean);
|
||||
}
|
||||
|
||||
export interface GetServersResponse__Output {
|
||||
/**
|
||||
* list of servers that the connection detail service knows about. Sorted in
|
||||
* ascending server_id order.
|
||||
* Must contain at least 1 result, otherwise 'end' must be true.
|
||||
*/
|
||||
'server': (_grpc_channelz_v1_Server__Output)[];
|
||||
/**
|
||||
* If set, indicates that the list of servers is the final list. Requesting
|
||||
* more servers will only return more if they are created after this RPC
|
||||
* completes.
|
||||
*/
|
||||
'end': (boolean);
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Long } from '@grpc/proto-loader';
|
||||
|
||||
export interface GetSocketRequest {
|
||||
/**
|
||||
* socket_id is the identifier of the specific socket to get.
|
||||
*/
|
||||
'socket_id'?: (number | string | Long);
|
||||
/**
|
||||
* If true, the response will contain only high level information
|
||||
* that is inexpensive to obtain. Fields thay may be omitted are
|
||||
* documented.
|
||||
*/
|
||||
'summary'?: (boolean);
|
||||
}
|
||||
|
||||
export interface GetSocketRequest__Output {
|
||||
/**
|
||||
* socket_id is the identifier of the specific socket to get.
|
||||
*/
|
||||
'socket_id': (string);
|
||||
/**
|
||||
* If true, the response will contain only high level information
|
||||
* that is inexpensive to obtain. Fields thay may be omitted are
|
||||
* documented.
|
||||
*/
|
||||
'summary': (boolean);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Socket as _grpc_channelz_v1_Socket, Socket__Output as _grpc_channelz_v1_Socket__Output } from '../../../grpc/channelz/v1/Socket';
|
||||
|
||||
export interface GetSocketResponse {
|
||||
/**
|
||||
* The Socket that corresponds to the requested socket_id. This field
|
||||
* should be set.
|
||||
*/
|
||||
'socket'?: (_grpc_channelz_v1_Socket | null);
|
||||
}
|
||||
|
||||
export interface GetSocketResponse__Output {
|
||||
/**
|
||||
* The Socket that corresponds to the requested socket_id. This field
|
||||
* should be set.
|
||||
*/
|
||||
'socket': (_grpc_channelz_v1_Socket__Output | null);
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Long } from '@grpc/proto-loader';
|
||||
|
||||
export interface GetSubchannelRequest {
|
||||
/**
|
||||
* subchannel_id is the identifier of the specific subchannel to get.
|
||||
*/
|
||||
'subchannel_id'?: (number | string | Long);
|
||||
}
|
||||
|
||||
export interface GetSubchannelRequest__Output {
|
||||
/**
|
||||
* subchannel_id is the identifier of the specific subchannel to get.
|
||||
*/
|
||||
'subchannel_id': (string);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Subchannel as _grpc_channelz_v1_Subchannel, Subchannel__Output as _grpc_channelz_v1_Subchannel__Output } from '../../../grpc/channelz/v1/Subchannel';
|
||||
|
||||
export interface GetSubchannelResponse {
|
||||
/**
|
||||
* The Subchannel that corresponds to the requested subchannel_id. This
|
||||
* field should be set.
|
||||
*/
|
||||
'subchannel'?: (_grpc_channelz_v1_Subchannel | null);
|
||||
}
|
||||
|
||||
export interface GetSubchannelResponse__Output {
|
||||
/**
|
||||
* The Subchannel that corresponds to the requested subchannel_id. This
|
||||
* field should be set.
|
||||
*/
|
||||
'subchannel': (_grpc_channelz_v1_Subchannel__Output | null);
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Long } from '@grpc/proto-loader';
|
||||
|
||||
export interface GetTopChannelsRequest {
|
||||
/**
|
||||
* start_channel_id indicates that only channels at or above this id should be
|
||||
* included in the results.
|
||||
* To request the first page, this should be set to 0. To request
|
||||
* subsequent pages, the client generates this value by adding 1 to
|
||||
* the highest seen result ID.
|
||||
*/
|
||||
'start_channel_id'?: (number | string | Long);
|
||||
/**
|
||||
* If non-zero, the server will return a page of results containing
|
||||
* at most this many items. If zero, the server will choose a
|
||||
* reasonable page size. Must never be negative.
|
||||
*/
|
||||
'max_results'?: (number | string | Long);
|
||||
}
|
||||
|
||||
export interface GetTopChannelsRequest__Output {
|
||||
/**
|
||||
* start_channel_id indicates that only channels at or above this id should be
|
||||
* included in the results.
|
||||
* To request the first page, this should be set to 0. To request
|
||||
* subsequent pages, the client generates this value by adding 1 to
|
||||
* the highest seen result ID.
|
||||
*/
|
||||
'start_channel_id': (string);
|
||||
/**
|
||||
* If non-zero, the server will return a page of results containing
|
||||
* at most this many items. If zero, the server will choose a
|
||||
* reasonable page size. Must never be negative.
|
||||
*/
|
||||
'max_results': (string);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Channel as _grpc_channelz_v1_Channel, Channel__Output as _grpc_channelz_v1_Channel__Output } from '../../../grpc/channelz/v1/Channel';
|
||||
|
||||
export interface GetTopChannelsResponse {
|
||||
/**
|
||||
* list of channels that the connection detail service knows about. Sorted in
|
||||
* ascending channel_id order.
|
||||
* Must contain at least 1 result, otherwise 'end' must be true.
|
||||
*/
|
||||
'channel'?: (_grpc_channelz_v1_Channel)[];
|
||||
/**
|
||||
* If set, indicates that the list of channels is the final list. Requesting
|
||||
* more channels can only return more if they are created after this RPC
|
||||
* completes.
|
||||
*/
|
||||
'end'?: (boolean);
|
||||
}
|
||||
|
||||
export interface GetTopChannelsResponse__Output {
|
||||
/**
|
||||
* list of channels that the connection detail service knows about. Sorted in
|
||||
* ascending channel_id order.
|
||||
* Must contain at least 1 result, otherwise 'end' must be true.
|
||||
*/
|
||||
'channel': (_grpc_channelz_v1_Channel__Output)[];
|
||||
/**
|
||||
* If set, indicates that the list of channels is the final list. Requesting
|
||||
* more channels can only return more if they are created after this RPC
|
||||
* completes.
|
||||
*/
|
||||
'end': (boolean);
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../google/protobuf/Any';
|
||||
|
||||
export interface _grpc_channelz_v1_Security_OtherSecurity {
|
||||
/**
|
||||
* The human readable version of the value.
|
||||
*/
|
||||
'name'?: (string);
|
||||
/**
|
||||
* The actual security details message.
|
||||
*/
|
||||
'value'?: (_google_protobuf_Any | null);
|
||||
}
|
||||
|
||||
export interface _grpc_channelz_v1_Security_OtherSecurity__Output {
|
||||
/**
|
||||
* The human readable version of the value.
|
||||
*/
|
||||
'name': (string);
|
||||
/**
|
||||
* The actual security details message.
|
||||
*/
|
||||
'value': (_google_protobuf_Any__Output | null);
|
||||
}
|
||||
|
||||
export interface _grpc_channelz_v1_Security_Tls {
|
||||
/**
|
||||
* The cipher suite name in the RFC 4346 format:
|
||||
* https://tools.ietf.org/html/rfc4346#appendix-C
|
||||
*/
|
||||
'standard_name'?: (string);
|
||||
/**
|
||||
* Some other way to describe the cipher suite if
|
||||
* the RFC 4346 name is not available.
|
||||
*/
|
||||
'other_name'?: (string);
|
||||
/**
|
||||
* the certificate used by this endpoint.
|
||||
*/
|
||||
'local_certificate'?: (Buffer | Uint8Array | string);
|
||||
/**
|
||||
* the certificate used by the remote endpoint.
|
||||
*/
|
||||
'remote_certificate'?: (Buffer | Uint8Array | string);
|
||||
'cipher_suite'?: "standard_name"|"other_name";
|
||||
}
|
||||
|
||||
export interface _grpc_channelz_v1_Security_Tls__Output {
|
||||
/**
|
||||
* The cipher suite name in the RFC 4346 format:
|
||||
* https://tools.ietf.org/html/rfc4346#appendix-C
|
||||
*/
|
||||
'standard_name'?: (string);
|
||||
/**
|
||||
* Some other way to describe the cipher suite if
|
||||
* the RFC 4346 name is not available.
|
||||
*/
|
||||
'other_name'?: (string);
|
||||
/**
|
||||
* the certificate used by this endpoint.
|
||||
*/
|
||||
'local_certificate': (Buffer);
|
||||
/**
|
||||
* the certificate used by the remote endpoint.
|
||||
*/
|
||||
'remote_certificate': (Buffer);
|
||||
'cipher_suite': "standard_name"|"other_name";
|
||||
}
|
||||
|
||||
/**
|
||||
* Security represents details about how secure the socket is.
|
||||
*/
|
||||
export interface Security {
|
||||
'tls'?: (_grpc_channelz_v1_Security_Tls | null);
|
||||
'other'?: (_grpc_channelz_v1_Security_OtherSecurity | null);
|
||||
'model'?: "tls"|"other";
|
||||
}
|
||||
|
||||
/**
|
||||
* Security represents details about how secure the socket is.
|
||||
*/
|
||||
export interface Security__Output {
|
||||
'tls'?: (_grpc_channelz_v1_Security_Tls__Output | null);
|
||||
'other'?: (_grpc_channelz_v1_Security_OtherSecurity__Output | null);
|
||||
'model': "tls"|"other";
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { ServerRef as _grpc_channelz_v1_ServerRef, ServerRef__Output as _grpc_channelz_v1_ServerRef__Output } from '../../../grpc/channelz/v1/ServerRef';
|
||||
import type { ServerData as _grpc_channelz_v1_ServerData, ServerData__Output as _grpc_channelz_v1_ServerData__Output } from '../../../grpc/channelz/v1/ServerData';
|
||||
import type { SocketRef as _grpc_channelz_v1_SocketRef, SocketRef__Output as _grpc_channelz_v1_SocketRef__Output } from '../../../grpc/channelz/v1/SocketRef';
|
||||
|
||||
/**
|
||||
* Server represents a single server. There may be multiple servers in a single
|
||||
* program.
|
||||
*/
|
||||
export interface Server {
|
||||
/**
|
||||
* The identifier for a Server. This should be set.
|
||||
*/
|
||||
'ref'?: (_grpc_channelz_v1_ServerRef | null);
|
||||
/**
|
||||
* The associated data of the Server.
|
||||
*/
|
||||
'data'?: (_grpc_channelz_v1_ServerData | null);
|
||||
/**
|
||||
* The sockets that the server is listening on. There are no ordering
|
||||
* guarantees. This may be absent.
|
||||
*/
|
||||
'listen_socket'?: (_grpc_channelz_v1_SocketRef)[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Server represents a single server. There may be multiple servers in a single
|
||||
* program.
|
||||
*/
|
||||
export interface Server__Output {
|
||||
/**
|
||||
* The identifier for a Server. This should be set.
|
||||
*/
|
||||
'ref': (_grpc_channelz_v1_ServerRef__Output | null);
|
||||
/**
|
||||
* The associated data of the Server.
|
||||
*/
|
||||
'data': (_grpc_channelz_v1_ServerData__Output | null);
|
||||
/**
|
||||
* The sockets that the server is listening on. There are no ordering
|
||||
* guarantees. This may be absent.
|
||||
*/
|
||||
'listen_socket': (_grpc_channelz_v1_SocketRef__Output)[];
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { ChannelTrace as _grpc_channelz_v1_ChannelTrace, ChannelTrace__Output as _grpc_channelz_v1_ChannelTrace__Output } from '../../../grpc/channelz/v1/ChannelTrace';
|
||||
import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp';
|
||||
import type { Long } from '@grpc/proto-loader';
|
||||
|
||||
/**
|
||||
* ServerData is data for a specific Server.
|
||||
*/
|
||||
export interface ServerData {
|
||||
/**
|
||||
* A trace of recent events on the server. May be absent.
|
||||
*/
|
||||
'trace'?: (_grpc_channelz_v1_ChannelTrace | null);
|
||||
/**
|
||||
* The number of incoming calls started on the server
|
||||
*/
|
||||
'calls_started'?: (number | string | Long);
|
||||
/**
|
||||
* The number of incoming calls that have completed with an OK status
|
||||
*/
|
||||
'calls_succeeded'?: (number | string | Long);
|
||||
/**
|
||||
* The number of incoming calls that have a completed with a non-OK status
|
||||
*/
|
||||
'calls_failed'?: (number | string | Long);
|
||||
/**
|
||||
* The last time a call was started on the server.
|
||||
*/
|
||||
'last_call_started_timestamp'?: (_google_protobuf_Timestamp | null);
|
||||
}
|
||||
|
||||
/**
|
||||
* ServerData is data for a specific Server.
|
||||
*/
|
||||
export interface ServerData__Output {
|
||||
/**
|
||||
* A trace of recent events on the server. May be absent.
|
||||
*/
|
||||
'trace': (_grpc_channelz_v1_ChannelTrace__Output | null);
|
||||
/**
|
||||
* The number of incoming calls started on the server
|
||||
*/
|
||||
'calls_started': (string);
|
||||
/**
|
||||
* The number of incoming calls that have completed with an OK status
|
||||
*/
|
||||
'calls_succeeded': (string);
|
||||
/**
|
||||
* The number of incoming calls that have a completed with a non-OK status
|
||||
*/
|
||||
'calls_failed': (string);
|
||||
/**
|
||||
* The last time a call was started on the server.
|
||||
*/
|
||||
'last_call_started_timestamp': (_google_protobuf_Timestamp__Output | null);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Long } from '@grpc/proto-loader';
|
||||
|
||||
/**
|
||||
* ServerRef is a reference to a Server.
|
||||
*/
|
||||
export interface ServerRef {
|
||||
/**
|
||||
* A globally unique identifier for this server. Must be a positive number.
|
||||
*/
|
||||
'server_id'?: (number | string | Long);
|
||||
/**
|
||||
* An optional name associated with the server.
|
||||
*/
|
||||
'name'?: (string);
|
||||
}
|
||||
|
||||
/**
|
||||
* ServerRef is a reference to a Server.
|
||||
*/
|
||||
export interface ServerRef__Output {
|
||||
/**
|
||||
* A globally unique identifier for this server. Must be a positive number.
|
||||
*/
|
||||
'server_id': (string);
|
||||
/**
|
||||
* An optional name associated with the server.
|
||||
*/
|
||||
'name': (string);
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { SocketRef as _grpc_channelz_v1_SocketRef, SocketRef__Output as _grpc_channelz_v1_SocketRef__Output } from '../../../grpc/channelz/v1/SocketRef';
|
||||
import type { SocketData as _grpc_channelz_v1_SocketData, SocketData__Output as _grpc_channelz_v1_SocketData__Output } from '../../../grpc/channelz/v1/SocketData';
|
||||
import type { Address as _grpc_channelz_v1_Address, Address__Output as _grpc_channelz_v1_Address__Output } from '../../../grpc/channelz/v1/Address';
|
||||
import type { Security as _grpc_channelz_v1_Security, Security__Output as _grpc_channelz_v1_Security__Output } from '../../../grpc/channelz/v1/Security';
|
||||
|
||||
/**
|
||||
* Information about an actual connection. Pronounced "sock-ay".
|
||||
*/
|
||||
export interface Socket {
|
||||
/**
|
||||
* The identifier for the Socket.
|
||||
*/
|
||||
'ref'?: (_grpc_channelz_v1_SocketRef | null);
|
||||
/**
|
||||
* Data specific to this Socket.
|
||||
*/
|
||||
'data'?: (_grpc_channelz_v1_SocketData | null);
|
||||
/**
|
||||
* The locally bound address.
|
||||
*/
|
||||
'local'?: (_grpc_channelz_v1_Address | null);
|
||||
/**
|
||||
* The remote bound address. May be absent.
|
||||
*/
|
||||
'remote'?: (_grpc_channelz_v1_Address | null);
|
||||
/**
|
||||
* Security details for this socket. May be absent if not available, or
|
||||
* there is no security on the socket.
|
||||
*/
|
||||
'security'?: (_grpc_channelz_v1_Security | null);
|
||||
/**
|
||||
* Optional, represents the name of the remote endpoint, if different than
|
||||
* the original target name.
|
||||
*/
|
||||
'remote_name'?: (string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about an actual connection. Pronounced "sock-ay".
|
||||
*/
|
||||
export interface Socket__Output {
|
||||
/**
|
||||
* The identifier for the Socket.
|
||||
*/
|
||||
'ref': (_grpc_channelz_v1_SocketRef__Output | null);
|
||||
/**
|
||||
* Data specific to this Socket.
|
||||
*/
|
||||
'data': (_grpc_channelz_v1_SocketData__Output | null);
|
||||
/**
|
||||
* The locally bound address.
|
||||
*/
|
||||
'local': (_grpc_channelz_v1_Address__Output | null);
|
||||
/**
|
||||
* The remote bound address. May be absent.
|
||||
*/
|
||||
'remote': (_grpc_channelz_v1_Address__Output | null);
|
||||
/**
|
||||
* Security details for this socket. May be absent if not available, or
|
||||
* there is no security on the socket.
|
||||
*/
|
||||
'security': (_grpc_channelz_v1_Security__Output | null);
|
||||
/**
|
||||
* Optional, represents the name of the remote endpoint, if different than
|
||||
* the original target name.
|
||||
*/
|
||||
'remote_name': (string);
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Timestamp as _google_protobuf_Timestamp, Timestamp__Output as _google_protobuf_Timestamp__Output } from '../../../google/protobuf/Timestamp';
|
||||
import type { Int64Value as _google_protobuf_Int64Value, Int64Value__Output as _google_protobuf_Int64Value__Output } from '../../../google/protobuf/Int64Value';
|
||||
import type { SocketOption as _grpc_channelz_v1_SocketOption, SocketOption__Output as _grpc_channelz_v1_SocketOption__Output } from '../../../grpc/channelz/v1/SocketOption';
|
||||
import type { Long } from '@grpc/proto-loader';
|
||||
|
||||
/**
|
||||
* SocketData is data associated for a specific Socket. The fields present
|
||||
* are specific to the implementation, so there may be minor differences in
|
||||
* the semantics. (e.g. flow control windows)
|
||||
*/
|
||||
export interface SocketData {
|
||||
/**
|
||||
* The number of streams that have been started.
|
||||
*/
|
||||
'streams_started'?: (number | string | Long);
|
||||
/**
|
||||
* The number of streams that have ended successfully:
|
||||
* On client side, received frame with eos bit set;
|
||||
* On server side, sent frame with eos bit set.
|
||||
*/
|
||||
'streams_succeeded'?: (number | string | Long);
|
||||
/**
|
||||
* The number of streams that have ended unsuccessfully:
|
||||
* On client side, ended without receiving frame with eos bit set;
|
||||
* On server side, ended without sending frame with eos bit set.
|
||||
*/
|
||||
'streams_failed'?: (number | string | Long);
|
||||
/**
|
||||
* The number of grpc messages successfully sent on this socket.
|
||||
*/
|
||||
'messages_sent'?: (number | string | Long);
|
||||
/**
|
||||
* The number of grpc messages received on this socket.
|
||||
*/
|
||||
'messages_received'?: (number | string | Long);
|
||||
/**
|
||||
* The number of keep alives sent. This is typically implemented with HTTP/2
|
||||
* ping messages.
|
||||
*/
|
||||
'keep_alives_sent'?: (number | string | Long);
|
||||
/**
|
||||
* The last time a stream was created by this endpoint. Usually unset for
|
||||
* servers.
|
||||
*/
|
||||
'last_local_stream_created_timestamp'?: (_google_protobuf_Timestamp | null);
|
||||
/**
|
||||
* The last time a stream was created by the remote endpoint. Usually unset
|
||||
* for clients.
|
||||
*/
|
||||
'last_remote_stream_created_timestamp'?: (_google_protobuf_Timestamp | null);
|
||||
/**
|
||||
* The last time a message was sent by this endpoint.
|
||||
*/
|
||||
'last_message_sent_timestamp'?: (_google_protobuf_Timestamp | null);
|
||||
/**
|
||||
* The last time a message was received by this endpoint.
|
||||
*/
|
||||
'last_message_received_timestamp'?: (_google_protobuf_Timestamp | null);
|
||||
/**
|
||||
* The amount of window, granted to the local endpoint by the remote endpoint.
|
||||
* This may be slightly out of date due to network latency. This does NOT
|
||||
* include stream level or TCP level flow control info.
|
||||
*/
|
||||
'local_flow_control_window'?: (_google_protobuf_Int64Value | null);
|
||||
/**
|
||||
* The amount of window, granted to the remote endpoint by the local endpoint.
|
||||
* This may be slightly out of date due to network latency. This does NOT
|
||||
* include stream level or TCP level flow control info.
|
||||
*/
|
||||
'remote_flow_control_window'?: (_google_protobuf_Int64Value | null);
|
||||
/**
|
||||
* Socket options set on this socket. May be absent if 'summary' is set
|
||||
* on GetSocketRequest.
|
||||
*/
|
||||
'option'?: (_grpc_channelz_v1_SocketOption)[];
|
||||
}
|
||||
|
||||
/**
|
||||
* SocketData is data associated for a specific Socket. The fields present
|
||||
* are specific to the implementation, so there may be minor differences in
|
||||
* the semantics. (e.g. flow control windows)
|
||||
*/
|
||||
export interface SocketData__Output {
|
||||
/**
|
||||
* The number of streams that have been started.
|
||||
*/
|
||||
'streams_started': (string);
|
||||
/**
|
||||
* The number of streams that have ended successfully:
|
||||
* On client side, received frame with eos bit set;
|
||||
* On server side, sent frame with eos bit set.
|
||||
*/
|
||||
'streams_succeeded': (string);
|
||||
/**
|
||||
* The number of streams that have ended unsuccessfully:
|
||||
* On client side, ended without receiving frame with eos bit set;
|
||||
* On server side, ended without sending frame with eos bit set.
|
||||
*/
|
||||
'streams_failed': (string);
|
||||
/**
|
||||
* The number of grpc messages successfully sent on this socket.
|
||||
*/
|
||||
'messages_sent': (string);
|
||||
/**
|
||||
* The number of grpc messages received on this socket.
|
||||
*/
|
||||
'messages_received': (string);
|
||||
/**
|
||||
* The number of keep alives sent. This is typically implemented with HTTP/2
|
||||
* ping messages.
|
||||
*/
|
||||
'keep_alives_sent': (string);
|
||||
/**
|
||||
* The last time a stream was created by this endpoint. Usually unset for
|
||||
* servers.
|
||||
*/
|
||||
'last_local_stream_created_timestamp': (_google_protobuf_Timestamp__Output | null);
|
||||
/**
|
||||
* The last time a stream was created by the remote endpoint. Usually unset
|
||||
* for clients.
|
||||
*/
|
||||
'last_remote_stream_created_timestamp': (_google_protobuf_Timestamp__Output | null);
|
||||
/**
|
||||
* The last time a message was sent by this endpoint.
|
||||
*/
|
||||
'last_message_sent_timestamp': (_google_protobuf_Timestamp__Output | null);
|
||||
/**
|
||||
* The last time a message was received by this endpoint.
|
||||
*/
|
||||
'last_message_received_timestamp': (_google_protobuf_Timestamp__Output | null);
|
||||
/**
|
||||
* The amount of window, granted to the local endpoint by the remote endpoint.
|
||||
* This may be slightly out of date due to network latency. This does NOT
|
||||
* include stream level or TCP level flow control info.
|
||||
*/
|
||||
'local_flow_control_window': (_google_protobuf_Int64Value__Output | null);
|
||||
/**
|
||||
* The amount of window, granted to the remote endpoint by the local endpoint.
|
||||
* This may be slightly out of date due to network latency. This does NOT
|
||||
* include stream level or TCP level flow control info.
|
||||
*/
|
||||
'remote_flow_control_window': (_google_protobuf_Int64Value__Output | null);
|
||||
/**
|
||||
* Socket options set on this socket. May be absent if 'summary' is set
|
||||
* on GetSocketRequest.
|
||||
*/
|
||||
'option': (_grpc_channelz_v1_SocketOption__Output)[];
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Any as _google_protobuf_Any, Any__Output as _google_protobuf_Any__Output } from '../../../google/protobuf/Any';
|
||||
|
||||
/**
|
||||
* SocketOption represents socket options for a socket. Specifically, these
|
||||
* are the options returned by getsockopt().
|
||||
*/
|
||||
export interface SocketOption {
|
||||
/**
|
||||
* The full name of the socket option. Typically this will be the upper case
|
||||
* name, such as "SO_REUSEPORT".
|
||||
*/
|
||||
'name'?: (string);
|
||||
/**
|
||||
* The human readable value of this socket option. At least one of value or
|
||||
* additional will be set.
|
||||
*/
|
||||
'value'?: (string);
|
||||
/**
|
||||
* Additional data associated with the socket option. At least one of value
|
||||
* or additional will be set.
|
||||
*/
|
||||
'additional'?: (_google_protobuf_Any | null);
|
||||
}
|
||||
|
||||
/**
|
||||
* SocketOption represents socket options for a socket. Specifically, these
|
||||
* are the options returned by getsockopt().
|
||||
*/
|
||||
export interface SocketOption__Output {
|
||||
/**
|
||||
* The full name of the socket option. Typically this will be the upper case
|
||||
* name, such as "SO_REUSEPORT".
|
||||
*/
|
||||
'name': (string);
|
||||
/**
|
||||
* The human readable value of this socket option. At least one of value or
|
||||
* additional will be set.
|
||||
*/
|
||||
'value': (string);
|
||||
/**
|
||||
* Additional data associated with the socket option. At least one of value
|
||||
* or additional will be set.
|
||||
*/
|
||||
'additional': (_google_protobuf_Any__Output | null);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../google/protobuf/Duration';
|
||||
|
||||
/**
|
||||
* For use with SocketOption's additional field. This is primarily used for
|
||||
* SO_LINGER.
|
||||
*/
|
||||
export interface SocketOptionLinger {
|
||||
/**
|
||||
* active maps to `struct linger.l_onoff`
|
||||
*/
|
||||
'active'?: (boolean);
|
||||
/**
|
||||
* duration maps to `struct linger.l_linger`
|
||||
*/
|
||||
'duration'?: (_google_protobuf_Duration | null);
|
||||
}
|
||||
|
||||
/**
|
||||
* For use with SocketOption's additional field. This is primarily used for
|
||||
* SO_LINGER.
|
||||
*/
|
||||
export interface SocketOptionLinger__Output {
|
||||
/**
|
||||
* active maps to `struct linger.l_onoff`
|
||||
*/
|
||||
'active': (boolean);
|
||||
/**
|
||||
* duration maps to `struct linger.l_linger`
|
||||
*/
|
||||
'duration': (_google_protobuf_Duration__Output | null);
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
|
||||
/**
|
||||
* For use with SocketOption's additional field. Tcp info for
|
||||
* SOL_TCP and TCP_INFO.
|
||||
*/
|
||||
export interface SocketOptionTcpInfo {
|
||||
'tcpi_state'?: (number);
|
||||
'tcpi_ca_state'?: (number);
|
||||
'tcpi_retransmits'?: (number);
|
||||
'tcpi_probes'?: (number);
|
||||
'tcpi_backoff'?: (number);
|
||||
'tcpi_options'?: (number);
|
||||
'tcpi_snd_wscale'?: (number);
|
||||
'tcpi_rcv_wscale'?: (number);
|
||||
'tcpi_rto'?: (number);
|
||||
'tcpi_ato'?: (number);
|
||||
'tcpi_snd_mss'?: (number);
|
||||
'tcpi_rcv_mss'?: (number);
|
||||
'tcpi_unacked'?: (number);
|
||||
'tcpi_sacked'?: (number);
|
||||
'tcpi_lost'?: (number);
|
||||
'tcpi_retrans'?: (number);
|
||||
'tcpi_fackets'?: (number);
|
||||
'tcpi_last_data_sent'?: (number);
|
||||
'tcpi_last_ack_sent'?: (number);
|
||||
'tcpi_last_data_recv'?: (number);
|
||||
'tcpi_last_ack_recv'?: (number);
|
||||
'tcpi_pmtu'?: (number);
|
||||
'tcpi_rcv_ssthresh'?: (number);
|
||||
'tcpi_rtt'?: (number);
|
||||
'tcpi_rttvar'?: (number);
|
||||
'tcpi_snd_ssthresh'?: (number);
|
||||
'tcpi_snd_cwnd'?: (number);
|
||||
'tcpi_advmss'?: (number);
|
||||
'tcpi_reordering'?: (number);
|
||||
}
|
||||
|
||||
/**
|
||||
* For use with SocketOption's additional field. Tcp info for
|
||||
* SOL_TCP and TCP_INFO.
|
||||
*/
|
||||
export interface SocketOptionTcpInfo__Output {
|
||||
'tcpi_state': (number);
|
||||
'tcpi_ca_state': (number);
|
||||
'tcpi_retransmits': (number);
|
||||
'tcpi_probes': (number);
|
||||
'tcpi_backoff': (number);
|
||||
'tcpi_options': (number);
|
||||
'tcpi_snd_wscale': (number);
|
||||
'tcpi_rcv_wscale': (number);
|
||||
'tcpi_rto': (number);
|
||||
'tcpi_ato': (number);
|
||||
'tcpi_snd_mss': (number);
|
||||
'tcpi_rcv_mss': (number);
|
||||
'tcpi_unacked': (number);
|
||||
'tcpi_sacked': (number);
|
||||
'tcpi_lost': (number);
|
||||
'tcpi_retrans': (number);
|
||||
'tcpi_fackets': (number);
|
||||
'tcpi_last_data_sent': (number);
|
||||
'tcpi_last_ack_sent': (number);
|
||||
'tcpi_last_data_recv': (number);
|
||||
'tcpi_last_ack_recv': (number);
|
||||
'tcpi_pmtu': (number);
|
||||
'tcpi_rcv_ssthresh': (number);
|
||||
'tcpi_rtt': (number);
|
||||
'tcpi_rttvar': (number);
|
||||
'tcpi_snd_ssthresh': (number);
|
||||
'tcpi_snd_cwnd': (number);
|
||||
'tcpi_advmss': (number);
|
||||
'tcpi_reordering': (number);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Duration as _google_protobuf_Duration, Duration__Output as _google_protobuf_Duration__Output } from '../../../google/protobuf/Duration';
|
||||
|
||||
/**
|
||||
* For use with SocketOption's additional field. This is primarily used for
|
||||
* SO_RCVTIMEO and SO_SNDTIMEO
|
||||
*/
|
||||
export interface SocketOptionTimeout {
|
||||
'duration'?: (_google_protobuf_Duration | null);
|
||||
}
|
||||
|
||||
/**
|
||||
* For use with SocketOption's additional field. This is primarily used for
|
||||
* SO_RCVTIMEO and SO_SNDTIMEO
|
||||
*/
|
||||
export interface SocketOptionTimeout__Output {
|
||||
'duration': (_google_protobuf_Duration__Output | null);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Long } from '@grpc/proto-loader';
|
||||
|
||||
/**
|
||||
* SocketRef is a reference to a Socket.
|
||||
*/
|
||||
export interface SocketRef {
|
||||
/**
|
||||
* The globally unique id for this socket. Must be a positive number.
|
||||
*/
|
||||
'socket_id'?: (number | string | Long);
|
||||
/**
|
||||
* An optional name associated with the socket.
|
||||
*/
|
||||
'name'?: (string);
|
||||
}
|
||||
|
||||
/**
|
||||
* SocketRef is a reference to a Socket.
|
||||
*/
|
||||
export interface SocketRef__Output {
|
||||
/**
|
||||
* The globally unique id for this socket. Must be a positive number.
|
||||
*/
|
||||
'socket_id': (string);
|
||||
/**
|
||||
* An optional name associated with the socket.
|
||||
*/
|
||||
'name': (string);
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { SubchannelRef as _grpc_channelz_v1_SubchannelRef, SubchannelRef__Output as _grpc_channelz_v1_SubchannelRef__Output } from '../../../grpc/channelz/v1/SubchannelRef';
|
||||
import type { ChannelData as _grpc_channelz_v1_ChannelData, ChannelData__Output as _grpc_channelz_v1_ChannelData__Output } from '../../../grpc/channelz/v1/ChannelData';
|
||||
import type { ChannelRef as _grpc_channelz_v1_ChannelRef, ChannelRef__Output as _grpc_channelz_v1_ChannelRef__Output } from '../../../grpc/channelz/v1/ChannelRef';
|
||||
import type { SocketRef as _grpc_channelz_v1_SocketRef, SocketRef__Output as _grpc_channelz_v1_SocketRef__Output } from '../../../grpc/channelz/v1/SocketRef';
|
||||
|
||||
/**
|
||||
* Subchannel is a logical grouping of channels, subchannels, and sockets.
|
||||
* A subchannel is load balanced over by it's ancestor
|
||||
*/
|
||||
export interface Subchannel {
|
||||
/**
|
||||
* The identifier for this channel.
|
||||
*/
|
||||
'ref'?: (_grpc_channelz_v1_SubchannelRef | null);
|
||||
/**
|
||||
* Data specific to this channel.
|
||||
*/
|
||||
'data'?: (_grpc_channelz_v1_ChannelData | null);
|
||||
/**
|
||||
* There are no ordering guarantees on the order of channel refs.
|
||||
* There may not be cycles in the ref graph.
|
||||
* A channel ref may be present in more than one channel or subchannel.
|
||||
*/
|
||||
'channel_ref'?: (_grpc_channelz_v1_ChannelRef)[];
|
||||
/**
|
||||
* At most one of 'channel_ref+subchannel_ref' and 'socket' is set.
|
||||
* There are no ordering guarantees on the order of subchannel refs.
|
||||
* There may not be cycles in the ref graph.
|
||||
* A sub channel ref may be present in more than one channel or subchannel.
|
||||
*/
|
||||
'subchannel_ref'?: (_grpc_channelz_v1_SubchannelRef)[];
|
||||
/**
|
||||
* There are no ordering guarantees on the order of sockets.
|
||||
*/
|
||||
'socket_ref'?: (_grpc_channelz_v1_SocketRef)[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Subchannel is a logical grouping of channels, subchannels, and sockets.
|
||||
* A subchannel is load balanced over by it's ancestor
|
||||
*/
|
||||
export interface Subchannel__Output {
|
||||
/**
|
||||
* The identifier for this channel.
|
||||
*/
|
||||
'ref': (_grpc_channelz_v1_SubchannelRef__Output | null);
|
||||
/**
|
||||
* Data specific to this channel.
|
||||
*/
|
||||
'data': (_grpc_channelz_v1_ChannelData__Output | null);
|
||||
/**
|
||||
* There are no ordering guarantees on the order of channel refs.
|
||||
* There may not be cycles in the ref graph.
|
||||
* A channel ref may be present in more than one channel or subchannel.
|
||||
*/
|
||||
'channel_ref': (_grpc_channelz_v1_ChannelRef__Output)[];
|
||||
/**
|
||||
* At most one of 'channel_ref+subchannel_ref' and 'socket' is set.
|
||||
* There are no ordering guarantees on the order of subchannel refs.
|
||||
* There may not be cycles in the ref graph.
|
||||
* A sub channel ref may be present in more than one channel or subchannel.
|
||||
*/
|
||||
'subchannel_ref': (_grpc_channelz_v1_SubchannelRef__Output)[];
|
||||
/**
|
||||
* There are no ordering guarantees on the order of sockets.
|
||||
*/
|
||||
'socket_ref': (_grpc_channelz_v1_SocketRef__Output)[];
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
// Original file: proto/channelz.proto
|
||||
|
||||
import type { Long } from '@grpc/proto-loader';
|
||||
|
||||
/**
|
||||
* SubchannelRef is a reference to a Subchannel.
|
||||
*/
|
||||
export interface SubchannelRef {
|
||||
/**
|
||||
* The globally unique id for this subchannel. Must be a positive number.
|
||||
*/
|
||||
'subchannel_id'?: (number | string | Long);
|
||||
/**
|
||||
* An optional name associated with the subchannel.
|
||||
*/
|
||||
'name'?: (string);
|
||||
}
|
||||
|
||||
/**
|
||||
* SubchannelRef is a reference to a Subchannel.
|
||||
*/
|
||||
export interface SubchannelRef__Output {
|
||||
/**
|
||||
* The globally unique id for this subchannel. Must be a positive number.
|
||||
*/
|
||||
'subchannel_id': (string);
|
||||
/**
|
||||
* An optional name associated with the subchannel.
|
||||
*/
|
||||
'name': (string);
|
||||
}
|
|
@ -249,6 +249,13 @@ export { GrpcObject } from './make-client';
|
|||
|
||||
export { ChannelOptions } from './channel-options';
|
||||
|
||||
export {
|
||||
getChannelzServiceDefinition,
|
||||
getChannelzHandlers
|
||||
} from './channelz';
|
||||
|
||||
export { addAdminServicesToServer } from './admin';
|
||||
|
||||
import * as experimental from './experimental';
|
||||
export { experimental };
|
||||
|
||||
|
@ -257,6 +264,7 @@ import * as resolver_uds from './resolver-uds';
|
|||
import * as resolver_ip from './resolver-ip';
|
||||
import * as load_balancer_pick_first from './load-balancer-pick-first';
|
||||
import * as load_balancer_round_robin from './load-balancer-round-robin';
|
||||
import * as channelz from './channelz';
|
||||
|
||||
const clientVersion = require('../../package.json').version;
|
||||
|
||||
|
@ -267,4 +275,5 @@ const clientVersion = require('../../package.json').version;
|
|||
resolver_ip.setup();
|
||||
load_balancer_pick_first.setup();
|
||||
load_balancer_round_robin.setup();
|
||||
channelz.setup();
|
||||
})();
|
||||
|
|
|
@ -26,6 +26,7 @@ import { SubchannelAddress } from './subchannel-address';
|
|||
import { ChannelOptions } from './channel-options';
|
||||
import { ConnectivityState } from './connectivity-state';
|
||||
import { Picker } from './picker';
|
||||
import { ChannelRef, SubchannelRef } from './channelz';
|
||||
|
||||
const TYPE_NAME = 'child_load_balancer_helper';
|
||||
|
||||
|
@ -67,6 +68,13 @@ export class ChildLoadBalancerHandler implements LoadBalancer {
|
|||
setChild(newChild: LoadBalancer) {
|
||||
this.child = newChild;
|
||||
}
|
||||
addChannelzChild(child: ChannelRef | SubchannelRef) {
|
||||
this.parent.channelControlHelper.addChannelzChild(child);
|
||||
}
|
||||
removeChannelzChild(child: ChannelRef | SubchannelRef) {
|
||||
this.parent.channelControlHelper.removeChannelzChild(child);
|
||||
}
|
||||
|
||||
private calledByPendingChild(): boolean {
|
||||
return this.child === this.parent.pendingChild;
|
||||
}
|
||||
|
|
|
@ -229,6 +229,7 @@ export class PickFirstLoadBalancer implements LoadBalancer {
|
|||
subchannel.removeConnectivityStateListener(
|
||||
this.pickedSubchannelStateListener
|
||||
);
|
||||
this.channelControlHelper.removeChannelzChild(subchannel.getChannelzRef());
|
||||
if (this.subchannels.length > 0) {
|
||||
if (this.triedAllSubchannels) {
|
||||
let newLBState: ConnectivityState;
|
||||
|
@ -321,6 +322,7 @@ export class PickFirstLoadBalancer implements LoadBalancer {
|
|||
this.updateState(ConnectivityState.READY, new PickFirstPicker(subchannel));
|
||||
subchannel.addConnectivityStateListener(this.pickedSubchannelStateListener);
|
||||
subchannel.ref();
|
||||
this.channelControlHelper.addChannelzChild(subchannel.getChannelzRef());
|
||||
this.resetSubchannelList();
|
||||
clearTimeout(this.connectionDelayTimeout);
|
||||
}
|
||||
|
@ -339,6 +341,7 @@ export class PickFirstLoadBalancer implements LoadBalancer {
|
|||
for (const subchannel of this.subchannels) {
|
||||
subchannel.removeConnectivityStateListener(this.subchannelStateListener);
|
||||
subchannel.unref();
|
||||
this.channelControlHelper.removeChannelzChild(subchannel.getChannelzRef());
|
||||
}
|
||||
this.currentSubchannelIndex = 0;
|
||||
this.subchannelStateCounts = {
|
||||
|
@ -369,6 +372,7 @@ export class PickFirstLoadBalancer implements LoadBalancer {
|
|||
);
|
||||
for (const subchannel of this.subchannels) {
|
||||
subchannel.ref();
|
||||
this.channelControlHelper.addChannelzChild(subchannel.getChannelzRef());
|
||||
}
|
||||
for (const subchannel of this.subchannels) {
|
||||
subchannel.addConnectivityStateListener(this.subchannelStateListener);
|
||||
|
@ -449,6 +453,7 @@ export class PickFirstLoadBalancer implements LoadBalancer {
|
|||
this.currentPick.removeConnectivityStateListener(
|
||||
this.pickedSubchannelStateListener
|
||||
);
|
||||
this.channelControlHelper.removeChannelzChild(this.currentPick.getChannelzRef());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -191,6 +191,7 @@ export class RoundRobinLoadBalancer implements LoadBalancer {
|
|||
for (const subchannel of this.subchannels) {
|
||||
subchannel.removeConnectivityStateListener(this.subchannelStateListener);
|
||||
subchannel.unref();
|
||||
this.channelControlHelper.removeChannelzChild(subchannel.getChannelzRef());
|
||||
}
|
||||
this.subchannelStateCounts = {
|
||||
[ConnectivityState.CONNECTING]: 0,
|
||||
|
@ -217,6 +218,7 @@ export class RoundRobinLoadBalancer implements LoadBalancer {
|
|||
for (const subchannel of this.subchannels) {
|
||||
subchannel.ref();
|
||||
subchannel.addConnectivityStateListener(this.subchannelStateListener);
|
||||
this.channelControlHelper.addChannelzChild(subchannel.getChannelzRef());
|
||||
const subchannelState = subchannel.getConnectivityState();
|
||||
this.subchannelStateCounts[subchannelState] += 1;
|
||||
if (
|
||||
|
|
|
@ -20,6 +20,7 @@ import { Subchannel } from './subchannel';
|
|||
import { SubchannelAddress } from './subchannel-address';
|
||||
import { ConnectivityState } from './connectivity-state';
|
||||
import { Picker } from './picker';
|
||||
import { ChannelRef, SubchannelRef } from './channelz';
|
||||
|
||||
/**
|
||||
* A collection of functions associated with a channel that a load balancer
|
||||
|
@ -47,6 +48,26 @@ export interface ChannelControlHelper {
|
|||
* Request new data from the resolver.
|
||||
*/
|
||||
requestReresolution(): void;
|
||||
addChannelzChild(child: ChannelRef | SubchannelRef): void;
|
||||
removeChannelzChild(child: ChannelRef | SubchannelRef): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a child ChannelControlHelper that overrides some methods of the
|
||||
* parent while letting others pass through to the parent unmodified. This
|
||||
* allows other code to create these children without needing to know about
|
||||
* all of the methods to be passed through.
|
||||
* @param parent
|
||||
* @param overrides
|
||||
*/
|
||||
export function createChildChannelControlHelper(parent: ChannelControlHelper, overrides: Partial<ChannelControlHelper>): ChannelControlHelper {
|
||||
return {
|
||||
createSubchannel: overrides.createSubchannel?.bind(overrides) ?? parent.createSubchannel.bind(parent),
|
||||
updateState: overrides.updateState?.bind(overrides) ?? parent.updateState.bind(parent),
|
||||
requestReresolution: overrides.requestReresolution?.bind(overrides) ?? parent.requestReresolution.bind(parent),
|
||||
addChannelzChild: overrides.addChannelzChild?.bind(overrides) ?? parent.addChannelzChild.bind(parent),
|
||||
removeChannelzChild: overrides.removeChannelzChild?.bind(overrides) ?? parent.removeChannelzChild.bind(parent)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -172,6 +172,12 @@ export class ResolvingLoadBalancer implements LoadBalancer {
|
|||
this.latestChildPicker = picker;
|
||||
this.updateState(newState, picker);
|
||||
},
|
||||
addChannelzChild: channelControlHelper.addChannelzChild.bind(
|
||||
channelControlHelper
|
||||
),
|
||||
removeChannelzChild: channelControlHelper.removeChannelzChild.bind(
|
||||
channelControlHelper
|
||||
)
|
||||
});
|
||||
this.innerResolver = createResolver(
|
||||
target,
|
||||
|
|
|
@ -411,6 +411,8 @@ export class Http2ServerCallStream<
|
|||
);
|
||||
this.cancelled = true;
|
||||
this.emit('cancelled', 'cancelled');
|
||||
this.emit('streamEnd', false);
|
||||
this.sendStatus({code: Status.CANCELLED, details: 'Cancelled by client', metadata: new Metadata()});
|
||||
});
|
||||
|
||||
this.stream.on('drain', () => {
|
||||
|
@ -513,6 +515,7 @@ export class Http2ServerCallStream<
|
|||
resolve();
|
||||
}
|
||||
|
||||
this.emit('receiveMessage');
|
||||
resolve(this.deserializeMessage(requestBytes));
|
||||
} catch (err) {
|
||||
err.code = Status.INTERNAL;
|
||||
|
@ -575,6 +578,8 @@ export class Http2ServerCallStream<
|
|||
}
|
||||
|
||||
sendStatus(statusObj: StatusObject) {
|
||||
this.emit('callEnd', statusObj.code);
|
||||
this.emit('streamEnd', statusObj.code === Status.OK);
|
||||
if (this.checkCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
@ -609,9 +614,6 @@ export class Http2ServerCallStream<
|
|||
}
|
||||
|
||||
sendError(error: ServerErrorResponse | ServerStatusResponse) {
|
||||
if (this.checkCancelled()) {
|
||||
return;
|
||||
}
|
||||
const status: StatusObject = {
|
||||
code: Status.UNKNOWN,
|
||||
details: 'message' in error ? error.message : 'Unknown Error',
|
||||
|
@ -653,6 +655,7 @@ export class Http2ServerCallStream<
|
|||
}
|
||||
|
||||
this.sendMetadata();
|
||||
this.emit('sendMessage');
|
||||
return this.stream.write(chunk);
|
||||
}
|
||||
|
||||
|
@ -688,6 +691,7 @@ export class Http2ServerCallStream<
|
|||
});
|
||||
return;
|
||||
}
|
||||
this.emit('receiveMessage');
|
||||
this.pushOrBufferMessage(readable, message);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -56,15 +56,14 @@ import {
|
|||
TcpSubchannelAddress,
|
||||
isTcpSubchannelAddress,
|
||||
subchannelAddressToString,
|
||||
stringToSubchannelAddress,
|
||||
} from './subchannel-address';
|
||||
import { parseUri } from './uri-parser';
|
||||
import { ChannelzCallTracker, ChannelzChildrenTracker, ChannelzTrace, registerChannelzServer, registerChannelzSocket, ServerInfo, ServerRef, SocketInfo, SocketRef, TlsInfo, unregisterChannelzRef } from './channelz';
|
||||
import { CipherNameAndProtocol, TLSSocket } from 'tls';
|
||||
|
||||
const TRACER_NAME = 'server';
|
||||
|
||||
function trace(text: string): void {
|
||||
logging.trace(LogVerbosity.DEBUG, TRACER_NAME, text);
|
||||
}
|
||||
|
||||
interface BindResult {
|
||||
port: number;
|
||||
count: number;
|
||||
|
@ -125,21 +124,101 @@ function getDefaultHandler(handlerType: HandlerType, methodName: string) {
|
|||
}
|
||||
}
|
||||
|
||||
interface ChannelzSessionInfo {
|
||||
ref: SocketRef;
|
||||
streamTracker: ChannelzCallTracker;
|
||||
messagesSent: number;
|
||||
messagesReceived: number;
|
||||
lastMessageSentTimestamp: Date | null;
|
||||
lastMessageReceivedTimestamp: Date | null;
|
||||
}
|
||||
|
||||
interface ChannelzListenerInfo {
|
||||
ref: SocketRef;
|
||||
}
|
||||
|
||||
export class Server {
|
||||
private http2ServerList: (http2.Http2Server | http2.Http2SecureServer)[] = [];
|
||||
private http2ServerList: { server: (http2.Http2Server | http2.Http2SecureServer), channelzRef: SocketRef }[] = [];
|
||||
|
||||
private handlers: Map<string, UntypedHandler> = new Map<
|
||||
string,
|
||||
UntypedHandler
|
||||
>();
|
||||
private sessions = new Set<http2.ServerHttp2Session>();
|
||||
private sessions = new Map<http2.ServerHttp2Session, ChannelzSessionInfo>();
|
||||
private started = false;
|
||||
private options: ChannelOptions;
|
||||
|
||||
// Channelz Info
|
||||
private channelzRef: ServerRef;
|
||||
private channelzTrace = new ChannelzTrace();
|
||||
private callTracker = new ChannelzCallTracker();
|
||||
private listenerChildrenTracker = new ChannelzChildrenTracker();
|
||||
private sessionChildrenTracker = new ChannelzChildrenTracker();
|
||||
|
||||
constructor(options?: ChannelOptions) {
|
||||
this.options = options ?? {};
|
||||
this.channelzRef = registerChannelzServer(() => this.getChannelzInfo());
|
||||
this.channelzTrace.addTrace('CT_INFO', 'Server created');
|
||||
this.trace('Server constructed');
|
||||
}
|
||||
|
||||
private getChannelzInfo(): ServerInfo {
|
||||
return {
|
||||
trace: this.channelzTrace,
|
||||
callTracker: this.callTracker,
|
||||
listenerChildren: this.listenerChildrenTracker.getChildLists(),
|
||||
sessionChildren: this.sessionChildrenTracker.getChildLists()
|
||||
};
|
||||
}
|
||||
|
||||
private getChannelzSessionInfoGetter(session: http2.ServerHttp2Session): () => SocketInfo {
|
||||
return () => {
|
||||
const sessionInfo = this.sessions.get(session)!;
|
||||
const sessionSocket = session.socket;
|
||||
const remoteAddress = sessionSocket.remoteAddress ? stringToSubchannelAddress(sessionSocket.remoteAddress, sessionSocket.remotePort) : null;
|
||||
const localAddress = stringToSubchannelAddress(sessionSocket.localAddress, sessionSocket.localPort);
|
||||
let tlsInfo: TlsInfo | null;
|
||||
if (session.encrypted) {
|
||||
const tlsSocket: TLSSocket = sessionSocket as TLSSocket;
|
||||
const cipherInfo: CipherNameAndProtocol & {standardName?: string} = tlsSocket.getCipher();
|
||||
const certificate = tlsSocket.getCertificate();
|
||||
const peerCertificate = tlsSocket.getPeerCertificate();
|
||||
tlsInfo = {
|
||||
cipherSuiteStandardName: cipherInfo.standardName ?? null,
|
||||
cipherSuiteOtherName: cipherInfo.standardName ? null : cipherInfo.name,
|
||||
localCertificate: (certificate && 'raw' in certificate) ? certificate.raw : null,
|
||||
remoteCertificate: (peerCertificate && 'raw' in peerCertificate) ? peerCertificate.raw : null
|
||||
};
|
||||
} else {
|
||||
tlsInfo = null;
|
||||
}
|
||||
const socketInfo: SocketInfo = {
|
||||
remoteAddress: remoteAddress,
|
||||
localAddress: localAddress,
|
||||
security: tlsInfo,
|
||||
remoteName: null,
|
||||
streamsStarted: sessionInfo.streamTracker.callsStarted,
|
||||
streamsSucceeded: sessionInfo.streamTracker.callsSucceeded,
|
||||
streamsFailed: sessionInfo.streamTracker.callsFailed,
|
||||
messagesSent: sessionInfo.messagesSent,
|
||||
messagesReceived: sessionInfo.messagesReceived,
|
||||
keepAlivesSent: 0,
|
||||
lastLocalStreamCreatedTimestamp: null,
|
||||
lastRemoteStreamCreatedTimestamp: sessionInfo.streamTracker.lastCallStartedTimestamp,
|
||||
lastMessageSentTimestamp: sessionInfo.lastMessageSentTimestamp,
|
||||
lastMessageReceivedTimestamp: sessionInfo.lastMessageReceivedTimestamp,
|
||||
localFlowControlWindow: session.state.localWindowSize ?? null,
|
||||
remoteFlowControlWindow: session.state.remoteWindowSize ?? null
|
||||
};
|
||||
return socketInfo;
|
||||
};
|
||||
}
|
||||
|
||||
private trace(text: string): void {
|
||||
logging.trace(LogVerbosity.DEBUG, TRACER_NAME, '(' + this.channelzRef.id + ') ' + text);
|
||||
}
|
||||
|
||||
|
||||
addProtoService(): void {
|
||||
throw new Error('Not implemented. Use addService() instead');
|
||||
}
|
||||
|
@ -299,7 +378,7 @@ export class Server {
|
|||
}
|
||||
return Promise.all(
|
||||
addressList.map((address) => {
|
||||
trace('Attempting to bind ' + subchannelAddressToString(address));
|
||||
this.trace('Attempting to bind ' + subchannelAddressToString(address));
|
||||
let addr: SubchannelAddress;
|
||||
if (isTcpSubchannelAddress(address)) {
|
||||
addr = {
|
||||
|
@ -312,22 +391,50 @@ export class Server {
|
|||
|
||||
const http2Server = setupServer();
|
||||
return new Promise<number | Error>((resolve, reject) => {
|
||||
function onError(err: Error): void {
|
||||
trace('Failed to bind ' + subchannelAddressToString(address) + ' with error ' + err.message);
|
||||
const onError = (err: Error) => {
|
||||
this.trace('Failed to bind ' + subchannelAddressToString(address) + ' with error ' + err.message);
|
||||
resolve(err);
|
||||
}
|
||||
|
||||
http2Server.once('error', onError);
|
||||
|
||||
http2Server.listen(addr, () => {
|
||||
trace('Successfully bound ' + subchannelAddressToString(address));
|
||||
this.http2ServerList.push(http2Server);
|
||||
const boundAddress = http2Server.address()!;
|
||||
let boundSubchannelAddress: SubchannelAddress;
|
||||
if (typeof boundAddress === 'string') {
|
||||
resolve(portNum);
|
||||
boundSubchannelAddress = {
|
||||
path: boundAddress
|
||||
};
|
||||
} else {
|
||||
resolve(boundAddress.port);
|
||||
boundSubchannelAddress = {
|
||||
host: boundAddress.address,
|
||||
port: boundAddress.port
|
||||
}
|
||||
}
|
||||
const channelzRef = registerChannelzSocket(subchannelAddressToString(boundSubchannelAddress), () => {
|
||||
return {
|
||||
localAddress: boundSubchannelAddress,
|
||||
remoteAddress: null,
|
||||
security: null,
|
||||
remoteName: null,
|
||||
streamsStarted: 0,
|
||||
streamsSucceeded: 0,
|
||||
streamsFailed: 0,
|
||||
messagesSent: 0,
|
||||
messagesReceived: 0,
|
||||
keepAlivesSent: 0,
|
||||
lastLocalStreamCreatedTimestamp: null,
|
||||
lastRemoteStreamCreatedTimestamp: null,
|
||||
lastMessageSentTimestamp: null,
|
||||
lastMessageReceivedTimestamp: null,
|
||||
localFlowControlWindow: null,
|
||||
remoteFlowControlWindow: null
|
||||
};
|
||||
});
|
||||
this.listenerChildrenTracker.refChild(channelzRef);
|
||||
this.http2ServerList.push({server: http2Server, channelzRef: channelzRef});
|
||||
this.trace('Successfully bound ' + subchannelAddressToString(boundSubchannelAddress));
|
||||
resolve('port' in boundSubchannelAddress ? boundSubchannelAddress.port : portNum);
|
||||
http2Server.removeListener('error', onError);
|
||||
});
|
||||
});
|
||||
|
@ -360,19 +467,46 @@ export class Server {
|
|||
const address = addressList[0];
|
||||
const http2Server = setupServer();
|
||||
return new Promise<BindResult>((resolve, reject) => {
|
||||
function onError(err: Error): void {
|
||||
trace('Failed to bind ' + subchannelAddressToString(address) + ' with error ' + err.message);
|
||||
const onError = (err: Error) => {
|
||||
this.trace('Failed to bind ' + subchannelAddressToString(address) + ' with error ' + err.message);
|
||||
resolve(bindWildcardPort(addressList.slice(1)));
|
||||
}
|
||||
|
||||
http2Server.once('error', onError);
|
||||
|
||||
http2Server.listen(address, () => {
|
||||
this.http2ServerList.push(http2Server);
|
||||
const boundAddress = http2Server.address() as AddressInfo;
|
||||
const boundSubchannelAddress: SubchannelAddress = {
|
||||
host: boundAddress.address,
|
||||
port: boundAddress.port
|
||||
};
|
||||
const channelzRef = registerChannelzSocket(subchannelAddressToString(boundSubchannelAddress), () => {
|
||||
return {
|
||||
localAddress: boundSubchannelAddress,
|
||||
remoteAddress: null,
|
||||
security: null,
|
||||
remoteName: null,
|
||||
streamsStarted: 0,
|
||||
streamsSucceeded: 0,
|
||||
streamsFailed: 0,
|
||||
messagesSent: 0,
|
||||
messagesReceived: 0,
|
||||
keepAlivesSent: 0,
|
||||
lastLocalStreamCreatedTimestamp: null,
|
||||
lastRemoteStreamCreatedTimestamp: null,
|
||||
lastMessageSentTimestamp: null,
|
||||
lastMessageReceivedTimestamp: null,
|
||||
localFlowControlWindow: null,
|
||||
remoteFlowControlWindow: null
|
||||
};
|
||||
});
|
||||
this.listenerChildrenTracker.refChild(channelzRef);
|
||||
this.http2ServerList.push({server: http2Server, channelzRef: channelzRef});
|
||||
this.trace('Successfully bound ' + subchannelAddressToString(boundSubchannelAddress));
|
||||
resolve(
|
||||
bindSpecificPort(
|
||||
addressList.slice(1),
|
||||
(http2Server.address() as AddressInfo).port,
|
||||
boundAddress.port,
|
||||
1
|
||||
)
|
||||
);
|
||||
|
@ -443,9 +577,12 @@ export class Server {
|
|||
forceShutdown(): void {
|
||||
// Close the server if it is still running.
|
||||
|
||||
for (const http2Server of this.http2ServerList) {
|
||||
for (const {server: http2Server, channelzRef: ref} of this.http2ServerList) {
|
||||
if (http2Server.listening) {
|
||||
http2Server.close();
|
||||
http2Server.close(() => {
|
||||
this.listenerChildrenTracker.unrefChild(ref);
|
||||
unregisterChannelzRef(ref);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -453,13 +590,14 @@ export class Server {
|
|||
|
||||
// Always destroy any available sessions. It's possible that one or more
|
||||
// tryShutdown() calls are in progress. Don't wait on them to finish.
|
||||
this.sessions.forEach((session) => {
|
||||
this.sessions.forEach((channelzInfo, session) => {
|
||||
// Cast NGHTTP2_CANCEL to any because TypeScript doesn't seem to
|
||||
// recognize destroy(code) as a valid signature.
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
session.destroy(http2.constants.NGHTTP2_CANCEL as any);
|
||||
});
|
||||
this.sessions.clear();
|
||||
unregisterChannelzRef(this.channelzRef);
|
||||
}
|
||||
|
||||
register<RequestType, ResponseType>(
|
||||
|
@ -491,7 +629,7 @@ export class Server {
|
|||
if (
|
||||
this.http2ServerList.length === 0 ||
|
||||
this.http2ServerList.every(
|
||||
(http2Server) => http2Server.listening !== true
|
||||
({server: http2Server}) => http2Server.listening !== true
|
||||
)
|
||||
) {
|
||||
throw new Error('server must be bound in order to start');
|
||||
|
@ -500,39 +638,47 @@ export class Server {
|
|||
if (this.started === true) {
|
||||
throw new Error('server is already started');
|
||||
}
|
||||
|
||||
this.channelzTrace.addTrace('CT_INFO', 'Starting');
|
||||
this.started = true;
|
||||
}
|
||||
|
||||
tryShutdown(callback: (error?: Error) => void): void {
|
||||
const wrappedCallback = (error?: Error) => {
|
||||
unregisterChannelzRef(this.channelzRef);
|
||||
callback(error);
|
||||
};
|
||||
let pendingChecks = 0;
|
||||
|
||||
function maybeCallback(): void {
|
||||
pendingChecks--;
|
||||
|
||||
if (pendingChecks === 0) {
|
||||
callback();
|
||||
wrappedCallback();
|
||||
}
|
||||
}
|
||||
|
||||
// Close the server if necessary.
|
||||
this.started = false;
|
||||
|
||||
for (const http2Server of this.http2ServerList) {
|
||||
for (const {server: http2Server, channelzRef: ref} of this.http2ServerList) {
|
||||
if (http2Server.listening) {
|
||||
pendingChecks++;
|
||||
http2Server.close(maybeCallback);
|
||||
http2Server.close(() => {
|
||||
this.listenerChildrenTracker.unrefChild(ref);
|
||||
unregisterChannelzRef(ref);
|
||||
maybeCallback();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.sessions.forEach((session) => {
|
||||
this.sessions.forEach((channelzInfo, session) => {
|
||||
if (!session.closed) {
|
||||
pendingChecks += 1;
|
||||
session.close(maybeCallback);
|
||||
}
|
||||
});
|
||||
if (pendingChecks === 0) {
|
||||
callback();
|
||||
wrappedCallback();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -540,6 +686,10 @@ export class Server {
|
|||
throw new Error('Not yet implemented');
|
||||
}
|
||||
|
||||
getChannelzRef() {
|
||||
return this.channelzRef;
|
||||
}
|
||||
|
||||
private _setupHandlers(
|
||||
http2Server: http2.Http2Server | http2.Http2SecureServer
|
||||
): void {
|
||||
|
@ -550,6 +700,9 @@ export class Server {
|
|||
http2Server.on(
|
||||
'stream',
|
||||
(stream: http2.ServerHttp2Stream, headers: http2.IncomingHttpHeaders) => {
|
||||
const channelzSessionInfo = this.sessions.get(stream.session as http2.ServerHttp2Session);
|
||||
this.callTracker.addCallStarted();
|
||||
channelzSessionInfo?.streamTracker.addCallStarted();
|
||||
const contentType = headers[http2.constants.HTTP2_HEADER_CONTENT_TYPE];
|
||||
|
||||
if (
|
||||
|
@ -563,9 +716,13 @@ export class Server {
|
|||
},
|
||||
{ endStream: true }
|
||||
);
|
||||
this.callTracker.addCallFailed();
|
||||
channelzSessionInfo?.streamTracker.addCallFailed();
|
||||
return;
|
||||
}
|
||||
|
||||
let call: Http2ServerCallStream<any, any> | null = null;
|
||||
|
||||
try {
|
||||
const path = headers[http2.constants.HTTP2_HEADER_PATH] as string;
|
||||
const serverAddress = http2Server.address();
|
||||
|
@ -578,7 +735,7 @@ export class Server {
|
|||
serverAddress.address + ':' + serverAddress.port;
|
||||
}
|
||||
}
|
||||
trace(
|
||||
this.trace(
|
||||
'Received call to method ' +
|
||||
path +
|
||||
' at address ' +
|
||||
|
@ -587,7 +744,7 @@ export class Server {
|
|||
const handler = this.handlers.get(path);
|
||||
|
||||
if (handler === undefined) {
|
||||
trace(
|
||||
this.trace(
|
||||
'No handler registered for method ' +
|
||||
path +
|
||||
'. Sending UNIMPLEMENTED status.'
|
||||
|
@ -595,7 +752,31 @@ export class Server {
|
|||
throw getUnimplementedStatusResponse(path);
|
||||
}
|
||||
|
||||
const call = new Http2ServerCallStream(stream, handler, this.options);
|
||||
call = new Http2ServerCallStream(stream, handler, this.options);
|
||||
call.once('callEnd', (code: Status) => {
|
||||
if (code === Status.OK) {
|
||||
this.callTracker.addCallSucceeded();
|
||||
} else {
|
||||
this.callTracker.addCallFailed();
|
||||
}
|
||||
});
|
||||
if (channelzSessionInfo) {
|
||||
call.once('streamEnd', (success: boolean) => {
|
||||
if (success) {
|
||||
channelzSessionInfo.streamTracker.addCallSucceeded();
|
||||
} else {
|
||||
channelzSessionInfo.streamTracker.addCallFailed();
|
||||
}
|
||||
});
|
||||
call.on('sendMessage', () => {
|
||||
channelzSessionInfo.messagesSent += 1;
|
||||
channelzSessionInfo.lastMessageSentTimestamp = new Date();
|
||||
});
|
||||
call.on('receiveMessage', () => {
|
||||
channelzSessionInfo.messagesReceived += 1;
|
||||
channelzSessionInfo.lastMessageReceivedTimestamp = new Date();
|
||||
});
|
||||
}
|
||||
const metadata: Metadata = call.receiveMetadata(headers) as Metadata;
|
||||
switch (handler.type) {
|
||||
case 'unary':
|
||||
|
@ -626,7 +807,11 @@ export class Server {
|
|||
throw new Error(`Unknown handler type: ${handler.type}`);
|
||||
}
|
||||
} catch (err) {
|
||||
const call = new Http2ServerCallStream(stream, null!, this.options);
|
||||
if (!call) {
|
||||
call = new Http2ServerCallStream(stream, null!, this.options);
|
||||
this.callTracker.addCallFailed();
|
||||
channelzSessionInfo?.streamTracker.addCallFailed()
|
||||
}
|
||||
|
||||
if (err.code === undefined) {
|
||||
err.code = Status.INTERNAL;
|
||||
|
@ -643,9 +828,25 @@ export class Server {
|
|||
return;
|
||||
}
|
||||
|
||||
this.sessions.add(session);
|
||||
const channelzRef = registerChannelzSocket(session.socket.remoteAddress ?? 'unknown', this.getChannelzSessionInfoGetter(session));
|
||||
|
||||
const channelzSessionInfo: ChannelzSessionInfo = {
|
||||
ref: channelzRef,
|
||||
streamTracker: new ChannelzCallTracker(),
|
||||
messagesSent: 0,
|
||||
messagesReceived: 0,
|
||||
lastMessageSentTimestamp: null,
|
||||
lastMessageReceivedTimestamp: null
|
||||
};
|
||||
|
||||
this.sessions.set(session, channelzSessionInfo);
|
||||
const clientAddress = session.socket.remoteAddress;
|
||||
this.channelzTrace.addTrace('CT_INFO', 'Connection established by client ' + clientAddress);
|
||||
this.sessionChildrenTracker.refChild(channelzRef);
|
||||
session.on('close', () => {
|
||||
this.channelzTrace.addTrace('CT_INFO', 'Connection dropped by client ' + clientAddress);
|
||||
this.sessionChildrenTracker.unrefChild(channelzRef);
|
||||
unregisterChannelzRef(channelzRef);
|
||||
this.sessions.delete(session);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
import { isIP } from "net";
|
||||
|
||||
export interface TcpSubchannelAddress {
|
||||
port: number;
|
||||
host: string;
|
||||
|
@ -60,3 +62,18 @@ export function subchannelAddressToString(address: SubchannelAddress): string {
|
|||
return address.path;
|
||||
}
|
||||
}
|
||||
|
||||
const DEFAULT_PORT = 443;
|
||||
|
||||
export function stringToSubchannelAddress(addressString: string, port?: number): SubchannelAddress {
|
||||
if (isIP(addressString)) {
|
||||
return {
|
||||
host: addressString,
|
||||
port: port ?? DEFAULT_PORT
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
path: addressString
|
||||
};
|
||||
}
|
||||
}
|
|
@ -18,36 +18,30 @@
|
|||
import * as http2 from 'http2';
|
||||
import { ChannelCredentials } from './channel-credentials';
|
||||
import { Metadata } from './metadata';
|
||||
import { Http2CallStream } from './call-stream';
|
||||
import { Call, Http2CallStream, WriteObject } from './call-stream';
|
||||
import { ChannelOptions } from './channel-options';
|
||||
import { PeerCertificate, checkServerIdentity } from 'tls';
|
||||
import { PeerCertificate, checkServerIdentity, TLSSocket, CipherNameAndProtocol } from 'tls';
|
||||
import { ConnectivityState } from './connectivity-state';
|
||||
import { BackoffTimeout, BackoffOptions } from './backoff-timeout';
|
||||
import { getDefaultAuthority } from './resolver';
|
||||
import * as logging from './logging';
|
||||
import { LogVerbosity } from './constants';
|
||||
import { LogVerbosity, Status } from './constants';
|
||||
import { getProxiedConnection, ProxyConnectionResult } from './http_proxy';
|
||||
import * as net from 'net';
|
||||
import { GrpcUri, parseUri, splitHostPort, uriToString } from './uri-parser';
|
||||
import { ConnectionOptions } from 'tls';
|
||||
import { FilterFactory, Filter } from './filter';
|
||||
import { FilterFactory, Filter, BaseFilter } from './filter';
|
||||
import {
|
||||
stringToSubchannelAddress,
|
||||
SubchannelAddress,
|
||||
subchannelAddressToString,
|
||||
} from './subchannel-address';
|
||||
import { SubchannelRef, ChannelzTrace, ChannelzChildrenTracker, SubchannelInfo, registerChannelzSubchannel, ChannelzCallTracker, SocketInfo, SocketRef, unregisterChannelzRef, registerChannelzSocket, TlsInfo } from './channelz';
|
||||
|
||||
const clientVersion = require('../../package.json').version;
|
||||
|
||||
const TRACER_NAME = 'subchannel';
|
||||
|
||||
function trace(text: string): void {
|
||||
logging.trace(LogVerbosity.DEBUG, TRACER_NAME, text);
|
||||
}
|
||||
|
||||
function refTrace(text: string): void {
|
||||
logging.trace(LogVerbosity.DEBUG, 'subchannel_refcount', text);
|
||||
}
|
||||
|
||||
const MIN_CONNECT_TIMEOUT_MS = 20000;
|
||||
const INITIAL_BACKOFF_MS = 1000;
|
||||
const BACKOFF_MULTIPLIER = 1.6;
|
||||
|
@ -66,6 +60,11 @@ export type ConnectivityStateListener = (
|
|||
newState: ConnectivityState
|
||||
) => void;
|
||||
|
||||
export interface SubchannelCallStatsTracker {
|
||||
addMessageSent(): void;
|
||||
addMessageReceived(): void;
|
||||
}
|
||||
|
||||
const {
|
||||
HTTP2_HEADER_AUTHORITY,
|
||||
HTTP2_HEADER_CONTENT_TYPE,
|
||||
|
@ -157,6 +156,26 @@ export class Subchannel {
|
|||
*/
|
||||
private subchannelAddressString: string;
|
||||
|
||||
// Channelz info
|
||||
private channelzRef: SubchannelRef;
|
||||
private channelzTrace: ChannelzTrace;
|
||||
private callTracker = new ChannelzCallTracker();
|
||||
private childrenTracker = new ChannelzChildrenTracker();
|
||||
|
||||
// Channelz socket info
|
||||
private channelzSocketRef: SocketRef | null = null;
|
||||
/**
|
||||
* Name of the remote server, if it is not the same as the subchannel
|
||||
* address, i.e. if connecting through an HTTP CONNECT proxy.
|
||||
*/
|
||||
private remoteName: string | null = null;
|
||||
private streamTracker = new ChannelzCallTracker();
|
||||
private keepalivesSent = 0;
|
||||
private messagesSent = 0;
|
||||
private messagesReceived = 0;
|
||||
private lastMessageSentTimestamp: Date | null = null;
|
||||
private lastMessageReceivedTimestamp: Date | null = null;
|
||||
|
||||
/**
|
||||
* A class representing a connection to a single backend.
|
||||
* @param channelTarget The target string for the channel as a whole
|
||||
|
@ -206,6 +225,87 @@ export class Subchannel {
|
|||
this.handleBackoffTimer();
|
||||
}, backoffOptions);
|
||||
this.subchannelAddressString = subchannelAddressToString(subchannelAddress);
|
||||
|
||||
this.channelzRef = registerChannelzSubchannel(this.subchannelAddressString, () => this.getChannelzInfo());
|
||||
this.channelzTrace = new ChannelzTrace();
|
||||
this.channelzTrace.addTrace('CT_INFO', 'Subchannel created');
|
||||
this.trace('Subchannel constructed');
|
||||
}
|
||||
|
||||
private getChannelzInfo(): SubchannelInfo {
|
||||
return {
|
||||
state: this.connectivityState,
|
||||
trace: this.channelzTrace,
|
||||
callTracker: this.callTracker,
|
||||
children: this.childrenTracker.getChildLists(),
|
||||
target: this.subchannelAddressString
|
||||
};
|
||||
}
|
||||
|
||||
private getChannelzSocketInfo(): SocketInfo | null {
|
||||
if (this.session === null) {
|
||||
return null;
|
||||
}
|
||||
const sessionSocket = this.session.socket;
|
||||
const remoteAddress = sessionSocket.remoteAddress ? stringToSubchannelAddress(sessionSocket.remoteAddress, sessionSocket.remotePort) : null;
|
||||
const localAddress = stringToSubchannelAddress(sessionSocket.localAddress, sessionSocket.localPort);
|
||||
let tlsInfo: TlsInfo | null;
|
||||
if (this.session.encrypted) {
|
||||
const tlsSocket: TLSSocket = sessionSocket as TLSSocket;
|
||||
const cipherInfo: CipherNameAndProtocol & {standardName?: string} = tlsSocket.getCipher();
|
||||
const certificate = tlsSocket.getCertificate();
|
||||
const peerCertificate = tlsSocket.getPeerCertificate();
|
||||
tlsInfo = {
|
||||
cipherSuiteStandardName: cipherInfo.standardName ?? null,
|
||||
cipherSuiteOtherName: cipherInfo.standardName ? null : cipherInfo.name,
|
||||
localCertificate: (certificate && 'raw' in certificate) ? certificate.raw : null,
|
||||
remoteCertificate: (peerCertificate && 'raw' in peerCertificate) ? peerCertificate.raw : null
|
||||
};
|
||||
} else {
|
||||
tlsInfo = null;
|
||||
}
|
||||
const socketInfo: SocketInfo = {
|
||||
remoteAddress: remoteAddress,
|
||||
localAddress: localAddress,
|
||||
security: tlsInfo,
|
||||
remoteName: this.remoteName,
|
||||
streamsStarted: this.streamTracker.callsStarted,
|
||||
streamsSucceeded: this.streamTracker.callsSucceeded,
|
||||
streamsFailed: this.streamTracker.callsFailed,
|
||||
messagesSent: this.messagesSent,
|
||||
messagesReceived: this.messagesReceived,
|
||||
keepAlivesSent: this.keepalivesSent,
|
||||
lastLocalStreamCreatedTimestamp: this.streamTracker.lastCallStartedTimestamp,
|
||||
lastRemoteStreamCreatedTimestamp: null,
|
||||
lastMessageSentTimestamp: this.lastMessageSentTimestamp,
|
||||
lastMessageReceivedTimestamp: this.lastMessageReceivedTimestamp,
|
||||
localFlowControlWindow: this.session.state.localWindowSize ?? null,
|
||||
remoteFlowControlWindow: this.session.state.remoteWindowSize ?? null
|
||||
};
|
||||
return socketInfo;
|
||||
}
|
||||
|
||||
private resetChannelzSocketInfo() {
|
||||
if (this.channelzSocketRef) {
|
||||
unregisterChannelzRef(this.channelzSocketRef);
|
||||
this.childrenTracker.unrefChild(this.channelzSocketRef);
|
||||
this.channelzSocketRef = null;
|
||||
}
|
||||
this.remoteName = null;
|
||||
this.streamTracker = new ChannelzCallTracker();
|
||||
this.keepalivesSent = 0;
|
||||
this.messagesSent = 0;
|
||||
this.messagesReceived = 0;
|
||||
this.lastMessageSentTimestamp = null;
|
||||
this.lastMessageReceivedTimestamp = null;
|
||||
}
|
||||
|
||||
private trace(text: string): void {
|
||||
logging.trace(LogVerbosity.DEBUG, TRACER_NAME, '(' + this.channelzRef.id + ') ' + this.subchannelAddressString + ' ' + text);
|
||||
}
|
||||
|
||||
private refTrace(text: string): void {
|
||||
logging.trace(LogVerbosity.DEBUG, 'subchannel_refcount', '(' + this.channelzRef.id + ') ' + this.subchannelAddressString + ' ' + text);
|
||||
}
|
||||
|
||||
private handleBackoffTimer() {
|
||||
|
@ -235,10 +335,12 @@ export class Subchannel {
|
|||
}
|
||||
|
||||
private sendPing() {
|
||||
this.keepalivesSent += 1;
|
||||
logging.trace(
|
||||
LogVerbosity.DEBUG,
|
||||
'keepalive',
|
||||
'Sending ping to ' + this.subchannelAddressString
|
||||
'(' + this.channelzRef.id + ') ' + this.subchannelAddressString + ' ' +
|
||||
'Sending ping'
|
||||
);
|
||||
this.keepaliveTimeoutId = setTimeout(() => {
|
||||
this.transitionToState([ConnectivityState.READY], ConnectivityState.IDLE);
|
||||
|
@ -267,9 +369,11 @@ export class Subchannel {
|
|||
|
||||
private createSession(proxyConnectionResult: ProxyConnectionResult) {
|
||||
if (proxyConnectionResult.realTarget) {
|
||||
trace(this.subchannelAddressString + ' creating HTTP/2 session through proxy to ' + proxyConnectionResult.realTarget);
|
||||
this.remoteName = uriToString(proxyConnectionResult.realTarget);
|
||||
this.trace('creating HTTP/2 session through proxy to ' + proxyConnectionResult.realTarget);
|
||||
} else {
|
||||
trace(this.subchannelAddressString + ' creating HTTP/2 session');
|
||||
this.remoteName = null;
|
||||
this.trace('creating HTTP/2 session');
|
||||
}
|
||||
const targetAuthority = getDefaultAuthority(
|
||||
proxyConnectionResult.realTarget ?? this.channelTarget
|
||||
|
@ -358,6 +462,8 @@ export class Subchannel {
|
|||
connectionOptions
|
||||
);
|
||||
this.session = session;
|
||||
this.channelzSocketRef = registerChannelzSocket(this.subchannelAddressString, () => this.getChannelzSocketInfo()!);
|
||||
this.childrenTracker.refChild(this.channelzSocketRef);
|
||||
session.unref();
|
||||
/* For all of these events, check if the session at the time of the event
|
||||
* is the same one currently attached to this subchannel, to ensure that
|
||||
|
@ -373,7 +479,7 @@ export class Subchannel {
|
|||
});
|
||||
session.once('close', () => {
|
||||
if (this.session === session) {
|
||||
trace(this.subchannelAddressString + ' connection closed');
|
||||
this.trace('connection closed');
|
||||
this.transitionToState(
|
||||
[ConnectivityState.CONNECTING],
|
||||
ConnectivityState.TRANSIENT_FAILURE
|
||||
|
@ -410,9 +516,8 @@ export class Subchannel {
|
|||
} ms`
|
||||
);
|
||||
}
|
||||
trace(
|
||||
this.subchannelAddressString +
|
||||
' connection closed by GOAWAY with code ' +
|
||||
this.trace(
|
||||
'connection closed by GOAWAY with code ' +
|
||||
errorCode
|
||||
);
|
||||
this.transitionToState(
|
||||
|
@ -425,12 +530,12 @@ export class Subchannel {
|
|||
session.once('error', (error) => {
|
||||
/* Do nothing here. Any error should also trigger a close event, which is
|
||||
* where we want to handle that. */
|
||||
trace(
|
||||
this.subchannelAddressString +
|
||||
' connection closed with error ' +
|
||||
this.trace(
|
||||
'connection closed with error ' +
|
||||
(error as Error).message
|
||||
);
|
||||
});
|
||||
registerChannelzSocket(this.subchannelAddressString, () => this.getChannelzSocketInfo()!);
|
||||
}
|
||||
|
||||
private startConnectingInternal() {
|
||||
|
@ -505,13 +610,12 @@ export class Subchannel {
|
|||
if (oldStates.indexOf(this.connectivityState) === -1) {
|
||||
return false;
|
||||
}
|
||||
trace(
|
||||
this.subchannelAddressString +
|
||||
' ' +
|
||||
this.trace(
|
||||
ConnectivityState[this.connectivityState] +
|
||||
' -> ' +
|
||||
ConnectivityState[newState]
|
||||
);
|
||||
this.channelzTrace.addTrace('CT_INFO', ConnectivityState[this.connectivityState] + ' -> ' + ConnectivityState[newState]);
|
||||
const previousState = this.connectivityState;
|
||||
this.connectivityState = newState;
|
||||
switch (newState) {
|
||||
|
@ -536,6 +640,7 @@ export class Subchannel {
|
|||
this.session.close();
|
||||
}
|
||||
this.session = null;
|
||||
this.resetChannelzSocketInfo();
|
||||
this.stopKeepalivePings();
|
||||
/* If the backoff timer has already ended by the time we get to the
|
||||
* TRANSIENT_FAILURE state, we want to immediately transition out of
|
||||
|
@ -551,6 +656,7 @@ export class Subchannel {
|
|||
this.session.close();
|
||||
}
|
||||
this.session = null;
|
||||
this.resetChannelzSocketInfo();
|
||||
this.stopKeepalivePings();
|
||||
break;
|
||||
default:
|
||||
|
@ -572,17 +678,18 @@ export class Subchannel {
|
|||
/* If no calls, channels, or subchannel pools have any more references to
|
||||
* this subchannel, we can be sure it will never be used again. */
|
||||
if (this.callRefcount === 0 && this.refcount === 0) {
|
||||
this.channelzTrace.addTrace('CT_INFO', 'Shutting down');
|
||||
this.transitionToState(
|
||||
[ConnectivityState.CONNECTING, ConnectivityState.READY],
|
||||
ConnectivityState.TRANSIENT_FAILURE
|
||||
);
|
||||
unregisterChannelzRef(this.channelzRef);
|
||||
}
|
||||
}
|
||||
|
||||
callRef() {
|
||||
refTrace(
|
||||
this.subchannelAddressString +
|
||||
' callRefcount ' +
|
||||
this.refTrace(
|
||||
'callRefcount ' +
|
||||
this.callRefcount +
|
||||
' -> ' +
|
||||
(this.callRefcount + 1)
|
||||
|
@ -600,9 +707,8 @@ export class Subchannel {
|
|||
}
|
||||
|
||||
callUnref() {
|
||||
refTrace(
|
||||
this.subchannelAddressString +
|
||||
' callRefcount ' +
|
||||
this.refTrace(
|
||||
'callRefcount ' +
|
||||
this.callRefcount +
|
||||
' -> ' +
|
||||
(this.callRefcount - 1)
|
||||
|
@ -621,9 +727,8 @@ export class Subchannel {
|
|||
}
|
||||
|
||||
ref() {
|
||||
refTrace(
|
||||
this.subchannelAddressString +
|
||||
' refcount ' +
|
||||
this.refTrace(
|
||||
'refcount ' +
|
||||
this.refcount +
|
||||
' -> ' +
|
||||
(this.refcount + 1)
|
||||
|
@ -632,9 +737,8 @@ export class Subchannel {
|
|||
}
|
||||
|
||||
unref() {
|
||||
refTrace(
|
||||
this.subchannelAddressString +
|
||||
' refcount ' +
|
||||
this.refTrace(
|
||||
'refcount ' +
|
||||
this.refcount +
|
||||
' -> ' +
|
||||
(this.refcount - 1)
|
||||
|
@ -696,11 +800,39 @@ export class Subchannel {
|
|||
LogVerbosity.DEBUG,
|
||||
'call_stream',
|
||||
'Starting stream on subchannel ' +
|
||||
'(' + this.channelzRef.id + ') ' +
|
||||
this.subchannelAddressString +
|
||||
' with headers\n' +
|
||||
headersString
|
||||
);
|
||||
callStream.attachHttp2Stream(http2Stream, this, extraFilters);
|
||||
this.callTracker.addCallStarted();
|
||||
callStream.addStatusWatcher(status => {
|
||||
if (status.code === Status.OK) {
|
||||
this.callTracker.addCallSucceeded();
|
||||
} else {
|
||||
this.callTracker.addCallFailed();
|
||||
}
|
||||
});
|
||||
const streamSession = this.session;
|
||||
this.streamTracker.addCallStarted();
|
||||
callStream.addStreamEndWatcher(success => {
|
||||
if (streamSession === this.session) {
|
||||
if (success) {
|
||||
this.streamTracker.addCallSucceeded();
|
||||
} else {
|
||||
this.streamTracker.addCallFailed();
|
||||
}
|
||||
}
|
||||
});
|
||||
callStream.attachHttp2Stream(http2Stream, this, extraFilters, {
|
||||
addMessageSent: () => {
|
||||
this.messagesSent += 1;
|
||||
this.lastMessageSentTimestamp = new Date();
|
||||
},
|
||||
addMessageReceived: () => {
|
||||
this.messagesReceived += 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -779,4 +911,8 @@ export class Subchannel {
|
|||
getAddress(): string {
|
||||
return this.subchannelAddressString;
|
||||
}
|
||||
|
||||
getChannelzRef(): SubchannelRef {
|
||||
return this.channelzRef;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,289 @@
|
|||
/*
|
||||
* Copyright 2019 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.
|
||||
*
|
||||
*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as protoLoader from '@grpc/proto-loader';
|
||||
import * as grpc from '../src';
|
||||
|
||||
import { ProtoGrpcType } from '../src/generated/channelz'
|
||||
import { ChannelzClient } from '../src/generated/grpc/channelz/v1/Channelz';
|
||||
import { Channel__Output } from '../src/generated/grpc/channelz/v1/Channel';
|
||||
import { Server__Output } from '../src/generated/grpc/channelz/v1/Server';
|
||||
import { ServiceClient, ServiceClientConstructor } from '../src/make-client';
|
||||
import { loadProtoFile } from './common';
|
||||
|
||||
const loadedChannelzProto = protoLoader.loadSync('channelz.proto', {
|
||||
keepCase: true,
|
||||
longs: String,
|
||||
enums: String,
|
||||
defaults: true,
|
||||
oneofs: true,
|
||||
includeDirs: [
|
||||
`${__dirname}/../../proto`
|
||||
]
|
||||
});
|
||||
const channelzGrpcObject = grpc.loadPackageDefinition(loadedChannelzProto) as unknown as ProtoGrpcType;
|
||||
|
||||
const TestServiceClient = loadProtoFile(`${__dirname}/fixtures/test_service.proto`).TestService as ServiceClientConstructor;
|
||||
|
||||
const testServiceImpl: grpc.UntypedServiceImplementation = {
|
||||
unary(call: grpc.ServerUnaryCall<any, any>, callback: grpc.sendUnaryData<any>) {
|
||||
if (call.request.error) {
|
||||
setTimeout(() => {
|
||||
callback({
|
||||
code: grpc.status.INVALID_ARGUMENT,
|
||||
details: call.request.message
|
||||
});
|
||||
}, call.request.errorAfter)
|
||||
} else {
|
||||
callback(null, {count: 1});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe('Channelz', () => {
|
||||
let channelzServer: grpc.Server;
|
||||
let channelzClient: ChannelzClient;
|
||||
let testServer: grpc.Server;
|
||||
let testClient: ServiceClient;
|
||||
|
||||
before((done) => {
|
||||
channelzServer = new grpc.Server();
|
||||
channelzServer.addService(grpc.getChannelzServiceDefinition(), grpc.getChannelzHandlers());
|
||||
channelzServer.bindAsync('localhost:0', grpc.ServerCredentials.createInsecure(), (error, port) => {
|
||||
if (error) {
|
||||
done(error);
|
||||
return;
|
||||
}
|
||||
channelzServer.start();
|
||||
channelzClient = new channelzGrpcObject.grpc.channelz.v1.Channelz(`localhost:${port}`, grpc.credentials.createInsecure());
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
channelzClient.close();
|
||||
channelzServer.forceShutdown();
|
||||
});
|
||||
|
||||
beforeEach((done) => {
|
||||
testServer = new grpc.Server();
|
||||
testServer.addService(TestServiceClient.service, testServiceImpl);
|
||||
testServer.bindAsync('localhost:0', grpc.ServerCredentials.createInsecure(), (error, port) => {
|
||||
if (error) {
|
||||
done(error);
|
||||
return;
|
||||
}
|
||||
testServer.start();
|
||||
testClient = new TestServiceClient(`localhost:${port}`, grpc.credentials.createInsecure());
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
testClient.close();
|
||||
testServer.forceShutdown();
|
||||
});
|
||||
|
||||
it('should see a newly created channel', (done) => {
|
||||
// Test that the specific test client channel info can be retrieved
|
||||
channelzClient.GetChannel({channel_id: testClient.getChannel().getChannelzRef().id}, (error, result) => {
|
||||
assert.ifError(error);
|
||||
assert(result);
|
||||
assert(result.channel);
|
||||
assert(result.channel.ref);
|
||||
assert.strictEqual(+result.channel.ref.channel_id, testClient.getChannel().getChannelzRef().id);
|
||||
// Test that the channel is in the list of top channels
|
||||
channelzClient.getTopChannels({start_channel_id: testClient.getChannel().getChannelzRef().id, max_results:1}, (error, result) => {
|
||||
assert.ifError(error);
|
||||
assert(result);
|
||||
assert.strictEqual(result.channel.length, 1);
|
||||
assert(result.channel[0].ref);
|
||||
assert.strictEqual(+result.channel[0].ref.channel_id, testClient.getChannel().getChannelzRef().id);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should see a newly created server', (done) => {
|
||||
// Test that the specific test server info can be retrieved
|
||||
channelzClient.getServer({server_id: testServer.getChannelzRef().id}, (error, result) => {
|
||||
assert.ifError(error);
|
||||
assert(result);
|
||||
assert(result.server);
|
||||
assert(result.server.ref);
|
||||
assert.strictEqual(+result.server.ref.server_id, testServer.getChannelzRef().id);
|
||||
// Test that the server is in the list of servers
|
||||
channelzClient.getServers({start_server_id: testServer.getChannelzRef().id, max_results: 1}, (error, result) => {
|
||||
assert.ifError(error);
|
||||
assert(result);
|
||||
assert.strictEqual(result.server.length, 1);
|
||||
assert(result.server[0].ref);
|
||||
assert.strictEqual(+result.server[0].ref.server_id, testServer.getChannelzRef().id);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should count successful calls', (done) => {
|
||||
testClient.unary({}, (error: grpc.ServiceError, value: unknown) => {
|
||||
assert.ifError(error);
|
||||
// Channel data tests
|
||||
channelzClient.GetChannel({channel_id: testClient.getChannel().getChannelzRef().id}, (error, channelResult) => {
|
||||
assert.ifError(error);
|
||||
assert(channelResult);
|
||||
assert(channelResult.channel);
|
||||
assert(channelResult.channel.ref);
|
||||
assert(channelResult.channel.data);
|
||||
assert.strictEqual(+channelResult.channel.data.calls_started, 1);
|
||||
assert.strictEqual(+channelResult.channel.data.calls_succeeded, 1);
|
||||
assert.strictEqual(+channelResult.channel.data.calls_failed, 0);
|
||||
assert.strictEqual(channelResult.channel.subchannel_ref.length, 1);
|
||||
channelzClient.getSubchannel({subchannel_id: channelResult.channel.subchannel_ref[0].subchannel_id}, (error, subchannelResult) => {
|
||||
assert.ifError(error);
|
||||
assert(subchannelResult);
|
||||
assert(subchannelResult.subchannel);
|
||||
assert(subchannelResult.subchannel.ref);
|
||||
assert(subchannelResult.subchannel.data);
|
||||
assert.strictEqual(subchannelResult.subchannel.ref.subchannel_id, channelResult.channel!.subchannel_ref[0].subchannel_id);
|
||||
assert.strictEqual(+subchannelResult.subchannel.data.calls_started, 1);
|
||||
assert.strictEqual(+subchannelResult.subchannel.data.calls_succeeded, 1);
|
||||
assert.strictEqual(+subchannelResult.subchannel.data.calls_failed, 0);
|
||||
assert.strictEqual(subchannelResult.subchannel.socket_ref.length, 1);
|
||||
channelzClient.getSocket({socket_id: subchannelResult.subchannel.socket_ref[0].socket_id}, (error, socketResult) => {
|
||||
assert.ifError(error);
|
||||
assert(socketResult);
|
||||
assert(socketResult.socket);
|
||||
assert(socketResult.socket.ref);
|
||||
assert(socketResult.socket.data);
|
||||
assert.strictEqual(socketResult.socket.ref.socket_id, subchannelResult.subchannel!.socket_ref[0].socket_id);
|
||||
assert.strictEqual(+socketResult.socket.data.streams_started, 1);
|
||||
assert.strictEqual(+socketResult.socket.data.streams_succeeded, 1);
|
||||
assert.strictEqual(+socketResult.socket.data.streams_failed, 0);
|
||||
assert.strictEqual(+socketResult.socket.data.messages_received, 1);
|
||||
assert.strictEqual(+socketResult.socket.data.messages_sent, 1);
|
||||
// Server data tests
|
||||
channelzClient.getServer({server_id: testServer.getChannelzRef().id}, (error, serverResult) => {
|
||||
assert.ifError(error);
|
||||
assert(serverResult);
|
||||
assert(serverResult.server);
|
||||
assert(serverResult.server.ref);
|
||||
assert(serverResult.server.data);
|
||||
assert.strictEqual(+serverResult.server.ref.server_id, testServer.getChannelzRef().id);
|
||||
assert.strictEqual(+serverResult.server.data.calls_started, 1);
|
||||
assert.strictEqual(+serverResult.server.data.calls_succeeded, 1);
|
||||
assert.strictEqual(+serverResult.server.data.calls_failed, 0);
|
||||
channelzClient.getServerSockets({server_id: testServer.getChannelzRef().id}, (error, socketsResult) => {
|
||||
assert.ifError(error);
|
||||
assert(socketsResult);
|
||||
assert.strictEqual(socketsResult.socket_ref.length, 1);
|
||||
channelzClient.getSocket({socket_id: socketsResult.socket_ref[0].socket_id}, (error, serverSocketResult) => {
|
||||
assert.ifError(error);
|
||||
assert(serverSocketResult);
|
||||
assert(serverSocketResult.socket);
|
||||
assert(serverSocketResult.socket.ref);
|
||||
assert(serverSocketResult.socket.data);
|
||||
assert.strictEqual(serverSocketResult.socket.ref.socket_id, socketsResult.socket_ref[0].socket_id);
|
||||
assert.strictEqual(+serverSocketResult.socket.data.streams_started, 1);
|
||||
assert.strictEqual(+serverSocketResult.socket.data.streams_succeeded, 1);
|
||||
assert.strictEqual(+serverSocketResult.socket.data.streams_failed, 0);
|
||||
assert.strictEqual(+serverSocketResult.socket.data.messages_received, 1);
|
||||
assert.strictEqual(+serverSocketResult.socket.data.messages_sent, 1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should count failed calls', (done) => {
|
||||
testClient.unary({error: true}, (error: grpc.ServiceError, value: unknown) => {
|
||||
assert(error);
|
||||
// Channel data tests
|
||||
channelzClient.GetChannel({channel_id: testClient.getChannel().getChannelzRef().id}, (error, channelResult) => {
|
||||
assert.ifError(error);
|
||||
assert(channelResult);
|
||||
assert(channelResult.channel);
|
||||
assert(channelResult.channel.ref);
|
||||
assert(channelResult.channel.data);
|
||||
assert.strictEqual(+channelResult.channel.data.calls_started, 1);
|
||||
assert.strictEqual(+channelResult.channel.data.calls_succeeded, 0);
|
||||
assert.strictEqual(+channelResult.channel.data.calls_failed, 1);
|
||||
assert.strictEqual(channelResult.channel.subchannel_ref.length, 1);
|
||||
channelzClient.getSubchannel({subchannel_id: channelResult.channel.subchannel_ref[0].subchannel_id}, (error, subchannelResult) => {
|
||||
assert.ifError(error);
|
||||
assert(subchannelResult);
|
||||
assert(subchannelResult.subchannel);
|
||||
assert(subchannelResult.subchannel.ref);
|
||||
assert(subchannelResult.subchannel.data);
|
||||
assert.strictEqual(subchannelResult.subchannel.ref.subchannel_id, channelResult.channel!.subchannel_ref[0].subchannel_id);
|
||||
assert.strictEqual(+subchannelResult.subchannel.data.calls_started, 1);
|
||||
assert.strictEqual(+subchannelResult.subchannel.data.calls_succeeded, 0);
|
||||
assert.strictEqual(+subchannelResult.subchannel.data.calls_failed, 1);
|
||||
assert.strictEqual(subchannelResult.subchannel.socket_ref.length, 1);
|
||||
channelzClient.getSocket({socket_id: subchannelResult.subchannel.socket_ref[0].socket_id}, (error, socketResult) => {
|
||||
assert.ifError(error);
|
||||
assert(socketResult);
|
||||
assert(socketResult.socket);
|
||||
assert(socketResult.socket.ref);
|
||||
assert(socketResult.socket.data);
|
||||
assert.strictEqual(socketResult.socket.ref.socket_id, subchannelResult.subchannel!.socket_ref[0].socket_id);
|
||||
assert.strictEqual(+socketResult.socket.data.streams_started, 1);
|
||||
assert.strictEqual(+socketResult.socket.data.streams_succeeded, 1);
|
||||
assert.strictEqual(+socketResult.socket.data.streams_failed, 0);
|
||||
assert.strictEqual(+socketResult.socket.data.messages_received, 0);
|
||||
assert.strictEqual(+socketResult.socket.data.messages_sent, 1);
|
||||
// Server data tests
|
||||
channelzClient.getServer({server_id: testServer.getChannelzRef().id}, (error, serverResult) => {
|
||||
assert.ifError(error);
|
||||
assert(serverResult);
|
||||
assert(serverResult.server);
|
||||
assert(serverResult.server.ref);
|
||||
assert(serverResult.server.data);
|
||||
assert.strictEqual(+serverResult.server.ref.server_id, testServer.getChannelzRef().id);
|
||||
assert.strictEqual(+serverResult.server.data.calls_started, 1);
|
||||
assert.strictEqual(+serverResult.server.data.calls_succeeded, 0);
|
||||
assert.strictEqual(+serverResult.server.data.calls_failed, 1);
|
||||
channelzClient.getServerSockets({server_id: testServer.getChannelzRef().id}, (error, socketsResult) => {
|
||||
assert.ifError(error);
|
||||
assert(socketsResult);
|
||||
assert.strictEqual(socketsResult.socket_ref.length, 1);
|
||||
channelzClient.getSocket({socket_id: socketsResult.socket_ref[0].socket_id}, (error, serverSocketResult) => {
|
||||
assert.ifError(error);
|
||||
assert(serverSocketResult);
|
||||
assert(serverSocketResult.socket);
|
||||
assert(serverSocketResult.socket.ref);
|
||||
assert(serverSocketResult.socket.data);
|
||||
assert.strictEqual(serverSocketResult.socket.ref.socket_id, socketsResult.socket_ref[0].socket_id);
|
||||
assert.strictEqual(+serverSocketResult.socket.data.streams_started, 1);
|
||||
assert.strictEqual(+serverSocketResult.socket.data.streams_succeeded, 0);
|
||||
assert.strictEqual(+serverSocketResult.socket.data.streams_failed, 1);
|
||||
assert.strictEqual(+serverSocketResult.socket.data.messages_received, 1);
|
||||
assert.strictEqual(+serverSocketResult.socket.data.messages_sent, 0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -454,6 +454,38 @@ function generateEnumInterface(formatter: TextFormatter, enumType: Protobuf.Enum
|
|||
formatter.writeLine('}');
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a list of methods that are exist in the generic Client class in the
|
||||
* gRPC libraries. TypeScript has a problem with methods in subclasses with the
|
||||
* same names as methods in the superclass, but with mismatched APIs. So, we
|
||||
* avoid generating methods with these names in the service client interfaces.
|
||||
* We always generate two service client methods per service method: one camel
|
||||
* cased, and one with the original casing. So we will still generate one
|
||||
* service client method for any conflicting name.
|
||||
*
|
||||
* Technically, at runtime conflicting name in the service client method
|
||||
* actually shadows the original method, but TypeScript does not have a good
|
||||
* way to represent that. So this change is not 100% accurate, but it gets the
|
||||
* generated code to compile.
|
||||
*
|
||||
* This is just a list of the methods in the Client class definitions in
|
||||
* grpc@1.24.11 and @grpc/grpc-js@1.4.0.
|
||||
*/
|
||||
const CLIENT_RESERVED_METHOD_NAMES = new Set([
|
||||
'close',
|
||||
'getChannel',
|
||||
'waitForReady',
|
||||
'makeUnaryRequest',
|
||||
'makeClientStreamRequest',
|
||||
'makeServerStreamRequest',
|
||||
'makeBidiStreamRequest',
|
||||
'resolveCallInterceptors',
|
||||
/* These methods are private, but TypeScript is not happy with overriding even
|
||||
* private methods with mismatched APIs. */
|
||||
'checkOptionalUnaryResponseArguments',
|
||||
'checkMetadataAndOptions'
|
||||
]);
|
||||
|
||||
function generateServiceClientInterface(formatter: TextFormatter, serviceType: Protobuf.Service, options: GeneratorOptions) {
|
||||
if (options.includeComments) {
|
||||
formatComment(formatter, serviceType.comment);
|
||||
|
@ -463,6 +495,9 @@ function generateServiceClientInterface(formatter: TextFormatter, serviceType: P
|
|||
for (const methodName of Object.keys(serviceType.methods).sort()) {
|
||||
const method = serviceType.methods[methodName];
|
||||
for (const name of [methodName, camelCase(methodName)]) {
|
||||
if (CLIENT_RESERVED_METHOD_NAMES.has(name)) {
|
||||
continue;
|
||||
}
|
||||
if (options.includeComments) {
|
||||
formatComment(formatter, method.comment);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@grpc/proto-loader",
|
||||
"version": "0.6.4",
|
||||
"version": "0.6.5",
|
||||
"author": "Google Inc.",
|
||||
"contributors": [
|
||||
{
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2021 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.
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
require('../fixtures/js_js');
|
||||
const interopClient = require('../interop/interop_client');
|
||||
const interopServer = require('../interop/interop_server');
|
||||
const serverGrpc = require('../any_grpc').server;
|
||||
|
||||
const hostOverride = 'foo.test.google.fr';
|
||||
|
||||
const testCases = [
|
||||
'empty_unary',
|
||||
'large_unary',
|
||||
'client_streaming',
|
||||
'server_streaming',
|
||||
'ping_pong',
|
||||
'empty_stream',
|
||||
'cancel_after_begin',
|
||||
'cancel_after_first_response',
|
||||
'timeout_on_sleeping_server',
|
||||
'custom_metadata',
|
||||
'status_code_and_message',
|
||||
'special_status_message',
|
||||
'unimplemented_service',
|
||||
'unimplemented_method'
|
||||
];
|
||||
|
||||
function getRandomTest() {
|
||||
return testCases[(Math.random() * testCases.length) | 0];
|
||||
}
|
||||
|
||||
let testCompleteCount = 0;
|
||||
|
||||
interopServer.getServer('0', true, (error, result) => {
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
const channelzServer = new serverGrpc.Server();
|
||||
channelzServer.bindAsync('localhost:0', serverGrpc.ServerCredentials.createInsecure(), (error, port) => {
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
console.log(`Serving channelz at port ${port}`);
|
||||
serverGrpc.addAdminServicesToServer(channelzServer);
|
||||
channelzServer.start();
|
||||
result.server.start();
|
||||
setInterval(() => {
|
||||
interopClient.runTest(`localhost:${result.port}`, hostOverride, getRandomTest(), true, true, () => {
|
||||
testCompleteCount += 1;
|
||||
if (testCompleteCount % 100 === 0) {
|
||||
console.log(`Completed ${testCompleteCount} tests`);
|
||||
}
|
||||
});
|
||||
}, 100);
|
||||
});
|
||||
})
|
|
@ -200,7 +200,7 @@ function handleHalfDuplex(call) {
|
|||
* Get a server object bound to the given port
|
||||
* @param {string} port Port to which to bind
|
||||
* @param {boolean} tls Indicates that the bound port should use TLS
|
||||
* @param {function(Error, {{server: Server, port: number}})} callback Callback
|
||||
* @param {function(Error, {server: Server, port: number})} callback Callback
|
||||
* to call with result or error
|
||||
* @param {object?} options Optional additional options to use when
|
||||
* constructing the server
|
||||
|
|
Loading…
Reference in New Issue