Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: configure opt-out metada auto-population for JUL handler #807

Merged
merged 3 commits into from
Dec 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -109,6 +111,9 @@
* else "global").
* <li>{@code com.google.cloud.logging.Synchronicity} the synchronicity of the write method to use
* to write logs to the Cloud Logging service (defaults to {@link Synchronicity#ASYNC}).
* <li>{@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}).
* </ul>
*
* <p>To add a {@code LoggingHandler} to an existing {@link Logger} and be sure to avoid infinite
Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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
Expand All @@ -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<WriteOption> writeOptions = new ArrayList<WriteOption>();
writeOptions.add(WriteOption.logName(logName));
writeOptions.add(WriteOption.resource(resource));
if (resource != null) {
writeOptions.add(WriteOption.resource(resource));
}
writeOptions.add(
WriteOption.labels(
ImmutableMap.of(
Expand All @@ -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));
Expand Down Expand Up @@ -365,6 +380,28 @@ public Synchronicity getSynchronicity() {
return getLogging().getWriteSynchronicity();
}

/**
* Sets the metadata auto population flag.
*/
public void setAutoPopulateMetadata(Boolean value) {
minherz marked this conversation as resolved.
Show resolved Hide resolved
checkNotNull(value);
this.autoPopulateMetadata = value;
List<WriteOption> 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
Expand Down Expand Up @@ -417,4 +454,8 @@ private Logging getLogging() {
}
return logging;
}

private static boolean isTrueOrNull(Boolean b) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Such methods ideally should accept additional variable with default value to be returned in case if checked parameter is null.

Copy link
Contributor Author

@minherz minherz Dec 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not "getter". This method is used to answer the question whether the parameter is null or Boolean.TRUE.

Copy link
Contributor

@losalex losalex Dec 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I was kinda suggesting to make it "getter", so it can be reused later if needed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is "getter":

public Boolean getAutoPopulateMetadata() {
return this.autoPopulateMetadata;
}

The above is a service method used at initialization only to enforce opt-out if one of the original sources of the configuration: LoggingOptions or config file has it set to FALSE. However, if the configuration is omitted then it should be interpreted as "allowed" according to the design requirement: to allow by default.

return b == null || b == Boolean.TRUE;
}
}
Loading