mirror of
https://github.com/google/nomulus.git
synced 2025-05-14 00:17:20 +02:00
Register quota metrics in GCP proxy
When a quota request is rejected, increment the metric counter by one. Also makes both frontend and backend metrics singleton because all the fields they have a static. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=185146804
This commit is contained in:
parent
c34e547659
commit
ce5baafc4a
6 changed files with 137 additions and 15 deletions
|
@ -15,11 +15,13 @@
|
||||||
package google.registry.proxy.handler;
|
package google.registry.proxy.handler;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static google.registry.proxy.Protocol.PROTOCOL_KEY;
|
||||||
import static google.registry.proxy.handler.EppServiceHandler.CLIENT_CERTIFICATE_HASH_KEY;
|
import static google.registry.proxy.handler.EppServiceHandler.CLIENT_CERTIFICATE_HASH_KEY;
|
||||||
import static google.registry.proxy.handler.ProxyProtocolHandler.REMOTE_ADDRESS_KEY;
|
import static google.registry.proxy.handler.ProxyProtocolHandler.REMOTE_ADDRESS_KEY;
|
||||||
|
|
||||||
import google.registry.proxy.EppProtocolModule.EppProtocol;
|
import google.registry.proxy.EppProtocolModule.EppProtocol;
|
||||||
import google.registry.proxy.WhoisProtocolModule.WhoisProtocol;
|
import google.registry.proxy.WhoisProtocolModule.WhoisProtocol;
|
||||||
|
import google.registry.proxy.metric.FrontendMetrics;
|
||||||
import google.registry.proxy.quota.QuotaManager;
|
import google.registry.proxy.quota.QuotaManager;
|
||||||
import google.registry.proxy.quota.QuotaManager.QuotaRebate;
|
import google.registry.proxy.quota.QuotaManager.QuotaRebate;
|
||||||
import google.registry.proxy.quota.QuotaManager.QuotaRequest;
|
import google.registry.proxy.quota.QuotaManager.QuotaRequest;
|
||||||
|
@ -40,9 +42,11 @@ public abstract class QuotaHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
|
||||||
protected final QuotaManager quotaManager;
|
protected final QuotaManager quotaManager;
|
||||||
protected QuotaResponse quotaResponse;
|
protected QuotaResponse quotaResponse;
|
||||||
|
protected final FrontendMetrics metrics;
|
||||||
|
|
||||||
protected QuotaHandler(QuotaManager quotaManager) {
|
protected QuotaHandler(QuotaManager quotaManager, FrontendMetrics metrics) {
|
||||||
this.quotaManager = quotaManager;
|
this.quotaManager = quotaManager;
|
||||||
|
this.metrics = metrics;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract String getUserId(ChannelHandlerContext ctx);
|
abstract String getUserId(ChannelHandlerContext ctx);
|
||||||
|
@ -57,7 +61,9 @@ public abstract class QuotaHandler extends ChannelInboundHandlerAdapter {
|
||||||
checkNotNull(userId, "Cannot obtain User ID");
|
checkNotNull(userId, "Cannot obtain User ID");
|
||||||
quotaResponse = quotaManager.acquireQuota(QuotaRequest.create(userId));
|
quotaResponse = quotaManager.acquireQuota(QuotaRequest.create(userId));
|
||||||
if (!quotaResponse.success()) {
|
if (!quotaResponse.success()) {
|
||||||
throw new OverQuotaException(isUserIdPii() ? "none" : userId);
|
String protocolName = ctx.channel().attr(PROTOCOL_KEY).get().name();
|
||||||
|
metrics.registerQuotaRejection(protocolName, isUserIdPii() ? "none" : userId);
|
||||||
|
throw new OverQuotaException(protocolName, isUserIdPii() ? "none" : userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.fireChannelRead(msg);
|
ctx.fireChannelRead(msg);
|
||||||
|
@ -72,8 +78,11 @@ public abstract class QuotaHandler extends ChannelInboundHandlerAdapter {
|
||||||
public abstract void channelInactive(ChannelHandlerContext ctx);
|
public abstract void channelInactive(ChannelHandlerContext ctx);
|
||||||
|
|
||||||
static class OverQuotaException extends Exception {
|
static class OverQuotaException extends Exception {
|
||||||
OverQuotaException(String userId) {
|
OverQuotaException(String protocol, String userId) {
|
||||||
super(String.format("USER ID: %s\nQuota exceeded, terminating connection.", userId));
|
super(
|
||||||
|
String.format(
|
||||||
|
"\nPROTOCOL: %s\nUSER ID: %s\nQuota exceeded, terminating connection.",
|
||||||
|
protocol, userId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,8 +90,8 @@ public abstract class QuotaHandler extends ChannelInboundHandlerAdapter {
|
||||||
public static class WhoisQuotaHandler extends QuotaHandler {
|
public static class WhoisQuotaHandler extends QuotaHandler {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
WhoisQuotaHandler(@WhoisProtocol QuotaManager quotaManager) {
|
WhoisQuotaHandler(@WhoisProtocol QuotaManager quotaManager, FrontendMetrics metrics) {
|
||||||
super(quotaManager);
|
super(quotaManager, metrics);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -117,8 +126,8 @@ public abstract class QuotaHandler extends ChannelInboundHandlerAdapter {
|
||||||
public static class EppQuotaHandler extends QuotaHandler {
|
public static class EppQuotaHandler extends QuotaHandler {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
EppQuotaHandler(@EppProtocol QuotaManager quotaManager) {
|
EppQuotaHandler(@EppProtocol QuotaManager quotaManager, FrontendMetrics metrics) {
|
||||||
super(quotaManager);
|
super(quotaManager, metrics);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -26,8 +26,10 @@ import google.registry.util.NonFinalForTesting;
|
||||||
import io.netty.handler.codec.http.FullHttpRequest;
|
import io.netty.handler.codec.http.FullHttpRequest;
|
||||||
import io.netty.handler.codec.http.FullHttpResponse;
|
import io.netty.handler.codec.http.FullHttpResponse;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
/** Backend metrics instrumentation. */
|
/** Backend metrics instrumentation. */
|
||||||
|
@Singleton
|
||||||
public class BackendMetrics {
|
public class BackendMetrics {
|
||||||
|
|
||||||
// Maximum request size is defined in the config file, this is not realistic and we'd be out of
|
// Maximum request size is defined in the config file, this is not realistic and we'd be out of
|
||||||
|
|
|
@ -31,10 +31,23 @@ import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
/** Frontend metrics instrumentation. */
|
/** Frontend metrics instrumentation. */
|
||||||
|
@Singleton
|
||||||
public class FrontendMetrics {
|
public class FrontendMetrics {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Labels to register front metrics with.
|
||||||
|
*
|
||||||
|
* <p>The client certificate hash value is only used for EPP metrics. For WHOIS metrics, it will
|
||||||
|
* always be {@code "none"}. In order to get the actual registrar name, one can use the {@code
|
||||||
|
* nomulus} tool:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* nomulus -e production list_registrars -f clientCertificateHash | grep $HASH
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
private static final ImmutableSet<LabelDescriptor> LABELS =
|
private static final ImmutableSet<LabelDescriptor> LABELS =
|
||||||
ImmutableSet.of(
|
ImmutableSet.of(
|
||||||
LabelDescriptor.create("protocol", "Name of the protocol."),
|
LabelDescriptor.create("protocol", "Name of the protocol."),
|
||||||
|
@ -68,6 +81,14 @@ public class FrontendMetrics {
|
||||||
"Connections",
|
"Connections",
|
||||||
LABELS);
|
LABELS);
|
||||||
|
|
||||||
|
static final IncrementableMetric quotaRejectionsCounter =
|
||||||
|
MetricRegistryImpl.getDefault()
|
||||||
|
.newIncrementableMetric(
|
||||||
|
"/proxy/frontend/quota_rejections",
|
||||||
|
"Total number rejected quota request made by proxy for each connection.",
|
||||||
|
"Rejections",
|
||||||
|
LABELS);
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public FrontendMetrics() {}
|
public FrontendMetrics() {}
|
||||||
|
|
||||||
|
@ -96,4 +117,9 @@ public class FrontendMetrics {
|
||||||
}
|
}
|
||||||
channelGroup.add(channel);
|
channelGroup.add(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonFinalForTesting
|
||||||
|
public void registerQuotaRejection(String protocol, String certHash) {
|
||||||
|
quotaRejectionsCounter.increment(protocol, certHash);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package google.registry.proxy.handler;
|
package google.registry.proxy.handler;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static google.registry.proxy.Protocol.PROTOCOL_KEY;
|
||||||
import static google.registry.proxy.handler.EppServiceHandler.CLIENT_CERTIFICATE_HASH_KEY;
|
import static google.registry.proxy.handler.EppServiceHandler.CLIENT_CERTIFICATE_HASH_KEY;
|
||||||
import static google.registry.testing.JUnitBackports.expectThrows;
|
import static google.registry.testing.JUnitBackports.expectThrows;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
@ -22,12 +23,16 @@ import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import google.registry.proxy.Protocol;
|
||||||
import google.registry.proxy.handler.QuotaHandler.EppQuotaHandler;
|
import google.registry.proxy.handler.QuotaHandler.EppQuotaHandler;
|
||||||
import google.registry.proxy.handler.QuotaHandler.OverQuotaException;
|
import google.registry.proxy.handler.QuotaHandler.OverQuotaException;
|
||||||
|
import google.registry.proxy.metric.FrontendMetrics;
|
||||||
import google.registry.proxy.quota.QuotaManager;
|
import google.registry.proxy.quota.QuotaManager;
|
||||||
import google.registry.proxy.quota.QuotaManager.QuotaRebate;
|
import google.registry.proxy.quota.QuotaManager.QuotaRebate;
|
||||||
import google.registry.proxy.quota.QuotaManager.QuotaRequest;
|
import google.registry.proxy.quota.QuotaManager.QuotaRequest;
|
||||||
import google.registry.proxy.quota.QuotaManager.QuotaResponse;
|
import google.registry.proxy.quota.QuotaManager.QuotaResponse;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.embedded.EmbeddedChannel;
|
import io.netty.channel.embedded.EmbeddedChannel;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
@ -43,15 +48,35 @@ import org.junit.runners.JUnit4;
|
||||||
public class EppQuotaHandlerTest {
|
public class EppQuotaHandlerTest {
|
||||||
|
|
||||||
private final QuotaManager quotaManager = mock(QuotaManager.class);
|
private final QuotaManager quotaManager = mock(QuotaManager.class);
|
||||||
private final EppQuotaHandler handler = new EppQuotaHandler(quotaManager);
|
private final FrontendMetrics metrics = mock(FrontendMetrics.class);
|
||||||
|
private final EppQuotaHandler handler = new EppQuotaHandler(quotaManager, metrics);
|
||||||
private final EmbeddedChannel channel = new EmbeddedChannel(handler);
|
private final EmbeddedChannel channel = new EmbeddedChannel(handler);
|
||||||
private final String clientCertHash = "blah/123!";
|
private final String clientCertHash = "blah/123!";
|
||||||
private final DateTime now = DateTime.now(DateTimeZone.UTC);
|
private final DateTime now = DateTime.now(DateTimeZone.UTC);
|
||||||
private final Object message = new Object();
|
private final Object message = new Object();
|
||||||
|
|
||||||
|
private void setProtocol(Channel channel) {
|
||||||
|
channel
|
||||||
|
.attr(PROTOCOL_KEY)
|
||||||
|
.set(
|
||||||
|
Protocol.frontendBuilder()
|
||||||
|
.name("epp")
|
||||||
|
.port(12345)
|
||||||
|
.handlerProviders(ImmutableList.of())
|
||||||
|
.relayProtocol(
|
||||||
|
Protocol.backendBuilder()
|
||||||
|
.name("backend")
|
||||||
|
.host("host.tld")
|
||||||
|
.port(1234)
|
||||||
|
.handlerProviders(ImmutableList.of())
|
||||||
|
.build())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
channel.attr(CLIENT_CERTIFICATE_HASH_KEY).set(clientCertHash);
|
channel.attr(CLIENT_CERTIFICATE_HASH_KEY).set(clientCertHash);
|
||||||
|
setProtocol(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -85,15 +110,18 @@ public class EppQuotaHandlerTest {
|
||||||
OverQuotaException e =
|
OverQuotaException e =
|
||||||
expectThrows(OverQuotaException.class, () -> channel.writeInbound(message));
|
expectThrows(OverQuotaException.class, () -> channel.writeInbound(message));
|
||||||
assertThat(e).hasMessageThat().contains(clientCertHash);
|
assertThat(e).hasMessageThat().contains(clientCertHash);
|
||||||
|
verify(metrics).registerQuotaRejection("epp", clientCertHash);
|
||||||
|
verifyNoMoreInteractions(metrics);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuccess_twoChannels_twoUserIds() {
|
public void testSuccess_twoChannels_twoUserIds() {
|
||||||
// Set up another user.
|
// Set up another user.
|
||||||
final EppQuotaHandler otherHandler = new EppQuotaHandler(quotaManager);
|
final EppQuotaHandler otherHandler = new EppQuotaHandler(quotaManager, metrics);
|
||||||
final EmbeddedChannel otherChannel = new EmbeddedChannel(otherHandler);
|
final EmbeddedChannel otherChannel = new EmbeddedChannel(otherHandler);
|
||||||
final String otherClientCertHash = "hola@9x";
|
final String otherClientCertHash = "hola@9x";
|
||||||
otherChannel.attr(CLIENT_CERTIFICATE_HASH_KEY).set(otherClientCertHash);
|
otherChannel.attr(CLIENT_CERTIFICATE_HASH_KEY).set(otherClientCertHash);
|
||||||
|
setProtocol(otherChannel);
|
||||||
final DateTime later = now.plus(Duration.standardSeconds(1));
|
final DateTime later = now.plus(Duration.standardSeconds(1));
|
||||||
|
|
||||||
when(quotaManager.acquireQuota(QuotaRequest.create(clientCertHash)))
|
when(quotaManager.acquireQuota(QuotaRequest.create(clientCertHash)))
|
||||||
|
@ -110,14 +138,17 @@ public class EppQuotaHandlerTest {
|
||||||
OverQuotaException e =
|
OverQuotaException e =
|
||||||
expectThrows(OverQuotaException.class, () -> otherChannel.writeInbound(message));
|
expectThrows(OverQuotaException.class, () -> otherChannel.writeInbound(message));
|
||||||
assertThat(e).hasMessageThat().contains(otherClientCertHash);
|
assertThat(e).hasMessageThat().contains(otherClientCertHash);
|
||||||
|
verify(metrics).registerQuotaRejection("epp", otherClientCertHash);
|
||||||
|
verifyNoMoreInteractions(metrics);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuccess_twoChannels_sameUserIds() {
|
public void testSuccess_twoChannels_sameUserIds() {
|
||||||
// Set up another channel for the same user.
|
// Set up another channel for the same user.
|
||||||
final EppQuotaHandler otherHandler = new EppQuotaHandler(quotaManager);
|
final EppQuotaHandler otherHandler = new EppQuotaHandler(quotaManager, metrics);
|
||||||
final EmbeddedChannel otherChannel = new EmbeddedChannel(otherHandler);
|
final EmbeddedChannel otherChannel = new EmbeddedChannel(otherHandler);
|
||||||
otherChannel.attr(CLIENT_CERTIFICATE_HASH_KEY).set(clientCertHash);
|
otherChannel.attr(CLIENT_CERTIFICATE_HASH_KEY).set(clientCertHash);
|
||||||
|
setProtocol(otherChannel);
|
||||||
final DateTime later = now.plus(Duration.standardSeconds(1));
|
final DateTime later = now.plus(Duration.standardSeconds(1));
|
||||||
|
|
||||||
when(quotaManager.acquireQuota(QuotaRequest.create(clientCertHash)))
|
when(quotaManager.acquireQuota(QuotaRequest.create(clientCertHash)))
|
||||||
|
@ -133,5 +164,7 @@ public class EppQuotaHandlerTest {
|
||||||
OverQuotaException e =
|
OverQuotaException e =
|
||||||
expectThrows(OverQuotaException.class, () -> otherChannel.writeInbound(message));
|
expectThrows(OverQuotaException.class, () -> otherChannel.writeInbound(message));
|
||||||
assertThat(e).hasMessageThat().contains(clientCertHash);
|
assertThat(e).hasMessageThat().contains(clientCertHash);
|
||||||
|
verify(metrics).registerQuotaRejection("epp", clientCertHash);
|
||||||
|
verifyNoMoreInteractions(metrics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package google.registry.proxy.handler;
|
package google.registry.proxy.handler;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static google.registry.proxy.Protocol.PROTOCOL_KEY;
|
||||||
import static google.registry.proxy.handler.ProxyProtocolHandler.REMOTE_ADDRESS_KEY;
|
import static google.registry.proxy.handler.ProxyProtocolHandler.REMOTE_ADDRESS_KEY;
|
||||||
import static google.registry.testing.JUnitBackports.expectThrows;
|
import static google.registry.testing.JUnitBackports.expectThrows;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
@ -22,11 +23,15 @@ import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import google.registry.proxy.Protocol;
|
||||||
import google.registry.proxy.handler.QuotaHandler.OverQuotaException;
|
import google.registry.proxy.handler.QuotaHandler.OverQuotaException;
|
||||||
import google.registry.proxy.handler.QuotaHandler.WhoisQuotaHandler;
|
import google.registry.proxy.handler.QuotaHandler.WhoisQuotaHandler;
|
||||||
|
import google.registry.proxy.metric.FrontendMetrics;
|
||||||
import google.registry.proxy.quota.QuotaManager;
|
import google.registry.proxy.quota.QuotaManager;
|
||||||
import google.registry.proxy.quota.QuotaManager.QuotaRequest;
|
import google.registry.proxy.quota.QuotaManager.QuotaRequest;
|
||||||
import google.registry.proxy.quota.QuotaManager.QuotaResponse;
|
import google.registry.proxy.quota.QuotaManager.QuotaResponse;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.embedded.EmbeddedChannel;
|
import io.netty.channel.embedded.EmbeddedChannel;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
@ -42,15 +47,35 @@ import org.junit.runners.JUnit4;
|
||||||
public class WhoisQuotaHandlerTest {
|
public class WhoisQuotaHandlerTest {
|
||||||
|
|
||||||
private final QuotaManager quotaManager = mock(QuotaManager.class);
|
private final QuotaManager quotaManager = mock(QuotaManager.class);
|
||||||
private final WhoisQuotaHandler handler = new WhoisQuotaHandler(quotaManager);
|
private final FrontendMetrics metrics = mock(FrontendMetrics.class);
|
||||||
|
private final WhoisQuotaHandler handler = new WhoisQuotaHandler(quotaManager, metrics);
|
||||||
private final EmbeddedChannel channel = new EmbeddedChannel(handler);
|
private final EmbeddedChannel channel = new EmbeddedChannel(handler);
|
||||||
private final DateTime now = DateTime.now(DateTimeZone.UTC);
|
private final DateTime now = DateTime.now(DateTimeZone.UTC);
|
||||||
private final String remoteAddress = "127.0.0.1";
|
private final String remoteAddress = "127.0.0.1";
|
||||||
private final Object message = new Object();
|
private final Object message = new Object();
|
||||||
|
|
||||||
|
private void setProtocol(Channel channel) {
|
||||||
|
channel
|
||||||
|
.attr(PROTOCOL_KEY)
|
||||||
|
.set(
|
||||||
|
Protocol.frontendBuilder()
|
||||||
|
.name("whois")
|
||||||
|
.port(12345)
|
||||||
|
.handlerProviders(ImmutableList.of())
|
||||||
|
.relayProtocol(
|
||||||
|
Protocol.backendBuilder()
|
||||||
|
.name("backend")
|
||||||
|
.host("host.tld")
|
||||||
|
.port(1234)
|
||||||
|
.handlerProviders(ImmutableList.of())
|
||||||
|
.build())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
channel.attr(REMOTE_ADDRESS_KEY).set(remoteAddress);
|
channel.attr(REMOTE_ADDRESS_KEY).set(remoteAddress);
|
||||||
|
setProtocol(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -80,15 +105,18 @@ public class WhoisQuotaHandlerTest {
|
||||||
OverQuotaException e =
|
OverQuotaException e =
|
||||||
expectThrows(OverQuotaException.class, () -> channel.writeInbound(message));
|
expectThrows(OverQuotaException.class, () -> channel.writeInbound(message));
|
||||||
assertThat(e).hasMessageThat().contains("none");
|
assertThat(e).hasMessageThat().contains("none");
|
||||||
|
verify(metrics).registerQuotaRejection("whois", "none");
|
||||||
|
verifyNoMoreInteractions(metrics);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuccess_twoChannels_twoUserIds() {
|
public void testSuccess_twoChannels_twoUserIds() {
|
||||||
// Set up another user.
|
// Set up another user.
|
||||||
final WhoisQuotaHandler otherHandler = new WhoisQuotaHandler(quotaManager);
|
final WhoisQuotaHandler otherHandler = new WhoisQuotaHandler(quotaManager, metrics);
|
||||||
final EmbeddedChannel otherChannel = new EmbeddedChannel(otherHandler);
|
final EmbeddedChannel otherChannel = new EmbeddedChannel(otherHandler);
|
||||||
final String otherRemoteAddress = "192.168.0.1";
|
final String otherRemoteAddress = "192.168.0.1";
|
||||||
otherChannel.attr(REMOTE_ADDRESS_KEY).set(otherRemoteAddress);
|
otherChannel.attr(REMOTE_ADDRESS_KEY).set(otherRemoteAddress);
|
||||||
|
setProtocol(otherChannel);
|
||||||
final DateTime later = now.plus(Duration.standardSeconds(1));
|
final DateTime later = now.plus(Duration.standardSeconds(1));
|
||||||
|
|
||||||
when(quotaManager.acquireQuota(QuotaRequest.create(remoteAddress)))
|
when(quotaManager.acquireQuota(QuotaRequest.create(remoteAddress)))
|
||||||
|
@ -105,18 +133,21 @@ public class WhoisQuotaHandlerTest {
|
||||||
OverQuotaException e =
|
OverQuotaException e =
|
||||||
expectThrows(OverQuotaException.class, () -> otherChannel.writeInbound(message));
|
expectThrows(OverQuotaException.class, () -> otherChannel.writeInbound(message));
|
||||||
assertThat(e).hasMessageThat().contains("none");
|
assertThat(e).hasMessageThat().contains("none");
|
||||||
|
verify(metrics).registerQuotaRejection("whois", "none");
|
||||||
|
verifyNoMoreInteractions(metrics);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuccess_oneUser_rateLimited() {
|
public void testSuccess_oneUser_rateLimited() {
|
||||||
// Set up another channel for the same user.
|
// Set up another channel for the same user.
|
||||||
final WhoisQuotaHandler otherHandler = new WhoisQuotaHandler(quotaManager);
|
final WhoisQuotaHandler otherHandler = new WhoisQuotaHandler(quotaManager, metrics);
|
||||||
final EmbeddedChannel otherChannel = new EmbeddedChannel(otherHandler);
|
final EmbeddedChannel otherChannel = new EmbeddedChannel(otherHandler);
|
||||||
otherChannel.attr(REMOTE_ADDRESS_KEY).set(remoteAddress);
|
otherChannel.attr(REMOTE_ADDRESS_KEY).set(remoteAddress);
|
||||||
|
setProtocol(otherChannel);
|
||||||
final DateTime later = now.plus(Duration.standardSeconds(1));
|
final DateTime later = now.plus(Duration.standardSeconds(1));
|
||||||
|
|
||||||
// Set up the third channel for the same user
|
// Set up the third channel for the same user
|
||||||
final WhoisQuotaHandler thirdHandler = new WhoisQuotaHandler(quotaManager);
|
final WhoisQuotaHandler thirdHandler = new WhoisQuotaHandler(quotaManager, metrics);
|
||||||
final EmbeddedChannel thirdChannel = new EmbeddedChannel(thirdHandler);
|
final EmbeddedChannel thirdChannel = new EmbeddedChannel(thirdHandler);
|
||||||
thirdChannel.attr(REMOTE_ADDRESS_KEY).set(remoteAddress);
|
thirdChannel.attr(REMOTE_ADDRESS_KEY).set(remoteAddress);
|
||||||
final DateTime evenLater = now.plus(Duration.standardSeconds(60));
|
final DateTime evenLater = now.plus(Duration.standardSeconds(60));
|
||||||
|
@ -137,10 +168,12 @@ public class WhoisQuotaHandlerTest {
|
||||||
OverQuotaException e =
|
OverQuotaException e =
|
||||||
expectThrows(OverQuotaException.class, () -> otherChannel.writeInbound(message));
|
expectThrows(OverQuotaException.class, () -> otherChannel.writeInbound(message));
|
||||||
assertThat(e).hasMessageThat().contains("none");
|
assertThat(e).hasMessageThat().contains("none");
|
||||||
|
verify(metrics).registerQuotaRejection("whois", "none");
|
||||||
|
|
||||||
// Allows the third channel.
|
// Allows the third channel.
|
||||||
assertThat(thirdChannel.writeInbound(message)).isTrue();
|
assertThat(thirdChannel.writeInbound(message)).isTrue();
|
||||||
assertThat((Object) thirdChannel.readInbound()).isEqualTo(message);
|
assertThat((Object) thirdChannel.readInbound()).isEqualTo(message);
|
||||||
assertThat(thirdChannel.isActive()).isTrue();
|
assertThat(thirdChannel.isActive()).isTrue();
|
||||||
|
verifyNoMoreInteractions(metrics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,4 +163,23 @@ public class FrontendMetricsTest {
|
||||||
.and()
|
.and()
|
||||||
.hasNoOtherValues();
|
.hasNoOtherValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccess_registerQuotaRejections() {
|
||||||
|
String otherCertHash = "foobar1234X";
|
||||||
|
String remoteAddress = "127.0.0.1";
|
||||||
|
String otherProtocol = "other protocol";
|
||||||
|
metrics.registerQuotaRejection(PROTOCOL, CERT_HASH);
|
||||||
|
metrics.registerQuotaRejection(PROTOCOL, otherCertHash);
|
||||||
|
metrics.registerQuotaRejection(PROTOCOL, otherCertHash);
|
||||||
|
metrics.registerQuotaRejection(otherProtocol, remoteAddress);
|
||||||
|
assertThat(FrontendMetrics.quotaRejectionsCounter)
|
||||||
|
.hasValueForLabels(1, PROTOCOL, CERT_HASH)
|
||||||
|
.and()
|
||||||
|
.hasValueForLabels(2, PROTOCOL, otherCertHash)
|
||||||
|
.and()
|
||||||
|
.hasValueForLabels(1, otherProtocol, remoteAddress)
|
||||||
|
.and()
|
||||||
|
.hasNoOtherValues();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue