All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.atlassian.bamboo.specs.util.Logger Maven / Gradle / Ivy

There is a newer version: 10.1.0
Show newest version
package com.atlassian.bamboo.specs.util;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;

import java.io.PrintStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Optional;

/**
 * Simple utility for logging to {@link System#out} at various log levels. Logging level is controlled by a system
 * property {@link Logger#LOG_LEVEL_PROPERTY}.
 *
 * @see Logger#LOG_LEVEL_PROPERTY
 * @see Logger.LogLevel
 */
public final class Logger {

    /**
     * Available levels of logging.
     */
    public enum LogLevel {
        /**
         * Default logging level.
         */
        INFO(1),

        /**
         * More detailed logging level.
         */
        DEBUG(2),

        /**
         * Most detailed logging level.
         */
        TRACE(3);

        LogLevel(int detailLevel) {
            this.detailLevel = detailLevel;
        }

        private final int detailLevel;

        /**
         * Whether the message at given {@code logLevel} should be logged.
         * 

* For example, if current logging level is {@link LogLevel#DEBUG}, the method will return true for logging at * {@link LogLevel#INFO}, but false for logging at {@link LogLevel#TRACE}. * * @param logLevel log level of the message * @return true if current log level is considered detailed enough for the passed {@code logLevel} to log the * message, false otherwise */ public boolean shouldLog(LogLevel logLevel) { return this.detailLevel >= logLevel.detailLevel; } } private static final ThreadLocal DATE_FORMAT = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS")); /** * Name of system property which will indicate logging level. The value should be set to one of the values of * {@link LogLevel} enum (case insensitive). *

* Usage example: *

{@code java -Dbamboo.specs.log.level=DEBUG ...}
*/ public static final String LOG_LEVEL_PROPERTY = "bamboo.specs.log.level"; /** * Name of system property which will indicate if date should be hidden in the log. Default is false. *

* Usage example: *

{@code java -Dbamboo.specs.log.hideDate=true ...}
*/ public static final String LOG_HIDE_DATE = "bamboo.specs.log.hideDate"; /** * Current log level. */ public static final LogLevel LOG_LEVEL = getLogLevel(); private final Class forClass; private final PrintStream printStream; private Logger(@NotNull Class forClass) { this(forClass, System.out); } // for testing Logger(@NotNull Class forClass, @NotNull PrintStream printStream) { this.forClass = forClass; this.printStream = printStream; } /** * Returns an instance of the logger for the given {@code class}. */ @NotNull public static Logger getLogger(@NotNull Class forClass) { return new Logger(forClass); } /** * Logs the given {@code message} at {@link LogLevel#INFO} level. The message is formatted using * {@link String#format(String, Object...)}. */ public void info(@NotNull String message, @NotNull Object... args) { log(LogLevel.INFO, message, args); } /** * Logs the given {@code throwable} at {@link LogLevel#INFO} level. */ public void info(@NotNull Throwable throwable) { log(LogLevel.INFO, throwable); } /** * Logs the given {@code throwable} and {@code message} at {@link LogLevel#INFO} level. The message is formatted * using {@link String#format(String, Object...)}. */ public void info(@NotNull Throwable throwable, @NotNull String message, @NotNull Object... args) { log(LogLevel.INFO, throwable, message, args); } /** * Logs the given {@code message} at {@link LogLevel#DEBUG} level. The message is formatted using * {@link String#format(String, Object...)}. */ public void debug(@NotNull String message, @NotNull Object... args) { log(LogLevel.DEBUG, message, args); } /** * Logs the given {@code throwable} at {@link LogLevel#DEBUG} level. */ public void debug(@NotNull Throwable throwable) { log(LogLevel.DEBUG, throwable); } /** * Logs the given {@code throwable} and {@code message} at {@link LogLevel#DEBUG} level. The message is formatted * using {@link String#format(String, Object...)}. */ public void debug(@NotNull Throwable throwable, @NotNull String message, @NotNull Object... args) { log(LogLevel.DEBUG, throwable, message, args); } /** * Logs the given {@code message} at {@link LogLevel#TRACE} level. The message is formatted using * {@link String#format(String, Object...)}. */ public void trace(@NotNull String message, @NotNull Object... args) { log(LogLevel.TRACE, message, args); } /** * Logs the given {@code throwable} at {@link LogLevel#TRACE} level. */ public void trace(@NotNull Throwable throwable) { log(LogLevel.TRACE, throwable); } /** * Logs the given {@code throwable} and {@code message} at {@link LogLevel#TRACE} level. The message is formatted * using {@link String#format(String, Object...)}. */ public void trace(@NotNull Throwable throwable, @NotNull String message, @NotNull Object... args) { log(LogLevel.TRACE, throwable, message, args); } /** * Logs the given {@code message} at {@code logLevel}. The message is formatted using * {@link String#format(String, Object...)}. */ public void log(@NotNull LogLevel logLevel, @NotNull String message, @NotNull Object... args) { if (getLogLevel().shouldLog(logLevel)) { prefixLogLine(logLevel); printStream.println(ArrayUtils.isNotEmpty(args) ? String.format(message, args) : message); } } /** * Logs the given {@code throwable} at {@code logLevel} level. */ public void log(@NotNull LogLevel logLevel, @NotNull Throwable throwable) { if (getLogLevel().shouldLog(logLevel)) { prefixLogLine(logLevel); throwable.printStackTrace(printStream); } } /** * Logs the given {@code throwable} and {@code message} at {@code logLevel}. The message is formatted * using {@link String#format(String, Object...)}. */ public void log(@NotNull LogLevel logLevel, @NotNull Throwable throwable, @NotNull String message, @NotNull Object... args) { log(logLevel, message, args); log(logLevel, throwable); } /** * Returns true if logging at {@link LogLevel#INFO} is enabled. */ public boolean isInfoEnabled() { return getLogLevel().shouldLog(LogLevel.INFO); } /** * Returns true if logging at {@link LogLevel#DEBUG} is enabled. */ public boolean isDebugEnabled() { return getLogLevel().shouldLog(LogLevel.DEBUG); } /** * Returns true if logging at {@link LogLevel#TRACE} is enabled. */ public boolean isTraceEnabled() { return getLogLevel().shouldLog(LogLevel.TRACE); } /** * Print prefix of the log line. * * @param logLevel at which log level is the message being printed */ private void prefixLogLine(LogLevel logLevel) { final boolean hideDate = Boolean.parseBoolean(System.getProperty(LOG_HIDE_DATE)); if (hideDate) { printStream.print(String.format("%s [%s] ", logLevel.name(), forClass.getSimpleName())); } else { printStream.print(String.format("%s %s [%s] ", DATE_FORMAT.get().format(new Date()), logLevel.name(), forClass.getSimpleName())); } } /** * Get current log level. */ @NotNull private static LogLevel getLogLevel() { return Optional.ofNullable(System.getProperty(LOG_LEVEL_PROPERTY)) .filter(StringUtils::isNotEmpty) .flatMap(levelStr -> Arrays.stream(LogLevel.values()) .filter(logLevel -> logLevel.name().equalsIgnoreCase(levelStr)) .findFirst()) .orElse(LogLevel.INFO); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy