• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 The gRPC Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.grpc;
18 
19 import static com.google.common.base.Preconditions.checkNotNull;
20 import static com.google.common.base.Preconditions.checkState;
21 
22 import com.google.common.annotations.VisibleForTesting;
23 import com.google.common.base.MoreObjects;
24 import com.google.common.base.Objects;
25 import java.net.SocketAddress;
26 import java.security.cert.Certificate;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.HashMap;
30 import java.util.Iterator;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.concurrent.ConcurrentHashMap;
34 import java.util.concurrent.ConcurrentMap;
35 import java.util.concurrent.ConcurrentNavigableMap;
36 import java.util.concurrent.ConcurrentSkipListMap;
37 import java.util.logging.Level;
38 import java.util.logging.Logger;
39 import javax.annotation.Nullable;
40 import javax.annotation.concurrent.Immutable;
41 import javax.net.ssl.SSLPeerUnverifiedException;
42 import javax.net.ssl.SSLSession;
43 
44 /**
45  * This is an internal API. Do NOT use.
46  */
47 @Internal
48 public final class InternalChannelz {
49   private static final Logger log = Logger.getLogger(InternalChannelz.class.getName());
50   private static final InternalChannelz INSTANCE = new InternalChannelz();
51 
52   private final ConcurrentNavigableMap<Long, InternalInstrumented<ServerStats>> servers
53       = new ConcurrentSkipListMap<>();
54   private final ConcurrentNavigableMap<Long, InternalInstrumented<ChannelStats>> rootChannels
55       = new ConcurrentSkipListMap<>();
56   private final ConcurrentMap<Long, InternalInstrumented<ChannelStats>> subchannels
57       = new ConcurrentHashMap<>();
58   // An InProcessTransport can appear in both otherSockets and perServerSockets simultaneously
59   private final ConcurrentMap<Long, InternalInstrumented<SocketStats>> otherSockets
60       = new ConcurrentHashMap<>();
61   private final ConcurrentMap<Long, ServerSocketMap> perServerSockets
62       = new ConcurrentHashMap<>();
63 
64   // A convenience class to avoid deeply nested types.
65   private static final class ServerSocketMap
66       extends ConcurrentSkipListMap<Long, InternalInstrumented<SocketStats>> {
67     private static final long serialVersionUID = -7883772124944661414L;
68   }
69 
70   @VisibleForTesting
InternalChannelz()71   public InternalChannelz() {
72   }
73 
instance()74   public static InternalChannelz instance() {
75     return INSTANCE;
76   }
77 
78   /** Adds a server. */
addServer(InternalInstrumented<ServerStats> server)79   public void addServer(InternalInstrumented<ServerStats> server) {
80     ServerSocketMap prev = perServerSockets.put(id(server), new ServerSocketMap());
81     assert prev == null;
82     add(servers, server);
83   }
84 
85   /** Adds a subchannel. */
addSubchannel(InternalInstrumented<ChannelStats> subchannel)86   public void addSubchannel(InternalInstrumented<ChannelStats> subchannel) {
87     add(subchannels, subchannel);
88   }
89 
90   /** Adds a root channel. */
addRootChannel(InternalInstrumented<ChannelStats> rootChannel)91   public void addRootChannel(InternalInstrumented<ChannelStats> rootChannel) {
92     add(rootChannels, rootChannel);
93   }
94 
95   /** Adds a socket. */
addClientSocket(InternalInstrumented<SocketStats> socket)96   public void addClientSocket(InternalInstrumented<SocketStats> socket) {
97     add(otherSockets, socket);
98   }
99 
addListenSocket(InternalInstrumented<SocketStats> socket)100   public void addListenSocket(InternalInstrumented<SocketStats> socket) {
101     add(otherSockets, socket);
102   }
103 
104   /** Adds a server socket. */
addServerSocket( InternalInstrumented<ServerStats> server, InternalInstrumented<SocketStats> socket)105   public void addServerSocket(
106       InternalInstrumented<ServerStats> server, InternalInstrumented<SocketStats> socket) {
107     ServerSocketMap serverSockets = perServerSockets.get(id(server));
108     assert serverSockets != null;
109     add(serverSockets, socket);
110   }
111 
112   /** Removes a server. */
removeServer(InternalInstrumented<ServerStats> server)113   public void removeServer(InternalInstrumented<ServerStats> server) {
114     remove(servers, server);
115     ServerSocketMap prev = perServerSockets.remove(id(server));
116     assert prev != null;
117     assert prev.isEmpty();
118   }
119 
removeSubchannel(InternalInstrumented<ChannelStats> subchannel)120   public void removeSubchannel(InternalInstrumented<ChannelStats> subchannel) {
121     remove(subchannels, subchannel);
122   }
123 
removeRootChannel(InternalInstrumented<ChannelStats> channel)124   public void removeRootChannel(InternalInstrumented<ChannelStats> channel) {
125     remove(rootChannels, channel);
126   }
127 
removeClientSocket(InternalInstrumented<SocketStats> socket)128   public void removeClientSocket(InternalInstrumented<SocketStats> socket) {
129     remove(otherSockets, socket);
130   }
131 
removeListenSocket(InternalInstrumented<SocketStats> socket)132   public void removeListenSocket(InternalInstrumented<SocketStats> socket) {
133     remove(otherSockets, socket);
134   }
135 
136   /** Removes a server socket. */
removeServerSocket( InternalInstrumented<ServerStats> server, InternalInstrumented<SocketStats> socket)137   public void removeServerSocket(
138       InternalInstrumented<ServerStats> server, InternalInstrumented<SocketStats> socket) {
139     ServerSocketMap socketsOfServer = perServerSockets.get(id(server));
140     assert socketsOfServer != null;
141     remove(socketsOfServer, socket);
142   }
143 
144   /** Returns a {@link RootChannelList}. */
getRootChannels(long fromId, int maxPageSize)145   public RootChannelList getRootChannels(long fromId, int maxPageSize) {
146     List<InternalInstrumented<ChannelStats>> channelList
147         = new ArrayList<>();
148     Iterator<InternalInstrumented<ChannelStats>> iterator
149         = rootChannels.tailMap(fromId).values().iterator();
150 
151     while (iterator.hasNext() && channelList.size() < maxPageSize) {
152       channelList.add(iterator.next());
153     }
154     return new RootChannelList(channelList, !iterator.hasNext());
155   }
156 
157   /** Returns a channel. */
158   @Nullable
getChannel(long id)159   public InternalInstrumented<ChannelStats> getChannel(long id) {
160     return rootChannels.get(id);
161   }
162 
163   /** Returns a subchannel. */
164   @Nullable
getSubchannel(long id)165   public InternalInstrumented<ChannelStats> getSubchannel(long id) {
166     return subchannels.get(id);
167   }
168 
169   /** Returns a server list. */
getServers(long fromId, int maxPageSize)170   public ServerList getServers(long fromId, int maxPageSize) {
171     List<InternalInstrumented<ServerStats>> serverList
172         = new ArrayList<>(maxPageSize);
173     Iterator<InternalInstrumented<ServerStats>> iterator
174         = servers.tailMap(fromId).values().iterator();
175 
176     while (iterator.hasNext() && serverList.size() < maxPageSize) {
177       serverList.add(iterator.next());
178     }
179     return new ServerList(serverList, !iterator.hasNext());
180   }
181 
182   /** Returns a server. */
183   @Nullable
getServer(long id)184   public InternalInstrumented<ServerStats> getServer(long id) {
185     return servers.get(id);
186   }
187 
188   /** Returns socket refs for a server. */
189   @Nullable
getServerSockets(long serverId, long fromId, int maxPageSize)190   public ServerSocketsList getServerSockets(long serverId, long fromId, int maxPageSize) {
191     ServerSocketMap serverSockets = perServerSockets.get(serverId);
192     if (serverSockets == null) {
193       return null;
194     }
195     List<InternalWithLogId> socketList = new ArrayList<>(maxPageSize);
196     Iterator<InternalInstrumented<SocketStats>> iterator
197         = serverSockets.tailMap(fromId).values().iterator();
198     while (socketList.size() < maxPageSize && iterator.hasNext()) {
199       socketList.add(iterator.next());
200     }
201     return new ServerSocketsList(socketList, !iterator.hasNext());
202   }
203 
204   /** Returns a socket. */
205   @Nullable
getSocket(long id)206   public InternalInstrumented<SocketStats> getSocket(long id) {
207     InternalInstrumented<SocketStats> clientSocket = otherSockets.get(id);
208     if (clientSocket != null) {
209       return clientSocket;
210     }
211     return getServerSocket(id);
212   }
213 
getServerSocket(long id)214   private InternalInstrumented<SocketStats> getServerSocket(long id) {
215     for (ServerSocketMap perServerSockets : perServerSockets.values()) {
216       InternalInstrumented<SocketStats> serverSocket = perServerSockets.get(id);
217       if (serverSocket != null) {
218         return serverSocket;
219       }
220     }
221     return null;
222   }
223 
224   @VisibleForTesting
containsServer(InternalLogId serverRef)225   public boolean containsServer(InternalLogId serverRef) {
226     return contains(servers, serverRef);
227   }
228 
229   @VisibleForTesting
containsSubchannel(InternalLogId subchannelRef)230   public boolean containsSubchannel(InternalLogId subchannelRef) {
231     return contains(subchannels, subchannelRef);
232   }
233 
getRootChannel(long id)234   public InternalInstrumented<ChannelStats> getRootChannel(long id) {
235     return rootChannels.get(id);
236   }
237 
238   @VisibleForTesting
containsClientSocket(InternalLogId transportRef)239   public boolean containsClientSocket(InternalLogId transportRef) {
240     return contains(otherSockets, transportRef);
241   }
242 
add(Map<Long, T> map, T object)243   private static <T extends InternalInstrumented<?>> void add(Map<Long, T> map, T object) {
244     T prev = map.put(object.getLogId().getId(), object);
245     assert prev == null;
246   }
247 
remove(Map<Long, T> map, T object)248   private static <T extends InternalInstrumented<?>> void remove(Map<Long, T> map, T object) {
249     T prev = map.remove(id(object));
250     assert prev != null;
251   }
252 
contains( Map<Long, T> map, InternalLogId id)253   private static <T extends InternalInstrumented<?>> boolean contains(
254       Map<Long, T> map, InternalLogId id) {
255     return map.containsKey(id.getId());
256   }
257 
258   public static final class RootChannelList {
259     public final List<InternalInstrumented<ChannelStats>> channels;
260     public final boolean end;
261 
262     /** Creates an instance. */
RootChannelList(List<InternalInstrumented<ChannelStats>> channels, boolean end)263     public RootChannelList(List<InternalInstrumented<ChannelStats>> channels, boolean end) {
264       this.channels = checkNotNull(channels);
265       this.end = end;
266     }
267   }
268 
269   public static final class ServerList {
270     public final List<InternalInstrumented<ServerStats>> servers;
271     public final boolean end;
272 
273     /** Creates an instance. */
ServerList(List<InternalInstrumented<ServerStats>> servers, boolean end)274     public ServerList(List<InternalInstrumented<ServerStats>> servers, boolean end) {
275       this.servers = checkNotNull(servers);
276       this.end = end;
277     }
278   }
279 
280   public static final class ServerSocketsList {
281     public final List<InternalWithLogId> sockets;
282     public final boolean end;
283 
284     /** Creates an instance. */
ServerSocketsList(List<InternalWithLogId> sockets, boolean end)285     public ServerSocketsList(List<InternalWithLogId> sockets, boolean end) {
286       this.sockets = sockets;
287       this.end = end;
288     }
289   }
290 
291   @Immutable
292   public static final class ServerStats {
293     public final long callsStarted;
294     public final long callsSucceeded;
295     public final long callsFailed;
296     public final long lastCallStartedNanos;
297     public final List<InternalInstrumented<SocketStats>> listenSockets;
298 
299     /**
300      * Creates an instance.
301      */
ServerStats( long callsStarted, long callsSucceeded, long callsFailed, long lastCallStartedNanos, List<InternalInstrumented<SocketStats>> listenSockets)302     public ServerStats(
303         long callsStarted,
304         long callsSucceeded,
305         long callsFailed,
306         long lastCallStartedNanos,
307         List<InternalInstrumented<SocketStats>> listenSockets) {
308       this.callsStarted = callsStarted;
309       this.callsSucceeded = callsSucceeded;
310       this.callsFailed = callsFailed;
311       this.lastCallStartedNanos = lastCallStartedNanos;
312       this.listenSockets = checkNotNull(listenSockets);
313     }
314 
315     public static final class Builder {
316       private long callsStarted;
317       private long callsSucceeded;
318       private long callsFailed;
319       private long lastCallStartedNanos;
320       public List<InternalInstrumented<SocketStats>> listenSockets = new ArrayList<>();
321 
setCallsStarted(long callsStarted)322       public Builder setCallsStarted(long callsStarted) {
323         this.callsStarted = callsStarted;
324         return this;
325       }
326 
setCallsSucceeded(long callsSucceeded)327       public Builder setCallsSucceeded(long callsSucceeded) {
328         this.callsSucceeded = callsSucceeded;
329         return this;
330       }
331 
setCallsFailed(long callsFailed)332       public Builder setCallsFailed(long callsFailed) {
333         this.callsFailed = callsFailed;
334         return this;
335       }
336 
setLastCallStartedNanos(long lastCallStartedNanos)337       public Builder setLastCallStartedNanos(long lastCallStartedNanos) {
338         this.lastCallStartedNanos = lastCallStartedNanos;
339         return this;
340       }
341 
342       /** Sets the listen sockets. */
addListenSockets(List<InternalInstrumented<SocketStats>> listenSockets)343       public Builder addListenSockets(List<InternalInstrumented<SocketStats>> listenSockets) {
344         checkNotNull(listenSockets, "listenSockets");
345         for (InternalInstrumented<SocketStats> ss : listenSockets) {
346           this.listenSockets.add(checkNotNull(ss, "null listen socket"));
347         }
348         return this;
349       }
350 
351       /**
352        * Builds an instance.
353        */
build()354       public ServerStats build() {
355         return new ServerStats(
356             callsStarted,
357             callsSucceeded,
358             callsFailed,
359             lastCallStartedNanos,
360             listenSockets);
361       }
362     }
363   }
364 
365   /**
366    * A data class to represent a channel's stats.
367    */
368   @Immutable
369   public static final class ChannelStats {
370     public final String target;
371     public final ConnectivityState state;
372     @Nullable public final ChannelTrace channelTrace;
373     public final long callsStarted;
374     public final long callsSucceeded;
375     public final long callsFailed;
376     public final long lastCallStartedNanos;
377     public final List<InternalWithLogId> subchannels;
378     public final List<InternalWithLogId> sockets;
379 
380     /**
381      * Creates an instance.
382      */
ChannelStats( String target, ConnectivityState state, @Nullable ChannelTrace channelTrace, long callsStarted, long callsSucceeded, long callsFailed, long lastCallStartedNanos, List<InternalWithLogId> subchannels, List<InternalWithLogId> sockets)383     private ChannelStats(
384         String target,
385         ConnectivityState state,
386         @Nullable ChannelTrace channelTrace,
387         long callsStarted,
388         long callsSucceeded,
389         long callsFailed,
390         long lastCallStartedNanos,
391         List<InternalWithLogId> subchannels,
392         List<InternalWithLogId> sockets) {
393       checkState(
394           subchannels.isEmpty() || sockets.isEmpty(),
395           "channels can have subchannels only, subchannels can have either sockets OR subchannels, "
396               + "neither can have both");
397       this.target = target;
398       this.state = state;
399       this.channelTrace = channelTrace;
400       this.callsStarted = callsStarted;
401       this.callsSucceeded = callsSucceeded;
402       this.callsFailed = callsFailed;
403       this.lastCallStartedNanos = lastCallStartedNanos;
404       this.subchannels = checkNotNull(subchannels);
405       this.sockets = checkNotNull(sockets);
406     }
407 
408     public static final class Builder {
409       private String target;
410       private ConnectivityState state;
411       private ChannelTrace channelTrace;
412       private long callsStarted;
413       private long callsSucceeded;
414       private long callsFailed;
415       private long lastCallStartedNanos;
416       private List<InternalWithLogId> subchannels = Collections.emptyList();
417       private List<InternalWithLogId> sockets = Collections.emptyList();
418 
setTarget(String target)419       public Builder setTarget(String target) {
420         this.target = target;
421         return this;
422       }
423 
setState(ConnectivityState state)424       public Builder setState(ConnectivityState state) {
425         this.state = state;
426         return this;
427       }
428 
setChannelTrace(ChannelTrace channelTrace)429       public Builder setChannelTrace(ChannelTrace channelTrace) {
430         this.channelTrace = channelTrace;
431         return this;
432       }
433 
setCallsStarted(long callsStarted)434       public Builder setCallsStarted(long callsStarted) {
435         this.callsStarted = callsStarted;
436         return this;
437       }
438 
setCallsSucceeded(long callsSucceeded)439       public Builder setCallsSucceeded(long callsSucceeded) {
440         this.callsSucceeded = callsSucceeded;
441         return this;
442       }
443 
setCallsFailed(long callsFailed)444       public Builder setCallsFailed(long callsFailed) {
445         this.callsFailed = callsFailed;
446         return this;
447       }
448 
setLastCallStartedNanos(long lastCallStartedNanos)449       public Builder setLastCallStartedNanos(long lastCallStartedNanos) {
450         this.lastCallStartedNanos = lastCallStartedNanos;
451         return this;
452       }
453 
454       /** Sets the subchannels. */
setSubchannels(List<InternalWithLogId> subchannels)455       public Builder setSubchannels(List<InternalWithLogId> subchannels) {
456         checkState(sockets.isEmpty());
457         this.subchannels = Collections.unmodifiableList(checkNotNull(subchannels));
458         return this;
459       }
460 
461       /** Sets the sockets. */
setSockets(List<InternalWithLogId> sockets)462       public Builder setSockets(List<InternalWithLogId> sockets) {
463         checkState(subchannels.isEmpty());
464         this.sockets = Collections.unmodifiableList(checkNotNull(sockets));
465         return this;
466       }
467 
468       /**
469        * Builds an instance.
470        */
build()471       public ChannelStats build() {
472         return new ChannelStats(
473             target,
474             state,
475             channelTrace,
476             callsStarted,
477             callsSucceeded,
478             callsFailed,
479             lastCallStartedNanos,
480             subchannels,
481             sockets);
482       }
483     }
484   }
485 
486   @Immutable
487   public static final class ChannelTrace {
488     public final long numEventsLogged;
489     public final long creationTimeNanos;
490     public final List<Event> events;
491 
ChannelTrace(long numEventsLogged, long creationTimeNanos, List<Event> events)492     private ChannelTrace(long numEventsLogged, long creationTimeNanos, List<Event> events) {
493       this.numEventsLogged = numEventsLogged;
494       this.creationTimeNanos = creationTimeNanos;
495       this.events = events;
496     }
497 
498     public static final class Builder {
499       private Long numEventsLogged;
500       private Long creationTimeNanos;
501       private List<Event> events = Collections.emptyList();
502 
setNumEventsLogged(long numEventsLogged)503       public Builder setNumEventsLogged(long numEventsLogged) {
504         this.numEventsLogged = numEventsLogged;
505         return this;
506       }
507 
setCreationTimeNanos(long creationTimeNanos)508       public Builder setCreationTimeNanos(long creationTimeNanos) {
509         this.creationTimeNanos = creationTimeNanos;
510         return this;
511       }
512 
setEvents(List<Event> events)513       public Builder setEvents(List<Event> events) {
514         this.events = Collections.unmodifiableList(new ArrayList<>(events));
515         return this;
516       }
517 
518       /** Builds a new ChannelTrace instance. */
build()519       public ChannelTrace build() {
520         checkNotNull(numEventsLogged, "numEventsLogged");
521         checkNotNull(creationTimeNanos, "creationTimeNanos");
522         return new ChannelTrace(numEventsLogged, creationTimeNanos, events);
523       }
524     }
525 
526     @Immutable
527     public static final class Event {
528       public final String description;
529       public final Severity severity;
530       public final long timestampNanos;
531 
532       // the oneof child_ref field in proto: one of channelRef and channelRef
533       @Nullable public final InternalWithLogId channelRef;
534       @Nullable public final InternalWithLogId subchannelRef;
535 
536       public enum Severity {
537         CT_UNKNOWN, CT_INFO, CT_WARNING, CT_ERROR
538       }
539 
Event( String description, Severity severity, long timestampNanos, @Nullable InternalWithLogId channelRef, @Nullable InternalWithLogId subchannelRef)540       private Event(
541           String description, Severity severity, long timestampNanos,
542           @Nullable InternalWithLogId channelRef, @Nullable InternalWithLogId subchannelRef) {
543         this.description = description;
544         this.severity = checkNotNull(severity, "severity");
545         this.timestampNanos = timestampNanos;
546         this.channelRef = channelRef;
547         this.subchannelRef = subchannelRef;
548       }
549 
550       @Override
hashCode()551       public int hashCode() {
552         return Objects.hashCode(description, severity, timestampNanos, channelRef, subchannelRef);
553       }
554 
555       @Override
equals(Object o)556       public boolean equals(Object o) {
557         if (o instanceof Event) {
558           Event that = (Event) o;
559           return Objects.equal(description, that.description)
560               && Objects.equal(severity, that.severity)
561               && timestampNanos == that.timestampNanos
562               && Objects.equal(channelRef, that.channelRef)
563               && Objects.equal(subchannelRef, that.subchannelRef);
564         }
565         return false;
566       }
567 
568       @Override
toString()569       public String toString() {
570         return MoreObjects.toStringHelper(this)
571             .add("description", description)
572             .add("severity", severity)
573             .add("timestampNanos", timestampNanos)
574             .add("channelRef", channelRef)
575             .add("subchannelRef", subchannelRef)
576             .toString();
577       }
578 
579       public static final class Builder {
580         private String description;
581         private Severity severity;
582         private Long timestampNanos;
583         private InternalWithLogId channelRef;
584         private InternalWithLogId subchannelRef;
585 
setDescription(String description)586         public Builder setDescription(String description) {
587           this.description = description;
588           return this;
589         }
590 
setTimestampNanos(long timestampNanos)591         public Builder setTimestampNanos(long timestampNanos) {
592           this.timestampNanos = timestampNanos;
593           return this;
594         }
595 
setSeverity(Severity severity)596         public Builder setSeverity(Severity severity) {
597           this.severity = severity;
598           return this;
599         }
600 
setChannelRef(InternalWithLogId channelRef)601         public Builder setChannelRef(InternalWithLogId channelRef) {
602           this.channelRef = channelRef;
603           return this;
604         }
605 
setSubchannelRef(InternalWithLogId subchannelRef)606         public Builder setSubchannelRef(InternalWithLogId subchannelRef) {
607           this.subchannelRef = subchannelRef;
608           return this;
609         }
610 
611         /** Builds a new Event instance. */
build()612         public Event build() {
613           checkNotNull(description, "description");
614           checkNotNull(severity, "severity");
615           checkNotNull(timestampNanos, "timestampNanos");
616           checkState(
617               channelRef == null || subchannelRef == null,
618               "at least one of channelRef and subchannelRef must be null");
619           return new Event(description, severity, timestampNanos, channelRef, subchannelRef);
620         }
621       }
622     }
623   }
624 
625   public static final class Security {
626     @Nullable
627     public final Tls tls;
628     @Nullable
629     public final OtherSecurity other;
630 
Security(Tls tls)631     public Security(Tls tls) {
632       this.tls = checkNotNull(tls);
633       this.other = null;
634     }
635 
Security(OtherSecurity other)636     public Security(OtherSecurity other) {
637       this.tls = null;
638       this.other = checkNotNull(other);
639     }
640   }
641 
642   public static final class OtherSecurity {
643     public final String name;
644     @Nullable
645     public final Object any;
646 
647     /**
648      * Creates an instance.
649      * @param name the name.
650      * @param any a com.google.protobuf.Any object
651      */
OtherSecurity(String name, @Nullable Object any)652     public OtherSecurity(String name, @Nullable Object any) {
653       this.name = checkNotNull(name);
654       checkState(
655           any == null || any.getClass().getName().endsWith("com.google.protobuf.Any"),
656           "the 'any' object must be of type com.google.protobuf.Any");
657       this.any = any;
658     }
659   }
660 
661   @Immutable
662   public static final class Tls {
663     public final String cipherSuiteStandardName;
664     @Nullable public final Certificate localCert;
665     @Nullable public final Certificate remoteCert;
666 
667     /**
668      * A constructor only for testing.
669      */
Tls(String cipherSuiteName, Certificate localCert, Certificate remoteCert)670     public Tls(String cipherSuiteName, Certificate localCert, Certificate remoteCert) {
671       this.cipherSuiteStandardName = cipherSuiteName;
672       this.localCert = localCert;
673       this.remoteCert = remoteCert;
674     }
675 
676     /**
677      * Creates an instance.
678      */
Tls(SSLSession session)679     public Tls(SSLSession session) {
680       String cipherSuiteStandardName = session.getCipherSuite();
681       Certificate localCert = null;
682       Certificate remoteCert = null;
683       Certificate[] localCerts = session.getLocalCertificates();
684       if (localCerts != null) {
685         localCert = localCerts[0];
686       }
687       try {
688         Certificate[] peerCerts = session.getPeerCertificates();
689         if (peerCerts != null) {
690           // The javadoc of getPeerCertificate states that the peer's own certificate is the first
691           // element of the list.
692           remoteCert = peerCerts[0];
693         }
694       } catch (SSLPeerUnverifiedException e) {
695         // peer cert is not available
696         log.log(
697             Level.FINE,
698             String.format("Peer cert not available for peerHost=%s", session.getPeerHost()),
699             e);
700       }
701       this.cipherSuiteStandardName = cipherSuiteStandardName;
702       this.localCert = localCert;
703       this.remoteCert = remoteCert;
704     }
705   }
706 
707   public static final class SocketStats {
708     @Nullable public final TransportStats data;
709     @Nullable public final SocketAddress local;
710     @Nullable public final SocketAddress remote;
711     public final SocketOptions socketOptions;
712     // Can be null if plaintext
713     @Nullable public final Security security;
714 
715     /** Creates an instance. */
SocketStats( TransportStats data, @Nullable SocketAddress local, @Nullable SocketAddress remote, SocketOptions socketOptions, Security security)716     public SocketStats(
717         TransportStats data,
718         @Nullable SocketAddress local,
719         @Nullable SocketAddress remote,
720         SocketOptions socketOptions,
721         Security security) {
722       this.data = data;
723       this.local = checkNotNull(local, "local socket");
724       this.remote = remote;
725       this.socketOptions = checkNotNull(socketOptions);
726       this.security = security;
727     }
728   }
729 
730   public static final class TcpInfo {
731     public final int state;
732     public final int caState;
733     public final int retransmits;
734     public final int probes;
735     public final int backoff;
736     public final int options;
737     public final int sndWscale;
738     public final int rcvWscale;
739     public final int rto;
740     public final int ato;
741     public final int sndMss;
742     public final int rcvMss;
743     public final int unacked;
744     public final int sacked;
745     public final int lost;
746     public final int retrans;
747     public final int fackets;
748     public final int lastDataSent;
749     public final int lastAckSent;
750     public final int lastDataRecv;
751     public final int lastAckRecv;
752     public final int pmtu;
753     public final int rcvSsthresh;
754     public final int rtt;
755     public final int rttvar;
756     public final int sndSsthresh;
757     public final int sndCwnd;
758     public final int advmss;
759     public final int reordering;
760 
TcpInfo(int state, int caState, int retransmits, int probes, int backoff, int options, int sndWscale, int rcvWscale, int rto, int ato, int sndMss, int rcvMss, int unacked, int sacked, int lost, int retrans, int fackets, int lastDataSent, int lastAckSent, int lastDataRecv, int lastAckRecv, int pmtu, int rcvSsthresh, int rtt, int rttvar, int sndSsthresh, int sndCwnd, int advmss, int reordering)761     TcpInfo(int state, int caState, int retransmits, int probes, int backoff, int options,
762         int sndWscale, int rcvWscale, int rto, int ato, int sndMss, int rcvMss, int unacked,
763         int sacked, int lost, int retrans, int fackets, int lastDataSent, int lastAckSent,
764         int lastDataRecv, int lastAckRecv, int pmtu, int rcvSsthresh, int rtt, int rttvar,
765         int sndSsthresh, int sndCwnd, int advmss, int reordering) {
766       this.state = state;
767       this.caState = caState;
768       this.retransmits = retransmits;
769       this.probes = probes;
770       this.backoff = backoff;
771       this.options = options;
772       this.sndWscale = sndWscale;
773       this.rcvWscale = rcvWscale;
774       this.rto = rto;
775       this.ato = ato;
776       this.sndMss = sndMss;
777       this.rcvMss = rcvMss;
778       this.unacked = unacked;
779       this.sacked = sacked;
780       this.lost = lost;
781       this.retrans = retrans;
782       this.fackets = fackets;
783       this.lastDataSent = lastDataSent;
784       this.lastAckSent = lastAckSent;
785       this.lastDataRecv = lastDataRecv;
786       this.lastAckRecv = lastAckRecv;
787       this.pmtu = pmtu;
788       this.rcvSsthresh = rcvSsthresh;
789       this.rtt = rtt;
790       this.rttvar = rttvar;
791       this.sndSsthresh = sndSsthresh;
792       this.sndCwnd = sndCwnd;
793       this.advmss = advmss;
794       this.reordering = reordering;
795     }
796 
797     public static final class Builder {
798       private int state;
799       private int caState;
800       private int retransmits;
801       private int probes;
802       private int backoff;
803       private int options;
804       private int sndWscale;
805       private int rcvWscale;
806       private int rto;
807       private int ato;
808       private int sndMss;
809       private int rcvMss;
810       private int unacked;
811       private int sacked;
812       private int lost;
813       private int retrans;
814       private int fackets;
815       private int lastDataSent;
816       private int lastAckSent;
817       private int lastDataRecv;
818       private int lastAckRecv;
819       private int pmtu;
820       private int rcvSsthresh;
821       private int rtt;
822       private int rttvar;
823       private int sndSsthresh;
824       private int sndCwnd;
825       private int advmss;
826       private int reordering;
827 
setState(int state)828       public Builder setState(int state) {
829         this.state = state;
830         return this;
831       }
832 
setCaState(int caState)833       public Builder setCaState(int caState) {
834         this.caState = caState;
835         return this;
836       }
837 
setRetransmits(int retransmits)838       public Builder setRetransmits(int retransmits) {
839         this.retransmits = retransmits;
840         return this;
841       }
842 
setProbes(int probes)843       public Builder setProbes(int probes) {
844         this.probes = probes;
845         return this;
846       }
847 
setBackoff(int backoff)848       public Builder setBackoff(int backoff) {
849         this.backoff = backoff;
850         return this;
851       }
852 
setOptions(int options)853       public Builder setOptions(int options) {
854         this.options = options;
855         return this;
856       }
857 
setSndWscale(int sndWscale)858       public Builder setSndWscale(int sndWscale) {
859         this.sndWscale = sndWscale;
860         return this;
861       }
862 
setRcvWscale(int rcvWscale)863       public Builder setRcvWscale(int rcvWscale) {
864         this.rcvWscale = rcvWscale;
865         return this;
866       }
867 
setRto(int rto)868       public Builder setRto(int rto) {
869         this.rto = rto;
870         return this;
871       }
872 
setAto(int ato)873       public Builder setAto(int ato) {
874         this.ato = ato;
875         return this;
876       }
877 
setSndMss(int sndMss)878       public Builder setSndMss(int sndMss) {
879         this.sndMss = sndMss;
880         return this;
881       }
882 
setRcvMss(int rcvMss)883       public Builder setRcvMss(int rcvMss) {
884         this.rcvMss = rcvMss;
885         return this;
886       }
887 
setUnacked(int unacked)888       public Builder setUnacked(int unacked) {
889         this.unacked = unacked;
890         return this;
891       }
892 
setSacked(int sacked)893       public Builder setSacked(int sacked) {
894         this.sacked = sacked;
895         return this;
896       }
897 
setLost(int lost)898       public Builder setLost(int lost) {
899         this.lost = lost;
900         return this;
901       }
902 
setRetrans(int retrans)903       public Builder setRetrans(int retrans) {
904         this.retrans = retrans;
905         return this;
906       }
907 
setFackets(int fackets)908       public Builder setFackets(int fackets) {
909         this.fackets = fackets;
910         return this;
911       }
912 
setLastDataSent(int lastDataSent)913       public Builder setLastDataSent(int lastDataSent) {
914         this.lastDataSent = lastDataSent;
915         return this;
916       }
917 
setLastAckSent(int lastAckSent)918       public Builder setLastAckSent(int lastAckSent) {
919         this.lastAckSent = lastAckSent;
920         return this;
921       }
922 
setLastDataRecv(int lastDataRecv)923       public Builder setLastDataRecv(int lastDataRecv) {
924         this.lastDataRecv = lastDataRecv;
925         return this;
926       }
927 
setLastAckRecv(int lastAckRecv)928       public Builder setLastAckRecv(int lastAckRecv) {
929         this.lastAckRecv = lastAckRecv;
930         return this;
931       }
932 
setPmtu(int pmtu)933       public Builder setPmtu(int pmtu) {
934         this.pmtu = pmtu;
935         return this;
936       }
937 
setRcvSsthresh(int rcvSsthresh)938       public Builder setRcvSsthresh(int rcvSsthresh) {
939         this.rcvSsthresh = rcvSsthresh;
940         return this;
941       }
942 
setRtt(int rtt)943       public Builder setRtt(int rtt) {
944         this.rtt = rtt;
945         return this;
946       }
947 
setRttvar(int rttvar)948       public Builder setRttvar(int rttvar) {
949         this.rttvar = rttvar;
950         return this;
951       }
952 
setSndSsthresh(int sndSsthresh)953       public Builder setSndSsthresh(int sndSsthresh) {
954         this.sndSsthresh = sndSsthresh;
955         return this;
956       }
957 
setSndCwnd(int sndCwnd)958       public Builder setSndCwnd(int sndCwnd) {
959         this.sndCwnd = sndCwnd;
960         return this;
961       }
962 
setAdvmss(int advmss)963       public Builder setAdvmss(int advmss) {
964         this.advmss = advmss;
965         return this;
966       }
967 
setReordering(int reordering)968       public Builder setReordering(int reordering) {
969         this.reordering = reordering;
970         return this;
971       }
972 
973       /** Builds an instance. */
build()974       public TcpInfo build() {
975         return new TcpInfo(
976             state, caState, retransmits, probes, backoff, options, sndWscale, rcvWscale,
977             rto, ato, sndMss, rcvMss, unacked, sacked, lost, retrans, fackets, lastDataSent,
978             lastAckSent, lastDataRecv, lastAckRecv, pmtu, rcvSsthresh, rtt, rttvar, sndSsthresh,
979             sndCwnd, advmss, reordering);
980       }
981     }
982   }
983 
984   public static final class SocketOptions {
985     public final Map<String, String> others;
986     // In netty, the value of a channel option may be null.
987     @Nullable public final Integer soTimeoutMillis;
988     @Nullable public final Integer lingerSeconds;
989     @Nullable public final TcpInfo tcpInfo;
990 
991     /** Creates an instance. */
SocketOptions( @ullable Integer timeoutMillis, @Nullable Integer lingerSeconds, @Nullable TcpInfo tcpInfo, Map<String, String> others)992     public SocketOptions(
993         @Nullable Integer timeoutMillis,
994         @Nullable Integer lingerSeconds,
995         @Nullable TcpInfo tcpInfo,
996         Map<String, String> others) {
997       checkNotNull(others);
998       this.soTimeoutMillis = timeoutMillis;
999       this.lingerSeconds = lingerSeconds;
1000       this.tcpInfo = tcpInfo;
1001       this.others = Collections.unmodifiableMap(new HashMap<>(others));
1002     }
1003 
1004     public static final class Builder {
1005       private final Map<String, String> others = new HashMap<>();
1006 
1007       private TcpInfo tcpInfo;
1008       private Integer timeoutMillis;
1009       private Integer lingerSeconds;
1010 
1011       /** The value of {@link java.net.Socket#getSoTimeout()}. */
setSocketOptionTimeoutMillis(Integer timeoutMillis)1012       public Builder setSocketOptionTimeoutMillis(Integer timeoutMillis) {
1013         this.timeoutMillis = timeoutMillis;
1014         return this;
1015       }
1016 
1017       /** The value of {@link java.net.Socket#getSoLinger()}.
1018        * Note: SO_LINGER is typically expressed in seconds.
1019        */
setSocketOptionLingerSeconds(Integer lingerSeconds)1020       public Builder setSocketOptionLingerSeconds(Integer lingerSeconds) {
1021         this.lingerSeconds = lingerSeconds;
1022         return this;
1023       }
1024 
setTcpInfo(TcpInfo tcpInfo)1025       public Builder setTcpInfo(TcpInfo tcpInfo) {
1026         this.tcpInfo = tcpInfo;
1027         return this;
1028       }
1029 
addOption(String name, String value)1030       public Builder addOption(String name, String value) {
1031         others.put(name, checkNotNull(value));
1032         return this;
1033       }
1034 
addOption(String name, int value)1035       public Builder addOption(String name, int value) {
1036         others.put(name, Integer.toString(value));
1037         return this;
1038       }
1039 
addOption(String name, boolean value)1040       public Builder addOption(String name, boolean value) {
1041         others.put(name, Boolean.toString(value));
1042         return this;
1043       }
1044 
build()1045       public SocketOptions build() {
1046         return new SocketOptions(timeoutMillis, lingerSeconds, tcpInfo, others);
1047       }
1048     }
1049   }
1050 
1051   /**
1052    * A data class to represent transport stats.
1053    */
1054   @Immutable
1055   public static final class TransportStats {
1056     public final long streamsStarted;
1057     public final long lastLocalStreamCreatedTimeNanos;
1058     public final long lastRemoteStreamCreatedTimeNanos;
1059     public final long streamsSucceeded;
1060     public final long streamsFailed;
1061     public final long messagesSent;
1062     public final long messagesReceived;
1063     public final long keepAlivesSent;
1064     public final long lastMessageSentTimeNanos;
1065     public final long lastMessageReceivedTimeNanos;
1066     public final long localFlowControlWindow;
1067     public final long remoteFlowControlWindow;
1068     // TODO(zpencer): report socket flags and other info
1069 
1070     /**
1071      * Creates an instance.
1072      */
TransportStats( long streamsStarted, long lastLocalStreamCreatedTimeNanos, long lastRemoteStreamCreatedTimeNanos, long streamsSucceeded, long streamsFailed, long messagesSent, long messagesReceived, long keepAlivesSent, long lastMessageSentTimeNanos, long lastMessageReceivedTimeNanos, long localFlowControlWindow, long remoteFlowControlWindow)1073     public TransportStats(
1074         long streamsStarted,
1075         long lastLocalStreamCreatedTimeNanos,
1076         long lastRemoteStreamCreatedTimeNanos,
1077         long streamsSucceeded,
1078         long streamsFailed,
1079         long messagesSent,
1080         long messagesReceived,
1081         long keepAlivesSent,
1082         long lastMessageSentTimeNanos,
1083         long lastMessageReceivedTimeNanos,
1084         long localFlowControlWindow,
1085         long remoteFlowControlWindow) {
1086       this.streamsStarted = streamsStarted;
1087       this.lastLocalStreamCreatedTimeNanos = lastLocalStreamCreatedTimeNanos;
1088       this.lastRemoteStreamCreatedTimeNanos = lastRemoteStreamCreatedTimeNanos;
1089       this.streamsSucceeded = streamsSucceeded;
1090       this.streamsFailed = streamsFailed;
1091       this.messagesSent = messagesSent;
1092       this.messagesReceived = messagesReceived;
1093       this.keepAlivesSent = keepAlivesSent;
1094       this.lastMessageSentTimeNanos = lastMessageSentTimeNanos;
1095       this.lastMessageReceivedTimeNanos = lastMessageReceivedTimeNanos;
1096       this.localFlowControlWindow = localFlowControlWindow;
1097       this.remoteFlowControlWindow = remoteFlowControlWindow;
1098     }
1099   }
1100 
1101   /** Unwraps a {@link InternalLogId} to return a {@code long}. */
id(InternalWithLogId withLogId)1102   public static long id(InternalWithLogId withLogId) {
1103     return withLogId.getLogId().getId();
1104   }
1105 }
1106