Move FlowRunner ICANN reporting logging to new FlowReporter

Since this reporting is getting more complicated (see b/36599833), it'll
be better to have a dedicated class to encapsulate it, which also lets us
keep the tests separate and focus FlowRunner more on its core purpose of
actually running the flow.

Note that this doesn't move the legacy log statement logging because that
specifically must be logged from the FlowRunner.run() method to preserve
the existing log signature matching in our ICANN activity reporting query.
(The new statement is designed to be robust to moves like this since it
doesn't use the logging callsite to match log lines, and it's not in use
yet anyway.)

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=153762008
This commit is contained in:
nickfelt 2017-04-20 15:04:26 -07:00 committed by Ben McIlwain
parent 89b3e9c55b
commit 12f267292a
4 changed files with 228 additions and 102 deletions

View file

@ -15,26 +15,22 @@
package google.registry.flows;
import static com.google.common.base.Throwables.getStackTraceAsString;
import static com.google.common.io.BaseEncoding.base64;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.xml.XmlTransformer.prettyPrint;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.googlecode.objectify.Work;
import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.DryRun;
import google.registry.flows.FlowModule.InputXml;
import google.registry.flows.FlowModule.Superuser;
import google.registry.flows.FlowModule.Transactional;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.model.eppcommon.Trid;
import google.registry.model.eppoutput.EppOutput;
import google.registry.monitoring.whitebox.EppMetric;
import google.registry.util.FormattingLogger;
import javax.inject.Inject;
import javax.inject.Provider;
import org.json.simple.JSONValue;
/** Run a flow, either transactionally or not, with logging and retrying as needed. */
public class FlowRunner {
@ -44,13 +40,6 @@ public class FlowRunner {
// JSON log line below instead, or change this one to be for human consumption only.
private static final String COMMAND_LOG_FORMAT = "EPP Command" + Strings.repeat("\n\t%s", 7);
/**
* Log signature used by reporting pipelines to extract matching log lines.
*
* <p><b>WARNING:<b/> DO NOT CHANGE this value unless you want to break reporting.
*/
private static final String REPORTING_LOG_SIGNATURE = "EPP-REPORTING-LOG-SIGNATURE";
private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass();
@Inject @ClientId String clientId;
@ -64,12 +53,12 @@ public class FlowRunner {
@Inject @Transactional boolean isTransactional;
@Inject SessionMetadata sessionMetadata;
@Inject Trid trid;
@Inject FlowReporter flowReporter;
@Inject FlowRunner() {}
/** Runs the EPP flow, and records metrics on the given builder. */
public EppOutput run(final EppMetric.Builder eppMetricBuilder) throws EppException {
String prettyXml = prettyPrint(inputXmlBytes);
String xmlBase64 = base64().encode(inputXmlBytes);
// This log line is very fragile since it's used for ICANN reporting - DO NOT CHANGE.
// New data to be logged should be added only to the JSON log statement below.
// TODO(b/20725722): remove this log statement entirely once we've transitioned to using the
@ -84,17 +73,8 @@ public class FlowRunner {
eppRequestSource,
isDryRun ? "DRY_RUN" : "LIVE",
isSuperuser ? "SUPERUSER" : "NORMAL");
// WARNING: This JSON log statement is parsed by reporting pipelines - be careful when changing.
// It should be safe to add new keys, but be very cautious in changing existing keys.
logger.infofmt(
"%s: %s",
REPORTING_LOG_SIGNATURE,
JSONValue.toJSONString(ImmutableMap.<String, Object>of(
"trid", trid.getServerTransactionId(),
"clientId", clientId,
"xml", prettyXml,
"xmlBytes", xmlBase64,
"icannActivityReportField", extractActivityReportField(flowClass))));
// Record information about this flow to the GAE request logs for reporting purposes.
flowReporter.recordToLogs();
eppMetricBuilder.setCommandNameFromFlow(flowClass.getSimpleName());
if (!isTransactional) {
eppMetricBuilder.incrementAttempts();
@ -134,16 +114,4 @@ public class FlowRunner {
this.output = output;
}
}
/**
* Returns the ICANN activity report field for the given flow class, or the empty string if no
* activity report field specification is found.
*/
private static final String extractActivityReportField(Class<? extends Flow> flowClass) {
ReportingSpec reportingSpec = flowClass.getAnnotation(ReportingSpec.class);
if (reportingSpec != null) {
return reportingSpec.value().getFieldName();
}
return "";
}
}