diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/GaeFlexLoggingEnhancer.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/GaeFlexLoggingEnhancer.java
new file mode 100644
index 000000000000..b4c80e288007
--- /dev/null
+++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/GaeFlexLoggingEnhancer.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.logging;
+
+import java.util.logging.LogRecord;
+
+import com.google.cloud.MonitoredResource.Builder;
+
+/**
+ * A Logging {@link Enhancer} that enhances the logging for the 
+ * GAE Flex environment. This enhancer can
+ * be configured in a logging.properties file with:
+ * 
+ * <pre>
+ * handlers=com.google.cloud.logging.LoggingHandler
+ * com.google.cloud.logging.LoggingHandler.log=gaeflex.log
+ * com.google.cloud.logging.LoggingHandler.resourceType=gae_app
+ * com.google.cloud.logging.LoggingHandler.enhancers=com.google.cloud.logging.GaeFlexLoggingEnhancer
+ * com.google.cloud.logging.LoggingHandler.formatter = java.util.logging.SimpleFormatter
+ * java.util.logging.SimpleFormatter.format=%3$s: %5$s%6$s
+ * </pre>
+ *
+ */
+public class GaeFlexLoggingEnhancer implements LoggingHandler.Enhancer {
+
+  private static final ThreadLocal<String> traceId = new ThreadLocal<>();
+
+  private final String gaeInstanceId;
+
+  /**
+   * Set the Trace ID associated with any logging done by the current thread.
+   * 
+   * @param id The traceID
+   */
+  public static void setCurrentTraceId(String id) {
+    traceId.set(id);
+  }
+
+  /**
+   * Get the Trace ID associated with any logging done by the current thread.
+   * 
+   * @return id The traceID
+   */
+  public static String getCurrentTraceId() {
+    return traceId.get();
+  }
+
+  public GaeFlexLoggingEnhancer() {
+    gaeInstanceId = System.getenv("GAE_INSTANCE"); // Are we running on a GAE instance?
+  }
+
+  @Override
+  public void enhanceMonitoredResource(Builder builder) {
+    if (gaeInstanceId != null) {
+      if (System.getenv("GAE_SERVICE") != null) {
+        builder.addLabel("module_id", System.getenv("GAE_SERVICE"));
+      }
+      if (System.getenv("GAE_VERSION") != null) {
+        builder.addLabel("version_id", System.getenv("GAE_VERSION"));
+      }
+    }
+  }
+
+  @Override
+  public void enhanceLogEntry(com.google.cloud.logging.LogEntry.Builder builder, LogRecord record) {
+    if (gaeInstanceId != null) {
+      builder.addLabel("appengine.googleapis.com/instance_name", gaeInstanceId);
+    }
+    String traceId = getCurrentTraceId();
+    if (traceId != null) {
+      builder.addLabel("appengine.googleapis.com/trace_id", traceId);
+    }
+  }
+}
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 d497f6e1b70b..ecb2706d9528 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
@@ -21,7 +21,9 @@
 import com.google.cloud.MonitoredResource;
 import com.google.cloud.logging.Logging.WriteOption;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
