Skip to content

Commit

Permalink
google-cloud-logging-logback: Allow user to specify custom LoggingOpt…
Browse files Browse the repository at this point in the history
…ions (#4729)

google-cloud-logging-logback: #3215 allow user to specify custom LoggingOptions
  • Loading branch information
olavloite authored Apr 2, 2019
1 parent de136c6 commit 4cd6272
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ See [Logback filters](https://logback.qos.ch/manual/filters.html#thresholdFilter
<level>INFO</level>
</filter>
<log>application.log</log> <!-- Optional : default java.log -->
<!-- Optional : will use the default credentials of the environment if this property is not set -->
<credentialsFile>/path/to/credentials.json</credentialsFile>
<enhancer>com.example.enhancers.TestLoggingEnhancer</enhancer> <!-- Optional -->
<enhancer>com.example.enhancers.AnotherEnhancer</enhancer> <!-- Optional -->
<flushLevel>WARN</flushLevel> <!-- Optional : default ERROR -->
Expand Down Expand Up @@ -88,6 +90,7 @@ Authentication
See the [Authentication](https://github.com/googleapis/google-cloud-java#authentication)
section in the base directory's README.

You can also specify custom credentials by setting the optional property credentialsFile in your configuration file.

Limitations
-----------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import ch.qos.logback.core.UnsynchronizedAppenderBase;
import ch.qos.logback.core.util.Loader;
import com.google.api.core.InternalApi;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.cloud.MonitoredResource;
import com.google.cloud.logging.LogEntry;
import com.google.cloud.logging.Logging;
Expand All @@ -32,6 +33,9 @@
import com.google.cloud.logging.MonitoredResourceUtil;
import com.google.cloud.logging.Payload;
import com.google.cloud.logging.Severity;
import com.google.common.base.Strings;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
Expand All @@ -55,6 +59,8 @@
* Standard, GCE and GKE, defaults to "global". See <a
* href="https://cloud.google.com/logging/docs/api/v2/resource-list">supported resource
* types</a>
* <li>&lt;credentialsFile&gt;/path/to/credentials/file&lt;/credentialsFile&gt; (Optional,
* defaults to the default credentials of the environment)
* <li>(Optional) add custom labels to log entries using {@link LoggingEnhancer} classes.
* <li>&lt;enhancer&gt;com.example.enhancer1&lt;/enhancer&gt;
* <li>&lt;enhancer&gt;com.example.enhancer2&lt;/enhancer&gt;
Expand All @@ -67,13 +73,15 @@ public class LoggingAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
private static final String LEVEL_VALUE_KEY = "levelValue";

private volatile Logging logging;
private LoggingOptions loggingOptions;
private List<LoggingEnhancer> loggingEnhancers;
private List<LoggingEventEnhancer> loggingEventEnhancers;
private WriteOption[] defaultWriteOptions;

private Level flushLevel;
private String log;
private String resourceType;
private String credentialsFile;
private Set<String> enhancerClassNames = new HashSet<>();
private Set<String> loggingEventEnhancerClassNames = new HashSet<>();

Expand Down Expand Up @@ -111,6 +119,17 @@ public void setResourceType(String resourceType) {
this.resourceType = resourceType;
}

/**
* Sets the credentials file to use to create the {@link LoggingOptions}. The credentials returned
* by {@link GoogleCredentials#getApplicationDefault()} will be used if no custom credentials file
* has been set.
*
* @param credentialsFile The credentials file to use.
*/
public void setCredentialsFile(String credentialsFile) {
this.credentialsFile = credentialsFile;
}

/** Add extra labels using classes that implement {@link LoggingEnhancer}. */
public void addEnhancer(String enhancerClassName) {
this.enhancerClassNames.add(enhancerClassName);
Expand Down Expand Up @@ -186,7 +205,7 @@ public synchronized void start() {
}

String getProjectId() {
return LoggingOptions.getDefaultInstance().getProjectId();
return getLoggingOptions().getProjectId();
}

@Override
Expand All @@ -212,13 +231,37 @@ Logging getLogging() {
if (logging == null) {
synchronized (this) {
if (logging == null) {
logging = LoggingOptions.getDefaultInstance().getService();
logging = getLoggingOptions().getService();
}
}
}
return logging;
}

/** Gets the {@link LoggingOptions} to use for this {@link LoggingAppender}. */
LoggingOptions getLoggingOptions() {
if (loggingOptions == null) {
if (Strings.isNullOrEmpty(credentialsFile)) {
loggingOptions = LoggingOptions.getDefaultInstance();
} else {
try {
loggingOptions =
LoggingOptions.newBuilder()
.setCredentials(
GoogleCredentials.fromStream(new FileInputStream(credentialsFile)))
.build();
} catch (IOException e) {
throw new RuntimeException(
String.format(
"Could not read credentials file %s. Please verify that the file exists and is a valid Google credentials file.",
credentialsFile),
e);
}
}
}
return loggingOptions;
}

private LogEntry logEntryFor(ILoggingEvent e) {
StringBuilder payload = new StringBuilder(e.getFormattedMessage()).append('\n');
writeStack(e.getThrowableProxy(), "", payload);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.fail;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.filter.ThresholdFilter;
Expand All @@ -31,6 +32,7 @@
import com.google.cloud.logging.LogEntry;
import com.google.cloud.logging.Logging;
import com.google.cloud.logging.Logging.WriteOption;
import com.google.cloud.logging.LoggingOptions;
import com.google.cloud.logging.Payload.StringPayload;
import com.google.cloud.logging.Severity;
import com.google.common.collect.ImmutableMap;
Expand Down Expand Up @@ -211,6 +213,32 @@ public void testMdcValuesAreConvertedToLabels() {
assertThat(capturedArgument.getValue().iterator().next()).isEqualTo(logEntry);
}

@Test
public void testCreateLoggingOptions() {
// Try to build LoggingOptions with custom credentials.
final String nonExistentFile = "/path/to/non/existent/file";
LoggingAppender appender = new LoggingAppender();
appender.setCredentialsFile(nonExistentFile);
try {
appender.getLoggingOptions();
fail("Expected exception");
} catch (Exception e) {
assertThat(e.getMessage().contains(nonExistentFile));
}
// Try to build LoggingOptions with default credentials.
LoggingOptions defaultOptions = null;
try {
defaultOptions = LoggingOptions.getDefaultInstance();
} catch (Exception e) {
// Could not build a default LoggingOptions instance.
}
if (defaultOptions != null) {
appender = new LoggingAppender();
LoggingOptions options = appender.getLoggingOptions();
assertThat(options).isEqualTo(defaultOptions);
}
}

private LoggingEvent createLoggingEvent(Level level, long timestamp) {
LoggingEvent loggingEvent = new LoggingEvent();
loggingEvent.setMessage("this is a test");
Expand Down

0 comments on commit 4cd6272

Please sign in to comment.