Initial, easy changes to support later addition of RDAP metrics

I split this out to avoid having a giant CL that changes everything. The actual
metrics will follow later.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=174356874
This commit is contained in:
mountford 2017-11-02 11:39:25 -07:00 committed by jianglai
parent c126c05810
commit 5b8ee87ecc
13 changed files with 127 additions and 46 deletions

View file

@ -33,6 +33,7 @@ import com.googlecode.objectify.cmd.Query;
import google.registry.config.RegistryConfig.Config; import google.registry.config.RegistryConfig.Config;
import google.registry.model.EppResource; import google.registry.model.EppResource;
import google.registry.model.registrar.Registrar; import google.registry.model.registrar.Registrar;
import google.registry.rdap.RdapMetrics.EndpointType;
import google.registry.rdap.RdapSearchResults.IncompletenessWarningType; import google.registry.rdap.RdapSearchResults.IncompletenessWarningType;
import google.registry.request.Action; import google.registry.request.Action;
import google.registry.request.FullServletPath; import google.registry.request.FullServletPath;
@ -92,6 +93,9 @@ public abstract class RdapActionBase implements Runnable {
/** Returns a string like "domain name" or "nameserver", used for error strings. */ /** Returns a string like "domain name" or "nameserver", used for error strings. */
abstract String getHumanReadableObjectTypeName(); abstract String getHumanReadableObjectTypeName();
/** Returns the endpoint type used for recording metrics. */
abstract EndpointType getEndpointType();
/** Returns the servlet action path; used to extract the search string from the incoming path. */ /** Returns the servlet action path; used to extract the search string from the incoming path. */
abstract String getActionPath(); abstract String getActionPath();
@ -381,23 +385,24 @@ public abstract class RdapActionBase implements Runnable {
* the query could not check deletion status (due to Datastore limitations such as the * the query could not check deletion status (due to Datastore limitations such as the
* limit of one field queried for inequality, for instance), it may need to be set to true * limit of one field queried for inequality, for instance), it may need to be set to true
* even when not including deleted records * even when not including deleted records
* @return an {@link RdapResourcesAndIncompletenessWarningType} object containing the list of * @return an {@link RdapResultSet} object containing the list of
* resources and an incompleteness warning flag, which is set to MIGHT_BE_INCOMPLETE iff * resources and an incompleteness warning flag, which is set to MIGHT_BE_INCOMPLETE iff
* any resources were excluded due to lack of visibility, and the resulting list of * any resources were excluded due to lack of visibility, and the resulting list of
* resources is less than the maximum allowable, which indicates that we may not have * resources is less than the maximum allowable, which indicates that we may not have
* fetched enough resources * fetched enough resources
*/ */
<T extends EppResource> RdapResourcesAndIncompletenessWarningType<T> getMatchingResources( <T extends EppResource> RdapResultSet<T> getMatchingResources(
Query<T> query, boolean checkForVisibility, DateTime now) { Query<T> query, boolean checkForVisibility, DateTime now) {
Optional<String> desiredRegistrar = getDesiredRegistrar(); Optional<String> desiredRegistrar = getDesiredRegistrar();
if (desiredRegistrar.isPresent()) { if (desiredRegistrar.isPresent()) {
query = query.filter("currentSponsorClientId", desiredRegistrar.get()); query = query.filter("currentSponsorClientId", desiredRegistrar.get());
} }
if (!checkForVisibility) { if (!checkForVisibility) {
return RdapResourcesAndIncompletenessWarningType.create(query.list()); return RdapResultSet.create(query.list());
} }
// If we are including deleted resources, we need to check that we're authorized for each one. // If we are including deleted resources, we need to check that we're authorized for each one.
List<T> resources = new ArrayList<>(); List<T> resources = new ArrayList<>();
int numResourcesQueried = 0;
boolean someExcluded = false; boolean someExcluded = false;
for (T resource : query) { for (T resource : query) {
if (shouldBeVisible(resource, now)) { if (shouldBeVisible(resource, now)) {
@ -405,14 +410,16 @@ public abstract class RdapActionBase implements Runnable {
} else { } else {
someExcluded = true; someExcluded = true;
} }
numResourcesQueried++;
if (resources.size() > rdapResultSetMaxSize) { if (resources.size() > rdapResultSetMaxSize) {
break; break;
} }
} }
return RdapResourcesAndIncompletenessWarningType.create( return RdapResultSet.create(
resources, resources,
(someExcluded && (resources.size() < rdapResultSetMaxSize + 1)) (someExcluded && (resources.size() < rdapResultSetMaxSize + 1))
? IncompletenessWarningType.MIGHT_BE_INCOMPLETE ? IncompletenessWarningType.MIGHT_BE_INCOMPLETE
: IncompletenessWarningType.NONE); : IncompletenessWarningType.NONE,
numResourcesQueried);
} }
} }

View file

@ -18,6 +18,7 @@ import static google.registry.request.Action.Method.GET;
import static google.registry.request.Action.Method.HEAD; import static google.registry.request.Action.Method.HEAD;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import google.registry.rdap.RdapMetrics.EndpointType;
import google.registry.request.Action; import google.registry.request.Action;
import google.registry.request.HttpException.NotImplementedException; import google.registry.request.HttpException.NotImplementedException;
import google.registry.request.auth.Auth; import google.registry.request.auth.Auth;
@ -46,6 +47,11 @@ public class RdapAutnumAction extends RdapActionBase {
return "autnum"; return "autnum";
} }
@Override
public EndpointType getEndpointType() {
return EndpointType.AUTNUM;
}
@Override @Override
public String getActionPath() { public String getActionPath() {
return PATH; return PATH;

View file

@ -24,6 +24,7 @@ import com.google.common.collect.ImmutableMap;
import google.registry.flows.EppException; import google.registry.flows.EppException;
import google.registry.model.domain.DomainResource; import google.registry.model.domain.DomainResource;
import google.registry.rdap.RdapJsonFormatter.OutputDataType; import google.registry.rdap.RdapJsonFormatter.OutputDataType;
import google.registry.rdap.RdapMetrics.EndpointType;
import google.registry.request.Action; import google.registry.request.Action;
import google.registry.request.HttpException.BadRequestException; import google.registry.request.HttpException.BadRequestException;
import google.registry.request.HttpException.NotFoundException; import google.registry.request.HttpException.NotFoundException;
@ -56,6 +57,11 @@ public class RdapDomainAction extends RdapActionBase {
return PATH; return PATH;
} }
@Override
public EndpointType getEndpointType() {
return EndpointType.DOMAIN;
}
@Override @Override
public ImmutableMap<String, Object> getJsonObjectForResource( public ImmutableMap<String, Object> getJsonObjectForResource(
String pathSearchString, boolean isHeadRequest) { String pathSearchString, boolean isHeadRequest) {

View file

@ -34,6 +34,7 @@ import google.registry.model.domain.DomainResource;
import google.registry.model.host.HostResource; import google.registry.model.host.HostResource;
import google.registry.rdap.RdapJsonFormatter.BoilerplateType; import google.registry.rdap.RdapJsonFormatter.BoilerplateType;
import google.registry.rdap.RdapJsonFormatter.OutputDataType; import google.registry.rdap.RdapJsonFormatter.OutputDataType;
import google.registry.rdap.RdapMetrics.EndpointType;
import google.registry.rdap.RdapSearchResults.IncompletenessWarningType; import google.registry.rdap.RdapSearchResults.IncompletenessWarningType;
import google.registry.request.Action; import google.registry.request.Action;
import google.registry.request.HttpException.BadRequestException; import google.registry.request.HttpException.BadRequestException;
@ -88,6 +89,11 @@ public class RdapDomainSearchAction extends RdapActionBase {
return "domain search"; return "domain search";
} }
@Override
public EndpointType getEndpointType() {
return EndpointType.DOMAINS;
}
@Override @Override
public String getActionPath() { public String getActionPath() {
return PATH; return PATH;
@ -468,15 +474,10 @@ public class RdapDomainSearchAction extends RdapActionBase {
return makeSearchResults(domains, IncompletenessWarningType.NONE, now); return makeSearchResults(domains, IncompletenessWarningType.NONE, now);
} }
/** Output JSON from data in an {@link RdapResourcesAndIncompletenessWarningType} object. */ /** Output JSON from data in an {@link RdapResultSet} object. */
private RdapSearchResults makeSearchResults( private RdapSearchResults makeSearchResults(
RdapResourcesAndIncompletenessWarningType<DomainResource> RdapResultSet<DomainResource> resultSet, DateTime now) {
resourcesAndIncompletenessWarningType, return makeSearchResults(resultSet.resources(), resultSet.incompletenessWarningType(), now);
DateTime now) {
return makeSearchResults(
resourcesAndIncompletenessWarningType.resources(),
resourcesAndIncompletenessWarningType.incompletenessWarningType(),
now);
} }
/** /**

View file

@ -27,6 +27,7 @@ import google.registry.model.contact.ContactResource;
import google.registry.model.domain.DesignatedContact; import google.registry.model.domain.DesignatedContact;
import google.registry.model.registrar.Registrar; import google.registry.model.registrar.Registrar;
import google.registry.rdap.RdapJsonFormatter.OutputDataType; import google.registry.rdap.RdapJsonFormatter.OutputDataType;
import google.registry.rdap.RdapMetrics.EndpointType;
import google.registry.request.Action; import google.registry.request.Action;
import google.registry.request.HttpException.BadRequestException; import google.registry.request.HttpException.BadRequestException;
import google.registry.request.HttpException.NotFoundException; import google.registry.request.HttpException.NotFoundException;
@ -66,6 +67,11 @@ public class RdapEntityAction extends RdapActionBase {
return "entity"; return "entity";
} }
@Override
public EndpointType getEndpointType() {
return EndpointType.ENTITY;
}
@Override @Override
public String getActionPath() { public String getActionPath() {
return PATH; return PATH;

View file

@ -31,6 +31,7 @@ import google.registry.model.domain.DesignatedContact;
import google.registry.model.registrar.Registrar; import google.registry.model.registrar.Registrar;
import google.registry.rdap.RdapJsonFormatter.BoilerplateType; import google.registry.rdap.RdapJsonFormatter.BoilerplateType;
import google.registry.rdap.RdapJsonFormatter.OutputDataType; import google.registry.rdap.RdapJsonFormatter.OutputDataType;
import google.registry.rdap.RdapMetrics.EndpointType;
import google.registry.rdap.RdapSearchResults.IncompletenessWarningType; import google.registry.rdap.RdapSearchResults.IncompletenessWarningType;
import google.registry.request.Action; import google.registry.request.Action;
import google.registry.request.HttpException.BadRequestException; import google.registry.request.HttpException.BadRequestException;
@ -76,6 +77,11 @@ public class RdapEntitySearchAction extends RdapActionBase {
return "entity search"; return "entity search";
} }
@Override
public EndpointType getEndpointType() {
return EndpointType.ENTITIES;
}
@Override @Override
public String getActionPath() { public String getActionPath() {
return PATH; return PATH;
@ -169,12 +175,10 @@ public class RdapEntitySearchAction extends RdapActionBase {
// Get the contact matches and return the results, fetching an additional contact to detect // Get the contact matches and return the results, fetching an additional contact to detect
// truncation. Don't bother searching for contacts by name if the request would not be able to // truncation. Don't bother searching for contacts by name if the request would not be able to
// see any names anyway. // see any names anyway.
RdapResourcesAndIncompletenessWarningType<ContactResource> RdapResultSet<ContactResource> resultSet;
resourcesAndIncompletenessWarningType;
RdapAuthorization authorization = getAuthorization(); RdapAuthorization authorization = getAuthorization();
if (authorization.role() == RdapAuthorization.Role.PUBLIC) { if (authorization.role() == RdapAuthorization.Role.PUBLIC) {
resourcesAndIncompletenessWarningType = resultSet = RdapResultSet.create(ImmutableList.of());
RdapResourcesAndIncompletenessWarningType.create(ImmutableList.of());
} else { } else {
Query<ContactResource> query = Query<ContactResource> query =
queryItems( queryItems(
@ -186,9 +190,9 @@ public class RdapEntitySearchAction extends RdapActionBase {
if (authorization.role() != RdapAuthorization.Role.ADMINISTRATOR) { if (authorization.role() != RdapAuthorization.Role.ADMINISTRATOR) {
query = query.filter("currentSponsorClientId in", authorization.clientIds()); query = query.filter("currentSponsorClientId in", authorization.clientIds());
} }
resourcesAndIncompletenessWarningType = getMatchingResources(query, false, now); resultSet = getMatchingResources(query, false, now);
} }
return makeSearchResults(resourcesAndIncompletenessWarningType, registrars, now); return makeSearchResults(resultSet, registrars, now);
} }
/** /**
@ -264,15 +268,9 @@ public class RdapEntitySearchAction extends RdapActionBase {
* arguments. * arguments.
*/ */
private RdapSearchResults makeSearchResults( private RdapSearchResults makeSearchResults(
RdapResourcesAndIncompletenessWarningType<ContactResource> RdapResultSet<ContactResource> resultSet, List<Registrar> registrars, DateTime now) {
resourcesAndIncompletenessWarningType,
List<Registrar> registrars,
DateTime now) {
return makeSearchResults( return makeSearchResults(
resourcesAndIncompletenessWarningType.resources(), resultSet.resources(), resultSet.incompletenessWarningType(), registrars, now);
resourcesAndIncompletenessWarningType.incompletenessWarningType(),
registrars,
now);
} }
/** /**

View file

@ -20,6 +20,7 @@ import static google.registry.request.Action.Method.HEAD;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import google.registry.rdap.RdapJsonFormatter.BoilerplateType; import google.registry.rdap.RdapJsonFormatter.BoilerplateType;
import google.registry.rdap.RdapMetrics.EndpointType;
import google.registry.request.Action; import google.registry.request.Action;
import google.registry.request.auth.Auth; import google.registry.request.auth.Auth;
import google.registry.util.Clock; import google.registry.util.Clock;
@ -44,6 +45,11 @@ public class RdapHelpAction extends RdapActionBase {
return "help"; return "help";
} }
@Override
public EndpointType getEndpointType() {
return EndpointType.HELP;
}
@Override @Override
public String getActionPath() { public String getActionPath() {
return PATH; return PATH;

View file

@ -18,6 +18,7 @@ import static google.registry.request.Action.Method.GET;
import static google.registry.request.Action.Method.HEAD; import static google.registry.request.Action.Method.HEAD;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import google.registry.rdap.RdapMetrics.EndpointType;
import google.registry.request.Action; import google.registry.request.Action;
import google.registry.request.HttpException.NotImplementedException; import google.registry.request.HttpException.NotImplementedException;
import google.registry.request.auth.Auth; import google.registry.request.auth.Auth;
@ -46,6 +47,11 @@ public class RdapIpAction extends RdapActionBase {
return "ip"; return "ip";
} }
@Override
public EndpointType getEndpointType() {
return EndpointType.IP;
}
@Override @Override
public String getActionPath() { public String getActionPath() {
return PATH; return PATH;

View file

@ -0,0 +1,31 @@
// Copyright 2017 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.rdap;
/** RDAP Instrumentation. */
public class RdapMetrics {
enum EndpointType {
AUTNUM,
DOMAIN,
DOMAINS,
ENTITY,
ENTITIES,
HELP,
IP,
NAMESERVER,
NAMESERVERS
}
}

View file

@ -24,6 +24,7 @@ import com.google.common.collect.ImmutableMap;
import google.registry.flows.EppException; import google.registry.flows.EppException;
import google.registry.model.host.HostResource; import google.registry.model.host.HostResource;
import google.registry.rdap.RdapJsonFormatter.OutputDataType; import google.registry.rdap.RdapJsonFormatter.OutputDataType;
import google.registry.rdap.RdapMetrics.EndpointType;
import google.registry.request.Action; import google.registry.request.Action;
import google.registry.request.HttpException.BadRequestException; import google.registry.request.HttpException.BadRequestException;
import google.registry.request.HttpException.NotFoundException; import google.registry.request.HttpException.NotFoundException;
@ -51,6 +52,11 @@ public class RdapNameserverAction extends RdapActionBase {
return "nameserver"; return "nameserver";
} }
@Override
public EndpointType getEndpointType() {
return EndpointType.NAMESERVER;
}
@Override @Override
public String getActionPath() { public String getActionPath() {
return PATH; return PATH;

View file

@ -29,6 +29,7 @@ import google.registry.model.domain.DomainResource;
import google.registry.model.host.HostResource; import google.registry.model.host.HostResource;
import google.registry.rdap.RdapJsonFormatter.BoilerplateType; import google.registry.rdap.RdapJsonFormatter.BoilerplateType;
import google.registry.rdap.RdapJsonFormatter.OutputDataType; import google.registry.rdap.RdapJsonFormatter.OutputDataType;
import google.registry.rdap.RdapMetrics.EndpointType;
import google.registry.rdap.RdapSearchResults.IncompletenessWarningType; import google.registry.rdap.RdapSearchResults.IncompletenessWarningType;
import google.registry.request.Action; import google.registry.request.Action;
import google.registry.request.HttpException.BadRequestException; import google.registry.request.HttpException.BadRequestException;
@ -75,6 +76,11 @@ public class RdapNameserverSearchAction extends RdapActionBase {
return "nameserver search"; return "nameserver search";
} }
@Override
public EndpointType getEndpointType() {
return EndpointType.NAMESERVERS;
}
@Override @Override
public String getActionPath() { public String getActionPath() {
return PATH; return PATH;
@ -244,17 +250,9 @@ public class RdapNameserverSearchAction extends RdapActionBase {
return makeSearchResults(getMatchingResources(query, shouldIncludeDeleted(), now), now); return makeSearchResults(getMatchingResources(query, shouldIncludeDeleted(), now), now);
} }
/** /** Output JSON for a lists of hosts contained in an {@link RdapResultSet}. */
* Output JSON for a lists of hosts contained in an {@link private RdapSearchResults makeSearchResults(RdapResultSet<HostResource> resultSet, DateTime now) {
* RdapResourcesAndIncompletenessWarningType}. return makeSearchResults(resultSet.resources(), resultSet.incompletenessWarningType(), now);
*/
private RdapSearchResults makeSearchResults(
RdapResourcesAndIncompletenessWarningType<HostResource> resourcesAndIncompletenessWarningType,
DateTime now) {
return makeSearchResults(
resourcesAndIncompletenessWarningType.resources(),
resourcesAndIncompletenessWarningType.incompletenessWarningType(),
now);
} }
/** Output JSON for a list of hosts. */ /** Output JSON for a list of hosts. */

View file

@ -20,17 +20,18 @@ import google.registry.rdap.RdapSearchResults.IncompletenessWarningType;
import java.util.List; import java.util.List;
@AutoValue @AutoValue
abstract class RdapResourcesAndIncompletenessWarningType<T extends EppResource> { abstract class RdapResultSet<T extends EppResource> {
static <S extends EppResource> RdapResourcesAndIncompletenessWarningType<S> create( static <S extends EppResource> RdapResultSet<S> create(List<S> resources) {
List<S> resources) { return create(resources, IncompletenessWarningType.NONE, resources.size());
return create(resources, IncompletenessWarningType.NONE);
} }
static <S extends EppResource> RdapResourcesAndIncompletenessWarningType<S> create( static <S extends EppResource> RdapResultSet<S> create(
List<S> resources, IncompletenessWarningType incompletenessWarningType) { List<S> resources,
return new AutoValue_RdapResourcesAndIncompletenessWarningType<>( IncompletenessWarningType incompletenessWarningType,
resources, incompletenessWarningType); int numResourcesRetrieved) {
return new AutoValue_RdapResultSet<>(
resources, incompletenessWarningType, numResourcesRetrieved);
} }
/** List of EPP resources. */ /** List of EPP resources. */
@ -38,5 +39,8 @@ abstract class RdapResourcesAndIncompletenessWarningType<T extends EppResource>
/** Type of warning to display regarding possible incomplete data. */ /** Type of warning to display regarding possible incomplete data. */
abstract IncompletenessWarningType incompletenessWarningType(); abstract IncompletenessWarningType incompletenessWarningType();
/** Number of resources retrieved from the database in the process of assembling the data set. */
abstract int numResourcesRetrieved();
} }

View file

@ -25,6 +25,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import google.registry.model.ofy.Ofy; import google.registry.model.ofy.Ofy;
import google.registry.rdap.RdapJsonFormatter.BoilerplateType; import google.registry.rdap.RdapJsonFormatter.BoilerplateType;
import google.registry.rdap.RdapMetrics.EndpointType;
import google.registry.testing.AppEngineRule; import google.registry.testing.AppEngineRule;
import google.registry.testing.FakeClock; import google.registry.testing.FakeClock;
import google.registry.testing.FakeResponse; import google.registry.testing.FakeResponse;
@ -64,6 +65,11 @@ public class RdapActionBaseTest {
return "human-readable string"; return "human-readable string";
} }
@Override
public EndpointType getEndpointType() {
return EndpointType.HELP;
}
@Override @Override
public String getActionPath() { public String getActionPath() {
return PATH; return PATH;