diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingConfig.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingConfig.java
index 9d0fd94b2..561edb228 100644
--- a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingConfig.java
+++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingConfig.java
@@ -41,6 +41,7 @@ class LoggingConfig {
private static final String RESOURCE_TYPE_TAG = "resourceType";
private static final String ENHANCERS_TAG = "enhancers";
private static final String USE_INHERITED_CONTEXT = "useInheritedContext";
+ private static final String AUTO_POPULATE_METADATA = "autoPopulateMetadata";
public LoggingConfig(String className) {
this.className = className;
@@ -76,6 +77,14 @@ Formatter getFormatter() {
return getFormatterProperty(FORMATTER_TAG, new SimpleFormatter());
}
+ Boolean getAutoPopulateMetadata() {
+ String flag = getProperty(AUTO_POPULATE_METADATA);
+ if (flag != null) {
+ return Boolean.parseBoolean(flag);
+ }
+ return null;
+ }
+
MonitoredResource getMonitoredResource(String projectId) {
String resourceType = getProperty(RESOURCE_TYPE_TAG, "");
return MonitoredResourceUtil.getResource(projectId, resourceType);
diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingHandler.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingHandler.java
index db18fe1a1..b644421da 100644
--- a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingHandler.java
+++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingHandler.java
@@ -17,6 +17,7 @@
package com.google.cloud.logging;
import static com.google.common.base.MoreObjects.firstNonNull;
+import static com.google.common.base.Preconditions.checkNotNull;
import com.google.cloud.MonitoredResource;
import com.google.cloud.logging.Logging.WriteOption;
@@ -25,6 +26,7 @@
import com.google.common.collect.Iterables;
import java.time.Instant;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@@ -109,6 +111,9 @@
* else "global").
*
{@code com.google.cloud.logging.LoggingHandler.autoPopulateMetadata} is a boolean flag that
+ * opts-out the population of the log entries metadata before the logs are sent to Cloud
+ * Logging (defaults to {@code true}).
*
*
* To add a {@code LoggingHandler} to an existing {@link Logger} and be sure to avoid infinite
@@ -139,6 +144,8 @@ public class LoggingHandler extends Handler {
private volatile Level flushLevel;
+ private volatile Boolean autoPopulateMetadata;
+
private WriteOption[] defaultWriteOptions;
/** Creates an handler that publishes messages to Cloud Logging. */
@@ -196,7 +203,10 @@ public LoggingHandler(
}
/**
- * Creates a handler that publishes messages to Cloud Logging.
+ * Creates a handler that publishes messages to Cloud Logging. Auto-population of the logs
+ * metadata can be opted-out in {@code options} argument or in the configuration file. At least
+ * one flag {@link LoggingOptions} or {@link LoggingConfig} has to be explicitly set to {@code
+ * false} in order to opt-out the metadata auto-population.
*
* @param log the name of the log to which log entries are written
* @param options options for the Cloud Logging service
@@ -222,14 +232,18 @@ public LoggingHandler(
setLevel(level);
baseLevel = level.equals(Level.ALL) ? Level.FINEST : level;
flushLevel = config.getFlushLevel();
+ Boolean f1 = options.getAutoPopulateMetadata();
+ Boolean f2 = config.getAutoPopulateMetadata();
+ autoPopulateMetadata = isTrueOrNull(f1) && isTrueOrNull(f2);
String logName = log != null ? log : config.getLogName();
-
MonitoredResource resource =
firstNonNull(
monitoredResource, config.getMonitoredResource(loggingOptions.getProjectId()));
List writeOptions = new ArrayList();
writeOptions.add(WriteOption.logName(logName));
- writeOptions.add(WriteOption.resource(resource));
+ if (resource != null) {
+ writeOptions.add(WriteOption.resource(resource));
+ }
writeOptions.add(
WriteOption.labels(
ImmutableMap.of(
@@ -240,6 +254,7 @@ public LoggingHandler(
if (destination != null) {
writeOptions.add(WriteOption.destination(destination));
}
+ writeOptions.add(WriteOption.autoPopulateMetadata(autoPopulateMetadata));
defaultWriteOptions = Iterables.toArray(writeOptions, WriteOption.class);
getLogging().setFlushSeverity(severityFor(flushLevel));
@@ -365,6 +380,28 @@ public Synchronicity getSynchronicity() {
return getLogging().getWriteSynchronicity();
}
+ /**
+ * Sets the metadata auto population flag.
+ */
+ public void setAutoPopulateMetadata(Boolean value) {
+ checkNotNull(value);
+ this.autoPopulateMetadata = value;
+ List writeOptions = Arrays.asList(defaultWriteOptions);
+ for (int i = 0; i < writeOptions.size(); i++) {
+ if (writeOptions.get(i).getOptionType() == WriteOption.OptionType.AUTO_POPULATE_METADATA) {
+ writeOptions.remove(i);
+ break;
+ }
+ }
+ writeOptions.add(WriteOption.autoPopulateMetadata(value));
+ defaultWriteOptions = Iterables.toArray(writeOptions, WriteOption.class);
+ }
+
+ /** Gets the metadata auto population flag. */
+ public Boolean getAutoPopulateMetadata() {
+ return this.autoPopulateMetadata;
+ }
+
/**
* Adds the provided {@code LoggingHandler} to {@code logger}. Use this method to register Cloud
* Logging handlers instead of {@link Logger#addHandler(Handler)} to avoid infinite recursion when
@@ -417,4 +454,8 @@ private Logging getLogging() {
}
return logging;
}
+
+ private static boolean isTrueOrNull(Boolean b) {
+ return b == null || b == Boolean.TRUE;
+ }
}
diff --git a/google-cloud-logging/src/test/java/com/google/cloud/logging/LoggingHandlerTest.java b/google-cloud-logging/src/test/java/com/google/cloud/logging/LoggingHandlerTest.java
index af4be4cce..6fc2f2fb5 100644
--- a/google-cloud-logging/src/test/java/com/google/cloud/logging/LoggingHandlerTest.java
+++ b/google-cloud-logging/src/test/java/com/google/cloud/logging/LoggingHandlerTest.java
@@ -19,6 +19,7 @@
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reset;
import static org.easymock.EasyMock.verify;
import com.google.cloud.MonitoredResource;
@@ -28,7 +29,6 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.util.Collections;
-import java.util.Map;
import java.util.logging.ErrorManager;
import java.util.logging.Filter;
import java.util.logging.Formatter;
@@ -41,6 +41,7 @@
import org.junit.Before;
import org.junit.Test;
+@SuppressWarnings("deprecation")
public class LoggingHandlerTest {
private static final String LOG_NAME = "java.log";
@@ -156,18 +157,6 @@ public class LoggingHandlerTest {
.setTimestamp(123456789L)
.build();
- private static final String CONFIG_NAMESPACE = "com.google.cloud.logging.LoggingHandler";
- private static final ImmutableMap CONFIG_MAP =
- ImmutableMap.builder()
- .put("log", "testLogName")
- .put("level", "ALL")
- .put("filter", "com.google.cloud.logging.LoggingHandlerTest$TestFilter")
- .put("formatter", "com.google.cloud.logging.LoggingHandlerTest$TestFormatter")
- .put("flushLevel", "CRITICAL")
- .put("enhancers", "com.google.cloud.logging.LoggingHandlerTest$TestLoggingEnhancer")
- .put("resourceType", "testResourceType")
- .put("synchronicity", "SYNC")
- .build();
private static final ImmutableMap BASE_SEVERITY_MAP =
ImmutableMap.of(
"levelName", Level.INFO.getName(), "levelValue", String.valueOf(Level.INFO.intValue()));
@@ -175,22 +164,10 @@ public class LoggingHandlerTest {
new WriteOption[] {
WriteOption.logName(LOG_NAME),
WriteOption.resource(DEFAULT_RESOURCE),
- WriteOption.labels(BASE_SEVERITY_MAP)
+ WriteOption.labels(BASE_SEVERITY_MAP),
+ WriteOption.autoPopulateMetadata(false),
};
- private static byte[] renderConfig(Map config) {
- StringBuilder str = new StringBuilder();
- for (Map.Entry entry : config.entrySet()) {
- str.append(CONFIG_NAMESPACE)
- .append('.')
- .append(entry.getKey())
- .append('=')
- .append(entry.getValue())
- .append(System.lineSeparator());
- }
- return str.toString().getBytes();
- }
-
private Logging logging;
private LoggingOptions options;
@@ -219,7 +196,10 @@ public void enhanceLogEntry(LogEntry.Builder builder) {
@Before
public void setUp() {
logging = EasyMock.createMock(Logging.class);
- options = EasyMock.createStrictMock(LoggingOptions.class);
+ options = EasyMock.createMock(LoggingOptions.class);
+ expect(options.getProjectId()).andStubReturn(PROJECT);
+ expect(options.getService()).andStubReturn(logging);
+ expect(options.getAutoPopulateMetadata()).andStubReturn(Boolean.FALSE);
}
@After
@@ -235,8 +215,6 @@ private static LogRecord newLogRecord(Level level, String message) {
@Test
public void testPublishLevels() {
- expect(options.getProjectId()).andReturn(PROJECT).anyTimes();
- expect(options.getService()).andReturn(logging);
logging.setFlushSeverity(Severity.ERROR);
expectLastCall().once();
logging.setWriteSynchronicity(Synchronicity.ASYNC);
@@ -290,8 +268,6 @@ public void testPublishLevels() {
@Test
public void testPublishCustomResource() {
- expect(options.getProjectId()).andReturn(PROJECT).anyTimes();
- expect(options.getService()).andReturn(logging);
logging.setFlushSeverity(Severity.ERROR);
expectLastCall().once();
logging.setWriteSynchronicity(Synchronicity.ASYNC);
@@ -301,7 +277,8 @@ public void testPublishCustomResource() {
ImmutableList.of(FINEST_ENTRY),
WriteOption.logName(LOG_NAME),
WriteOption.resource(resource),
- WriteOption.labels(BASE_SEVERITY_MAP));
+ WriteOption.labels(BASE_SEVERITY_MAP),
+ WriteOption.autoPopulateMetadata(false));
expectLastCall().once();
replay(options, logging);
Handler handler = new LoggingHandler(LOG_NAME, options, resource);
@@ -334,8 +311,6 @@ public void testPublishCustomResourceWithProject() {
@Test
public void testPublishKubernetesContainerResource() {
- expect(options.getProjectId()).andReturn(PROJECT).anyTimes();
- expect(options.getService()).andReturn(logging);
logging.setFlushSeverity(Severity.ERROR);
expectLastCall().once();
logging.setWriteSynchronicity(Synchronicity.ASYNC);
@@ -358,7 +333,8 @@ public void testPublishKubernetesContainerResource() {
ImmutableList.of(FINEST_ENTRY),
WriteOption.logName(LOG_NAME),
WriteOption.resource(resource),
- WriteOption.labels(BASE_SEVERITY_MAP));
+ WriteOption.labels(BASE_SEVERITY_MAP),
+ WriteOption.autoPopulateMetadata(false));
expectLastCall().once();
replay(options, logging);
Handler handler = new LoggingHandler(LOG_NAME, options, resource);
@@ -369,18 +345,11 @@ public void testPublishKubernetesContainerResource() {
@Test
public void testEnhancedLogEntry() {
- expect(options.getProjectId()).andReturn(PROJECT).anyTimes();
- expect(options.getService()).andReturn(logging);
- MonitoredResource resource = MonitoredResource.of("custom", ImmutableMap.of());
logging.setFlushSeverity(Severity.ERROR);
expectLastCall().once();
logging.setWriteSynchronicity(Synchronicity.ASYNC);
expectLastCall().once();
- logging.write(
- ImmutableList.of(FINEST_ENHANCED_ENTRY),
- WriteOption.logName(LOG_NAME),
- WriteOption.resource(resource),
- WriteOption.labels(BASE_SEVERITY_MAP));
+ logging.write(ImmutableList.of(FINEST_ENHANCED_ENTRY), DEFAULT_OPTIONS);
expectLastCall().once();
replay(options, logging);
LoggingEnhancer enhancer =
@@ -391,7 +360,8 @@ public void enhanceLogEntry(Builder builder) {
}
};
Handler handler =
- new LoggingHandler(LOG_NAME, options, resource, Collections.singletonList(enhancer));
+ new LoggingHandler(
+ LOG_NAME, options, DEFAULT_RESOURCE, Collections.singletonList(enhancer));
handler.setLevel(Level.ALL);
handler.setFormatter(new TestFormatter());
handler.publish(newLogRecord(Level.FINEST, MESSAGE));
@@ -399,24 +369,18 @@ public void enhanceLogEntry(Builder builder) {
@Test
public void testTraceEnhancedLogEntry() {
- expect(options.getProjectId()).andReturn(PROJECT).anyTimes();
- expect(options.getService()).andReturn(logging);
- MonitoredResource resource = MonitoredResource.of("custom", ImmutableMap.of());
logging.setFlushSeverity(Severity.ERROR);
expectLastCall().once();
logging.setWriteSynchronicity(Synchronicity.ASYNC);
expectLastCall().once();
- logging.write(
- ImmutableList.of(TRACE_ENTRY),
- WriteOption.logName(LOG_NAME),
- WriteOption.resource(resource),
- WriteOption.labels(BASE_SEVERITY_MAP));
+ logging.write(ImmutableList.of(TRACE_ENTRY), DEFAULT_OPTIONS);
expectLastCall().once();
replay(options, logging);
LoggingEnhancer enhancer = new TraceLoggingEnhancer();
TraceLoggingEnhancer.setCurrentTraceId("projects/projectId/traces/traceId");
Handler handler =
- new LoggingHandler(LOG_NAME, options, resource, Collections.singletonList(enhancer));
+ new LoggingHandler(
+ LOG_NAME, options, DEFAULT_RESOURCE, Collections.singletonList(enhancer));
handler.setLevel(Level.ALL);
handler.setFormatter(new TestFormatter());
handler.publish(newLogRecord(Level.FINEST, MESSAGE));
@@ -424,8 +388,6 @@ public void testTraceEnhancedLogEntry() {
@Test
public void testReportWriteError() {
- expect(options.getProjectId()).andReturn(PROJECT).anyTimes();
- expect(options.getService()).andReturn(logging);
RuntimeException ex = new RuntimeException();
logging.setFlushSeverity(Severity.ERROR);
expectLastCall().once();
@@ -448,8 +410,6 @@ public void testReportWriteError() {
@Test
public void testReportFlushError() {
- expect(options.getProjectId()).andReturn(PROJECT).anyTimes();
- expect(options.getService()).andReturn(logging);
RuntimeException ex = new RuntimeException();
logging.setFlushSeverity(Severity.ERROR);
expectLastCall().once();
@@ -475,8 +435,6 @@ public void testReportFlushError() {
@Test
public void testReportFormatError() {
- expect(options.getProjectId()).andReturn(PROJECT).anyTimes();
- expect(options.getService()).andReturn(logging);
logging.setFlushSeverity(Severity.ERROR);
expectLastCall().once();
logging.setWriteSynchronicity(Synchronicity.ASYNC);
@@ -501,8 +459,6 @@ public void testReportFormatError() {
// BUG(1795): rewrite this test when flush actually works.
// @Test
public void testFlushLevel() {
- expect(options.getProjectId()).andReturn(PROJECT).anyTimes();
- expect(options.getService()).andReturn(logging);
logging.setFlushSeverity(Severity.ERROR);
expectLastCall().once();
logging.setWriteSynchronicity(Synchronicity.ASYNC);
@@ -529,8 +485,6 @@ public void testFlushLevel() {
@Test
public void testSyncWrite() {
- expect(options.getProjectId()).andReturn(PROJECT).anyTimes();
- expect(options.getService()).andReturn(logging);
LogEntry entry =
LogEntry.newBuilder(Payload.StringPayload.of(MESSAGE))
.setSeverity(Severity.DEBUG)
@@ -560,8 +514,6 @@ public void testSyncWrite() {
@Test
public void testAddHandler() {
- expect(options.getProjectId()).andReturn(PROJECT).anyTimes();
- expect(options.getService()).andReturn(logging);
logging.setFlushSeverity(Severity.ERROR);
expectLastCall().once();
logging.setWriteSynchronicity(Synchronicity.ASYNC);
@@ -586,8 +538,6 @@ public void close() {
@Test
public void testClose() throws Exception {
- expect(options.getProjectId()).andReturn(PROJECT).anyTimes();
- expect(options.getService()).andReturn(logging);
logging.setFlushSeverity(Severity.ERROR);
expectLastCall().once();
logging.setWriteSynchronicity(Synchronicity.ASYNC);
@@ -602,13 +552,35 @@ public void testClose() throws Exception {
handler.setFormatter(new TestFormatter());
handler.publish(newLogRecord(Level.FINEST, MESSAGE));
handler.close();
- handler.close();
+ }
+
+ @Test
+ public void testAutoPopulationEnabled() {
+ reset(options);
+ options = EasyMock.createMock(LoggingOptions.class);
+ expect(options.getProjectId()).andStubReturn(PROJECT);
+ expect(options.getService()).andStubReturn(logging);
+ expect(options.getAutoPopulateMetadata()).andStubReturn(true);
+ logging.setFlushSeverity(Severity.ERROR);
+ expectLastCall().andVoid();
+ logging.setWriteSynchronicity(Synchronicity.ASYNC);
+ expectLastCall().andVoid();
+ logging.write(
+ ImmutableList.of(INFO_ENTRY),
+ WriteOption.logName(LOG_NAME),
+ WriteOption.resource(DEFAULT_RESOURCE),
+ WriteOption.labels(BASE_SEVERITY_MAP),
+ WriteOption.autoPopulateMetadata(true));
+ expectLastCall().once();
+ replay(options, logging);
+ Handler handler = new LoggingHandler(LOG_NAME, options, DEFAULT_RESOURCE);
+ handler.setLevel(Level.ALL);
+ handler.setFormatter(new TestFormatter());
+ handler.publish(newLogRecord(Level.INFO, MESSAGE));
}
private void testPublishCustomResourceWithDestination(
LogEntry entry, LogDestinationName destination) {
- expect(options.getProjectId()).andReturn(PROJECT).anyTimes();
- expect(options.getService()).andReturn(logging);
logging.setFlushSeverity(Severity.ERROR);
expectLastCall().once();
logging.setWriteSynchronicity(Synchronicity.ASYNC);
@@ -619,7 +591,8 @@ private void testPublishCustomResourceWithDestination(
WriteOption.logName(LOG_NAME),
WriteOption.resource(resource),
WriteOption.labels(BASE_SEVERITY_MAP),
- WriteOption.destination(destination));
+ WriteOption.destination(destination),
+ WriteOption.autoPopulateMetadata(false));
expectLastCall().once();
replay(options, logging);
Handler handler = new LoggingHandler(LOG_NAME, options, resource, null, destination);