2323import ch .qos .logback .core .UnsynchronizedAppenderBase ;
2424import ch .qos .logback .core .util .Loader ;
2525import com .google .api .core .InternalApi ;
26+ import com .google .auth .oauth2 .GoogleCredentials ;
2627import com .google .cloud .MonitoredResource ;
2728import com .google .cloud .logging .LogEntry ;
2829import com .google .cloud .logging .Logging ;
3233import com .google .cloud .logging .MonitoredResourceUtil ;
3334import com .google .cloud .logging .Payload ;
3435import com .google .cloud .logging .Severity ;
36+ import com .google .common .base .Strings ;
37+ import java .io .FileInputStream ;
38+ import java .io .IOException ;
3539import java .util .ArrayList ;
3640import java .util .Collections ;
3741import java .util .HashSet ;
5559 * Standard, GCE and GKE, defaults to "global". See <a
5660 * href="https://cloud.google.com/logging/docs/api/v2/resource-list">supported resource
5761 * types</a>
62+ * <li><credentialsFile>/path/to/credentials/file</credentialsFile> (Optional,
63+ * defaults to the default credentials of the environment)
5864 * <li>(Optional) add custom labels to log entries using {@link LoggingEnhancer} classes.
5965 * <li><enhancer>com.example.enhancer1</enhancer>
6066 * <li><enhancer>com.example.enhancer2</enhancer>
@@ -67,13 +73,15 @@ public class LoggingAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
6773 private static final String LEVEL_VALUE_KEY = "levelValue" ;
6874
6975 private volatile Logging logging ;
76+ private LoggingOptions loggingOptions ;
7077 private List <LoggingEnhancer > loggingEnhancers ;
7178 private List <LoggingEventEnhancer > loggingEventEnhancers ;
7279 private WriteOption [] defaultWriteOptions ;
7380
7481 private Level flushLevel ;
7582 private String log ;
7683 private String resourceType ;
84+ private String credentialsFile ;
7785 private Set <String > enhancerClassNames = new HashSet <>();
7886 private Set <String > loggingEventEnhancerClassNames = new HashSet <>();
7987
@@ -111,6 +119,17 @@ public void setResourceType(String resourceType) {
111119 this .resourceType = resourceType ;
112120 }
113121
122+ /**
123+ * Sets the credentials file to use to create the {@link LoggingOptions}. The credentials returned
124+ * by {@link GoogleCredentials#getApplicationDefault()} will be used if no custom credentials file
125+ * has been set.
126+ *
127+ * @param credentialsFile The credentials file to use.
128+ */
129+ public void setCredentialsFile (String credentialsFile ) {
130+ this .credentialsFile = credentialsFile ;
131+ }
132+
114133 /** Add extra labels using classes that implement {@link LoggingEnhancer}. */
115134 public void addEnhancer (String enhancerClassName ) {
116135 this .enhancerClassNames .add (enhancerClassName );
@@ -186,7 +205,7 @@ public synchronized void start() {
186205 }
187206
188207 String getProjectId () {
189- return LoggingOptions . getDefaultInstance ().getProjectId ();
208+ return getLoggingOptions ().getProjectId ();
190209 }
191210
192211 @ Override
@@ -212,13 +231,37 @@ Logging getLogging() {
212231 if (logging == null ) {
213232 synchronized (this ) {
214233 if (logging == null ) {
215- logging = LoggingOptions . getDefaultInstance ().getService ();
234+ logging = getLoggingOptions ().getService ();
216235 }
217236 }
218237 }
219238 return logging ;
220239 }
221240
241+ /** Gets the {@link LoggingOptions} to use for this {@link LoggingAppender}. */
242+ LoggingOptions getLoggingOptions () {
243+ if (loggingOptions == null ) {
244+ if (Strings .isNullOrEmpty (credentialsFile )) {
245+ loggingOptions = LoggingOptions .getDefaultInstance ();
246+ } else {
247+ try {
248+ loggingOptions =
249+ LoggingOptions .newBuilder ()
250+ .setCredentials (
251+ GoogleCredentials .fromStream (new FileInputStream (credentialsFile )))
252+ .build ();
253+ } catch (IOException e ) {
254+ throw new RuntimeException (
255+ String .format (
256+ "Could not read credentials file %s. Please verify that the file exists and is a valid Google credentials file." ,
257+ credentialsFile ),
258+ e );
259+ }
260+ }
261+ }
262+ return loggingOptions ;
263+ }
264+
222265 private LogEntry logEntryFor (ILoggingEvent e ) {
223266 StringBuilder payload = new StringBuilder (e .getFormattedMessage ()).append ('\n' );
224267 writeStack (e .getThrowableProxy (), "" , payload );
0 commit comments