diff --git a/core/src/main/java/google/registry/rdap/RdapActionBase.java b/core/src/main/java/google/registry/rdap/RdapActionBase.java index 1dc9a5829..f3cee274a 100644 --- a/core/src/main/java/google/registry/rdap/RdapActionBase.java +++ b/core/src/main/java/google/registry/rdap/RdapActionBase.java @@ -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()); } diff --git a/core/src/main/java/google/registry/rdap/RdapMetrics.java b/core/src/main/java/google/registry/rdap/RdapMetrics.java index b39fd5fab..b845df842 100644 --- a/core/src/main/java/google/registry/rdap/RdapMetrics.java +++ b/core/src/main/java/google/registry/rdap/RdapMetrics.java @@ -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 numDomainsRetrieved, - Optional numHostsRetrieved) { + Optional numHostsRetrieved, + Optional 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) diff --git a/core/src/test/java/google/registry/rdap/RdapActionBaseTest.java b/core/src/test/java/google/registry/rdap/RdapActionBaseTest.java index 1979d0070..ad5d9e440 100644 --- a/core/src/test/java/google/registry/rdap/RdapActionBaseTest.java +++ b/core/src/test/java/google/registry/rdap/RdapActionBaseTest.java @@ -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 { .setRequestMethod(Action.Method.GET) .setStatusCode(200) .setIncompletenessWarningType(IncompletenessWarningType.COMPLETE) + .setProcessingTime(0L) .build()); } diff --git a/core/src/test/java/google/registry/rdap/RdapEntityActionTest.java b/core/src/test/java/google/registry/rdap/RdapEntityActionTest.java index 105ff2401..01e58beea 100644 --- a/core/src/test/java/google/registry/rdap/RdapEntityActionTest.java +++ b/core/src/test/java/google/registry/rdap/RdapEntityActionTest.java @@ -235,6 +235,7 @@ class RdapEntityActionTest extends RdapActionBaseTestCase { .setRequestMethod(Action.Method.GET) .setStatusCode(200) .setIncompletenessWarningType(IncompletenessWarningType.COMPLETE) + .setProcessingTime(0L) .build()); } } diff --git a/core/src/test/java/google/registry/rdap/RdapHelpActionTest.java b/core/src/test/java/google/registry/rdap/RdapHelpActionTest.java index 916d29c62..c20b04b41 100644 --- a/core/src/test/java/google/registry/rdap/RdapHelpActionTest.java +++ b/core/src/test/java/google/registry/rdap/RdapHelpActionTest.java @@ -82,6 +82,7 @@ class RdapHelpActionTest extends RdapActionBaseTestCase { .setRequestMethod(Action.Method.GET) .setStatusCode(200) .setIncompletenessWarningType(IncompletenessWarningType.COMPLETE) + .setProcessingTime(0L) .build()); } } diff --git a/core/src/test/java/google/registry/rdap/RdapMetricsTest.java b/core/src/test/java/google/registry/rdap/RdapMetricsTest.java index 4f4a6639a..92d2a61e0 100644 --- a/core/src/test/java/google/registry/rdap/RdapMetricsTest.java +++ b/core/src/test/java/google/registry/rdap/RdapMetricsTest.java @@ -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(); + } } diff --git a/core/src/test/java/google/registry/rdap/RdapNameserverActionTest.java b/core/src/test/java/google/registry/rdap/RdapNameserverActionTest.java index 513896f5a..a3778ad0e 100644 --- a/core/src/test/java/google/registry/rdap/RdapNameserverActionTest.java +++ b/core/src/test/java/google/registry/rdap/RdapNameserverActionTest.java @@ -287,6 +287,7 @@ class RdapNameserverActionTest extends RdapActionBaseTestCase .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());