diff --git a/java/google/registry/flows/BUILD b/java/google/registry/flows/BUILD index 4ce8e5d2c..0ddfb72dd 100644 --- a/java/google/registry/flows/BUILD +++ b/java/google/registry/flows/BUILD @@ -44,6 +44,7 @@ java_library( "//java/google/registry/mapreduce", "//java/google/registry/mapreduce/inputs", "//java/google/registry/model", + "//java/google/registry/monitoring/metrics", "//java/google/registry/monitoring/whitebox", "//java/google/registry/pricing", "//java/google/registry/request", diff --git a/java/google/registry/flows/EppController.java b/java/google/registry/flows/EppController.java index c19a4f2cd..e49e52406 100644 --- a/java/google/registry/flows/EppController.java +++ b/java/google/registry/flows/EppController.java @@ -42,7 +42,8 @@ public final class EppController { @Inject Clock clock; @Inject FlowComponent.Builder flowComponentBuilder; - @Inject EppMetric.Builder metric; + @Inject EppMetric.Builder metricBuilder; + @Inject EppMetrics eppMetrics; @Inject BigQueryMetricsEnqueuer bigQueryMetricsEnqueuer; @Inject EppController() {} @@ -54,20 +55,20 @@ public final class EppController { boolean isDryRun, boolean isSuperuser, byte[] inputXmlBytes) { - metric.setClientId(sessionMetadata.getClientId()); - metric.setPrivilegeLevel(isSuperuser ? "SUPERUSER" : "NORMAL"); + metricBuilder.setClientId(sessionMetadata.getClientId()); + metricBuilder.setPrivilegeLevel(isSuperuser ? "SUPERUSER" : "NORMAL"); try { EppInput eppInput; try { eppInput = unmarshal(EppInput.class, inputXmlBytes); } catch (EppException e) { // Send the client an error message, with no clTRID since we couldn't unmarshal it. - metric.setStatus(e.getResult().getCode()); + metricBuilder.setStatus(e.getResult().getCode()); return getErrorResponse(clock, e.getResult(), Trid.create(null)); } - metric.setCommandName(eppInput.getCommandName()); + metricBuilder.setCommandName(eppInput.getCommandName()); if (!eppInput.getTargetIds().isEmpty()) { - metric.setEppTarget(Joiner.on(',').join(eppInput.getTargetIds())); + metricBuilder.setEppTarget(Joiner.on(',').join(eppInput.getTargetIds())); } EppOutput output = runFlowConvertEppErrors(flowComponentBuilder .flowModule(new FlowModule.Builder() @@ -81,11 +82,14 @@ public final class EppController { .build()) .build()); if (output.isResponse()) { - metric.setStatus(output.getResponse().getResult().getCode()); + metricBuilder.setStatus(output.getResponse().getResult().getCode()); } return output; } finally { - bigQueryMetricsEnqueuer.export(metric.build()); + EppMetric metric = metricBuilder.build(); + bigQueryMetricsEnqueuer.export(metric); + eppMetrics.incrementEppRequests(metric); + eppMetrics.recordProcessingTime(metric); } } diff --git a/java/google/registry/flows/EppMetrics.java b/java/google/registry/flows/EppMetrics.java new file mode 100644 index 000000000..c0cad474b --- /dev/null +++ b/java/google/registry/flows/EppMetrics.java @@ -0,0 +1,72 @@ +// Copyright 2016 The Domain Registry Authors. 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. +// See the License for the specific language governing permissions and +// limitations under the License. + +package google.registry.flows; + +import com.google.common.collect.ImmutableSet; +import google.registry.monitoring.metrics.EventMetric; +import google.registry.monitoring.metrics.IncrementableMetric; +import google.registry.monitoring.metrics.LabelDescriptor; +import google.registry.monitoring.metrics.MetricRegistryImpl; +import google.registry.monitoring.whitebox.EppMetric; +import javax.inject.Inject; + +/** EPP Instrumentation. */ +public class EppMetrics { + + private static final ImmutableSet LABEL_DESCRIPTORS = + ImmutableSet.of( + LabelDescriptor.create("command", "The name of the command."), + LabelDescriptor.create("client_id", "The name of the client."), + LabelDescriptor.create("status", "The return status of the command.")); + + private static final IncrementableMetric eppRequests = + MetricRegistryImpl.getDefault() + .newIncrementableMetric( + "/epp/requests", "Count of EPP Requests", "count", LABEL_DESCRIPTORS); + + private static final EventMetric processingTime = + MetricRegistryImpl.getDefault() + .newEventMetric( + "/epp/processing_time", + "EPP Processing Time", + "milliseconds", + LABEL_DESCRIPTORS, + EventMetric.DEFAULT_FITTER); + + @Inject + public EppMetrics() {} + + /** + * Increment a counter which tracks EPP requests. + * + * @see EppController + * @see FlowRunner + */ + public void incrementEppRequests(EppMetric metric) { + eppRequests.increment( + metric.getCommandName().or(""), + metric.getClientId().or(""), + metric.getStatus().isPresent() ? metric.getStatus().toString() : ""); + } + + /** Record the server-side processing time for an EPP request. */ + public void recordProcessingTime(EppMetric metric) { + processingTime.record( + metric.getEndTimestamp().getMillis() - metric.getStartTimestamp().getMillis(), + metric.getCommandName().or(""), + metric.getClientId().or(""), + metric.getStatus().isPresent() ? metric.getStatus().toString() : ""); + } +} diff --git a/javatests/google/registry/flows/EppControllerTest.java b/javatests/google/registry/flows/EppControllerTest.java index b99a4c43a..3f08decb1 100644 --- a/javatests/google/registry/flows/EppControllerTest.java +++ b/javatests/google/registry/flows/EppControllerTest.java @@ -52,6 +52,7 @@ public class EppControllerTest extends ShardableTestCase { @Mock SessionMetadata sessionMetadata; @Mock TransportCredentials transportCredentials; + @Mock EppMetrics eppMetrics; @Mock BigQueryMetricsEnqueuer metricsEnqueuer; @Mock FlowComponent.Builder flowComponentBuilder; @Mock FlowComponent flowComponent; @@ -76,10 +77,11 @@ public class EppControllerTest extends ShardableTestCase { when(result.getCode()).thenReturn(Code.SuccessWithNoMessages); eppController = new EppController(); - eppController.metric = new EppMetric.Builder(); + eppController.metricBuilder = new EppMetric.Builder(); eppController.bigQueryMetricsEnqueuer = metricsEnqueuer; eppController.clock = new FakeClock(); eppController.flowComponentBuilder = flowComponentBuilder; + eppController.eppMetrics = eppMetrics; } @Test