/**
* Copyright 2016 LinkedIn Corp. All rights reserved.
*
* 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.
*/
package com.github.ambry.network;
import com.codahale.metrics.Counter;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.Histogram;
import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
/**
* Metrics for the network layer
*/
public class NetworkMetrics {
// Selector metrics
public final Counter sendInFlight;
public final Counter selectorConnectionClosed;
public final Counter selectorConnectionCreated;
public final Counter selectorSelectCount;
public final Histogram selectorSelectTime;
public final Counter selectorIOCount;
public final Histogram selectorIOTime;
public final Counter selectorNioCloseErrorCount;
public final Counter selectorDisconnectedErrorCount;
public final Counter selectorIOErrorCount;
public final Counter selectorKeyOperationErrorCount;
public final Counter selectorCloseKeyErrorCount;
public final Counter selectorCloseSocketErrorCount;
private final List<AtomicLong> selectorActiveConnectionsList;
// Plaintext metrics
// the bytes rate to receive the entire request
public final Meter plaintextReceiveBytesRate;
// the bytes rate to send the entire response
public final Meter plaintextSendBytesRate;
// the time to receive 1KB data in one read call
public final Histogram plaintextReceiveTimePerKB;
// the time to send data in one write call
public final Histogram plaintextSendTimePerKB;
// SSL metrics
public final Counter sslFactoryInitializationCount;
public final Counter sslTransmissionInitializationCount;
public final Counter sslFactoryInitializationErrorCount;
public final Counter sslTransmissionInitializationErrorCount;
public final Histogram sslHandshakeTime;
public final Counter sslHandshakeCount;
public final Counter sslHandshakeErrorCount;
// the bytes rate to receive the entire request
public final Meter sslReceiveBytesRate;
// the bytes rate to send the entire response
public final Meter sslSendBytesRate;
// the time to receive 1KB data in one read call
public final Histogram sslReceiveTimePerKB;
// the time to send data in one write call
public final Histogram sslSendTimePerKB;
public final Histogram sslEncryptionTimePerKB;
public final Histogram sslDecryptionTimePerKB;
// the count of renegotiation after initial handshake done
public final Counter sslRenegotiationCount;
// NetworkClient metrics
public final Histogram networkClientSendAndPollTime;
public final Histogram requestQueueTime;
public final Histogram requestSendTime;
public final Histogram requestSendTotalTime;
public final Histogram requestResponseRoundTripTime;
public final Histogram requestResponseTotalTime;
public final Counter connectionTimeOutError;
public final Counter networkClientIOError;
public final Counter networkClientException;
private List<AtomicLong> networkClientPendingRequestList;
public NetworkMetrics(MetricRegistry registry) {
sendInFlight = registry.counter(MetricRegistry.name(Selector.class, "SendInFlight"));
selectorConnectionClosed = registry.counter(MetricRegistry.name(Selector.class, "SelectorConnectionClosed"));
selectorConnectionCreated = registry.counter(MetricRegistry.name(Selector.class, "SelectorConnectionCreated"));
selectorSelectCount = registry.counter(MetricRegistry.name(Selector.class, "SelectorSelectCount"));
selectorIOCount = registry.counter(MetricRegistry.name(Selector.class, "SelectorIOCount"));
selectorSelectTime = registry.histogram(MetricRegistry.name(Selector.class, "SelectorSelectTime"));
selectorIOTime = registry.histogram(MetricRegistry.name(Selector.class, "SelectorIOTime"));
selectorNioCloseErrorCount = registry.counter(MetricRegistry.name(Selector.class, "SelectorNioCloseErrorCount"));
selectorDisconnectedErrorCount =
registry.counter(MetricRegistry.name(Selector.class, "SelectorDisconnectedErrorCount"));
selectorIOErrorCount = registry.counter(MetricRegistry.name(Selector.class, "SelectorIoErrorCount"));
selectorKeyOperationErrorCount =
registry.counter(MetricRegistry.name(Selector.class, "SelectorKeyOperationErrorCount"));
selectorCloseKeyErrorCount = registry.counter(MetricRegistry.name(Selector.class, "SelectorCloseKeyErrorCount"));
selectorCloseSocketErrorCount =
registry.counter(MetricRegistry.name(Selector.class, "SelectorCloseSocketErrorCount"));
plaintextReceiveBytesRate = registry.meter(MetricRegistry.name(Selector.class, "PlaintextReceiveBytesRate"));
plaintextSendBytesRate = registry.meter(MetricRegistry.name(Selector.class, "PlaintextSendBytesRate"));
plaintextReceiveTimePerKB = registry.histogram(MetricRegistry.name(Selector.class, "PlaintextReceiveTimePerKB"));
plaintextSendTimePerKB = registry.histogram(MetricRegistry.name(Selector.class, "PlaintextSendTimePerKB"));
sslReceiveBytesRate = registry.meter(MetricRegistry.name(Selector.class, "SslReceiveBytesRate"));
sslSendBytesRate = registry.meter(MetricRegistry.name(Selector.class, "SslSendBytesRate"));
sslEncryptionTimePerKB = registry.histogram(MetricRegistry.name(Selector.class, "SslEncryptionTimePerKB"));
sslDecryptionTimePerKB = registry.histogram(MetricRegistry.name(Selector.class, "SslDecryptionTimePerKB"));
sslReceiveTimePerKB = registry.histogram(MetricRegistry.name(Selector.class, "SslReceiveTimePerKB"));
sslSendTimePerKB = registry.histogram(MetricRegistry.name(Selector.class, "SslSendTimePerKB"));
sslFactoryInitializationCount =
registry.counter(MetricRegistry.name(Selector.class, "SslFactoryInitializationCount"));
sslFactoryInitializationErrorCount =
registry.counter(MetricRegistry.name(Selector.class, "SslFactoryInitializationErrorCount"));
sslTransmissionInitializationCount =
registry.counter(MetricRegistry.name(Selector.class, "SslTransmissionInitializationCount"));
sslTransmissionInitializationErrorCount =
registry.counter(MetricRegistry.name(Selector.class, "SslTransmissionInitializationErrorCount"));
sslHandshakeTime = registry.histogram(MetricRegistry.name(Selector.class, "SslHandshakeTime"));
sslHandshakeCount = registry.counter(MetricRegistry.name(Selector.class, "SslHandshakeCount"));
sslHandshakeErrorCount = registry.counter(MetricRegistry.name(Selector.class, "SslHandshakeErrorCount"));
sslRenegotiationCount = registry.counter(MetricRegistry.name(Selector.class, "SslRenegotiationCount"));
networkClientSendAndPollTime =
registry.histogram(MetricRegistry.name(NetworkClient.class, "NetworkClientSendAndPollTime"));
requestQueueTime = registry.histogram(MetricRegistry.name(NetworkClient.class, "RequestQueueTime"));
requestSendTime = registry.histogram(MetricRegistry.name(NetworkClient.class, "RequestSendTime"));
requestSendTotalTime = registry.histogram(MetricRegistry.name(NetworkClient.class, "RequestSendTotalTime"));
requestResponseRoundTripTime =
registry.histogram(MetricRegistry.name(NetworkClient.class, "RequestResponseRoundTripTime"));
requestResponseTotalTime = registry.histogram(MetricRegistry.name(NetworkClient.class, "RequestResponseTotalTime"));
connectionTimeOutError = registry.counter(MetricRegistry.name(NetworkClient.class, "ConnectionTimeOutError"));
networkClientIOError = registry.counter(MetricRegistry.name(NetworkClient.class, "NetworkClientIOError"));
networkClientException = registry.counter(MetricRegistry.name(NetworkClient.class, "NetworkClientException"));
selectorActiveConnectionsList = new ArrayList<>();
networkClientPendingRequestList = new ArrayList<>();
final Gauge<Long> selectorActiveConnectionsCount = new Gauge<Long>() {
@Override
public Long getValue() {
long activeConnectionsCount = 0;
for (AtomicLong activeConnection : selectorActiveConnectionsList) {
activeConnectionsCount += activeConnection.get();
}
return activeConnectionsCount;
}
};
registry.register(MetricRegistry.name(Selector.class, "SelectorActiveConnectionsCount"),
selectorActiveConnectionsCount);
final Gauge<Long> networkClientPendingRequestsCount = new Gauge<Long>() {
@Override
public Long getValue() {
long pendingRequestsCount = 0;
for (AtomicLong pendingRequest : networkClientPendingRequestList) {
pendingRequestsCount += pendingRequest.get();
}
return pendingRequestsCount;
}
};
registry.register(MetricRegistry.name(NetworkClient.class, "NetworkClientPendingConnectionsCount"),
networkClientPendingRequestsCount);
}
/**
* Registers the number of active connections for a selector
* @param numActiveConnections count of current active connections
*/
void registerSelectorActiveConnections(final AtomicLong numActiveConnections) {
selectorActiveConnectionsList.add(numActiveConnections);
}
/**
* Registers the count of pending connections to be checked out by the Network client
* @param numPendingConnections the count of pending connections to be checked out
*/
void registerNetworkClientPendingConnections(final AtomicLong numPendingConnections) {
networkClientPendingRequestList.add(numPendingConnections);
}
}
class ServerNetworkMetrics extends NetworkMetrics {
// SocketRequestResponseChannel metrics
private final List<Gauge<Integer>> responseQueueSize;
private final Gauge<Integer> requestQueueSize;
// SocketServer metrics
public final Counter acceptConnectionErrorCount;
public final Counter acceptorShutDownErrorCount;
public final Counter processorShutDownErrorCount;
public final Counter processNewResponseErrorCount;
public Gauge<Integer> numberOfProcessorThreads;
public ServerNetworkMetrics(final SocketRequestResponseChannel channel, MetricRegistry registry,
final List<Processor> processorThreads) {
super(registry);
requestQueueSize = new Gauge<Integer>() {
@Override
public Integer getValue() {
return channel.getRequestQueueSize();
}
};
registry.register(MetricRegistry.name(SocketRequestResponseChannel.class, "RequestQueueSize"), requestQueueSize);
responseQueueSize = new ArrayList<Gauge<Integer>>(channel.getNumberOfProcessors());
for (int i = 0; i < channel.getNumberOfProcessors(); i++) {
final int index = i;
responseQueueSize.add(i, new Gauge<Integer>() {
@Override
public Integer getValue() {
return channel.getResponseQueueSize(index);
}
});
registry.register(MetricRegistry.name(SocketRequestResponseChannel.class, i + "-ResponseQueueSize"),
responseQueueSize.get(i));
}
numberOfProcessorThreads = new Gauge<Integer>() {
@Override
public Integer getValue() {
return getLiveThreads(processorThreads);
}
};
registry.register(MetricRegistry.name(SocketServer.class, "NumberOfProcessorThreads"), numberOfProcessorThreads);
acceptConnectionErrorCount =
registry.counter(MetricRegistry.name(SocketServer.class, "AcceptConnectionErrorCount"));
acceptorShutDownErrorCount =
registry.counter(MetricRegistry.name(SocketServer.class, "AcceptorShutDownErrorCount"));
processorShutDownErrorCount =
registry.counter(MetricRegistry.name(SocketServer.class, "ProcessorShutDownErrorCount"));
processNewResponseErrorCount =
registry.counter(MetricRegistry.name(SocketServer.class, "ProcessNewResponseErrorCount"));
}
private int getLiveThreads(List<Processor> replicaThreads) {
int count = 0;
for (Processor thread : replicaThreads) {
if (thread.isRunning()) {
count++;
}
}
return count;
}
}