gRPC service utilities providing health checking, server reflection, channelz observability, and binary logging capabilities
—
Runtime introspection service providing detailed information about gRPC channels, servers, and connections for debugging and monitoring. Channelz enables deep visibility into gRPC communication patterns and connection health.
Main service providing channelz observability data through gRPC endpoints.
/**
* The channelz service provides stats about a running gRPC process.
* Enables runtime introspection of channels, servers, and connections.
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/4206")
public final class ChannelzService extends ChannelzGrpc.ChannelzImplBase {
/**
* Creates a channelz service instance
* @param maxPageSize Maximum number of items returned per page in responses
* @return ChannelzService instance ready to be added to a server
*/
public static ChannelzService newInstance(int maxPageSize);
/**
* Returns top level channels (ManagedChannels)
* @param request Request specifying pagination options
* @param responseObserver Observer for receiving channel information
*/
public void getTopChannels(
GetTopChannelsRequest request,
StreamObserver<GetTopChannelsResponse> responseObserver
);
/**
* Returns a specific top level channel (ManagedChannel)
* @param request Request specifying channel ID
* @param responseObserver Observer for receiving channel details
*/
public void getChannel(
GetChannelRequest request,
StreamObserver<GetChannelResponse> responseObserver
);
/**
* Returns servers managed by this process
* @param request Request specifying pagination options
* @param responseObserver Observer for receiving server information
*/
public void getServers(
GetServersRequest request,
StreamObserver<GetServersResponse> responseObserver
);
/**
* Returns a specific server
* @param request Request specifying server ID
* @param responseObserver Observer for receiving server details
*/
public void getServer(
GetServerRequest request,
StreamObserver<GetServerResponse> responseObserver
);
/**
* Returns a subchannel
* @param request Request specifying subchannel ID
* @param responseObserver Observer for receiving subchannel details
*/
public void getSubchannel(
GetSubchannelRequest request,
StreamObserver<GetSubchannelResponse> responseObserver
);
/**
* Returns a socket
* @param request Request specifying socket ID
* @param responseObserver Observer for receiving socket details
*/
public void getSocket(
GetSocketRequest request,
StreamObserver<GetSocketResponse> responseObserver
);
/**
* Returns server sockets
* @param request Request specifying server ID and pagination
* @param responseObserver Observer for receiving server socket information
*/
public void getServerSockets(
GetServerSocketsRequest request,
StreamObserver<GetServerSocketsResponse> responseObserver
);
}Usage Examples:
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.protobuf.services.ChannelzService;
// Add channelz service to server for observability
Server server = ServerBuilder.forPort(8080)
.addService(ChannelzService.newInstance(100)) // Max 100 items per page
.addService(new MyBusinessService())
.build();
server.start();Channelz provides detailed metrics that can be integrated with monitoring systems:
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.protobuf.services.ChannelzService;
import io.grpc.protobuf.services.HealthStatusManager;
public class ObservableServer {
private final Server server;
private final HealthStatusManager healthManager;
public ObservableServer(int port) {
this.healthManager = new HealthStatusManager();
this.server = ServerBuilder.forPort(port)
// Add channelz for detailed observability
.addService(ChannelzService.newInstance(50))
// Add health checking
.addService(healthManager.getHealthService())
// Add business services
.addService(new UserService())
.addService(new OrderService())
.build();
}
public void start() throws IOException {
server.start();
healthManager.setStatus("", ServingStatus.SERVING);
System.out.println("Observable server started on port " + server.getPort());
System.out.println("Channelz available for monitoring and debugging");
}
public void shutdown() {
healthManager.enterTerminalState();
server.shutdown();
}
}Accessing channelz data from a client for monitoring purposes:
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.channelz.v1.ChannelzGrpc;
import io.grpc.channelz.v1.GetTopChannelsRequest;
import io.grpc.channelz.v1.GetServersRequest;
public class ChannelzMonitor {
private final ChannelzGrpc.ChannelzBlockingStub channelzStub;
public ChannelzMonitor(String host, int port) {
ManagedChannel channel = ManagedChannelBuilder.forAddress(host, port)
.usePlaintext()
.build();
this.channelzStub = ChannelzGrpc.newBlockingStub(channel);
}
public void printTopChannels() {
GetTopChannelsRequest request = GetTopChannelsRequest.newBuilder()
.setMaxResults(10)
.build();
GetTopChannelsResponse response = channelzStub.getTopChannels(request);
System.out.println("Top Channels:");
response.getChannelList().forEach(channel -> {
System.out.printf("Channel ID: %d, Target: %s, State: %s%n",
channel.getRef().getChannelId(),
channel.getData().getTarget(),
channel.getData().getState().getState()
);
});
}
public void printServers() {
GetServersRequest request = GetServersRequest.newBuilder()
.setMaxResults(10)
.build();
GetServersResponse response = channelzStub.getServers(request);
System.out.println("Servers:");
response.getServerList().forEach(server -> {
System.out.printf("Server ID: %d, Listen Sockets: %d, Calls: %d%n",
server.getRef().getServerId(),
server.getData().getListenSocketCount(),
server.getData().getCallsStarted()
);
});
}
}Using channelz to diagnose connectivity problems:
public class ChannelzDebugger {
private final ChannelzGrpc.ChannelzBlockingStub channelzStub;
public ChannelzDebugger(String host, int port) {
ManagedChannel channel = ManagedChannelBuilder.forAddress(host, port)
.usePlaintext()
.build();
this.channelzStub = ChannelzGrpc.newBlockingStub(channel);
}
public void debugChannelState(long channelId) {
GetChannelRequest request = GetChannelRequest.newBuilder()
.setChannelId(channelId)
.build();
try {
GetChannelResponse response = channelzStub.getChannel(request);
ChannelData data = response.getChannel().getData();
System.out.println("Channel Debug Information:");
System.out.println("Target: " + data.getTarget());
System.out.println("State: " + data.getState().getState());
System.out.println("Calls Started: " + data.getCallsStarted());
System.out.println("Calls Succeeded: " + data.getCallsSucceeded());
System.out.println("Calls Failed: " + data.getCallsFailed());
System.out.println("Last Call Started: " + data.getLastCallStartedTimestamp());
// Print subchannel information
data.getSubchannelRefList().forEach(subchannelRef -> {
System.out.println("Subchannel ID: " + subchannelRef.getSubchannelId());
debugSubchannel(subchannelRef.getSubchannelId());
});
} catch (Exception e) {
System.err.println("Failed to get channel info: " + e.getMessage());
}
}
private void debugSubchannel(long subchannelId) {
GetSubchannelRequest request = GetSubchannelRequest.newBuilder()
.setSubchannelId(subchannelId)
.build();
try {
GetSubchannelResponse response = channelzStub.getSubchannel(request);
SubchannelData data = response.getSubchannel().getData();
System.out.println(" Subchannel State: " + data.getState().getState());
System.out.println(" Target: " + data.getTarget());
} catch (Exception e) {
System.err.println(" Failed to get subchannel info: " + e.getMessage());
}
}
}Channelz is automatically included when using the admin interface:
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.services.AdminInterface;
// Admin interface includes channelz automatically
Server server = ServerBuilder.forPort(8080)
.addServices(AdminInterface.getStandardServices()) // Includes channelz
.addService(new MyBusinessService())
.build();Channelz data collection has minimal performance impact but consider these guidelines:
// Use reasonable page sizes to avoid memory issues
ChannelzService channelzService = ChannelzService.newInstance(50); // Reasonable page size
// For high-traffic servers, channelz provides valuable debugging info
// but monitor memory usage if you have many channels/connections
Server server = ServerBuilder.forPort(8080)
.addService(channelzService)
.addService(new HighTrafficService())
.build();Install with Tessl CLI
npx tessl i tessl/maven-io-grpc--grpc-services