2121import com .google .cloud .MonitoredResource ;
2222import com .google .cloud .logging .Logging .WriteOption ;
2323import com .google .common .collect .ImmutableList ;
24- import com .google .common .collect .ImmutableMap ;
24+
25+ import java .util .ArrayList ;
26+ import java .util .Collections ;
2527import java .util .LinkedList ;
2628import java .util .List ;
2729import java .util .logging .ErrorManager ;
7678 * <li>{@code com.google.cloud.logging.LoggingHandler.flushLevel} specifies the flush log level.
7779 * When a log with this level is published, logs are transmitted to the Stackdriver Logging
7880 * service (defaults to {@link LoggingLevel#ERROR}).
81+ * <li>{@code com.google.cloud.logging.LoggingHandler.enhancers} specifies a comma separated list
82+ * of {@link Enhancer} classes. This handler will call each enhancer list whenever it builds
83+ * a {@link MonitoredResource} or {@link LogEntry} instance (defaults to empty list).
84+ * <li>{@code com.google.cloud.logging.LoggingHandler.resourceType} the type name to use when
85+ * creating the default {@link MonitoredResource} (defaults to "global").
7986 * </ul>
8087 *
8188 * <p>To add a {@code LoggingHandler} to an existing {@link Logger} and be sure to avoid infinite
@@ -99,6 +106,7 @@ public class LoggingHandler extends Handler {
99106 private volatile Logging logging ;
100107 private Level flushLevel ;
101108 private long flushSize ;
109+ private final List <Enhancer > enhancers ;
102110
103111 /**
104112 * Creates an handler that publishes messages to Stackdriver Logging.
@@ -131,9 +139,30 @@ public LoggingHandler(String log, LoggingOptions options) {
131139 *
132140 * @param log the name of the log to which log entries are written
133141 * @param options options for the Stackdriver Logging service
134- * @param monitoredResource the monitored resource to which log entries refer
142+ * @param monitoredResource the monitored resource to which log entries refer. If it is null
143+ * then a default resource is created based on the project ID. When creating a default resource, if
144+ * any {@link Enhancer} instances are configured and then each
145+ * {@link Enhancer#enhanceMonitoredResource(com.google.cloud.MonitoredResource.Builder)} method
146+ * is called before building the default resource.
135147 */
136148 public LoggingHandler (String log , LoggingOptions options , MonitoredResource monitoredResource ) {
149+ this (log , options , monitoredResource ,null );
150+ }
151+
152+ /**
153+ * Creates a handler that publishes messages to Stackdriver Logging.
154+ *
155+ * @param log the name of the log to which log entries are written
156+ * @param options options for the Stackdriver Logging service
157+ * @param monitoredResource the monitored resource to which log entries refer. If it is null
158+ * then a default resource is created based on the project ID. When creating a default resource, if
159+ * any {@link Enhancer} instances are configured and then each
160+ * {@link Enhancer#enhanceMonitoredResource(com.google.cloud.MonitoredResource.Builder)} method
161+ * is called before building the default resource.
162+ * @param enhancers List of {@link Enhancer} instances used to enhance any {@link MonitoredResource}
163+ * or {@link LogEntry} instances built by this handler.
164+ */
165+ public LoggingHandler (String log , LoggingOptions options , MonitoredResource monitoredResource , List <Enhancer > enhancers ) {
137166 LogConfigHelper helper = new LogConfigHelper ();
138167 String className = getClass ().getName ();
139168 this .options = options != null ? options : LoggingOptions .getDefaultInstance ();
@@ -143,7 +172,9 @@ public LoggingHandler(String log, LoggingOptions options, MonitoredResource moni
143172 setFilter (helper .getFilterProperty (className + ".filter" , null ));
144173 setFormatter (helper .getFormatterProperty (className + ".formatter" , new SimpleFormatter ()));
145174 String logName = firstNonNull (log , helper .getProperty (className + ".log" , "java.log" ));
146- MonitoredResource resource = firstNonNull (monitoredResource , getDefaultResource ());
175+ this .enhancers = enhancers != null ? enhancers : helper .getEnhancerProperty (className + ".enhancers" );
176+ String resourceType = helper .getProperty (className + ".resourceType" , "global" );
177+ MonitoredResource resource = monitoredResource != null ? monitoredResource : getDefaultResource (resourceType );
147178 writeOptions = new WriteOption []{WriteOption .logName (logName ), WriteOption .resource (resource )};
148179 }
149180
@@ -178,8 +209,13 @@ private static boolean hasLoggingHandler(Logger logger) {
178209 return false ;
179210 }
180211
181- private MonitoredResource getDefaultResource () {
182- return MonitoredResource .of ("global" , ImmutableMap .of ("project_id" , options .getProjectId ()));
212+ private MonitoredResource getDefaultResource (String resourceType ) {
213+ MonitoredResource .Builder builder = MonitoredResource .newBuilder (resourceType );
214+ builder .addLabel ("project_id" , options .getProjectId ());
215+ for (Enhancer enhancer : enhancers ) {
216+ enhancer .enhanceMonitoredResource (builder );
217+ }
218+ return builder .build ();
183219 }
184220
185221 private static class LogConfigHelper {
@@ -237,6 +273,24 @@ Formatter getFormatterProperty(String name, Formatter defaultValue) {
237273 }
238274 return defaultValue ;
239275 }
276+
277+ List <Enhancer > getEnhancerProperty (String name ) {
278+ String list = manager .getProperty (name );
279+ try {
280+ List <Enhancer > enhancers = new ArrayList <>();
281+ if (list != null ) {
282+ String [] items = list .split ("," );
283+ for (String e_name : items ) {
284+ Class <? extends Enhancer > clz = (Class <? extends Enhancer >) ClassLoader .getSystemClassLoader ().loadClass (e_name );
285+ enhancers .add ((Enhancer ) clz .newInstance ());
286+ }
287+ }
288+ return enhancers ;
289+ } catch (Exception ex ) {
290+ // If we cannot create the enhancers we fall back to the default
291+ }
292+ return Collections .emptyList ();
293+ }
240294 }
241295
242296 /**
@@ -311,12 +365,16 @@ private LogEntry entryFor(LogRecord record) {
311365 .addLabel ("levelValue" , String .valueOf (level .intValue ()))
312366 .setTimestamp (record .getMillis ())
313367 .setSeverity (severityFor (level ));
368+
369+ for (Enhancer enhancer : enhancers ) {
370+ enhancer .enhanceLogEntry (builder , record );
371+ }
314372 enhanceLogEntry (builder , record );
315373 return builder .build ();
316374 }
317375
376+ @ Deprecated
318377 protected void enhanceLogEntry (LogEntry .Builder builder , LogRecord record ) {
319- // no-op in this class
320378 }
321379
322380 private static Severity severityFor (Level level ) {
@@ -430,4 +488,14 @@ public synchronized long setFlushSize(long flushSize) {
430488 public static void addHandler (Logger logger , LoggingHandler handler ) {
431489 logger .addHandler (handler );
432490 }
491+
492+ /**
493+ * A Log Enhancer.
494+ * May be used to enhance the {@link MonitoredResource} and/or the {@link LogEntry}
495+ */
496+ interface Enhancer {
497+ void enhanceMonitoredResource (MonitoredResource .Builder builder );
498+ void enhanceLogEntry (LogEntry .Builder builder , LogRecord record );
499+ }
500+
433501}
0 commit comments