+
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.logging.ErrorManager;
@@ -76,6 +78,11 @@
  * <li>{@code com.google.cloud.logging.LoggingHandler.flushLevel} specifies the flush log level.
  *     When a log with this level is published, logs are transmitted to the Stackdriver Logging
  *     service (defaults to {@link LoggingLevel#ERROR}).
+ * <li>{@code com.google.cloud.logging.LoggingHandler.enhancers} specifies a comma separated list
+ *     of {@link Enhancer} classes. This handler will call each enhancer list whenever it builds
+ *     a {@link MonitoredResource} or {@link LogEntry} instance (defaults to empty list).
+ * <li>{@code com.google.cloud.logging.LoggingHandler.resourceType} the type name to use when 
+ *     creating the default {@link MonitoredResource} (defaults to "global").
  * </ul>
  *
  * <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 {
   private volatile Logging logging;
   private Level flushLevel;
   private long flushSize;
+  private final List<Enhancer> enhancers;
 
   /**
    * Creates an handler that publishes messages to Stackdriver Logging.
@@ -131,9 +139,30 @@ public LoggingHandler(String log, LoggingOptions options) {
    *
    * @param log the name of the log to which log entries are written
    * @param options options for the Stackdriver Logging service
-   * @param monitoredResource the monitored resource to which log entries refer
+   * @param monitoredResource the monitored resource to which log entries refer. If it is null 
+   * then a default resource is created based on the project ID. When creating a default resource, if
+   * any {@link Enhancer} instances are configured and then each
+   * {@link Enhancer#enhanceMonitoredResource(com.google.cloud.MonitoredResource.Builder)} method
+   * is called before building the default resource.
    */
   public LoggingHandler(String log, LoggingOptions options, MonitoredResource monitoredResource) {
+    this(log, options, monitoredResource,null);
+  }
+  
+  /**
+   * Creates a handler that publishes messages to Stackdriver Logging.
+   *
+   * @param log the name of the log to which log entries are written
+   * @param options options for the Stackdriver Logging service
+   * @param monitoredResource the monitored resource to which log entries refer. If it is null 
+   * then a default resource is created based on the project ID. When creating a default resource, if
+   * any {@link Enhancer} instances are configured and then each
+   * {@link Enhancer#enhanceMonitoredResource(com.google.cloud.MonitoredResource.Builder)} method
+   * is called before building the default resource.
+   * @param enhancers List of {@link Enhancer} instances used to enhance any {@link MonitoredResource}
+   * or {@link LogEntry} instances built by this handler.
+   */
+  public LoggingHandler(String log, LoggingOptions options, MonitoredResource monitoredResource, List<Enhancer> enhancers) {
     LogConfigHelper helper = new LogConfigHelper();
     String className = getClass().getName();
     this.options = options != null ? options : LoggingOptions.getDefaultInstance();
@@ -143,7 +172,9 @@ public LoggingHandler(String log, LoggingOptions options, MonitoredResource moni
     setFilter(helper.getFilterProperty(className + ".filter", null));
     setFormatter(helper.getFormatterProperty(className + ".formatter", new SimpleFormatter()));
     String logName = firstNonNull(log, helper.getProperty(className + ".log", "java.log"));
-    MonitoredResource resource = firstNonNull(monitoredResource, getDefaultResource());
+    this.enhancers = enhancers != null ? enhancers : helper.getEnhancerProperty(className + ".enhancers");
+    String resourceType = helper.getProperty(className + ".resourceType", "global");
+    MonitoredResource resource = monitoredResource != null ? monitoredResource : getDefaultResource(resourceType);
     writeOptions = new WriteOption[]{WriteOption.logName(logName), WriteOption.resource(resource)};
   }
 
@@ -178,8 +209,13 @@ private static boolean hasLoggingHandler(Logger logger) {
     return false;
   }
 
-  private MonitoredResource getDefaultResource() {
-    return MonitoredResource.of("global", ImmutableMap.of("project_id", options.getProjectId()));
+  private MonitoredResource getDefaultResource(String resourceType) {
+    MonitoredResource.Builder builder = MonitoredResource.newBuilder(resourceType);
+    builder.addLabel("project_id", options.getProjectId());
+    for (Enhancer enhancer : enhancers) {
+      enhancer.enhanceMonitoredResource(builder);
+    }
+    return builder.build();    
   }
 
   private static class LogConfigHelper {
@@ -237,6 +273,24 @@ Formatter getFormatterProperty(String name, Formatter defaultValue) {
       }
       return defaultValue;
     }
+    
+    List<Enhancer> getEnhancerProperty(String name) {
+      String list = manager.getProperty(name);
+      try {
+        List<Enhancer> enhancers = new ArrayList<>();
+        if (list != null) {
+          String[] items = list.split(",");
+          for (String e_name : items) { 
+            Class<? extends Enhancer> clz = (Class<? extends Enhancer>) ClassLoader.getSystemClassLoader().loadClass(e_name);
+            enhancers.add((Enhancer) clz.newInstance());
+          }
+        }
+        return enhancers;
+      } catch (Exception ex) {
+        // If we cannot create the enhancers we fall back to the default
+      }
+      return Collections.emptyList();
+    }
   }
 
   /**
@@ -311,12 +365,16 @@ private LogEntry entryFor(LogRecord record) {
         .addLabel("levelValue", String.valueOf(level.intValue()))
         .setTimestamp(record.getMillis())
         .setSeverity(severityFor(level));
+    
+    for (Enhancer enhancer : enhancers) {
+      enhancer.enhanceLogEntry(builder, record);
+    }
     enhanceLogEntry(builder, record);
     return builder.build();
   }
   
+  @Deprecated
   protected void enhanceLogEntry(LogEntry.Builder builder, LogRecord record) {
-    // no-op in this class
   }
   
   private static Severity severityFor(Level level) {
@@ -430,4 +488,14 @@ public synchronized long setFlushSize(long flushSize) {
   public static void addHandler(Logger logger, LoggingHandler handler) {
     logger.addHandler(handler);
   }
+  
+  /**
+   * A Log Enhancer.
+   * May be used to enhance the {@link MonitoredResource} and/or the {@link LogEntry}
+   */
+  interface Enhancer {
+    void enhanceMonitoredResource(MonitoredResource.Builder builder);
+    void enhanceLogEntry(LogEntry.Builder builder, LogRecord record);
+  }
+
 }
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 a1c1697d18af..7b4f3298c1d4 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
@@ -17,11 +17,14 @@
 package com.google.cloud.logging;
 
 import com.google.cloud.MonitoredResource;
+import com.google.cloud.logging.LogEntry.Builder;
 import com.google.cloud.logging.Logging.WriteOption;
 import com.google.cloud.logging.Payload.StringPayload;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.util.concurrent.Futures;
+
+import java.util.Collections;
 import java.util.logging.ErrorManager;
 import java.util.logging.Formatter;
 import java.util.logging.Handler;
@@ -46,6 +49,13 @@ public class LoggingHandlerTest {
       .addLabel("levelValue", String.valueOf(Level.FINEST.intValue()))
       .setTimestamp(123456789L)
       .build();
+  private static final LogEntry FINEST_ENHANCED_ENTRY = LogEntry.newBuilder(StringPayload.of(MESSAGE))
+      .setSeverity(Severity.DEBUG)
+      .addLabel("levelName", "FINEST")
+      .addLabel("levelValue", String.valueOf(Level.FINEST.intValue()))
+      .addLabel("enhanced", "true")
+      .setTimestamp(123456789L)
+      .build();
   private static final LogEntry FINER_ENTRY = LogEntry.newBuilder(StringPayload.of(MESSAGE))
       .setSeverity(Severity.DEBUG)
       .addLabel("levelName", "FINER")
@@ -227,6 +237,33 @@ public void testPublishCustomResource() {
     handler.publish(newLogRecord(Level.FINEST, MESSAGE));
   }
 
+  @Test
+  public void testEnhancedLogEntry() {
+    EasyMock.expect(options.getProjectId()).andReturn(PROJECT).anyTimes();
+    EasyMock.expect(options.getService()).andReturn(logging);
+    MonitoredResource resource = MonitoredResource.of("custom", ImmutableMap.<String, String>of());
+    logging.writeAsync(ImmutableList.of(FINEST_ENHANCED_ENTRY), WriteOption.logName(LOG_NAME),
+        WriteOption.resource(resource));
+    EasyMock.expectLastCall().andReturn(Futures.immediateFuture(null));
+    EasyMock.replay(options, logging);
+    LoggingHandler.Enhancer enhancer = new LoggingHandler.Enhancer() {
+      @Override
+      public void enhanceMonitoredResource(MonitoredResource.Builder builder) {
+        throw new IllegalStateException();
+      }
+
+      @Override
+      public void enhanceLogEntry(Builder builder, LogRecord record) {
+        builder.addLabel("enhanced", "true");
+      }
+    };
+    Handler handler =
+        new LoggingHandler(LOG_NAME, options, resource, Collections.singletonList(enhancer));
+    handler.setLevel(Level.ALL);
+    handler.setFormatter(new TestFormatter());
+    handler.publish(newLogRecord(Level.FINEST, MESSAGE));
+  }
+  
   @Test
   public void testReportFlushError() {
     EasyMock.expect(options.getProjectId()).andReturn(PROJECT).anyTimes();