All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.grpc.protobuf.services.ChannelzProtoUtil Maven / Gradle / Ivy

The newest version!
/*
 * 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.
 */

package io.grpc.protobuf.services;

import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.protobuf.Any;
import com.google.protobuf.ByteString;
import com.google.protobuf.Int64Value;
import com.google.protobuf.MessageLite;
import com.google.protobuf.util.Durations;
import com.google.protobuf.util.Timestamps;
import io.grpc.ConnectivityState;
import io.grpc.InternalChannelz;
import io.grpc.InternalChannelz.ChannelStats;
import io.grpc.InternalChannelz.ChannelTrace.Event;
import io.grpc.InternalChannelz.RootChannelList;
import io.grpc.InternalChannelz.ServerList;
import io.grpc.InternalChannelz.ServerSocketsList;
import io.grpc.InternalChannelz.ServerStats;
import io.grpc.InternalChannelz.SocketStats;
import io.grpc.InternalChannelz.TransportStats;
import io.grpc.InternalInstrumented;
import io.grpc.InternalWithLogId;
import io.grpc.Status;
import io.grpc.channelz.v1.Address;
import io.grpc.channelz.v1.Address.OtherAddress;
import io.grpc.channelz.v1.Address.TcpIpAddress;
import io.grpc.channelz.v1.Address.UdsAddress;
import io.grpc.channelz.v1.Channel;
import io.grpc.channelz.v1.ChannelConnectivityState;
import io.grpc.channelz.v1.ChannelConnectivityState.State;
import io.grpc.channelz.v1.ChannelData;
import io.grpc.channelz.v1.ChannelRef;
import io.grpc.channelz.v1.ChannelTrace;
import io.grpc.channelz.v1.ChannelTraceEvent;
import io.grpc.channelz.v1.ChannelTraceEvent.Severity;
import io.grpc.channelz.v1.GetServerSocketsResponse;
import io.grpc.channelz.v1.GetServersResponse;
import io.grpc.channelz.v1.GetTopChannelsResponse;
import io.grpc.channelz.v1.Security;
import io.grpc.channelz.v1.Security.OtherSecurity;
import io.grpc.channelz.v1.Security.Tls;
import io.grpc.channelz.v1.Server;
import io.grpc.channelz.v1.ServerData;
import io.grpc.channelz.v1.ServerRef;
import io.grpc.channelz.v1.Socket;
import io.grpc.channelz.v1.SocketData;
import io.grpc.channelz.v1.SocketOption;
import io.grpc.channelz.v1.SocketOptionLinger;
import io.grpc.channelz.v1.SocketOptionTcpInfo;
import io.grpc.channelz.v1.SocketOptionTimeout;
import io.grpc.channelz.v1.SocketRef;
import io.grpc.channelz.v1.Subchannel;
import io.grpc.channelz.v1.SubchannelRef;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.security.cert.CertificateEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * A static utility class for turning internal data structures into protos.
 *
 * 

