mirror of
https://github.com/google/nomulus
synced 2026-05-13 11:21:46 +00:00
Add RDAP latency metrics (#3015)
* RDAP latency metrics * refactor code * refactors * refactor * record latency in RdapMetricInformation object * lint * fix tests * add for tests * formatter
This commit is contained in:
@@ -51,6 +51,7 @@ import google.registry.util.Clock;
|
||||
import jakarta.inject.Inject;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -131,6 +132,7 @@ public abstract class RdapActionBase implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Instant startTime = clock.now();
|
||||
metricInformationBuilder.setIncludeDeleted(includeDeletedParam.orElse(false));
|
||||
metricInformationBuilder.setRole(rdapAuthorization.role());
|
||||
metricInformationBuilder.setRequestMethod(requestMethod);
|
||||
@@ -179,6 +181,9 @@ public abstract class RdapActionBase implements Runnable {
|
||||
setError(SC_INTERNAL_SERVER_ERROR, "Internal Server Error", "An error was encountered");
|
||||
logger.atSevere().withCause(e).log("Exception encountered while processing RDAP command.");
|
||||
}
|
||||
long processingTime = Duration.between(startTime, clock.now()).toMillis();
|
||||
metricInformationBuilder.setProcessingTime(processingTime);
|
||||
|
||||
rdapMetrics.updateMetrics(metricInformationBuilder.build());
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
package google.registry.rdap;
|
||||
|
||||
import static com.google.monitoring.metrics.EventMetric.DEFAULT_FITTER;
|
||||
|
||||
import com.google.auto.value.AutoBuilder;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -133,6 +135,16 @@ public class RdapMetrics {
|
||||
LABEL_DESCRIPTORS_FOR_RETRIEVAL_COUNTS,
|
||||
FIBONACCI_FITTER);
|
||||
|
||||
@VisibleForTesting
|
||||
static final EventMetric requestTime =
|
||||
MetricRegistryImpl.getDefault()
|
||||
.newEventMetric(
|
||||
"/rdap/request_time",
|
||||
"RDAP Request Time",
|
||||
"milliseconds",
|
||||
LABEL_DESCRIPTORS_FOR_RESPONSES,
|
||||
DEFAULT_FITTER);
|
||||
|
||||
@Inject
|
||||
public RdapMetrics() {}
|
||||
|
||||
@@ -181,6 +193,15 @@ public class RdapMetrics {
|
||||
getLabelStringForPrefixLength(rdapMetricInformation.prefixLength()),
|
||||
rdapMetricInformation.includeDeleted() ? "YES" : "NO");
|
||||
}
|
||||
if (rdapMetricInformation.processingTime().isPresent()) {
|
||||
requestTime.record(
|
||||
rdapMetricInformation.processingTime().get(),
|
||||
rdapMetricInformation.endpointType().toString(),
|
||||
rdapMetricInformation.searchType().toString(),
|
||||
rdapMetricInformation.wildcardType().toString(),
|
||||
String.valueOf(rdapMetricInformation.statusCode()),
|
||||
rdapMetricInformation.incompletenessWarningType().toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,6 +223,8 @@ public class RdapMetrics {
|
||||
* than were actually returned in the response; absent if a search was not performed.
|
||||
* @param numHostsRetrieved Number of hosts retrieved from the database; this might be more than
|
||||
* were actually returned in the response; absent if a search was not performed.
|
||||
* @param processingTime The processing time for the request in milliseconds; absent if not
|
||||
* recorded.
|
||||
*/
|
||||
public record RdapMetricInformation(
|
||||
EndpointType endpointType,
|
||||
@@ -215,7 +238,8 @@ public class RdapMetrics {
|
||||
int statusCode,
|
||||
IncompletenessWarningType incompletenessWarningType,
|
||||
Optional<Long> numDomainsRetrieved,
|
||||
Optional<Long> numHostsRetrieved) {
|
||||
Optional<Long> numHostsRetrieved,
|
||||
Optional<Long> processingTime) {
|
||||
|
||||
@AutoBuilder
|
||||
interface Builder {
|
||||
@@ -243,9 +267,12 @@ public class RdapMetrics {
|
||||
|
||||
Builder setNumHostsRetrieved(long numHostsRetrieved);
|
||||
|
||||
Builder setProcessingTime(long processingTime);
|
||||
|
||||
RdapMetricInformation build();
|
||||
}
|
||||
|
||||
|
||||
static Builder builder() {
|
||||
return new AutoBuilder_RdapMetrics_RdapMetricInformation_Builder()
|
||||
.setSearchType(SearchType.NONE)
|
||||
|
||||
@@ -21,6 +21,7 @@ import static google.registry.rdap.RdapTestHelper.parseJsonObject;
|
||||
import static google.registry.request.Action.Method.GET;
|
||||
import static google.registry.request.Action.Method.HEAD;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static org.joda.time.Duration.millis;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import google.registry.rdap.RdapMetrics.EndpointType;
|
||||
@@ -31,6 +32,7 @@ import google.registry.rdap.RdapObjectClasses.ReplyPayloadBase;
|
||||
import google.registry.rdap.RdapSearchResults.IncompletenessWarningType;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.auth.Auth;
|
||||
import google.registry.testing.FakeClock;
|
||||
import java.util.Optional;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -63,6 +65,9 @@ class RdapActionBaseTest extends RdapActionBaseTestCase<RdapActionBaseTest.RdapT
|
||||
if (pathSearchString.equals("RuntimeException")) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
if (pathSearchString.equals("advanceClock")) {
|
||||
((FakeClock) clock).advanceBy(millis(50));
|
||||
}
|
||||
return new ReplyPayloadBase(BoilerplateType.OTHER) {
|
||||
@JsonableElement String key = "value";
|
||||
};
|
||||
@@ -130,6 +135,7 @@ class RdapActionBaseTest extends RdapActionBaseTestCase<RdapActionBaseTest.RdapT
|
||||
.setRequestMethod(Action.Method.GET)
|
||||
.setStatusCode(200)
|
||||
.setIncompletenessWarningType(IncompletenessWarningType.COMPLETE)
|
||||
.setProcessingTime(0L)
|
||||
.build());
|
||||
}
|
||||
|
||||
@@ -149,6 +155,7 @@ class RdapActionBaseTest extends RdapActionBaseTestCase<RdapActionBaseTest.RdapT
|
||||
.setRequestMethod(Action.Method.GET)
|
||||
.setStatusCode(400)
|
||||
.setIncompletenessWarningType(IncompletenessWarningType.COMPLETE)
|
||||
.setProcessingTime(0L)
|
||||
.build());
|
||||
}
|
||||
|
||||
@@ -172,4 +179,24 @@ class RdapActionBaseTest extends RdapActionBaseTestCase<RdapActionBaseTest.RdapT
|
||||
assertThat(payload).contains("\n");
|
||||
assertThat(parseJsonObject(payload)).isEqualTo(loadJsonFile("rdapjson_toplevel.json"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMetrics_recordsProcessingTime() {
|
||||
generateActualJson("advanceClock");
|
||||
verify(rdapMetrics)
|
||||
.updateMetrics(
|
||||
RdapMetrics.RdapMetricInformation.builder()
|
||||
.setEndpointType(EndpointType.HELP)
|
||||
.setSearchType(SearchType.NONE)
|
||||
.setWildcardType(WildcardType.INVALID)
|
||||
.setPrefixLength(0)
|
||||
.setIncludeDeleted(false)
|
||||
.setRegistrarSpecified(false)
|
||||
.setRole(RdapAuthorization.Role.PUBLIC)
|
||||
.setRequestMethod(Action.Method.GET)
|
||||
.setStatusCode(200)
|
||||
.setIncompletenessWarningType(IncompletenessWarningType.COMPLETE)
|
||||
.setProcessingTime(50L)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -435,6 +435,7 @@ class RdapDomainActionTest extends RdapActionBaseTestCase<RdapDomainAction> {
|
||||
.setRequestMethod(Action.Method.GET)
|
||||
.setStatusCode(200)
|
||||
.setIncompletenessWarningType(IncompletenessWarningType.COMPLETE)
|
||||
.setProcessingTime(0L)
|
||||
.build());
|
||||
}
|
||||
|
||||
|
||||
@@ -235,6 +235,7 @@ class RdapEntityActionTest extends RdapActionBaseTestCase<RdapEntityAction> {
|
||||
.setRequestMethod(Action.Method.GET)
|
||||
.setStatusCode(200)
|
||||
.setIncompletenessWarningType(IncompletenessWarningType.COMPLETE)
|
||||
.setProcessingTime(0L)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@ class RdapHelpActionTest extends RdapActionBaseTestCase<RdapHelpAction> {
|
||||
.setRequestMethod(Action.Method.GET)
|
||||
.setStatusCode(200)
|
||||
.setIncompletenessWarningType(IncompletenessWarningType.COMPLETE)
|
||||
.setProcessingTime(0L)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ class RdapMetricsTest {
|
||||
RdapMetrics.responses.reset();
|
||||
RdapMetrics.numberOfDomainsRetrieved.reset();
|
||||
RdapMetrics.numberOfHostsRetrieved.reset();
|
||||
RdapMetrics.requestTime.reset();
|
||||
}
|
||||
|
||||
private RdapMetrics.RdapMetricInformation.Builder getBuilder() {
|
||||
@@ -274,4 +275,13 @@ class RdapMetricsTest {
|
||||
assertThat(RdapMetrics.numberOfDomainsRetrieved).hasNoOtherValues();
|
||||
assertThat(RdapMetrics.numberOfHostsRetrieved).hasNoOtherValues();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRecordProcessingTime() {
|
||||
rdapMetrics.updateMetrics(getBuilder().setProcessingTime(100L).build());
|
||||
assertThat(RdapMetrics.requestTime)
|
||||
.hasDataSetForLabels(ImmutableSet.of(100L), "DOMAINS", "NONE", "INVALID", "200", "COMPLETE")
|
||||
.and()
|
||||
.hasNoOtherValues();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,6 +287,7 @@ class RdapNameserverActionTest extends RdapActionBaseTestCase<RdapNameserverActi
|
||||
.setRequestMethod(Action.Method.GET)
|
||||
.setStatusCode(200)
|
||||
.setIncompletenessWarningType(IncompletenessWarningType.COMPLETE)
|
||||
.setProcessingTime(0L)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,8 @@ public abstract class RdapSearchActionTestCase<A extends RdapSearchActionBase>
|
||||
.setRole(metricRole)
|
||||
.setRequestMethod(requestMethod)
|
||||
.setStatusCode(metricStatusCode)
|
||||
.setIncompletenessWarningType(incompletenessWarningType);
|
||||
.setIncompletenessWarningType(incompletenessWarningType)
|
||||
.setProcessingTime(0L);
|
||||
numDomainsRetrieved.ifPresent(builder::setNumDomainsRetrieved);
|
||||
numHostsRetrieved.ifPresent(builder::setNumHostsRetrieved);
|
||||
verify(rdapMetrics).updateMetrics(builder.build());
|
||||
|
||||
Reference in New Issue
Block a user