Skip to content

Commit 42a834b

Browse files
committed
increase coverage
1 parent 6996afd commit 42a834b

2 files changed

Lines changed: 258 additions & 110 deletions

File tree

netty/src/main/java/io/grpc/netty/TcpMetrics.java

Lines changed: 119 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,85 @@
3030

3131
final class TcpMetrics {
3232

33-
static final LongCounterMetricInstrument connectionsCreated;
34-
static final LongUpDownCounterMetricInstrument connectionCount;
35-
static final LongCounterMetricInstrument packetsRetransmitted;
36-
static final LongCounterMetricInstrument recurringRetransmits;
37-
static final DoubleHistogramMetricInstrument minRtt;
38-
39-
// Note: Metrics like delivery_rate, bytes_sent, packets_sent,
40-
// bytes_retransmitted, etc., are not
41-
// currently exposed by Netty's EpollTcpInfo.java wrapper around
42-
// getSockOpt(TCP_INFO)."
33+
private static final Metrics DEFAULT_METRICS;
34+
35+
static {
36+
boolean epollAvailable = false;
37+
try {
38+
Class<?> epollClass = Class.forName("io.netty.channel.epoll.Epoll");
39+
Method isAvailableMethod = epollClass.getDeclaredMethod("isAvailable");
40+
epollAvailable = (Boolean) isAvailableMethod.invoke(null);
41+
} catch (Throwable t) {
42+
// Ignored
43+
}
44+
DEFAULT_METRICS = new Metrics(MetricInstrumentRegistry.getDefaultRegistry(), epollAvailable);
45+
}
46+
47+
static Metrics getDefaultMetrics() {
48+
return DEFAULT_METRICS;
49+
}
50+
51+
static final class Metrics {
52+
final LongCounterMetricInstrument connectionsCreated;
53+
final LongUpDownCounterMetricInstrument connectionCount;
54+
final LongCounterMetricInstrument packetsRetransmitted;
55+
final LongCounterMetricInstrument recurringRetransmits;
56+
final DoubleHistogramMetricInstrument minRtt;
57+
58+
Metrics(MetricInstrumentRegistry registry, boolean epollAvailable) {
59+
List<String> requiredLabels = Collections.singletonList("grpc.target");
60+
List<String> optionalLabels = Arrays.asList(
61+
"network.local.address",
62+
"network.local.port",
63+
"network.peer.address",
64+
"network.peer.port");
65+
66+
connectionsCreated = safelyRegisterLongCounter(registry,
67+
"grpc.tcp.connections_created",
68+
"Number of TCP connections created.",
69+
"{connection}",
70+
requiredLabels,
71+
optionalLabels);
72+
73+
connectionCount = safelyRegisterLongUpDownCounter(registry,
74+
"grpc.tcp.connection_count",
75+
"Number of currently open TCP connections.",
76+
"{connection}",
77+
requiredLabels,
78+
optionalLabels);
79+
80+
if (epollAvailable) {
81+
packetsRetransmitted = safelyRegisterLongCounter(registry,
82+
"grpc.tcp.packets_retransmitted",
83+
"Total number of packets retransmitted for a single TCP connection.",
84+
"{packet}",
85+
requiredLabels,
86+
optionalLabels);
87+
88+
recurringRetransmits = safelyRegisterLongCounter(registry,
89+
"grpc.tcp.recurring_retransmits",
90+
"Total number of unacknowledged packets to be retransmitted "
91+
+ "since the last acknowledgment.",
92+
"{packet}",
93+
requiredLabels,
94+
optionalLabels);
95+
96+
minRtt = safelyRegisterDoubleHistogram(registry,
97+
"grpc.tcp.min_rtt",
98+
"Minimum RTT observed for a single TCP connection.",
99+
"s",
100+
Arrays.asList(0.0001, 0.0005, 0.001, 0.005, 0.01, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5,
101+
5.0, 10.0, 25.0, 50.0, 100.0, 250.0),
102+
requiredLabels,
103+
optionalLabels);
104+
} else {
105+
packetsRetransmitted = null;
106+
recurringRetransmits = null;
107+
minRtt = null;
108+
}
109+
}
110+
}
111+
43112
/**
44113
* Safe metric registration or retrieval for environments where TcpMetrics might
45114
* be loaded multiple times (e.g., shaded and unshaded).
@@ -102,81 +171,30 @@ private static DoubleHistogramMetricInstrument safelyRegisterDoubleHistogram(
102171
}
103172
}
104173

105-
static {
106-
MetricInstrumentRegistry registry = MetricInstrumentRegistry.getDefaultRegistry();
107-
List<String> requiredLabels = Collections.singletonList("grpc.target");
108-
List<String> optionalLabels = Arrays.asList(
109-
"network.local.address",
110-
"network.local.port",
111-
"network.peer.address",
112-
"network.peer.port"
113-
);
114-
115-
connectionsCreated = safelyRegisterLongCounter(registry,
116-
"grpc.tcp.connections_created",
117-
"Number of TCP connections created.",
118-
"{connection}",
119-
requiredLabels,
120-
optionalLabels
121-
);
122-
123-
connectionCount = safelyRegisterLongUpDownCounter(registry,
124-
"grpc.tcp.connection_count",
125-
"Number of currently open TCP connections.",
126-
"{connection}",
127-
requiredLabels,
128-
optionalLabels
129-
);
130-
131-
boolean epollAvailable = false;
132-
try {
133-
Class<?> epollClass = Class.forName("io.netty.channel.epoll.Epoll");
134-
Method isAvailableMethod = epollClass.getDeclaredMethod("isAvailable");
135-
epollAvailable = (Boolean) isAvailableMethod.invoke(null);
136-
} catch (Throwable t) {
137-
// Ignored
138-
}
139-
140-
if (epollAvailable) {
141-
packetsRetransmitted = safelyRegisterLongCounter(registry,
142-
"grpc.tcp.packets_retransmitted",
143-
"Total number of packets retransmitted for a single TCP connection.",
144-
"{packet}",
145-
requiredLabels,
146-
optionalLabels);
147-
148-
recurringRetransmits = safelyRegisterLongCounter(registry,
149-
"grpc.tcp.recurring_retransmits",
150-
"Total number of unacknowledged packets to be retransmitted "
151-
+ "since the last acknowledgment.",
152-
"{packet}",
153-
requiredLabels,
154-
optionalLabels);
155-
156-
minRtt = safelyRegisterDoubleHistogram(registry,
157-
"grpc.tcp.min_rtt",
158-
"Minimum RTT observed for a single TCP connection.",
159-
"s",
160-
Arrays.asList(0.0001, 0.0005, 0.001, 0.005, 0.01, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5,
161-
5.0, 10.0, 25.0, 50.0, 100.0, 250.0),
162-
requiredLabels,
163-
optionalLabels);
164-
} else {
165-
// Initialize to null if epoll is not available, as these metrics won't be used.
166-
packetsRetransmitted = null;
167-
recurringRetransmits = null;
168-
minRtt = null;
169-
}
170-
}
171-
172-
173174
static final class Tracker {
174175
private final MetricRecorder metricRecorder;
175176
private final String target;
177+
private final Metrics metrics;
178+
private final String epollSocketChannelClassName;
179+
private final String epollTcpInfoClassName;
176180

177181
Tracker(MetricRecorder metricRecorder, String target) {
182+
this(metricRecorder, target, DEFAULT_METRICS);
183+
}
184+
185+
Tracker(MetricRecorder metricRecorder, String target, Metrics metrics) {
186+
this(metricRecorder, target, metrics,
187+
"io.netty.channel.epoll.EpollSocketChannel",
188+
"io.netty.channel.epoll.EpollTcpInfo");
189+
}
190+
191+
Tracker(MetricRecorder metricRecorder, String target, Metrics metrics,
192+
String epollSocketChannelClassName, String epollTcpInfoClassName) {
178193
this.metricRecorder = metricRecorder;
179194
this.target = target;
195+
this.metrics = metrics;
196+
this.epollSocketChannelClassName = epollSocketChannelClassName;
197+
this.epollTcpInfoClassName = epollTcpInfoClassName;
180198
}
181199

182200
private static final long RECORD_INTERVAL_MILLIS;
@@ -200,9 +218,9 @@ static final class Tracker {
200218
void channelActive(Channel channel) {
201219
if (metricRecorder != null && target != null) {
202220
java.util.List<String> labelValues = getLabelValues(channel);
203-
metricRecorder.addLongCounter(TcpMetrics.connectionsCreated, 1,
221+
metricRecorder.addLongCounter(metrics.connectionsCreated, 1,
204222
Collections.singletonList(target), labelValues);
205-
metricRecorder.addLongUpDownCounter(TcpMetrics.connectionCount, 1,
223+
metricRecorder.addLongUpDownCounter(metrics.connectionCount, 1,
206224
Collections.singletonList(target), labelValues);
207225
scheduleNextReport(channel);
208226
}
@@ -240,7 +258,7 @@ void channelInactive(Channel channel) {
240258
}
241259
if (metricRecorder != null && target != null) {
242260
java.util.List<String> labelValues = getLabelValues(channel);
243-
metricRecorder.addLongUpDownCounter(TcpMetrics.connectionCount, -1,
261+
metricRecorder.addLongUpDownCounter(metrics.connectionCount, -1,
244262
Collections.singletonList(target), labelValues);
245263
// Final collection on close
246264
recordTcpInfo(channel);
@@ -253,28 +271,33 @@ private void recordTcpInfo(Channel channel) {
253271
}
254272
java.util.List<String> labelValues = getLabelValues(channel);
255273
try {
256-
if (channel.getClass().getName().equals("io.netty.channel.epoll.EpollSocketChannel")) {
257-
Method tcpInfoMethod = channel.getClass().getMethod("tcpInfo",
258-
Class.forName("io.netty.channel.epoll.EpollTcpInfo"));
259-
Object info = Class.forName("io.netty.channel.epoll.EpollTcpInfo")
260-
.getDeclaredConstructor().newInstance();
274+
if (channel.getClass().getName().equals(epollSocketChannelClassName)) {
275+
Class<?> tcpInfoClass = Class.forName(epollTcpInfoClassName);
276+
Method tcpInfoMethod = channel.getClass().getMethod("tcpInfo", tcpInfoClass);
277+
Object info = tcpInfoClass.getDeclaredConstructor().newInstance();
261278
tcpInfoMethod.invoke(channel, info);
262279

263-
Method totalRetransMethod = info.getClass().getMethod("totalRetrans");
264-
Method retransmitsMethod = info.getClass().getMethod("retransmits");
265-
Method rttMethod = info.getClass().getMethod("rtt");
280+
Method totalRetransMethod = tcpInfoClass.getMethod("totalRetrans");
281+
Method retransmitsMethod = tcpInfoClass.getMethod("retransmits");
282+
Method rttMethod = tcpInfoClass.getMethod("rtt");
266283

267284
long totalRetrans = (Long) totalRetransMethod.invoke(info);
268285
int retransmits = (Integer) retransmitsMethod.invoke(info);
269286
long rtt = (Long) rttMethod.invoke(info);
270287

271-
metricRecorder.addLongCounter(TcpMetrics.packetsRetransmitted, totalRetrans,
272-
Collections.singletonList(target), labelValues);
273-
metricRecorder.addLongCounter(TcpMetrics.recurringRetransmits, retransmits,
274-
Collections.singletonList(target), labelValues);
275-
metricRecorder.recordDoubleHistogram(TcpMetrics.minRtt,
276-
rtt / 1000000.0, // Convert microseconds to seconds
277-
Collections.singletonList(target), labelValues);
288+
if (metrics.packetsRetransmitted != null) {
289+
metricRecorder.addLongCounter(metrics.packetsRetransmitted, totalRetrans,
290+
Collections.singletonList(target), labelValues);
291+
}
292+
if (metrics.recurringRetransmits != null) {
293+
metricRecorder.addLongCounter(metrics.recurringRetransmits, retransmits,
294+
Collections.singletonList(target), labelValues);
295+
}
296+
if (metrics.minRtt != null) {
297+
metricRecorder.recordDoubleHistogram(metrics.minRtt,
298+
rtt / 1000000.0, // Convert microseconds to seconds
299+
Collections.singletonList(target), labelValues);
300+
}
278301
}
279302
} catch (Throwable t) {
280303
// Epoll not available or error getting tcp_info, just ignore.

0 commit comments

Comments
 (0)