Repository: aurora Updated Branches: refs/heads/master 6a5309ae3 -> d542bd1d5
Replace scheduler log scaffolding with logback. Reviewed at https://reviews.apache.org/r/41785/ Project: http://git-wip-us.apache.org/repos/asf/aurora/repo Commit: http://git-wip-us.apache.org/repos/asf/aurora/commit/d542bd1d Tree: http://git-wip-us.apache.org/repos/asf/aurora/tree/d542bd1d Diff: http://git-wip-us.apache.org/repos/asf/aurora/diff/d542bd1d Branch: refs/heads/master Commit: d542bd1d58bc5dcf6ead95d902c0a8cecbbffe9e Parents: 6a5309a Author: Bill Farner <[email protected]> Authored: Mon Jan 11 23:57:49 2016 -0500 Committer: Bill Farner <[email protected]> Committed: Mon Jan 11 23:57:49 2016 -0500 ---------------------------------------------------------------------- NEWS | 5 + build.gradle | 12 +- .../org/apache/aurora/common/logging/Glog.java | 208 ------------ .../aurora/common/logging/LogFormatter.java | 80 ----- .../aurora/common/logging/RootLogConfig.java | 296 ----------------- .../aurora/common/logging/log4j/GlogLayout.java | 98 ------ .../common/net/http/handlers/LogConfig.java | 137 -------- .../common/net/http/handlers/logconfig.st | 44 --- .../aurora/common/logging/LogFormatterTest.java | 72 ---- .../common/logging/RootLogConfigTest.java | 333 ------------------- config/legacy_untested_classes.txt | 2 + .../upstart/aurora-scheduler-kerberos.conf | 6 +- examples/vagrant/upstart/aurora-scheduler.conf | 9 +- .../aurora/scheduler/app/Log4jConfigurator.java | 68 ---- .../aurora/scheduler/app/SchedulerMain.java | 41 --- .../scheduler/http/JettyServerModule.java | 1 - .../apache/aurora/scheduler/http/LogConfig.java | 126 +++++++ src/main/resources/logback.xml | 33 ++ .../apache/aurora/scheduler/http/logconfig.st | 44 +++ 19 files changed, 222 insertions(+), 1393 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/aurora/blob/d542bd1d/NEWS ---------------------------------------------------------------------- diff --git a/NEWS b/NEWS index ecb26d2..acaff9e 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,11 @@ - Log destination is configurable for the thermos runner. See the configuration reference for details on how to configure destination per-process. Command line options may also be passed through the scheduler in order to configure the global default behavior. +- Changed scheduler logging to use logback. + Operators wishing to customize logging may do so with standard logback configuration as described + at http://logback.qos.ch/manual/configuration.html + With this change, we have removed the following scheduler command line arguments as they were + made redundant: `logtostderr`, `alsologtostderr`, `vlog`, `vmodule`, and `use_glog_formatter`. 0.11.0 ------ http://git-wip-us.apache.org/repos/asf/aurora/blob/d542bd1d/build.gradle ---------------------------------------------------------------------- diff --git a/build.gradle b/build.gradle index 8e7ea37..169fb25 100644 --- a/build.gradle +++ b/build.gradle @@ -87,7 +87,6 @@ For more details, please see https://issues.apache.org/jira/browse/AURORA-1169 ext.jerseyRev = '1.19' ext.jsrRev = '3.0.1' ext.junitRev = '4.12' - ext.log4jRev = '1.2.17' ext.protobufRev = '2.6.1' ext.servletRev = '3.1.0' ext.slf4jRev = '1.7.12' @@ -100,6 +99,10 @@ For more details, please see https://issues.apache.org/jira/browse/AURORA-1169 configurations { compile { exclude module: 'junit-dep' + // We use logback, so we do not want to pull in log4j artifacts. + exclude module: 'log4j' + exclude module: 'slf4j-log4j12' + // ResolutionStrategy needs to be set in the allprojects block otherwise dependent projects // will not inherit it. Note that dependencies still need to be specified in a dependencies // block - this only affects strategy. @@ -112,11 +115,9 @@ For more details, please see https://issues.apache.org/jira/browse/AURORA-1169 force "com.google.guava:guava:${guavaRev}" force "com.google.protobuf:protobuf-java:${protobufRev}" force "junit:junit:${junitRev}" - force "log4j:log4j:${log4jRev}" force "org.apache.thrift:libthrift:${thriftRev}" force "org.hamcrest:hamcrest-core:1.3" force "org.slf4j:slf4j-api:${slf4jRev}" - force "org.slf4j:slf4j-jdk14:${slf4jRev}" } } } @@ -165,11 +166,9 @@ project(':commons') { compile "commons-lang:commons-lang:${commonsLangRev}" compile "javax.servlet:javax.servlet-api:${servletRev}" compile "joda-time:joda-time:2.9.1" - compile "log4j:log4j:${log4jRev}" compile "org.antlr:stringtemplate:${stringTemplateRev}" compile "org.apache.zookeeper:zookeeper:${zookeeperRev}" compile "org.easymock:easymock:3.4" - compile "org.slf4j:slf4j-jdk14:${slf4jRev}" // There are a few testing support libs in the src/main/java trees that use junit - currently: // src/main/java/org/apache/aurora/common/zookeeper/testing @@ -343,6 +342,7 @@ dependencies { compile project(':commons-args') compile 'aopalliance:aopalliance:1.0' + compile 'ch.qos.logback:logback-classic:1.1.3' compile "com.google.code.findbugs:jsr305:${jsrRev}" compile "com.google.inject:guice:${guiceRev}" compile "com.google.inject.extensions:guice-assistedinject:${guiceRev}" @@ -357,7 +357,6 @@ dependencies { compile "com.sun.jersey.contribs:jersey-guice:${jerseyRev}" compile 'javax.inject:javax.inject:1' compile "javax.servlet:javax.servlet-api:${servletRev}" - compile "log4j:log4j:${log4jRev}" compile "org.antlr:stringtemplate:${stringTemplateRev}" compile 'org.apache.mesos:mesos:0.25.0' compile "org.apache.shiro:shiro-guice:${shiroRev}" @@ -370,7 +369,6 @@ dependencies { compile 'org.mybatis:mybatis:3.3.0' compile 'org.mybatis:mybatis-guice:3.7' compile 'org.quartz-scheduler:quartz:2.2.2' - compile "org.slf4j:slf4j-jdk14:${slf4jRev}" compile "uno.perk:forward:1.0.0" testCompile "com.sun.jersey:jersey-client:${jerseyRev}" http://git-wip-us.apache.org/repos/asf/aurora/blob/d542bd1d/commons/src/main/java/org/apache/aurora/common/logging/Glog.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/org/apache/aurora/common/logging/Glog.java b/commons/src/main/java/org/apache/aurora/common/logging/Glog.java deleted file mode 100644 index 5bae399..0000000 --- a/commons/src/main/java/org/apache/aurora/common/logging/Glog.java +++ /dev/null @@ -1,208 +0,0 @@ -/** - * 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 org.apache.aurora.common.logging; - -import javax.annotation.Nullable; - -import com.google.common.base.Objects; -import com.google.common.base.Throwables; - -import org.joda.time.DateTimeZone; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; - -/** - * A utility that can format log records to match the format generated by glog: - * <pre> - * I0218 17:36:47.461 (source) (message) - * </pre> - */ -public final class Glog { - - /** - * Classifies the importance of a log message. - */ - public enum Level { - - /** - * Indicates the message's classification is unknown. This most likely indicates a - * configuration or programming error that can be corrected by mapping the underlying log - * system's level appropriately. - */ - UNKNOWN('U'), - - /** - * Indicates the message is for debugging purposes only. - */ - DEBUG('D'), - - /** - * Indicates a message of general interest. - */ - INFO('I'), - - /** - * Indicates a warning message likely worth of attention. - */ - WARNING('W'), - - /** - * Indicates an unexpected error. - */ - ERROR('E'), - - /** - * Indicates a fatal exception generally paired with actions to shut down the errored process. - */ - FATAL('F'); - - final char label; - - private Level(char label) { - this.label = label; - } - } - - /** - * An object that can provide details of a log record. - * - * @param <T> The type of log record the formatter handles. - */ - public interface Formatter<T> { - - /** - * Gets the message contained in the log record. - * - * @param record The record to extract a message from. - * @return The formatted message. - */ - String getMessage(T record); - - /** - * Gets the class name of the class that sent the log record for logging. - * - * @param record The record to extract a producing class name from. - * @return The producing class if known; otherwise {@code null}. - */ - @Nullable - String getClassName(T record); - - /** - * Gets the name of the method of within the class that sent the log record for logging. - * - * @param record The record to extract a producing method name from. - * @return The producing method name if known; otherwise {@code null}. - */ - @Nullable - String getMethodName(T record); - - /** - * Gets the level of the log record. - * - * @param record The record to extract a log level from. - * @return The record's log level. Can be {@code null} or {@link Level#UNKNOWN} if unknown. - */ - @Nullable - Level getLevel(T record); - - /** - * Gets the timestamp in milliseconds since the epoch when the log record was generated. - * - * @param record The record to extract a time stamp from. - * @return The log record's birth date. - */ - long getTimeStamp(T record); - - /** - * Gets the id of the thread that generated the log record. - * - * @param record The record to extract a thread id from. - * @return The id of the thread that generated the log record. - */ - long getThreadId(T record); - - /** - * Gets the exception associated with the log record if any. - * - * @param record The record to extract an exception from. - * @return The exception associated with the log record; may be {@code null}. - */ - @Nullable - Throwable getThrowable(T record); - } - - private static final DateTimeFormatter DATE_TIME_FORMATTER = - DateTimeFormat.forPattern("MMdd HH:mm:ss.SSS").withZone(DateTimeZone.UTC); - - private static final int BASE_MESSAGE_LENGTH = - 1 // Level char. - + 4 // Month + day - + 1 // space - + 12 // Timestamp - + 1 // space - + 6 // THREAD - + 4 // Room for thread ID. - + 1; // space - - /** - * Converts the given log record into a glog format log line using the given formatter. - * - * @param formatter A formatter that understands how to unpack the given log record. - * @param record A structure containing log data. - * @param <T> The type of log record. - * @return A glog formatted log line. - */ - public static <T> String formatRecord(Formatter<T> formatter, T record) { - String message = formatter.getMessage(record); - int messageLength = BASE_MESSAGE_LENGTH - + 2 // Colon and space - + message.length(); - - String className = formatter.getClassName(record); - String methodName = null; - if (className != null) { - messageLength += className.length(); - methodName = formatter.getMethodName(record); - if (methodName != null) { - messageLength += 1; // Period between class and method. - messageLength += methodName.length(); - } - } - - StringBuilder sb = new StringBuilder(messageLength) - .append(Objects.firstNonNull(formatter.getLevel(record), Level.UNKNOWN).label) - .append(DATE_TIME_FORMATTER.print(formatter.getTimeStamp(record))) - .append(" THREAD") - .append(formatter.getThreadId(record)); - - if (className != null) { - sb.append(' ').append(className); - if (methodName != null) { - sb.append('.').append(methodName); - } - } - - sb.append(": ").append(message); - Throwable throwable = formatter.getThrowable(record); - if (throwable != null) { - sb.append('\n').append(Throwables.getStackTraceAsString(throwable)); - } - - return sb.append('\n').toString(); - } - - private Glog() { - // utility - } -} http://git-wip-us.apache.org/repos/asf/aurora/blob/d542bd1d/commons/src/main/java/org/apache/aurora/common/logging/LogFormatter.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/org/apache/aurora/common/logging/LogFormatter.java b/commons/src/main/java/org/apache/aurora/common/logging/LogFormatter.java deleted file mode 100644 index 0cb621d..0000000 --- a/commons/src/main/java/org/apache/aurora/common/logging/LogFormatter.java +++ /dev/null @@ -1,80 +0,0 @@ -/** - * 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 org.apache.aurora.common.logging; - -import java.util.logging.Formatter; -import java.util.logging.Level; -import java.util.logging.LogRecord; - -import com.google.common.collect.ImmutableMap; - -/** - * Log formatter to match the format generated by glog. - * - * @see Glog - */ -public class LogFormatter extends Formatter implements Glog.Formatter<LogRecord> { - - private static final ImmutableMap<Level, Glog.Level> LEVEL_LABELS = - ImmutableMap.<Level, Glog.Level>builder() - .put(Level.FINEST, Glog.Level.DEBUG) - .put(Level.FINER, Glog.Level.DEBUG) - .put(Level.FINE, Glog.Level.DEBUG) - .put(Level.CONFIG, Glog.Level.INFO) - .put(Level.INFO, Glog.Level.INFO) - .put(Level.WARNING, Glog.Level.WARNING) - .put(Level.SEVERE, Glog.Level.ERROR) - .build(); - - - @Override - public String format(final LogRecord record) { - return Glog.formatRecord(this, record); - } - - @Override - public String getMessage(LogRecord record) { - return formatMessage(record); - } - - @Override - public String getClassName(LogRecord record) { - return record.getSourceClassName(); - } - - @Override - public String getMethodName(LogRecord record) { - return record.getSourceMethodName(); - } - - @Override - public Glog.Level getLevel(LogRecord record) { - return LEVEL_LABELS.get(record.getLevel()); - } - - @Override - public long getTimeStamp(LogRecord record) { - return record.getMillis(); - } - - @Override - public long getThreadId(LogRecord record) { - return record.getThreadID(); - } - - @Override - public Throwable getThrowable(LogRecord record) { - return record.getThrown(); - } -} http://git-wip-us.apache.org/repos/asf/aurora/blob/d542bd1d/commons/src/main/java/org/apache/aurora/common/logging/RootLogConfig.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/org/apache/aurora/common/logging/RootLogConfig.java b/commons/src/main/java/org/apache/aurora/common/logging/RootLogConfig.java deleted file mode 100644 index 26dd0aa..0000000 --- a/commons/src/main/java/org/apache/aurora/common/logging/RootLogConfig.java +++ /dev/null @@ -1,296 +0,0 @@ -/** - * 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 org.apache.aurora.common.logging; - -import java.util.Map; -import java.util.logging.ConsoleHandler; -import java.util.logging.Handler; -import java.util.logging.Level; -import java.util.logging.LogManager; -import java.util.logging.Logger; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; - -/** - * A configuration class for the root java.util.logging Logger. - * - * Defines flags to control the behavior behavior of the root logger similarly to Google's glog - * library (see http://code.google.com/p/google-glog ). - */ -public class RootLogConfig { - /** - * An enum reflecting log {@link Level} constants. - */ - public enum LogLevel { - FINEST(Level.FINEST), - FINER(Level.FINER), - FINE(Level.FINE), - CONFIG(Level.CONFIG), - INFO(Level.INFO), - WARNING(Level.WARNING), - SEVERE(Level.SEVERE); - - private final Level level; - - private LogLevel(Level level) { - this.level = level; - } - - private Level getLevel() { - return level; - } - } - - /** - * Represents a logging configuration for java.util.logging. - */ - public static final class Configuration { - boolean logToStderr = false; - boolean alsoLogToStderr = false; - boolean useGLogFormatter = true; - LogLevel vlog = LogLevel.INFO; - ImmutableMap<Class<?>, LogLevel> vmodule = ImmutableMap.of(); - String rootLoggerName = ""; - - Configuration() { - // Guard for internal use only. - } - - /** - * Returns {@code true} if configured to log just to stderr. - */ - public boolean isLogToStderr() { - return logToStderr; - } - - /** - * Returns {@code true} if configured to log to stderr in addition to log files.. - */ - public boolean isAlsoLogToStderr() { - return alsoLogToStderr; - } - - /** - * Returns {@code true} if configured to log in google-glog format. - */ - public boolean isUseGLogFormatter() { - return useGLogFormatter; - } - - /** - * Returns the default global log level. - */ - public LogLevel getVlog() { - return vlog; - } - - /** - * Returns the custom log levels configured for individual classes. - */ - public ImmutableMap<Class<?>, LogLevel> getVmodule() { - return vmodule; - } - - /** - * Applies this configuration to the root log. - */ - public void apply() { - RootLogConfig.configure(this); - } - } - - /** - * A builder-pattern class used to perform the configuration programmatically - * (i.e. not through flags). - * Example: - * <code> - * RootLogConfig.builder().logToStderr(true).build().apply(); - * </code> - */ - public static final class Builder { - private final Configuration configuration; - - private Builder() { - this.configuration = new Configuration(); - } - - /** - * Only log messages to stderr, instead of log files. Overrides alsologtostderr. - * Default: false. - * - * @param flag True to enable, false to disable. - * @return this Configuration object. - */ - public Builder logToStderr(boolean flag) { - configuration.logToStderr = flag; - return this; - } - - /** - * Also log messages to stderr, in addition to log files. - * Overridden by logtostderr. - * Default: false. - * - * @param flag True to enable, false to disable. - * @return this Configuration object. - */ - public Builder alsoLogToStderr(boolean flag) { - configuration.alsoLogToStderr = flag; - return this; - } - - /** - * Format log messages in one-line with a header, similar to google-glog. - * Default: false. - * - * @param flag True to enable, false to disable. - * @return this Configuration object. - */ - public Builder useGLogFormatter(boolean flag) { - configuration.useGLogFormatter = flag; - return this; - } - - /** - * Output log messages at least at the given verbosity level. - * Overridden by vmodule. - * Default: INFO - * - * @param level LogLevel enumerator for the minimum log message verbosity level that is output. - * @return this Configuration object. - */ - public Builder vlog(LogLevel level) { - Preconditions.checkNotNull(level); - configuration.vlog = level; - return this; - } - - /** - * Output log messages for a given set of classes at the associated verbosity levels. - * Overrides vlog. - * Default: no classes are treated specially. - * - * @param pairs Map of classes and correspoding log levels. - * @return this Configuration object. - */ - public Builder vmodule(Map<Class<?>, LogLevel> pairs) { - Preconditions.checkNotNull(pairs); - configuration.vmodule = ImmutableMap.copyOf(pairs); - return this; - } - - /** - * Returns the built up configuration. - */ - public Configuration build() { - return configuration; - } - - // Intercepts the root logger, for testing purposes only. - @VisibleForTesting - Builder rootLoggerName(String name) { - Preconditions.checkNotNull(name); - Preconditions.checkArgument(!name.isEmpty()); - configuration.rootLoggerName = name; - return this; - } - } - - /** - * Creates a new Configuration builder object. - * - * @return The builder. - */ - public static Builder builder() { - return new Builder(); - } - - private static void configure(Configuration configuration) { - // Edit the properties of the root logger. - Logger rootLogger = Logger.getLogger(configuration.rootLoggerName); - if (configuration.logToStderr) { - setLoggerToStderr(rootLogger); - } else if (configuration.alsoLogToStderr) { - setLoggerToAlsoStderr(rootLogger); - } - if (configuration.useGLogFormatter) { - setGLogFormatter(rootLogger); - } - if (configuration.vlog != null) { - setVlog(rootLogger, configuration.vlog); - } - if (configuration.vmodule != null) { - setVmodules(configuration.vmodule); - } - } - - private static void setLoggerToStderr(Logger logger) { - LogManager.getLogManager().reset(); - setConsoleHandler(logger, true); - } - - private static void setLoggerToAlsoStderr(Logger logger) { - setConsoleHandler(logger, false); - } - - private static void setConsoleHandler(Logger logger, boolean removeOtherHandlers) { - Handler consoleHandler = null; - for (Handler h : logger.getHandlers()) { - if (h instanceof ConsoleHandler) { - consoleHandler = h; - } else if (removeOtherHandlers) { - logger.removeHandler(h); - } - } - if (consoleHandler == null) { - consoleHandler = new ConsoleHandler(); - logger.addHandler(new ConsoleHandler()); - } - consoleHandler.setLevel(Level.ALL); - consoleHandler.setFilter(null); - } - - private static void setGLogFormatter(Logger logger) { - for (Handler h : logger.getHandlers()) { - h.setFormatter(new LogFormatter()); - } - } - - private static void setVmodules(Map<Class<?>, LogLevel> vmodules) { - for (Map.Entry<Class<?>, LogLevel> entry : vmodules.entrySet()) { - String className = entry.getKey().getName(); - Logger logger = Logger.getLogger(className); - setVlog(logger, entry.getValue()); - } - } - - private static void setVlog(Logger logger, LogLevel logLevel) { - final Level newLevel = logLevel.getLevel(); - logger.setLevel(newLevel); - do { - for (Handler handler : logger.getHandlers()) { - Level handlerLevel = handler.getLevel(); - if (newLevel.intValue() < handlerLevel.intValue()) { - handler.setLevel(newLevel); - } - } - } while (logger.getUseParentHandlers() && (logger = logger.getParent()) != null); - } - - // Utility class. - private RootLogConfig() { - } -} http://git-wip-us.apache.org/repos/asf/aurora/blob/d542bd1d/commons/src/main/java/org/apache/aurora/common/logging/log4j/GlogLayout.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/org/apache/aurora/common/logging/log4j/GlogLayout.java b/commons/src/main/java/org/apache/aurora/common/logging/log4j/GlogLayout.java deleted file mode 100644 index 1a90ded..0000000 --- a/commons/src/main/java/org/apache/aurora/common/logging/log4j/GlogLayout.java +++ /dev/null @@ -1,98 +0,0 @@ -/** - * 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 org.apache.aurora.common.logging.log4j; - -import com.google.common.collect.ImmutableMap; - -import org.apache.aurora.common.logging.Glog; -import org.apache.log4j.Layout; -import org.apache.log4j.Level; -import org.apache.log4j.spi.LocationInfo; -import org.apache.log4j.spi.LoggingEvent; -import org.apache.log4j.spi.ThrowableInformation; - -/** - * Log4j Layout to match the format generated by glog. - * - * @see Glog - */ -public class GlogLayout extends Layout implements Glog.Formatter<LoggingEvent> { - - private static final ImmutableMap<Level, Glog.Level> LEVEL_LABELS = - ImmutableMap.<Level, Glog.Level>builder() - .put(Level.TRACE, Glog.Level.DEBUG) - .put(Level.DEBUG, Glog.Level.DEBUG) - .put(Level.INFO, Glog.Level.INFO) - .put(Level.WARN, Glog.Level.WARNING) - .put(Level.ERROR, Glog.Level.ERROR) - .put(Level.FATAL, Glog.Level.FATAL) - .build(); - - @Override - public String format(LoggingEvent record) { - return Glog.formatRecord(this, record); - } - - @Override - public boolean ignoresThrowable() { - return false; // We handle stack trace formatting. - } - - @Override - public void activateOptions() { - // We use no options - } - - @Override - public String getMessage(LoggingEvent record) { - return record.getRenderedMessage(); - } - - @Override - public String getClassName(LoggingEvent record) { - LocationInfo locationInformation = record.getLocationInformation(); - return (locationInformation != null) - ? locationInformation.getClassName() - : null; - } - - @Override - public String getMethodName(LoggingEvent record) { - LocationInfo locationInformation = record.getLocationInformation(); - return (locationInformation != null) - ? record.getLocationInformation().getMethodName() - : null; - } - - @Override - public Glog.Level getLevel(LoggingEvent record) { - return LEVEL_LABELS.get(record.getLevel()); - } - - @Override - public long getTimeStamp(LoggingEvent record) { - return record.getTimeStamp(); - } - - @Override - public long getThreadId(LoggingEvent record) { - return Thread.currentThread().getId(); - } - - @Override - public Throwable getThrowable(LoggingEvent record) { - ThrowableInformation throwableInformation = record.getThrowableInformation(); - return throwableInformation != null ? throwableInformation.getThrowable() : null; - } -} http://git-wip-us.apache.org/repos/asf/aurora/blob/d542bd1d/commons/src/main/java/org/apache/aurora/common/net/http/handlers/LogConfig.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/LogConfig.java b/commons/src/main/java/org/apache/aurora/common/net/http/handlers/LogConfig.java deleted file mode 100644 index d3c6ddd..0000000 --- a/commons/src/main/java/org/apache/aurora/common/net/http/handlers/LogConfig.java +++ /dev/null @@ -1,137 +0,0 @@ -/** - * 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 org.apache.aurora.common.net.http.handlers; - -import java.io.StringWriter; -import java.util.List; -import java.util.Optional; -import java.util.logging.Handler; -import java.util.logging.Level; -import java.util.logging.LogManager; -import java.util.logging.Logger; -import java.util.logging.LoggingMXBean; - -import javax.ws.rs.FormParam; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; - -import com.google.common.collect.Lists; -import com.google.common.collect.Ordering; - -import org.apache.aurora.common.util.templating.StringTemplateHelper; -import org.apache.aurora.common.util.templating.StringTemplateHelper.TemplateException; -import org.apache.commons.lang.StringUtils; - -/** - * Servlet that allows for dynamic adjustment of the logging configuration. - * - * @author William Farner - */ -@Path("/logconfig") -public class LogConfig { - private static final List<String> LOG_LEVELS = Lists.newArrayList( - Level.SEVERE.getName(), - Level.WARNING.getName(), - Level.INFO.getName(), - Level.CONFIG.getName(), - Level.FINE.getName(), - Level.FINER.getName(), - Level.FINEST.getName(), - "INHERIT" // Display value for a null level, the logger inherits from its ancestor. - ); - - private final StringTemplateHelper template = - new StringTemplateHelper(getClass(), "logconfig", false); - - @POST - @Produces(MediaType.TEXT_HTML) - public String post( - @FormParam("logger") String loggerName, - @FormParam("level") String loggerLevel) throws TemplateException { - - Optional<String> configChange = Optional.empty(); - if (loggerName != null && loggerLevel != null) { - Logger logger = Logger.getLogger(loggerName); - Level newLevel = loggerLevel.equals("INHERIT") ? null : Level.parse(loggerLevel); - logger.setLevel(newLevel); - if (newLevel != null) { - maybeAdjustHandlerLevels(logger, newLevel); - } - - configChange = Optional.of(String.format("%s level changed to %s", loggerName, loggerLevel)); - } - - return displayPage(configChange); - } - - @GET - @Produces(MediaType.TEXT_HTML) - public String get() throws TemplateException { - return displayPage(Optional.empty()); - } - - protected String displayPage(Optional<String> configChange) throws TemplateException { - StringWriter writer = new StringWriter(); - - template.writeTemplate(writer, stringTemplate -> { - LoggingMXBean logBean = LogManager.getLoggingMXBean(); - - if (configChange.isPresent()) { - stringTemplate.setAttribute("configChange", configChange.get()); - } - - List<LoggerConfig> loggerConfigs = Lists.newArrayList(); - for (String logger : Ordering.natural().immutableSortedCopy(logBean.getLoggerNames())) { - loggerConfigs.add(new LoggerConfig(logger, logBean.getLoggerLevel(logger))); - } - - stringTemplate.setAttribute("loggers", loggerConfigs); - stringTemplate.setAttribute("levels", LOG_LEVELS); - }); - - return writer.toString(); - } - - private void maybeAdjustHandlerLevels(Logger logger, Level newLevel) { - do { - for (Handler handler : logger.getHandlers()) { - Level handlerLevel = handler.getLevel(); - if (newLevel.intValue() < handlerLevel.intValue()) { - handler.setLevel(newLevel); - } - } - } while (logger.getUseParentHandlers() && (logger = logger.getParent()) != null); - } - - private class LoggerConfig { - private final String name; - private final String level; - - public LoggerConfig(String name, String level) { - this.name = name; - this.level = StringUtils.isBlank(level) ? "INHERIT" : level; - } - - public String getName() { - return name; - } - - public String getLevel() { - return level; - } - } -} http://git-wip-us.apache.org/repos/asf/aurora/blob/d542bd1d/commons/src/main/resources/org/apache/aurora/common/net/http/handlers/logconfig.st ---------------------------------------------------------------------- diff --git a/commons/src/main/resources/org/apache/aurora/common/net/http/handlers/logconfig.st b/commons/src/main/resources/org/apache/aurora/common/net/http/handlers/logconfig.st deleted file mode 100644 index 02b85c2..0000000 --- a/commons/src/main/resources/org/apache/aurora/common/net/http/handlers/logconfig.st +++ /dev/null @@ -1,44 +0,0 @@ -<html> - <title>Logger Config</title> - <head> - <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script> - </head> - <body> - <table border=1 cellpadding=0 cellspacing=0 align=left> - <tr> - <th>Logger</th> - <th>Level</th> - </tr> - $loggers:{ logger | - <tr> - <td>$logger.name$</td> - <td> - <select id="$logger.name$" name="level" class="selectlevels" data-loglevel="$logger.level$"> - $levels:{ level | - <option value='$level$'>$level$</option> - }$ - </select> - </td> - </tr> - }$ - </table> - <script> - \$(document).ready(function() { - // For every logger changed the select to match the current level. - \$('.selectlevels').each(function() { - \$(this).val(\$(this).data('loglevel')); - }); - // Every time a logger value is changed post the logger name and new level. - \$('.selectlevels').change(function() { - \$.post("/logconfig", - { logger : \$(this).attr('id'), level : \$(this).val() }, - function() { - // Reload the page so the new logger value is visible. - location.reload(); - } - ); - }); - }); - </script> - </body> -</html> http://git-wip-us.apache.org/repos/asf/aurora/blob/d542bd1d/commons/src/test/java/org/apache/aurora/common/logging/LogFormatterTest.java ---------------------------------------------------------------------- diff --git a/commons/src/test/java/org/apache/aurora/common/logging/LogFormatterTest.java b/commons/src/test/java/org/apache/aurora/common/logging/LogFormatterTest.java deleted file mode 100644 index 9f04191..0000000 --- a/commons/src/test/java/org/apache/aurora/common/logging/LogFormatterTest.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * 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 org.apache.aurora.common.logging; - -import java.util.logging.Level; -import java.util.logging.LogRecord; - -import com.google.common.base.Throwables; - -import org.junit.Before; -import org.junit.Test; - -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; - -/** - * @author William Farner - */ -public class LogFormatterTest { - - private static final int THREAD_ID = 105; - private static final long TIME_MILLIS = 1298065054839L; - private static final String TIME_STRING = "0218 21:37:34.839"; - - private LogFormatter formatter; - - @Before - public void setUp() { - formatter = new LogFormatter(); - } - - @Test - public void testSimpleMessage() { - String message = "Configurated the whizzbanger."; - - LogRecord record = makeRecord(Level.INFO, message); - - assertThat(formatter.format(record), is( - String.format("I%s THREAD%d: %s\n", TIME_STRING, THREAD_ID, message))); - } - - @Test - public void testException() { - String message = "The fuzzbizzer failed."; - Throwable exception = new RuntimeException("No such fizzbuzzer."); - - LogRecord record = makeRecord(Level.WARNING, message); - record.setThrown(exception); - - assertThat(formatter.format(record), is( - String.format("W%s THREAD%d: %s\n%s\n", TIME_STRING, THREAD_ID, message, - Throwables.getStackTraceAsString(exception)))); - } - - private static LogRecord makeRecord(Level level, String message) { - LogRecord record = new LogRecord(level, message); - record.setMillis(TIME_MILLIS); - record.setThreadID(THREAD_ID); - return record; - } -} http://git-wip-us.apache.org/repos/asf/aurora/blob/d542bd1d/commons/src/test/java/org/apache/aurora/common/logging/RootLogConfigTest.java ---------------------------------------------------------------------- diff --git a/commons/src/test/java/org/apache/aurora/common/logging/RootLogConfigTest.java b/commons/src/test/java/org/apache/aurora/common/logging/RootLogConfigTest.java deleted file mode 100644 index 9d55a1a..0000000 --- a/commons/src/test/java/org/apache/aurora/common/logging/RootLogConfigTest.java +++ /dev/null @@ -1,333 +0,0 @@ -/** - * 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 org.apache.aurora.common.logging; - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.logging.ConsoleHandler; -import java.util.logging.Handler; -import java.util.logging.Level; -import java.util.logging.LogRecord; -import java.util.logging.Logger; - -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; - -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * @author Franco Callari - * @author Keith Tsui. - */ -public class RootLogConfigTest { - private static class FakeHandler extends Handler { - boolean hasPublished = false; - FakeHandler() { reset(); } - void reset() { hasPublished = false; } - public void publish(LogRecord record) { hasPublished = true; } - public void flush() {} - public void close() throws SecurityException {} - } - - // Dummy classes used by the tests for --vmodule. - private static class ClassA { - static Logger logger = Logger.getLogger(ClassA.class.getName()); - } - - private static class ClassB { - static Logger logger = Logger.getLogger(ClassB.class.getName()); - } - - private ByteArrayOutputStream fakeErrorLog; - private PrintStream errPrintStream; - Logger fakeRootLogger, testLogger; - FakeHandler fakeFileLog; - ConsoleHandler consoleHandler; - - private void assertHasLoggedToStderr() { - errPrintStream.flush(); - assertTrue(fakeErrorLog.size() > 0); - } - - private void assertHasNotLoggedToStderr() { - errPrintStream.flush(); - assertEquals(fakeErrorLog.size(), 0); - } - - private void assertHasLoggedToFile() { - assertTrue(fakeFileLog.hasPublished); - } - - private void assertHasNotLoggedToFile() { - assertFalse(fakeFileLog.hasPublished); - } - - // Passes if logger log at least at the given level, directing to stderr. - private void assertErrorLogAtLevel(Logger logger, Level level) { - List<Level> levels = Arrays.asList( - Level.SEVERE, Level.WARNING, Level.INFO, Level.CONFIG, - Level.FINE, Level.FINER, Level.FINEST); - for (Level l : levels) { - logger.log(l, "Message"); - if (level.intValue() <= l.intValue()) { - assertHasLoggedToStderr(); - } else { - assertHasNotLoggedToStderr(); - } - resetLogs(); - } - } - - // Passes if logger does not allow verbose logging. - private void assertNoVerboseLogging(Logger logger) { - logger.config("Config"); - logger.fine("Fine"); - logger.finer("Finer"); - logger.finest("Finest"); - assertHasNotLoggedToStderr(); - assertHasNotLoggedToFile(); - } - - private void resetLogs() { - errPrintStream.flush(); - fakeErrorLog.reset(); - fakeFileLog.reset(); - } - - // The following two methods are used to inject our fake root logger, so to avoid test flakyness - // due to background threads. - private RootLogConfig.Builder getConfig() { - return RootLogConfig.builder().rootLoggerName(fakeRootLogger.getName()); - } - - private void setFakeRootForLogger(Logger logger) { - Preconditions.checkArgument(logger != fakeRootLogger); - logger.setUseParentHandlers(true); - logger.setParent(fakeRootLogger); - } - - @Before - public void setUp() { - // Intercept stderr (this must be done first). - fakeErrorLog = new ByteArrayOutputStream(); - errPrintStream = new PrintStream(fakeErrorLog); - System.setErr(errPrintStream); - - // Create other members - consoleHandler = new ConsoleHandler(); - fakeFileLog = new FakeHandler(); - - // Emulate default setup (just a console handler), but avoiding the use - // of the global root logger so not to get a flaky test due to background threads. - fakeRootLogger = Logger.getLogger("FakeRoot-" + UUID.randomUUID().toString()); - fakeRootLogger.setUseParentHandlers(false); - for (Handler h : fakeRootLogger.getHandlers()) { - fakeRootLogger.removeHandler(h); - } - fakeRootLogger.addHandler(consoleHandler); - - testLogger = Logger.getLogger(RootLogConfigTest.class.getName()); - testLogger.setUseParentHandlers(true); - testLogger.setParent(fakeRootLogger); - - setFakeRootForLogger(ClassA.logger); - setFakeRootForLogger(ClassB.logger); - - resetLogs(); - } - - @Test - public void testDefaultConfig() { - // Verify that default info, warning, severe logging goes to stderr, no logging below info. - assertErrorLogAtLevel(testLogger, Level.INFO); - resetLogs(); - assertNoVerboseLogging(testLogger); - } - - @Test - public void testLogToStderr() { - // Add a fake handler, verify that it works along with the console. - fakeRootLogger.addHandler(fakeFileLog); - testLogger.info("Info"); - assertHasLoggedToStderr(); - assertHasLoggedToFile(); - - // Configure logtostderr - getConfig().logToStderr(true).build().apply(); - resetLogs(); - - // Verify that severe, warning, info logs go to stderr only. - testLogger.severe("Severe"); - assertHasLoggedToStderr(); - assertHasNotLoggedToFile(); - resetLogs(); - testLogger.warning("Warning"); - assertHasLoggedToStderr(); - assertHasNotLoggedToFile(); - resetLogs(); - testLogger.info("Info"); - assertHasLoggedToStderr(); - assertHasNotLoggedToFile(); - resetLogs(); - - assertNoVerboseLogging(testLogger); - } - - @Test - public void testAlsoLogToStderr() { - // Add a fake handler, remove console handler, verify that it works. - fakeRootLogger.removeHandler(consoleHandler); - fakeRootLogger.addHandler(fakeFileLog); - testLogger.info("Info"); - assertHasNotLoggedToStderr(); - assertHasLoggedToFile(); - resetLogs(); - - // Configure alsologtostderr - getConfig().alsoLogToStderr(true).build().apply(); - resetLogs(); - - // Verify that severe, warning, info logs go to both. - testLogger.severe("Severe"); - assertHasLoggedToStderr(); - assertHasLoggedToFile(); - resetLogs(); - testLogger.warning("Warning"); - assertHasLoggedToStderr(); - assertHasLoggedToFile(); - resetLogs(); - testLogger.info("Info"); - assertHasLoggedToStderr(); - assertHasLoggedToFile(); - resetLogs(); - - assertNoVerboseLogging(testLogger); - } - - @Test - public void testLogToStderrOverridesAlsoLogToStderr() { - // Add a fake handler, remove console handler, verify that it works. - fakeRootLogger.removeHandler(consoleHandler); - fakeRootLogger.addHandler(fakeFileLog); - testLogger.info("Info"); - assertHasNotLoggedToStderr(); - assertHasLoggedToFile(); - - // Configure with logtostderr AND alsologtostderr - getConfig().logToStderr(true).alsoLogToStderr(true).build().apply(); - resetLogs(); - - // Verify that severe, warning, info logs go to stderr only. - testLogger.severe("Severe"); - assertHasLoggedToStderr(); - assertHasNotLoggedToFile(); - resetLogs(); - testLogger.warning("Warning"); - assertHasLoggedToStderr(); - assertHasNotLoggedToFile(); - resetLogs(); - testLogger.info("Info"); - assertHasLoggedToStderr(); - assertHasNotLoggedToFile(); - resetLogs(); - - assertNoVerboseLogging(testLogger); - } - - @Test - public void testUseGLogFormatter() { - // Configure glogformatter. We test in "logtostderr" mode so to verify correct formatting - // for both handlers. - getConfig().logToStderr(true).useGLogFormatter(true).build().apply(); - resetLogs(); - - testLogger.severe("Severe Log Message"); - assertHasLoggedToStderr(); - String output = fakeErrorLog.toString(); - // Verify that it is all in one line and chope the \n. - assertTrue(output.split("\n").length == 1); - assertTrue(output.endsWith("\n")); - output = output.replaceAll("\n", ""); - - // Verify that it is on glog format. - assertTrue("Unexpected output: " + output, - output.matches("E\\d+ " // Level, month, day. - + "\\d\\d:\\d\\d:\\d\\d\\.\\d+ " // Timestamp. - + "THREAD\\d+ " // Thread id. - + RootLogConfigTest.class.getName() + "\\.testUseGLogFormatter: " // Class name. - + "Severe Log Message" // Message. - )); - } - - @Test - public void testVlog() { - // Configure with logtoStderr and vlog==FINE; - getConfig().logToStderr(true).vlog(RootLogConfig.LogLevel.FINE).build().apply(); - resetLogs(); - - // Verify logging at levels fine and above. - assertErrorLogAtLevel(testLogger, Level.FINE); - } - - @Test - public void testVModule() { - // Configure with ClassA using FINE and ClassB using WARNING; - Map<Class<?>, RootLogConfig.LogLevel> vmoduleMap = - ImmutableMap.of(ClassA.class, RootLogConfig.LogLevel.FINE, - ClassB.class, RootLogConfig.LogLevel.WARNING); - getConfig().logToStderr(true).vmodule(vmoduleMap).build().apply(); - resetLogs(); - - // No verbose logging other than in ClassA and ClassB. - assertNoVerboseLogging(testLogger); - - // ClassA logs at FINE and above - assertErrorLogAtLevel(ClassA.logger, Level.FINE); - resetLogs(); - - // ClassB logs at WARNING and above - assertErrorLogAtLevel(ClassB.logger, Level.WARNING); - } - - @Test - public void testVModuleOverridesVlog() { - // Configure with ClassA using FINE and ClassB using FINER; - Map<Class<?>, RootLogConfig.LogLevel> vmoduleMap = - ImmutableMap.of(ClassA.class, RootLogConfig.LogLevel.FINEST, - ClassB.class, RootLogConfig.LogLevel.INFO); - // Configure setting default vlog=FINER - getConfig() - .logToStderr(true).vlog(RootLogConfig.LogLevel.FINER).vmodule(vmoduleMap).build().apply(); - resetLogs(); - - // Default logging is at finer level. - assertErrorLogAtLevel(testLogger, Level.FINER); - - // ClassA logs at FINEST and above - assertErrorLogAtLevel(ClassA.logger, Level.FINEST); - resetLogs(); - - // ClassB logs at INFO and above - assertErrorLogAtLevel(ClassB.logger, Level.INFO); - } -} http://git-wip-us.apache.org/repos/asf/aurora/blob/d542bd1d/config/legacy_untested_classes.txt ---------------------------------------------------------------------- diff --git a/config/legacy_untested_classes.txt b/config/legacy_untested_classes.txt index f183518..6b71fd2 100644 --- a/config/legacy_untested_classes.txt +++ b/config/legacy_untested_classes.txt @@ -18,6 +18,8 @@ org/apache/aurora/scheduler/cron/quartz/CronSchedulerImpl org/apache/aurora/scheduler/cron/quartz/CronSchedulerImpl$1 org/apache/aurora/scheduler/http/AbortCallback org/apache/aurora/scheduler/http/JerseyTemplateServlet +org/apache/aurora/scheduler/http/LogConfig +org/apache/aurora/scheduler/http/LogConfig$LoggerConfig org/apache/aurora/scheduler/http/Maintenance org/apache/aurora/scheduler/http/Maintenance$1 org/apache/aurora/scheduler/http/Maintenance$2 http://git-wip-us.apache.org/repos/asf/aurora/blob/d542bd1d/examples/vagrant/upstart/aurora-scheduler-kerberos.conf ---------------------------------------------------------------------- diff --git a/examples/vagrant/upstart/aurora-scheduler-kerberos.conf b/examples/vagrant/upstart/aurora-scheduler-kerberos.conf index 4f43892..57fa312 100644 --- a/examples/vagrant/upstart/aurora-scheduler-kerberos.conf +++ b/examples/vagrant/upstart/aurora-scheduler-kerberos.conf @@ -24,12 +24,12 @@ env DIST_DIR=/home/vagrant/aurora/dist # Flags that control the behavior of the JVM. env JAVA_OPTS='-Djava.library.path=/usr/lib - -Dlog4j.configuration="file:///etc/zookeeper/conf/log4j.properties" + -Xdebug + -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 -Djava.security.krb5.conf=/home/vagrant/src/krb5-1.13.1/build/testdir/krb5.conf -Dsun.security.krb5.debug=true -Dsun.security.jgss.debug=true -Djavax.net.debug=all - -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 ' chdir /home/vagrant/aurora/dist/install/aurora-scheduler @@ -46,8 +46,6 @@ exec bin/aurora-scheduler \ -backup_dir=/var/lib/aurora/backups \ -thermos_executor_path=$DIST_DIR/thermos_executor.pex \ -thermos_executor_flags="--announcer-enable --announcer-ensemble localhost:2181" \ - -vlog=INFO \ - -logtostderr \ -allowed_container_types=MESOS,DOCKER \ -shiro_realm_modules=KERBEROS5_AUTHN,INI_AUTHNZ \ -shiro_ini_path=/home/vagrant/aurora/src/test/resources/org/apache/aurora/scheduler/http/api/security/shiro-example.ini \ http://git-wip-us.apache.org/repos/asf/aurora/blob/d542bd1d/examples/vagrant/upstart/aurora-scheduler.conf ---------------------------------------------------------------------- diff --git a/examples/vagrant/upstart/aurora-scheduler.conf b/examples/vagrant/upstart/aurora-scheduler.conf index 4033184..8120ff7 100644 --- a/examples/vagrant/upstart/aurora-scheduler.conf +++ b/examples/vagrant/upstart/aurora-scheduler.conf @@ -22,7 +22,10 @@ env LIBPROCESS_IP=192.168.33.7 env DIST_DIR=/home/vagrant/aurora/dist # Flags that control the behavior of the JVM. -env JAVA_OPTS='-Djava.library.path=/usr/lib -Dlog4j.configuration="file:///etc/zookeeper/conf/log4j.properties" -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005' +env JAVA_OPTS='-Djava.library.path=/usr/lib + -Xdebug + -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 +' chdir /home/vagrant/aurora/dist/install/aurora-scheduler exec bin/aurora-scheduler \ @@ -38,12 +41,10 @@ exec bin/aurora-scheduler \ -backup_dir=/var/lib/aurora/backups \ -thermos_executor_path=$DIST_DIR/thermos_executor.pex \ -thermos_executor_flags="--announcer-enable --announcer-ensemble localhost:2181" \ - -vlog=INFO \ - -logtostderr \ -allowed_container_types=MESOS,DOCKER \ -http_authentication_mechanism=BASIC \ -use_beta_db_task_store=true \ -shiro_ini_path=etc/shiro.example.ini \ -enable_h2_console=true \ -tier_config=/home/vagrant/aurora/src/test/resources/org/apache/aurora/scheduler/tiers-example.json \ - -receive_revocable_resources=true \ No newline at end of file + -receive_revocable_resources=true http://git-wip-us.apache.org/repos/asf/aurora/blob/d542bd1d/src/main/java/org/apache/aurora/scheduler/app/Log4jConfigurator.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/aurora/scheduler/app/Log4jConfigurator.java b/src/main/java/org/apache/aurora/scheduler/app/Log4jConfigurator.java deleted file mode 100644 index 348ff13..0000000 --- a/src/main/java/org/apache/aurora/scheduler/app/Log4jConfigurator.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * 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 org.apache.aurora.scheduler.app; - -import java.util.Objects; - -import org.apache.aurora.common.logging.RootLogConfig; -import org.apache.aurora.common.logging.RootLogConfig.Configuration; -import org.apache.aurora.common.logging.log4j.GlogLayout; -import org.apache.log4j.BasicConfigurator; -import org.apache.log4j.ConsoleAppender; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; - -/** - * Configures log4j logging. - */ -final class Log4jConfigurator { - private static final org.slf4j.Logger LOG = - org.slf4j.LoggerFactory.getLogger(Log4jConfigurator.class.getName()); - - /** - * Configures log4j to log to stderr with a glog format. - * - * @param glogConfig The glog configuration in effect. - */ - static void configureConsole(Configuration glogConfig) { - Objects.requireNonNull(glogConfig); - - BasicConfigurator.configure( - new ConsoleAppender(new GlogLayout(), ConsoleAppender.SYSTEM_ERR)); - Logger.getRootLogger().setLevel(getLevel(glogConfig)); - } - - private static Level getLevel(RootLogConfig.Configuration logConfig) { - switch (logConfig.getVlog()) { - case FINEST: // fall through - case FINER: // fall through - case FINE: // fall through - case CONFIG: - return Level.TRACE; - case INFO: - return Level.INFO; - case WARNING: - return Level.WARN; - case SEVERE: - return Level.ERROR; - default: - LOG.warn("Mapping unexpected vlog value of {} to log4j TRACE", logConfig.getVlog()); - return Level.TRACE; - } - } - - private Log4jConfigurator() { - // Utility class. - } -} http://git-wip-us.apache.org/repos/asf/aurora/blob/d542bd1d/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java b/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java index de018dd..0659c35 100644 --- a/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java +++ b/src/main/java/org/apache/aurora/scheduler/app/SchedulerMain.java @@ -15,9 +15,7 @@ package org.apache.aurora.scheduler.app; import java.net.InetSocketAddress; import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicLong; @@ -44,8 +42,6 @@ import org.apache.aurora.common.args.CmdLine; import org.apache.aurora.common.args.constraints.NotEmpty; import org.apache.aurora.common.args.constraints.NotNull; import org.apache.aurora.common.inject.Bindings; -import org.apache.aurora.common.logging.RootLogConfig; -import org.apache.aurora.common.logging.RootLogConfig.LogLevel; import org.apache.aurora.common.stats.Stats; import org.apache.aurora.common.zookeeper.Group; import org.apache.aurora.common.zookeeper.SingletonService; @@ -72,38 +68,12 @@ import org.apache.aurora.scheduler.zookeeper.guice.client.flagged.FlaggedClientC import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static org.apache.aurora.common.logging.RootLogConfig.Configuration; - /** * Launcher for the aurora scheduler. */ public class SchedulerMain { private static final Logger LOG = LoggerFactory.getLogger(SchedulerMain.class); - @CmdLine(name = "logtostderr", help = "Log messages to stderr instead of logfiles.") - private static final Arg<Boolean> LOGTOSTDERR = Arg.create(false); - - @CmdLine(name = "alsologtostderr", - help = "Log messages to stderr, in addition to log files. Ignored when --logtostderr") - private static final Arg<Boolean> ALSOLOGTOSTDERR = Arg.create(false); - - @CmdLine(name = "vlog", - help = "The value is one of the constants in java.util.logging.Level. " - + "Shows all messages with level equal or higher " - + "than the value of this flag.") - private static final Arg<LogLevel> VLOG = Arg.create(LogLevel.INFO); - - @CmdLine(name = "vmodule", - help = "Per-class verbose level. The argument has to contain a comma-separated list " - + "of <class_name>=<log_level>. <class_name> is the full-qualified name of a " - + "class, <log_level> is one of the constants in java.util.logging.Level. " - + "<log_level> overrides any value given by --vlog.") - private static final Arg<Map<Class<?>, LogLevel>> VMODULE = - Arg.<Map<Class<?>, LogLevel>>create(new HashMap<>()); - - @CmdLine(name = "use_glog_formatter", help = "True to use the glog formatter exclusively.") - private static final Arg<Boolean> USE_GLOG_FORMATTER = Arg.create(true); - @NotNull @CmdLine(name = "cluster_name", help = "Name to identify the cluster being served.") private static final Arg<String> CLUSTER_NAME = Arg.create(); @@ -145,17 +115,6 @@ public class SchedulerMain { Runtime.getRuntime().addShutdownHook(new Thread(SchedulerMain.this::stop, "ShutdownHook")); startupServices.awaitHealthy(); - // Setup log4j to match our jul glog config in order to pick up zookeeper logging. - Configuration logConfiguration = RootLogConfig.builder() - .logToStderr(LOGTOSTDERR.get()) - .alsoLogToStderr(ALSOLOGTOSTDERR.get()) - .useGLogFormatter(USE_GLOG_FORMATTER.get()) - .vlog(VLOG.get()) - .vmodule(VMODULE.get()) - .build(); - logConfiguration.apply(); - Log4jConfigurator.configureConsole(logConfiguration); - LeadershipListener leaderListener = schedulerLifecycle.prepare(); HostAndPort httpAddress = httpService.getAddress(); http://git-wip-us.apache.org/repos/asf/aurora/blob/d542bd1d/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java b/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java index 6c5654b..df649ff 100644 --- a/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java +++ b/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java @@ -59,7 +59,6 @@ import org.apache.aurora.common.args.CmdLine; import org.apache.aurora.common.net.http.handlers.AbortHandler; import org.apache.aurora.common.net.http.handlers.ContentionPrinter; import org.apache.aurora.common.net.http.handlers.HealthHandler; -import org.apache.aurora.common.net.http.handlers.LogConfig; import org.apache.aurora.common.net.http.handlers.QuitHandler; import org.apache.aurora.common.net.http.handlers.ThreadStackPrinter; import org.apache.aurora.common.net.http.handlers.TimeSeriesDataSource; http://git-wip-us.apache.org/repos/asf/aurora/blob/d542bd1d/src/main/java/org/apache/aurora/scheduler/http/LogConfig.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/aurora/scheduler/http/LogConfig.java b/src/main/java/org/apache/aurora/scheduler/http/LogConfig.java new file mode 100644 index 0000000..47d1282 --- /dev/null +++ b/src/main/java/org/apache/aurora/scheduler/http/LogConfig.java @@ -0,0 +1,126 @@ +/** + * 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 org.apache.aurora.scheduler.http; + +import java.io.StringWriter; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import com.google.common.collect.FluentIterable; +import com.google.common.collect.Lists; +import com.google.common.collect.Ordering; + +import org.apache.aurora.common.util.templating.StringTemplateHelper; +import org.apache.aurora.common.util.templating.StringTemplateHelper.TemplateException; +import org.apache.commons.lang.StringUtils; +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; + +/** + * Servlet that allows for dynamic adjustment of the logging configuration. + * + * @author William Farner + */ +@Path("/logconfig") +public class LogConfig { + private static final List<String> LOG_LEVELS = Lists.newArrayList( + Level.OFF.levelStr, + Level.ERROR.levelStr, + Level.WARN.levelStr, + Level.INFO.levelStr, + Level.DEBUG.levelStr, + Level.TRACE.levelStr, + Level.ALL.levelStr, + "INHERIT" // Display value for a null level, the logger inherits from its ancestor. + ); + + private final StringTemplateHelper template = + new StringTemplateHelper(getClass(), "logconfig", false); + + @POST + @Produces(MediaType.TEXT_HTML) + public String post( + @FormParam("logger") String loggerName, + @FormParam("level") String loggerLevel) throws TemplateException { + + Optional<String> configChange = Optional.empty(); + if (loggerName != null && loggerLevel != null) { + Logger logger = (Logger) LoggerFactory.getLogger(loggerName); + Level newLevel = Level.toLevel(loggerLevel, null); + logger.setLevel(newLevel); + + configChange = Optional.of(String.format("%s level changed to %s", loggerName, loggerLevel)); + } + + return displayPage(configChange); + } + + @GET + @Produces(MediaType.TEXT_HTML) + public String get() throws TemplateException { + return displayPage(Optional.empty()); + } + + protected String displayPage(Optional<String> configChange) throws TemplateException { + StringWriter writer = new StringWriter(); + + template.writeTemplate(writer, stringTemplate -> { + if (configChange.isPresent()) { + stringTemplate.setAttribute("configChange", configChange.get()); + } + + LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); + + Set<LoggerConfig> loggers = FluentIterable.from(context.getLoggerList()) + .transform(logger -> new LoggerConfig( + logger.getName(), + Optional.ofNullable(logger.getLevel()).map(l -> l.levelStr).orElse("INHERIT"))) + .toSortedSet(Ordering.natural().onResultOf(LoggerConfig::getName)); + + stringTemplate.setAttribute("loggers", loggers); + stringTemplate.setAttribute("levels", LOG_LEVELS); + }); + + return writer.toString(); + } + + private static class LoggerConfig { + private final String name; + private final String level; + + LoggerConfig(String name, String level) { + this.name = name; + this.level = StringUtils.isBlank(level) ? "INHERIT" : level; + } + + public String getName() { + return name; + } + + public String getLevel() { + return level; + } + } +} http://git-wip-us.apache.org/repos/asf/aurora/blob/d542bd1d/src/main/resources/logback.xml ---------------------------------------------------------------------- diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..faf0dbc --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,33 @@ +<?xml version="1.0"?> +<!-- +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this work except in compliance with the License. +You may obtain a copy of the License in the LICENSE file, or 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. +--> +<!-- + According to logback documentation, a file on the classpath named logback.xml will be the last + search target before falling back to a default. As such, we include logback.xml on the classpath + to provide a reasonable default, but allow users to override in any format they wish. + http://logback.qos.ch/manual/configuration.html +--> +<configuration> + <appender name="STDERR" class="ch.qos.logback.core.ConsoleAppender"> + <target>System.err</target> + <encoder> + <pattern> + %.-1level%date{MMdd HH:mm:ss.SSS} [%thread, %class{0}:%line] %message %xThrowable%n + </pattern> + </encoder> + </appender> + <root level="info"> + <appender-ref ref="STDERR" /> + </root> +</configuration> http://git-wip-us.apache.org/repos/asf/aurora/blob/d542bd1d/src/main/resources/org/apache/aurora/scheduler/http/logconfig.st ---------------------------------------------------------------------- diff --git a/src/main/resources/org/apache/aurora/scheduler/http/logconfig.st b/src/main/resources/org/apache/aurora/scheduler/http/logconfig.st new file mode 100644 index 0000000..02b85c2 --- /dev/null +++ b/src/main/resources/org/apache/aurora/scheduler/http/logconfig.st @@ -0,0 +1,44 @@ +<html> + <title>Logger Config</title> + <head> + <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script> + </head> + <body> + <table border=1 cellpadding=0 cellspacing=0 align=left> + <tr> + <th>Logger</th> + <th>Level</th> + </tr> + $loggers:{ logger | + <tr> + <td>$logger.name$</td> + <td> + <select id="$logger.name$" name="level" class="selectlevels" data-loglevel="$logger.level$"> + $levels:{ level | + <option value='$level$'>$level$</option> + }$ + </select> + </td> + </tr> + }$ + </table> + <script> + \$(document).ready(function() { + // For every logger changed the select to match the current level. + \$('.selectlevels').each(function() { + \$(this).val(\$(this).data('loglevel')); + }); + // Every time a logger value is changed post the logger name and new level. + \$('.selectlevels').change(function() { + \$.post("/logconfig", + { logger : \$(this).attr('id'), level : \$(this).val() }, + function() { + // Reload the page so the new logger value is visible. + location.reload(); + } + ); + }); + }); + </script> + </body> +</html>
