Skip to content

Commit

Permalink
Logging Enhancer
Browse files Browse the repository at this point in the history
  • Loading branch information
gregw committed Jan 16, 2017
1 parent 646ee05 commit 4801395
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright 2017 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
* GAE Flex environment. This enhance 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<>();

/**
* 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();
}

private String gaeInstanceId;

@Override
public void enhanceMonitoredResource(Builder builder) {
gaeInstanceId = System.getenv("GAE_INSTANCE"); // Are we running on a GAE instance?
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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -95,11 +97,11 @@ public class LoggingHandler extends Handler {

private final LoggingOptions options;
private final WriteOption[] writeOptions;
private final String gaeInstanceId;
private List<LogEntry> buffer = new LinkedList<>();
private volatile Logging logging;
private Level flushLevel;
private long flushSize;
private final List<Enhancer> enhancers;

/**
* Creates an handler that publishes messages to Stackdriver Logging.
Expand Down Expand Up @@ -137,6 +139,20 @@ public LoggingHandler(String log, LoggingOptions options) {
* then a more comprehensive default resource may be created.
*/
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 null a default
* @param enhancers List of {@link Enhancer} instances.
* resource is created based on the project ID. If a Google App Engine environment is detected
* then a more comprehensive default resource may be created.
*/
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();
Expand All @@ -146,8 +162,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"));
gaeInstanceId = System.getenv("GAE_INSTANCE");
MonitoredResource resource = firstNonNull(monitoredResource, getDefaultResource());
this.enhancers = firstNonNull(enhancers, helper.getEnhancerProperty(className + ".enhancers"));
String resourceType = helper.getProperty(className + ".resourceType", "global");
MonitoredResource resource = firstNonNull(monitoredResource, getDefaultResource(resourceType));
writeOptions = new WriteOption[]{WriteOption.logName(logName), WriteOption.resource(resource)};
}

Expand Down Expand Up @@ -182,21 +199,13 @@ private static boolean hasLoggingHandler(Logger logger) {
return false;
}

private MonitoredResource getDefaultResource() {
// Are we running on a GAE instance?
if (gaeInstanceId!=null && options.getProjectId()!=null) {
MonitoredResource.Builder builder = MonitoredResource.newBuilder("gae_app")
.addLabel("project_id", options.getProjectId());
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"));
}
return builder.build();
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 MonitoredResource.of("global", ImmutableMap.of("project_id", options.getProjectId()));
return builder.build();
}

private static class LogConfigHelper {
Expand Down Expand Up @@ -254,6 +263,25 @@ 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) {
ex.printStackTrace();
// If we cannot create the enhancers we fall back to the default
}
return Collections.emptyList();
}
}

/**
Expand Down Expand Up @@ -327,16 +355,15 @@ private LogEntry entryFor(LogRecord record) {
.addLabel("levelName", level.getName())
.addLabel("levelValue", String.valueOf(level.intValue()))
.setSeverity(severityFor(level));
if (gaeInstanceId != null) {
builder.addLabel("appengine.googleapis.com/instance_name", gaeInstanceId);
}

enhanceLogEntry(builder, record);
return builder.build();
}

protected void enhanceLogEntry(LogEntry.Builder builder, LogRecord record) {
// no-op in this class
for (Enhancer enhancer : enhancers) {
enhancer.enhanceLogEntry(builder, record);
}
}

private static Severity severityFor(Level level) {
Expand Down Expand Up @@ -450,4 +477,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 enhanced the {@link MonitoredResource} and/or the {@link LogEntry}
*/
interface Enhancer {
void enhanceMonitoredResource(MonitoredResource.Builder builder);
void enhanceLogEntry(LogEntry.Builder builder, LogRecord record);
}

}

0 comments on commit 4801395

Please sign in to comment.