Works with both regular and lite protos. */ final class ChannelzProtoUtil { private static final Logger logger = Logger.getLogger(ChannelzProtoUtil.class.getName()); private ChannelzProtoUtil() { // do not instantiate. } static ChannelRef toChannelRef(InternalWithLogId obj) { return ChannelRef .newBuilder() .setChannelId(obj.getLogId().getId()) .setName(obj.toString()) .build(); } static SubchannelRef toSubchannelRef(InternalWithLogId obj) { return SubchannelRef .newBuilder() .setSubchannelId(obj.getLogId().getId()) .setName(obj.toString()) .build(); } static ServerRef toServerRef(InternalWithLogId obj) { return ServerRef .newBuilder() .setServerId(obj.getLogId().getId()) .setName(obj.toString()) .build(); } static SocketRef toSocketRef(InternalWithLogId obj) { return SocketRef .newBuilder() .setSocketId(obj.getLogId().getId()) .setName(obj.toString()) .build(); } static Server toServer(InternalInstrumented obj) { ServerStats stats = getFuture(obj.getStats()); Server.Builder builder = Server .newBuilder() .setRef(toServerRef(obj)) .setData(toServerData(stats)); for (InternalInstrumented listenSocket : stats.listenSockets) { builder.addListenSocket(toSocketRef(listenSocket)); } return builder.build(); } static ServerData toServerData(ServerStats stats) { return ServerData .newBuilder() .setCallsStarted(stats.callsStarted) .setCallsSucceeded(stats.callsSucceeded) .setCallsFailed(stats.callsFailed) .setLastCallStartedTimestamp(Timestamps.fromNanos(stats.lastCallStartedNanos)) .build(); } static Security toSecurity(InternalChannelz.Security security) { Preconditions.checkNotNull(security); Preconditions.checkState( security.tls != null ^ security.other != null, "one of tls or othersecurity must be non null"); if (security.tls != null) { Tls.Builder tlsBuilder = Tls.newBuilder().setStandardName(security.tls.cipherSuiteStandardName); try { if (security.tls.localCert != null) { tlsBuilder.setLocalCertificate(ByteString.copyFrom( security.tls.localCert.getEncoded())); } if (security.tls.remoteCert != null) { tlsBuilder.setRemoteCertificate(ByteString.copyFrom( security.tls.remoteCert.getEncoded())); } } catch (CertificateEncodingException e) { logger.log(Level.FINE, "Caught exception", e); } return Security.newBuilder().setTls(tlsBuilder).build(); } else { OtherSecurity.Builder builder = OtherSecurity.newBuilder().setName(security.other.name); if (security.other.any != null) { builder.setValue((Any) security.other.any); } return Security.newBuilder().setOther(builder).build(); } } static Socket toSocket(InternalInstrumented obj) { SocketStats socketStats = getFuture(obj.getStats()); Socket.Builder builder = Socket.newBuilder() .setRef(toSocketRef(obj)) .setLocal(toAddress(socketStats.local)); if (socketStats.security != null) { builder.setSecurity(toSecurity(socketStats.security)); } // listen sockets do not have remote nor data if (socketStats.remote != null) { builder.setRemote(toAddress(socketStats.remote)); } builder.setData(extractSocketData(socketStats)); return builder.build(); } static Address toAddress(SocketAddress address) { Preconditions.checkNotNull(address); Address.Builder builder = Address.newBuilder(); if (address instanceof InetSocketAddress) { InetSocketAddress inetAddress = (InetSocketAddress) address; builder.setTcpipAddress( TcpIpAddress .newBuilder() .setIpAddress( ByteString.copyFrom(inetAddress.getAddress().getAddress())) .setPort(inetAddress.getPort()) .build()); } else if (address.getClass().getName().endsWith("io.netty.channel.unix.DomainSocketAddress")) { builder.setUdsAddress( UdsAddress .newBuilder() .setFilename(address.toString()) // DomainSocketAddress.toString returns filename .build()); } else { builder.setOtherAddress(OtherAddress.newBuilder().setName(address.toString()).build()); } return builder.build(); } static SocketData extractSocketData(SocketStats socketStats) { SocketData.Builder builder = SocketData.newBuilder(); if (socketStats.data != null) { TransportStats s = socketStats.data; builder .setStreamsStarted(s.streamsStarted) .setStreamsSucceeded(s.streamsSucceeded) .setStreamsFailed(s.streamsFailed) .setMessagesSent(s.messagesSent) .setMessagesReceived(s.messagesReceived) .setKeepAlivesSent(s.keepAlivesSent) .setLastLocalStreamCreatedTimestamp( Timestamps.fromNanos(s.lastLocalStreamCreatedTimeNanos)) .setLastRemoteStreamCreatedTimestamp( Timestamps.fromNanos(s.lastRemoteStreamCreatedTimeNanos)) .setLastMessageSentTimestamp( Timestamps.fromNanos(s.lastMessageSentTimeNanos)) .setLastMessageReceivedTimestamp( Timestamps.fromNanos(s.lastMessageReceivedTimeNanos)) .setLocalFlowControlWindow( Int64Value.of(s.localFlowControlWindow)) .setRemoteFlowControlWindow( Int64Value.of(s.remoteFlowControlWindow)); } builder.addAllOption(toSocketOptionsList(socketStats.socketOptions)); return builder.build(); } public static final String SO_LINGER = "SO_LINGER"; public static final String SO_TIMEOUT = "SO_TIMEOUT"; public static final String TCP_INFO = "TCP_INFO"; static SocketOption toSocketOptionLinger(int lingerSeconds) { final SocketOptionLinger lingerOpt; if (lingerSeconds >= 0) { lingerOpt = SocketOptionLinger .newBuilder() .setActive(true) .setDuration(Durations.fromSeconds(lingerSeconds)) .build(); } else { lingerOpt = SocketOptionLinger.getDefaultInstance(); } return SocketOption.newBuilder() .setName(SO_LINGER) .setAdditional(packToAny("SocketOptionLinger", lingerOpt)) .build(); } static SocketOption toSocketOptionTimeout(String name, int timeoutMillis) { Preconditions.checkNotNull(name); return SocketOption.newBuilder() .setName(name) .setAdditional( packToAny( "SocketOptionTimeout", SocketOptionTimeout.newBuilder() .setDuration(Durations.fromMillis(timeoutMillis)) .build())) .build(); } static SocketOption toSocketOptionTcpInfo(InternalChannelz.TcpInfo i) { SocketOptionTcpInfo tcpInfo = SocketOptionTcpInfo.newBuilder() .setTcpiState(i.state) .setTcpiCaState(i.caState) .setTcpiRetransmits(i.retransmits) .setTcpiProbes(i.probes) .setTcpiBackoff(i.backoff) .setTcpiOptions(i.options) .setTcpiSndWscale(i.sndWscale) .setTcpiRcvWscale(i.rcvWscale) .setTcpiRto(i.rto) .setTcpiAto(i.ato) .setTcpiSndMss(i.sndMss) .setTcpiRcvMss(i.rcvMss) .setTcpiUnacked(i.unacked) .setTcpiSacked(i.sacked) .setTcpiLost(i.lost) .setTcpiRetrans(i.retrans) .setTcpiFackets(i.fackets) .setTcpiLastDataSent(i.lastDataSent) .setTcpiLastAckSent(i.lastAckSent) .setTcpiLastDataRecv(i.lastDataRecv) .setTcpiLastAckRecv(i.lastAckRecv) .setTcpiPmtu(i.pmtu) .setTcpiRcvSsthresh(i.rcvSsthresh) .setTcpiRtt(i.rtt) .setTcpiRttvar(i.rttvar) .setTcpiSndSsthresh(i.sndSsthresh) .setTcpiSndCwnd(i.sndCwnd) .setTcpiAdvmss(i.advmss) .setTcpiReordering(i.reordering) .build(); return SocketOption.newBuilder() .setName(TCP_INFO) .setAdditional(packToAny("SocketOptionTcpInfo", tcpInfo)) .build(); } static SocketOption toSocketOptionAdditional(String name, String value) { Preconditions.checkNotNull(name); Preconditions.checkNotNull(value); return SocketOption.newBuilder().setName(name).setValue(value).build(); } static List toSocketOptionsList(InternalChannelz.SocketOptions options) { Preconditions.checkNotNull(options); List ret = new ArrayList<>(); if (options.lingerSeconds != null) { ret.add(toSocketOptionLinger(options.lingerSeconds)); } if (options.soTimeoutMillis != null) { ret.add(toSocketOptionTimeout(SO_TIMEOUT, options.soTimeoutMillis)); } if (options.tcpInfo != null) { ret.add(toSocketOptionTcpInfo(options.tcpInfo)); } for (Map.Entry entry : options.others.entrySet()) { ret.add(toSocketOptionAdditional(entry.getKey(), entry.getValue())); } return ret; } static Channel toChannel(InternalInstrumented channel) { ChannelStats stats = getFuture(channel.getStats()); Channel.Builder channelBuilder = Channel .newBuilder() .setRef(toChannelRef(channel)) .setData(extractChannelData(stats)); for (InternalWithLogId subchannel : stats.subchannels) { channelBuilder.addSubchannelRef(toSubchannelRef(subchannel)); } return channelBuilder.build(); } static ChannelData extractChannelData(InternalChannelz.ChannelStats stats) { ChannelData.Builder builder = ChannelData.newBuilder(); builder.setTarget(stats.target) .setState(toChannelConnectivityState(stats.state)) .setCallsStarted(stats.callsStarted) .setCallsSucceeded(stats.callsSucceeded) .setCallsFailed(stats.callsFailed) .setLastCallStartedTimestamp(Timestamps.fromNanos(stats.lastCallStartedNanos)); if (stats.channelTrace != null) { builder.setTrace(toChannelTrace(stats.channelTrace)); } return builder.build(); } static ChannelConnectivityState toChannelConnectivityState(ConnectivityState s) { return ChannelConnectivityState.newBuilder().setState(toState(s)).build(); } private static ChannelTrace toChannelTrace(InternalChannelz.ChannelTrace channelTrace) { return ChannelTrace.newBuilder() .setNumEventsLogged(channelTrace.numEventsLogged) .setCreationTimestamp(Timestamps.fromNanos(channelTrace.creationTimeNanos)) .addAllEvents(toChannelTraceEvents(channelTrace.events)) .build(); } private static List toChannelTraceEvents(List events) { List channelTraceEvents = new ArrayList<>(); for (Event event : events) { ChannelTraceEvent.Builder builder = ChannelTraceEvent.newBuilder() .setDescription(event.description) .setSeverity(toSeverity(event.severity)) .setTimestamp(Timestamps.fromNanos(event.timestampNanos)); if (event.channelRef != null) { builder.setChannelRef(toChannelRef(event.channelRef)); } if (event.subchannelRef != null) { builder.setSubchannelRef(toSubchannelRef(event.subchannelRef)); } channelTraceEvents.add(builder.build()); } return Collections.unmodifiableList(channelTraceEvents); } static Severity toSeverity(Event.Severity severity) { if (severity == null) { return Severity.CT_UNKNOWN; } switch (severity) { case CT_INFO: return Severity.CT_INFO; case CT_ERROR: return Severity.CT_ERROR; case CT_WARNING: return Severity.CT_WARNING; default: return Severity.CT_UNKNOWN; } } static State toState(ConnectivityState state) { if (state == null) { return State.UNKNOWN; } switch (state) { case IDLE: return State.IDLE; case READY: return State.READY; case CONNECTING: return State.CONNECTING; case SHUTDOWN: return State.SHUTDOWN; case TRANSIENT_FAILURE: return State.TRANSIENT_FAILURE; default: return State.UNKNOWN; } } static Subchannel toSubchannel(InternalInstrumented subchannel) { ChannelStats stats = getFuture(subchannel.getStats()); Subchannel.Builder subchannelBuilder = Subchannel .newBuilder() .setRef(toSubchannelRef(subchannel)) .setData(extractChannelData(stats)); Preconditions.checkState(stats.sockets.isEmpty() || stats.subchannels.isEmpty()); for (InternalWithLogId childSocket : stats.sockets) { subchannelBuilder.addSocketRef(toSocketRef(childSocket)); } for (InternalWithLogId childSubchannel : stats.subchannels) { subchannelBuilder.addSubchannelRef(toSubchannelRef(childSubchannel)); } return subchannelBuilder.build(); } static GetTopChannelsResponse toGetTopChannelResponse(RootChannelList rootChannels) { GetTopChannelsResponse.Builder responseBuilder = GetTopChannelsResponse .newBuilder() .setEnd(rootChannels.end); for (InternalInstrumented c : rootChannels.channels) { responseBuilder.addChannel(ChannelzProtoUtil.toChannel(c)); } return responseBuilder.build(); } static GetServersResponse toGetServersResponse(ServerList servers) { GetServersResponse.Builder responseBuilder = GetServersResponse .newBuilder() .setEnd(servers.end); for (InternalInstrumented s : servers.servers) { responseBuilder.addServer(ChannelzProtoUtil.toServer(s)); } return responseBuilder.build(); } static GetServerSocketsResponse toGetServerSocketsResponse(ServerSocketsList serverSockets) { GetServerSocketsResponse.Builder responseBuilder = GetServerSocketsResponse .newBuilder() .setEnd(serverSockets.end); for (InternalWithLogId s : serverSockets.sockets) { responseBuilder.addSocketRef(ChannelzProtoUtil.toSocketRef(s)); } return responseBuilder.build(); } private static T getFuture(ListenableFuture future) { try { T ret = future.get(); if (ret == null) { throw Status.UNIMPLEMENTED .withDescription("The entity's stats can not be retrieved. " + "If this is an InProcessTransport this is expected.") .asRuntimeException(); } return ret; } catch (InterruptedException e) { throw Status.INTERNAL.withCause(e).asRuntimeException(); } catch (ExecutionException e) { throw Status.INTERNAL.withCause(e).asRuntimeException(); } } // A version of Any.pack() that works with protolite. private static Any packToAny(String typeName, MessageLite value) { return Any.newBuilder() .setTypeUrl("type.googleapis.com/grpc.channelz.v1." + typeName) .setValue(value.toByteString()) .build(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy