Add metrics for registrar console requests

Cardinality of this metric:

clientId: there are currently 650 (on sandbox, because of OTE), and 200 on production.
explicitClientId: 2
roles: 2 now, might be 3 soon if we add vendors
status: 2

So we're talking about a cardinality of 2,000-8,000. Less when you consider that registrars only seldom actually need to access the console (certainly not daily or even weekly).

Compare with, e.g., the /epp/processing_time from the above EppMetrics.java which has:
Epp commands: 26 (manual counting)
client IDs: 200 on prod
status: the actual status CODE of the command. Can have many values, but looking at the past few weeks' metrics I counted 20
Note that not every command results in every status. Looking a few weeks back we can see around 80-100 (commands+status) combination.
buckets: 16

so that's over 250,000-1,000,000 cardinality, on a very high-volume metric.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=218699280
This commit is contained in:
guyben 2018-10-25 09:34:21 -07:00 committed by jianglai
parent f6d9b46622
commit 97aa98eb35
11 changed files with 223 additions and 25 deletions

View file

@ -26,11 +26,13 @@ java_library(
"//java/google/registry/util",
"//third_party/objectify:objectify-v4_1",
"@com_google_appengine_api_1_0_sdk",
"@com_google_auto_value",
"@com_google_code_findbugs_jsr305",
"@com_google_dagger",
"@com_google_flogger",
"@com_google_flogger_system_backend",
"@com_google_guava",
"@com_google_monitoring_client_metrics",
"@com_google_re2j",
"@io_bazel_rules_closure//closure/templates",
"@javax_inject",

View file

@ -75,6 +75,7 @@ public final class ConsoleUiAction implements Runnable {
@Inject HttpServletRequest req;
@Inject Response response;
@Inject RegistrarConsoleMetrics registrarConsoleMetrics;
@Inject AuthenticatedRegistrarAccessor registrarAccessor;
@Inject UserService userService;
@Inject XsrfTokenManager xsrfTokenManager;
@ -134,15 +135,19 @@ public final class ConsoleUiAction implements Runnable {
data.put("username", user.getNickname());
data.put("logoutUrl", userService.createLogoutURL(PATH));
data.put("xsrfToken", xsrfTokenManager.generateToken(user.getEmail()));
ImmutableSetMultimap<String, Role> roleMap = registrarAccessor.getAllClientIdWithRoles();
ImmutableSetMultimap<Role, String> roleMapInverse = roleMap.inverse();
// TODO(guyben):just return all the clientIDs in a single list, and add an "isAdmin" or "roles"
// item
data.put("ownerClientIds", roleMapInverse.get(OWNER));
data.put(
"adminClientIds", Sets.difference(roleMapInverse.get(ADMIN), roleMapInverse.get(OWNER)));
// We set the initual value to the value that will show if guessClientId throws.
String clientId = "<null>";
try {
String clientId = paramClientId.orElse(registrarAccessor.guessClientId());
clientId = paramClientId.orElse(registrarAccessor.guessClientId());
data.put("clientId", clientId);
ImmutableSetMultimap<Role, String> roleMap =
registrarAccessor.getAllClientIdWithRoles().inverse();
data.put("ownerClientIds", roleMap.get(OWNER));
data.put("adminClientIds", Sets.difference(roleMap.get(ADMIN), roleMap.get(OWNER)));
// We want to load the registrar even if we won't use it later (even if we remove the
// requireFeeExtension) - to make sure the user indeed has access to the guessed registrar.
//
@ -162,7 +167,13 @@ public final class ConsoleUiAction implements Runnable {
.setCssRenamingMap(CSS_RENAMING_MAP_SUPPLIER.get())
.setData(data)
.render());
registrarConsoleMetrics.registerConsoleRequest(
clientId, paramClientId.isPresent(), roleMap.get(clientId), "FORBIDDEN");
return;
} catch (Exception e) {
registrarConsoleMetrics.registerConsoleRequest(
clientId, paramClientId.isPresent(), roleMap.get(clientId), "UNEXPECTED ERROR");
throw e;
}
String payload = TOFU_SUPPLIER.get()
@ -171,5 +182,7 @@ public final class ConsoleUiAction implements Runnable {
.setData(data)
.render();
response.setPayload(payload);
registrarConsoleMetrics.registerConsoleRequest(
clientId, paramClientId.isPresent(), roleMap.get(clientId), "SUCCESS");
}
}

View file

@ -0,0 +1,69 @@
// Copyright 2018 The Nomulus 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.ui.server.registrar;
import com.google.common.collect.ImmutableSet;
import com.google.monitoring.metrics.IncrementableMetric;
import com.google.monitoring.metrics.LabelDescriptor;
import com.google.monitoring.metrics.MetricRegistryImpl;
import google.registry.ui.server.registrar.AuthenticatedRegistrarAccessor.Role;
import javax.inject.Inject;
final class RegistrarConsoleMetrics {
private static final ImmutableSet<LabelDescriptor> CONSOLE_LABEL_DESCRIPTORS =
ImmutableSet.of(
LabelDescriptor.create("clientId", "target registrar client ID"),
LabelDescriptor.create("explicitClientId", "whether the client ID is set explicitly"),
LabelDescriptor.create("role", "Role[s] of the user making the request"),
LabelDescriptor.create("status", "whether the request is successful"));
static final IncrementableMetric consoleRequestMetric =
MetricRegistryImpl.getDefault()
.newIncrementableMetric(
"/console/registrar/console_requests",
"Count of /registrar requests",
"count",
CONSOLE_LABEL_DESCRIPTORS);
private static final ImmutableSet<LabelDescriptor> SETTINGS_LABEL_DESCRIPTORS =
ImmutableSet.of(
LabelDescriptor.create("clientId", "target registrar client ID"),
LabelDescriptor.create("action", "action performed"),
LabelDescriptor.create("role", "Role[s] of the user making the request"),
LabelDescriptor.create("status", "whether the request is successful"));
static final IncrementableMetric settingsRequestMetric =
MetricRegistryImpl.getDefault()
.newIncrementableMetric(
"/console/registrar/setting_requests",
"Count of /registrar-settings requests",
"count",
SETTINGS_LABEL_DESCRIPTORS);
@Inject
public RegistrarConsoleMetrics() {}
void registerConsoleRequest(
String clientId, boolean explicitClientId, ImmutableSet<Role> roles, String status) {
consoleRequestMetric.increment(
clientId, String.valueOf(explicitClientId), String.valueOf(roles), status);
}
void registerSettingsRequest(
String clientId, String action, ImmutableSet<Role> roles, String status) {
settingsRequestMetric.increment(clientId, action, String.valueOf(roles), status);
}
}

View file

@ -21,6 +21,7 @@ import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.security.JsonResponseHelper.Status.ERROR;
import static google.registry.security.JsonResponseHelper.Status.SUCCESS;
import com.google.auto.value.AutoValue;
import com.google.common.base.Ascii;
import com.google.common.base.Strings;
import com.google.common.collect.HashMultimap;
@ -80,6 +81,7 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
@Inject JsonActionRunner jsonActionRunner;
@Inject AppEngineServiceUtils appEngineServiceUtils;
@Inject RegistrarConsoleMetrics registrarConsoleMetrics;
@Inject SendEmailUtils sendEmailUtils;
@Inject AuthenticatedRegistrarAccessor registrarAccessor;
@Inject AuthResult authResult;
@ -114,34 +116,55 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
@SuppressWarnings("unchecked")
Map<String, ?> args = (Map<String, Object>)
Optional.<Object>ofNullable(input.get(ARGS_PARAM)).orElse(ImmutableMap.of());
logger.atInfo().log("Received request '%s' on registrar '%s' with args %s", op, clientId, args);
String status = "SUCCESS";
try {
switch (op) {
case "update":
return update(args, clientId);
return update(args, clientId).toJsonResponse();
case "read":
return read(clientId);
return read(clientId).toJsonResponse();
default:
return JsonResponseHelper.create(ERROR, "Unknown or unsupported operation: " + op);
throw new IllegalArgumentException("Unknown or unsupported operation: " + op);
}
} catch (FormFieldException e) {
logger.atWarning().withCause(e).log(
"Failed to perform operation '%s' on registrar '%s' for args %s", op, clientId, args);
return JsonResponseHelper.createFormFieldError(e.getMessage(), e.getFieldName());
} catch (Throwable e) {
logger.atWarning().withCause(e).log(
"Failed to perform operation '%s' on registrar '%s' for args %s", op, clientId, args);
status = "ERROR: " + e.getClass().getSimpleName();
if (e instanceof FormFieldException) {
FormFieldException formFieldException = (FormFieldException) e;
return JsonResponseHelper.createFormFieldError(
formFieldException.getMessage(), formFieldException.getFieldName());
}
return JsonResponseHelper.create(
ERROR, Optional.ofNullable(e.getMessage()).orElse("Unspecified error"));
} finally {
registrarConsoleMetrics.registerSettingsRequest(
clientId, op, registrarAccessor.getAllClientIdWithRoles().get(clientId), status);
}
}
Map<String, Object> read(String clientId) {
return JsonResponseHelper.create(
SUCCESS, "Success", registrarAccessor.getRegistrar(clientId).toJsonMap());
@AutoValue
abstract static class RegistrarResult {
abstract String message();
abstract Registrar registrar();
Map<String, Object> toJsonResponse() {
return JsonResponseHelper.create(SUCCESS, message(), registrar().toJsonMap());
}
static RegistrarResult create(String message, Registrar registrar) {
return new AutoValue_RegistrarSettingsAction_RegistrarResult(message, registrar);
}
}
Map<String, Object> update(final Map<String, ?> args, String clientId) {
private RegistrarResult read(String clientId) {
return RegistrarResult.create("Success", registrarAccessor.getRegistrar(clientId));
}
private RegistrarResult update(final Map<String, ?> args, String clientId) {
return ofy()
.transact(
() -> {
@ -196,8 +219,7 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
// Email and return update.
sendExternalUpdatesIfNecessary(
registrar, contacts, updatedRegistrar, updatedContacts);
return JsonResponseHelper.create(
SUCCESS, "Saved " + clientId, updatedRegistrar.toJsonMap());
return RegistrarResult.create("Saved " + clientId, updatedRegistrar);
});
}

View file

@ -28,6 +28,7 @@ java_library(
"@com_google_flogger_system_backend",
"@com_google_guava",
"@com_google_guava_testlib",
"@com_google_monitoring_client_contrib",
"@com_google_truth",
"@com_google_truth_extensions_truth_java8_extension",
"@com_googlecode_json_simple",

View file

@ -16,6 +16,7 @@ package google.registry.ui.server.registrar;
import static com.google.common.net.HttpHeaders.LOCATION;
import static com.google.common.truth.Truth.assertThat;
import static com.google.monitoring.metrics.contrib.LongMetricSubject.assertThat;
import static google.registry.testing.DatastoreHelper.loadRegistrar;
import static google.registry.ui.server.registrar.AuthenticatedRegistrarAccessor.Role.ADMIN;
import static google.registry.ui.server.registrar.AuthenticatedRegistrarAccessor.Role.OWNER;
@ -38,6 +39,7 @@ import google.registry.testing.FakeResponse;
import google.registry.testing.UserInfo;
import java.util.Optional;
import javax.servlet.http.HttpServletRequest;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@ -73,6 +75,7 @@ public class ConsoleUiActionTest {
action.technicalDocsUrl = "http://example.com/technical-docs";
action.req = request;
action.response = response;
action.registrarConsoleMetrics = new RegistrarConsoleMetrics();
action.registrarAccessor = registrarAccessor;
action.userService = UserServiceFactory.getUserService();
action.xsrfTokenManager = new XsrfTokenManager(new FakeClock(), action.userService);
@ -91,24 +94,39 @@ public class ConsoleUiActionTest {
when(registrarAccessor.guessClientId()).thenCallRealMethod();
// Used for error message in guessClientId
registrarAccessor.authResult = authResult;
RegistrarConsoleMetrics.consoleRequestMetric.reset();
}
@After
public void tearDown() throws Exception {
assertThat(RegistrarConsoleMetrics.consoleRequestMetric).hasNoOtherValues();
}
public void assertMetric(String clientId, String explicitClientId, String roles, String status) {
assertThat(RegistrarConsoleMetrics.consoleRequestMetric)
.hasValueForLabels(1, clientId, explicitClientId, roles, status);
RegistrarConsoleMetrics.consoleRequestMetric.reset(clientId, explicitClientId, roles, status);
}
@Test
public void testWebPage_disallowsIframe() {
action.run();
assertThat(response.getHeaders()).containsEntry("X-Frame-Options", "SAMEORIGIN");
assertMetric("TheRegistrar", "false", "[OWNER]", "SUCCESS");
}
@Test
public void testWebPage_setsHtmlUtf8ContentType() {
action.run();
assertThat(response.getContentType()).isEqualTo(MediaType.HTML_UTF_8);
assertMetric("TheRegistrar", "false", "[OWNER]", "SUCCESS");
}
@Test
public void testWebPage_containsUserNickname() {
action.run();
assertThat(response.getPayload()).contains("marla.singer");
assertMetric("TheRegistrar", "false", "[OWNER]", "SUCCESS");
}
@Test
@ -116,6 +134,7 @@ public class ConsoleUiActionTest {
action.run();
assertThat(response.getPayload()).contains("Registrar Console");
assertThat(response.getPayload()).contains("reg-content-and-footer");
assertMetric("TheRegistrar", "false", "[OWNER]", "SUCCESS");
}
@Test
@ -131,6 +150,7 @@ public class ConsoleUiActionTest {
action.run();
assertThat(response.getPayload()).contains("<h1>You need permission</h1>");
assertThat(response.getPayload()).contains("not associated with Nomulus.");
assertMetric("<null>", "false", "[]", "FORBIDDEN");
}
@Test
@ -153,22 +173,25 @@ public class ConsoleUiActionTest {
@Test
public void testSettingClientId_notAllowed_showsNeedPermissionPage() {
action.paramClientId = Optional.of("OtherClientId");
when(registrarAccessor.getRegistrar("OtherClientId"))
// Behaves the same way if fakeRegistrar exists, but we don't have access to it
action.paramClientId = Optional.of("fakeRegistrar");
when(registrarAccessor.getRegistrar("fakeRegistrar"))
.thenThrow(new ForbiddenException("forbidden"));
action.run();
assertThat(response.getPayload()).contains("<h1>You need permission</h1>");
assertThat(response.getPayload()).contains("not associated with the registrar OtherClientId.");
assertThat(response.getPayload()).contains("not associated with the registrar fakeRegistrar.");
assertMetric("fakeRegistrar", "true", "[]", "FORBIDDEN");
}
@Test
public void testSettingClientId_allowed_showsRegistrarConsole() {
action.paramClientId = Optional.of("OtherClientId");
when(registrarAccessor.getRegistrar("OtherClientId"))
action.paramClientId = Optional.of("OtherRegistrar");
when(registrarAccessor.getRegistrar("OtherRegistrar"))
.thenReturn(loadRegistrar("TheRegistrar"));
action.run();
assertThat(response.getPayload()).contains("Registrar Console");
assertThat(response.getPayload()).contains("reg-content-and-footer");
assertMetric("OtherRegistrar", "true", "[OWNER, ADMIN]", "SUCCESS");
}
@Test
@ -177,5 +200,6 @@ public class ConsoleUiActionTest {
assertThat(response.getPayload()).contains("<option value=\"TheRegistrar\" selected>");
assertThat(response.getPayload()).contains("<option value=\"OtherRegistrar\">");
assertThat(response.getPayload()).contains("<option value=\"AdminRegistrar\">");
assertMetric("TheRegistrar", "false", "[OWNER]", "SUCCESS");
}
}

View file

@ -51,6 +51,7 @@ public class ContactSettingsTest extends RegistrarSettingsActionTestCase {
List<Map<String, ?>> results = (List<Map<String, ?>>) response.get("results");
assertThat(results.get(0).get("contacts"))
.isEqualTo(loadRegistrar(CLIENT_ID).toJsonMap().get("contacts"));
assertMetric(CLIENT_ID, "read", "[OWNER]", "SUCCESS");
}
@Test
@ -60,6 +61,7 @@ public class ContactSettingsTest extends RegistrarSettingsActionTestCase {
"id", CLIENT_ID,
"args", loadRegistrar(CLIENT_ID).toJsonMap()));
assertThat(response).containsEntry("status", "SUCCESS");
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test
@ -88,6 +90,7 @@ public class ContactSettingsTest extends RegistrarSettingsActionTestCase {
.setTypes(ImmutableList.of(RegistrarContact.Type.ADMIN))
.build();
assertThat(loadRegistrar(CLIENT_ID).getContacts()).containsExactly(newContact);
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test
@ -105,6 +108,7 @@ public class ContactSettingsTest extends RegistrarSettingsActionTestCase {
assertThat(response).containsEntry("status", "ERROR");
assertThat(response).containsEntry("message", "Must have at least one "
+ RegistrarContact.Type.ADMIN.getDisplayName() + " contact");
assertMetric(CLIENT_ID, "update", "[OWNER]", "ERROR: ContactRequirementException");
}
@Test
@ -131,6 +135,7 @@ public class ContactSettingsTest extends RegistrarSettingsActionTestCase {
assertThat(response).containsEntry("status", "ERROR");
assertThat(response).containsEntry("message", "Please provide a phone number for at least one "
+ RegistrarContact.Type.TECH.getDisplayName() + " contact");
assertMetric(CLIENT_ID, "update", "[OWNER]", "ERROR: ContactRequirementException");
}
@Test
@ -157,6 +162,7 @@ public class ContactSettingsTest extends RegistrarSettingsActionTestCase {
assertThat(response)
.containsEntry(
"message", "An abuse contact visible in domain WHOIS query must be designated");
assertMetric(CLIENT_ID, "update", "[OWNER]", "ERROR: ContactRequirementException");
}
@Test
@ -183,5 +189,6 @@ public class ContactSettingsTest extends RegistrarSettingsActionTestCase {
assertThat(response)
.containsEntry(
"message", "The abuse contact visible in domain WHOIS query must have a phone number");
assertMetric(CLIENT_ID, "update", "[OWNER]", "ERROR: ContactRequirementException");
}
}

View file

@ -62,6 +62,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
.url(SyncRegistrarsSheetAction.PATH)
.method("GET")
.header("Host", "backend.hostname"));
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test
@ -74,6 +75,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
"message",
"One email address (etphonehome@example.com) cannot be used for multiple contacts");
assertNoTasksEnqueued("sheet");
assertMetric(CLIENT_ID, "update", "[OWNER]", "ERROR: ContactRequirementException");
}
/**
@ -89,6 +91,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
"results", ImmutableList.of(),
"message", "forbidden test error");
assertNoTasksEnqueued("sheet");
assertMetric(CLIENT_ID, "read", "[]", "ERROR: ForbiddenException");
}
/** This is the default read test for the registrar settings actions. */
@ -100,6 +103,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
"status", "SUCCESS",
"message", "Success",
"results", asList(loadRegistrar(CLIENT_ID).toJsonMap()));
assertMetric(CLIENT_ID, "read", "[OWNER]", "SUCCESS");
}
@Test
@ -114,6 +118,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
"results", ImmutableList.of(),
"message", "This field is required.");
assertNoTasksEnqueued("sheet");
assertMetric(CLIENT_ID, "update", "[OWNER]", "ERROR: FormFieldException");
}
@Test
@ -128,6 +133,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
"results", ImmutableList.of(),
"message", "This field is required.");
assertNoTasksEnqueued("sheet");
assertMetric(CLIENT_ID, "update", "[OWNER]", "ERROR: FormFieldException");
}
@Test
@ -144,6 +150,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
"status", "SUCCESS",
"message", "Saved TheRegistrar",
"results", asList(loadRegistrar(CLIENT_ID).toJsonMap()));
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test
@ -158,6 +165,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
"results", ImmutableList.of(),
"message", "forbidden test error");
assertNoTasksEnqueued("sheet");
assertMetric(CLIENT_ID, "update", "[]", "ERROR: ForbiddenException");
}
@Test
@ -174,6 +182,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
"results", ImmutableList.of(),
"message", "Please enter a valid email address.");
assertNoTasksEnqueued("sheet");
assertMetric(CLIENT_ID, "update", "[OWNER]", "ERROR: FormFieldException");
}
@Test
@ -188,6 +197,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
"results", ImmutableList.of(),
"message", "Not a valid ISO date-time string.");
assertNoTasksEnqueued("sheet");
assertMetric(CLIENT_ID, "update", "[OWNER]", "ERROR: FormFieldException");
}
@Test
@ -204,6 +214,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
"results", ImmutableList.of(),
"message", "Please only use ASCII-US characters.");
assertNoTasksEnqueued("sheet");
assertMetric(CLIENT_ID, "update", "[OWNER]", "ERROR: FormFieldException");
}
private <T> void doTestUpdate(
@ -230,26 +241,31 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
public void testUpdate_premiumPriceAck() {
doTestUpdate(
Registrar::getPremiumPriceAckRequired, true, Registrar.Builder::setPremiumPriceAckRequired);
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test
public void testUpdate_whoisServer() {
doTestUpdate(Registrar::getWhoisServer, "new-whois.example", Registrar.Builder::setWhoisServer);
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test
public void testUpdate_phoneNumber() {
doTestUpdate(Registrar::getPhoneNumber, "+1.2345678900", Registrar.Builder::setPhoneNumber);
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test
public void testUpdate_faxNumber() {
doTestUpdate(Registrar::getFaxNumber, "+1.2345678900", Registrar.Builder::setFaxNumber);
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test
public void testUpdate_url() {
doTestUpdate(Registrar::getUrl, "new-url.example", Registrar.Builder::setUrl);
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test
@ -258,6 +274,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
Registrar::getIpAddressWhitelist,
ImmutableList.of(CidrAddressBlock.create("1.1.1.0/24")),
Registrar.Builder::setIpAddressWhitelist);
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test
@ -266,6 +283,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
Registrar::getClientCertificate,
CertificateSamples.SAMPLE_CERT,
(builder, s) -> builder.setClientCertificate(s, clock.nowUtc()));
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test
@ -274,6 +292,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
Registrar::getFailoverClientCertificate,
CertificateSamples.SAMPLE_CERT,
(builder, s) -> builder.setFailoverClientCertificate(s, clock.nowUtc()));
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test
@ -283,6 +302,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
Registrar::getAllowedTlds,
ImmutableSet.of("newtld"),
(builder, s) -> builder.setAllowedTlds(s));
assertMetric(CLIENT_ID, "update", "[ADMIN]", "SUCCESS");
}
@Test
@ -302,6 +322,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
"status", "ERROR",
"results", ImmutableList.of(),
"message", "Only admin can update allowed TLDs.");
assertMetric(CLIENT_ID, "update", "[OWNER]", "ERROR: ForbiddenException");
assertNoTasksEnqueued("sheet");
}
@ -323,6 +344,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
"status", "ERROR",
"results", ImmutableList.of(),
"message", "TLDs do not exist: invalidtld");
assertMetric(CLIENT_ID, "update", "[ADMIN]", "ERROR: IllegalArgumentException");
assertNoTasksEnqueued("sheet");
}
@ -343,6 +365,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
"status", "SUCCESS",
"message", "Saved TheRegistrar",
"results", asList(loadRegistrar(CLIENT_ID).toJsonMap()));
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test
@ -351,6 +374,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
Registrar::getLocalizedAddress,
loadRegistrar(CLIENT_ID).getLocalizedAddress().asBuilder().setCity("newCity").build(),
Registrar.Builder::setLocalizedAddress);
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test
@ -359,6 +383,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
Registrar::getLocalizedAddress,
loadRegistrar(CLIENT_ID).getLocalizedAddress().asBuilder().setCountryCode("GB").build(),
Registrar.Builder::setLocalizedAddress);
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test
@ -367,6 +392,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
Registrar::getLocalizedAddress,
loadRegistrar(CLIENT_ID).getLocalizedAddress().asBuilder().setState("NJ").build(),
Registrar.Builder::setLocalizedAddress);
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test
@ -379,6 +405,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
.setStreet(ImmutableList.of("new street"))
.build(),
Registrar.Builder::setLocalizedAddress);
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test
@ -387,6 +414,7 @@ public class RegistrarSettingsActionTest extends RegistrarSettingsActionTestCase
Registrar::getLocalizedAddress,
loadRegistrar(CLIENT_ID).getLocalizedAddress().asBuilder().setZip("new zip").build(),
Registrar.Builder::setLocalizedAddress);
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
private static String getLastUpdateTime() {

View file

@ -14,6 +14,7 @@
package google.registry.ui.server.registrar;
import static com.google.monitoring.metrics.contrib.LongMetricSubject.assertThat;
import static google.registry.config.RegistryConfig.getGSuiteOutgoingEmailAddress;
import static google.registry.config.RegistryConfig.getGSuiteOutgoingEmailDisplayName;
import static google.registry.security.JsonHttpTestUtils.createJsonPayload;
@ -53,6 +54,7 @@ import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.joda.time.DateTime;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.runner.RunWith;
@ -92,7 +94,7 @@ public class RegistrarSettingsActionTestCase {
// of updating allowed tld for registrar
createTlds("newtld");
disallowRegistrarAccess(CLIENT_ID, "newtld");
action.registrarAccessor = mock(AuthenticatedRegistrarAccessor.class);
action.registrarAccessor = null;
action.appEngineServiceUtils = appEngineServiceUtils;
when(appEngineServiceUtils.getCurrentVersionHostname("backend")).thenReturn("backend.hostname");
action.jsonActionRunner = new JsonActionRunner(
@ -103,6 +105,7 @@ public class RegistrarSettingsActionTestCase {
new SendEmailUtils(
getGSuiteOutgoingEmailAddress(), getGSuiteOutgoingEmailDisplayName(), emailService);
action.registryEnvironment = RegistryEnvironment.get();
action.registrarConsoleMetrics = new RegistrarConsoleMetrics();
action.authResult =
AuthResult.create(
AuthLevel.USER,
@ -117,10 +120,24 @@ public class RegistrarSettingsActionTestCase {
// We set the default to a user with access, as that's the most common test case. When we want
// to specifically check a user without access, we can switch user for that specific test.
setUserWithAccess();
RegistrarConsoleMetrics.settingsRequestMetric.reset();
}
@After
public void tearDown() throws Exception {
assertThat(RegistrarConsoleMetrics.settingsRequestMetric).hasNoOtherValues();
}
public void assertMetric(String clientId, String op, String roles, String status) {
assertThat(RegistrarConsoleMetrics.settingsRequestMetric)
.hasValueForLabels(1, clientId, op, roles, status);
RegistrarConsoleMetrics.settingsRequestMetric.reset(clientId, op, roles, status);
}
/** Sets registrarAccessor.getRegistrar to succeed for all AccessTypes. */
protected void setUserWithAccess() {
action.registrarAccessor = mock(AuthenticatedRegistrarAccessor.class);
when(action.registrarAccessor.getAllClientIdWithRoles())
.thenReturn(ImmutableSetMultimap.of(CLIENT_ID, OWNER));
when(action.registrarAccessor.getRegistrar(CLIENT_ID))
@ -129,6 +146,8 @@ public class RegistrarSettingsActionTestCase {
/** Sets registrarAccessor.getRegistrar to always fail. */
protected void setUserWithoutAccess() {
action.registrarAccessor = mock(AuthenticatedRegistrarAccessor.class);
when(action.registrarAccessor.getAllClientIdWithRoles()).thenReturn(ImmutableSetMultimap.of());
when(action.registrarAccessor.getRegistrar(CLIENT_ID))
.thenThrow(new ForbiddenException("forbidden test error"));
@ -138,7 +157,11 @@ public class RegistrarSettingsActionTestCase {
* Sets registrarAccessor.getAllClientIdWithRoles to return a map with admin role for CLIENT_ID
*/
protected void setUserAdmin() {
action.registrarAccessor = mock(AuthenticatedRegistrarAccessor.class);
when(action.registrarAccessor.getAllClientIdWithRoles())
.thenReturn(ImmutableSetMultimap.of(CLIENT_ID, ADMIN));
when(action.registrarAccessor.getRegistrar(CLIENT_ID))
.thenAnswer(x -> loadRegistrar(CLIENT_ID));
}
}

View file

@ -61,6 +61,7 @@ public class SecuritySettingsTest extends RegistrarSettingsActionTestCase {
assertThat(response).containsEntry("status", "SUCCESS");
assertThat(response).containsEntry("results", asList(modified.toJsonMap()));
assertThat(loadRegistrar(CLIENT_ID)).isEqualTo(modified);
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test
@ -73,6 +74,7 @@ public class SecuritySettingsTest extends RegistrarSettingsActionTestCase {
"args", reqJson));
assertThat(response).containsEntry("status", "ERROR");
assertThat(response).containsEntry("message", "Invalid X.509 PEM certificate");
assertMetric(CLIENT_ID, "update", "[OWNER]", "ERROR: FormFieldException");
}
@Test
@ -88,6 +90,7 @@ public class SecuritySettingsTest extends RegistrarSettingsActionTestCase {
assertThat(registrar.getClientCertificateHash()).isEqualTo(SAMPLE_CERT_HASH);
assertThat(registrar.getFailoverClientCertificate()).isNull();
assertThat(registrar.getFailoverClientCertificateHash()).isNull();
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test
@ -100,6 +103,7 @@ public class SecuritySettingsTest extends RegistrarSettingsActionTestCase {
Registrar registrar = loadRegistrar(CLIENT_ID);
assertThat(registrar.getFailoverClientCertificate()).isEqualTo(SAMPLE_CERT2);
assertThat(registrar.getFailoverClientCertificateHash()).isEqualTo(SAMPLE_CERT2_HASH);
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test
@ -122,6 +126,7 @@ public class SecuritySettingsTest extends RegistrarSettingsActionTestCase {
assertThat(registrar.getClientCertificateHash()).isEqualTo(SAMPLE_CERT_HASH);
assertThat(registrar.getFailoverClientCertificate()).isEqualTo(SAMPLE_CERT2);
assertThat(registrar.getFailoverClientCertificateHash()).isEqualTo(SAMPLE_CERT2_HASH);
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test

View file

@ -61,6 +61,7 @@ public class WhoisSettingsTest extends RegistrarSettingsActionTestCase {
assertThat(response.get("status")).isEqualTo("SUCCESS");
assertThat(response.get("results")).isEqualTo(asList(modified.toJsonMap()));
assertThat(loadRegistrar(CLIENT_ID)).isEqualTo(modified);
assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS");
}
@Test
@ -87,6 +88,7 @@ public class WhoisSettingsTest extends RegistrarSettingsActionTestCase {
assertThat(response.get("field")).isEqualTo("localizedAddress.state");
assertThat(response.get("message")).isEqualTo("Unknown US state code.");
assertThat(loadRegistrar(CLIENT_ID)).isNotEqualTo(modified);
assertMetric(CLIENT_ID, "update", "[OWNER]", "ERROR: FormFieldException");
}
@Test
@ -114,6 +116,7 @@ public class WhoisSettingsTest extends RegistrarSettingsActionTestCase {
assertThat((String) response.get("message"))
.contains("Number of characters (600) not in range");
assertThat(loadRegistrar(CLIENT_ID)).isNotEqualTo(modified);
assertMetric(CLIENT_ID, "update", "[OWNER]", "ERROR: FormFieldException");
}
@Test
@ -127,5 +130,6 @@ public class WhoisSettingsTest extends RegistrarSettingsActionTestCase {
assertThat(response.get("field")).isEqualTo("whoisServer");
assertThat(response.get("message")).isEqualTo("Not a valid hostname.");
assertThat(loadRegistrar(CLIENT_ID)).isNotEqualTo(modified);
assertMetric(CLIENT_ID, "update", "[OWNER]", "ERROR: FormFieldException");
}
}