mirror of
https://github.com/google/nomulus.git
synced 2025-05-13 07:57:13 +02:00
Make GCP proxy log in a Stackdriver logging compliant format
When not running locally, the logging formatter is set to convert the log record to a single-line JSON string that Stackdriver logging agent running in GKE will pick up and parse correctly. Also removed redundant logging handler in the proxy frontend connection. They have two problems: 1) it is possible to leak PII when all frontend traffic is logged, such as client IPs. Even though this is less of a concern because the GCP TCP proxy load balancer masquerade source IPs. 2) We are only logging the HTTP request/response that the frontend connection is sending to/receiving from the backend connection, but the backend already has its own logging handler to log the same message that it gets from/sends to the GAE app, so the logging in the frontend connection does not really give extra information. Logging of some potential PII information such as the source IP of a proxied connection are also removed. Thirdly, added a k8s autoscaling object that scales the containers based on CPU load. The default target load is 80%. This, in connection with GKE cluster VM autoscaling, means that when traffic is low, we'll only have one VM running one container of the proxy. Fixes a bug where the MetricsComponent generates a separate ProxyConfig that does not call parse method on the command line args passed, resulting default Environment always being used in constructing the metric reporter. Lastly a little bit of cleaning of the MOE config script, no newlines are necessary as the BUILD are formatted after string substitution. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=188029019
This commit is contained in:
parent
09e9823b9d
commit
84eab90000
12 changed files with 317 additions and 51 deletions
|
@ -28,9 +28,9 @@ import com.google.api.services.cloudkms.v1.CloudKMS;
|
|||
import com.google.api.services.cloudkms.v1.model.DecryptRequest;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.monitoring.metrics.MetricReporter;
|
||||
import dagger.Component;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
@ -42,11 +42,12 @@ import google.registry.proxy.WhoisProtocolModule.WhoisProtocol;
|
|||
import google.registry.util.Clock;
|
||||
import google.registry.util.FormattingLogger;
|
||||
import google.registry.util.SystemClock;
|
||||
import io.netty.handler.logging.LogLevel;
|
||||
import io.netty.handler.logging.LoggingHandler;
|
||||
import io.netty.handler.ssl.OpenSsl;
|
||||
import io.netty.handler.ssl.SslProvider;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
@ -83,28 +84,27 @@ public class ProxyModule {
|
|||
boolean log;
|
||||
|
||||
/**
|
||||
* Enable FINE level logging.
|
||||
* Configure logging parameters depending on the {@link Environment}.
|
||||
*
|
||||
* <p>Set the loggers log level to {@code FINE}, and also add a console handler that actually
|
||||
* output {@code FINE} level messages to stdout. The handler filters out all non FINE level log
|
||||
* record to avoid double logging. Log records at level higher than FINE (e. g. INFO) will be
|
||||
* handled at parent loggers. Note that {@code FINE} level corresponds to {@code DEBUG} level in
|
||||
* Netty.
|
||||
* <p>If not running locally, set the logging formatter to {@link GcpJsonFormatter} that formats
|
||||
* the log in a single-line json string printed to {@code STDOUT} or {@code STDERR}, will be
|
||||
* correctly parsed by Stackdriver logging.
|
||||
*
|
||||
* @see <a href="https://cloud.google.com/kubernetes-engine/docs/how-to/logging#best_practices">
|
||||
* Logging Best Practices</a>
|
||||
*/
|
||||
private static void enableDebugLevelLogging() {
|
||||
ImmutableList<Logger> parentLoggers =
|
||||
ImmutableList.of(
|
||||
Logger.getLogger("io.netty.handler.logging.LoggingHandler"),
|
||||
// Parent of all FormattingLoggers, so that we do not have to configure each
|
||||
// FormattingLogger individually.
|
||||
Logger.getLogger("google.registry.proxy"));
|
||||
for (Logger logger : parentLoggers) {
|
||||
logger.setLevel(Level.FINE);
|
||||
Handler handler = new ConsoleHandler();
|
||||
handler.setFilter(record -> Objects.equals(record.getLevel(), Level.FINE));
|
||||
handler.setLevel(Level.FINE);
|
||||
logger.addHandler(handler);
|
||||
private void configureLogging() {
|
||||
// Remove all other handlers on the root logger to avoid double logging.
|
||||
Logger rootLogger = Logger.getLogger("");
|
||||
Arrays.asList(rootLogger.getHandlers()).forEach(h -> rootLogger.removeHandler(h));
|
||||
|
||||
// If running on in a non-local environment, use GCP JSON formater.
|
||||
Handler rootHandler = new ConsoleHandler();
|
||||
rootHandler.setLevel(Level.FINE);
|
||||
if (env != Environment.LOCAL) {
|
||||
rootHandler.setFormatter(new GcpJsonFormatter());
|
||||
}
|
||||
rootLogger.addHandler(rootHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -122,10 +122,7 @@ public class ProxyModule {
|
|||
jCommander.usage();
|
||||
throw e;
|
||||
}
|
||||
if (log) {
|
||||
logger.info("DEBUG LOGGING: ENABLED");
|
||||
enableDebugLevelLogging();
|
||||
}
|
||||
configureLogging();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -158,11 +155,23 @@ public class ProxyModule {
|
|||
return env;
|
||||
}
|
||||
|
||||
/** Shared logging handler, set to default DEBUG(FINE) level. */
|
||||
/**
|
||||
* Provides shared logging handler.
|
||||
*
|
||||
* <p>The {@link LoggingHandler} records logs at {@code LogLevel.DEBUG} (internal Netty log
|
||||
* level), which corresponds to {@code Level.FINE} (JUL log level). It uses a JUL logger called
|
||||
* {@code io.netty.handler.logging.LoggingHandler} to actually process the logs. This logger is
|
||||
* set to {@code Level.FINE} if {@code --log} parameter is passed, so that it does not filter out
|
||||
* logs that the {@link LoggingHandler} captures. Otherwise the logs are silently ignored because
|
||||
* the default logger level is {@code Level.INFO}.
|
||||
*/
|
||||
@Singleton
|
||||
@Provides
|
||||
static LoggingHandler provideLoggingHandler() {
|
||||
return new LoggingHandler();
|
||||
LoggingHandler provideLoggingHandler() {
|
||||
if (log) {
|
||||
Logger.getLogger("io.netty.handler.logging.LoggingHandler").setLevel(Level.FINE);
|
||||
}
|
||||
return new LoggingHandler(LogLevel.DEBUG);
|
||||
}
|
||||
|
||||
@Singleton
|
||||
|
@ -308,10 +317,14 @@ public class ProxyModule {
|
|||
HttpsRelayProtocolModule.class,
|
||||
WhoisProtocolModule.class,
|
||||
EppProtocolModule.class,
|
||||
HealthCheckProtocolModule.class
|
||||
HealthCheckProtocolModule.class,
|
||||
MetricsModule.class
|
||||
}
|
||||
)
|
||||
interface ProxyComponent {
|
||||
|
||||
ImmutableMap<Integer, FrontendProtocol> portToProtocolMap();
|
||||
|
||||
MetricReporter metricReporter();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue