logging: two log formatters: ColorfulConsoleFormatter and SimpleFormatter
authorFrantišek Kučera <franta-hg@frantovo.cz>
Mon, 17 Nov 2014 21:58:52 +0100
changeset 164634176c6602
parent 15 93fa6ce675e5
child 17 505031965440
logging: two log formatters: ColorfulConsoleFormatter and SimpleFormatter
java/copy-image-resizer/src/cz/frantovo/copyImageResizer/logging/AbstractFormatter.java
java/copy-image-resizer/src/cz/frantovo/copyImageResizer/logging/AbstractInitializer.java
java/copy-image-resizer/src/cz/frantovo/copyImageResizer/logging/ColorfulConsoleFormatter.java
java/copy-image-resizer/src/cz/frantovo/copyImageResizer/logging/ConsoleLoggerInitializer.java
java/copy-image-resizer/src/cz/frantovo/copyImageResizer/logging/SimpleFormatter.java
java/copy-image-resizer/src/cz/frantovo/copyImageResizer/logging/SimpleLoggerInitializer.java
scripts/copy-image-resizer.sh
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/logging/AbstractFormatter.java	Mon Nov 17 21:58:52 2014 +0100
     1.3 @@ -0,0 +1,46 @@
     1.4 +/**
     1.5 + * copy-image-resizer
     1.6 + * Copyright © 2013 František Kučera (frantovo.cz)
     1.7 + *
     1.8 + * This program is free software: you can redistribute it and/or modify
     1.9 + * it under the terms of the GNU General Public License as published by
    1.10 + * the Free Software Foundation, either version 3 of the License, or
    1.11 + * (at your option) any later version.
    1.12 + *
    1.13 + * This program is distributed in the hope that it will be useful,
    1.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    1.16 + * GNU General Public License for more details.
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License
    1.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
    1.20 + */
    1.21 +package cz.frantovo.copyImageResizer.logging;
    1.22 +
    1.23 +import java.util.logging.Formatter;
    1.24 +
    1.25 +/**
    1.26 + *
    1.27 + * @author Ing. František Kučera (frantovo.cz)
    1.28 + */
    1.29 +public abstract class AbstractFormatter extends Formatter {
    1.30 +
    1.31 +	protected static String rpad(String s, int n) {
    1.32 +		if (n > 0) {
    1.33 +			return String.format("%1$-" + n + "s", s);
    1.34 +		} else {
    1.35 +			return s;
    1.36 +		}
    1.37 +	}
    1.38 +
    1.39 +	private boolean printStacktrace = false;
    1.40 +
    1.41 +	public boolean isPrintStacktrace() {
    1.42 +		return printStacktrace;
    1.43 +	}
    1.44 +
    1.45 +	public void setPrintStacktrace(boolean printStacktrace) {
    1.46 +		this.printStacktrace = printStacktrace;
    1.47 +	}
    1.48 +
    1.49 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/logging/AbstractInitializer.java	Mon Nov 17 21:58:52 2014 +0100
     2.3 @@ -0,0 +1,76 @@
     2.4 +/**
     2.5 + * copy-image-resizer
     2.6 + * Copyright © 2013 František Kučera (frantovo.cz)
     2.7 + *
     2.8 + * This program is free software: you can redistribute it and/or modify
     2.9 + * it under the terms of the GNU General Public License as published by
    2.10 + * the Free Software Foundation, either version 3 of the License, or
    2.11 + * (at your option) any later version.
    2.12 + *
    2.13 + * This program is distributed in the hope that it will be useful,
    2.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    2.16 + * GNU General Public License for more details.
    2.17 + *
    2.18 + * You should have received a copy of the GNU General Public License
    2.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
    2.20 + */
    2.21 +package cz.frantovo.copyImageResizer.logging;
    2.22 +
    2.23 +import cz.frantovo.copyImageResizer.Constants;
    2.24 +import java.util.logging.ConsoleHandler;
    2.25 +import java.util.logging.Handler;
    2.26 +import java.util.logging.Level;
    2.27 +import java.util.logging.Logger;
    2.28 +
    2.29 +/**
    2.30 + *
    2.31 + * @author Ing. František Kučera (frantovo.cz)
    2.32 + */
    2.33 +public abstract class AbstractInitializer {
    2.34 +
    2.35 +	private static final Logger log = Logger.getLogger(AbstractInitializer.class.getName());
    2.36 +
    2.37 +	public static final String LEVEL_PROPERTY = AbstractInitializer.class.getName() + ".level";
    2.38 +	protected static final Level DEFAULT_LEVEL = Level.INFO;
    2.39 +
    2.40 +	protected abstract AbstractFormatter createFormatter();
    2.41 +
    2.42 +	public AbstractInitializer() {
    2.43 +		Logger logger = Logger.getLogger(Constants.JAVA_PACKAGE);
    2.44 +		ConsoleHandler handler = new ConsoleHandler();
    2.45 +		AbstractFormatter formatter = createFormatter();
    2.46 +
    2.47 +		logger.addHandler(handler);
    2.48 +		handler.setFormatter(formatter);
    2.49 +
    2.50 +		setLevel(logger, handler, formatter);
    2.51 +
    2.52 +		/**
    2.53 +		 * TODO: optional FileHandler – detailed logs in file in ~/sql-dk/log/…
    2.54 +		 */
    2.55 +	}
    2.56 +
    2.57 +	protected void setLevel(Logger logger, Handler handler, AbstractFormatter formatter) {
    2.58 +		boolean levelParseError = false;
    2.59 +		Level level;
    2.60 +		String cliLevel = System.getProperty(LEVEL_PROPERTY);
    2.61 +		if (cliLevel == null) {
    2.62 +			level = DEFAULT_LEVEL;
    2.63 +		} else {
    2.64 +			try {
    2.65 +				level = Level.parse(cliLevel);
    2.66 +			} catch (IllegalArgumentException e) {
    2.67 +				level = DEFAULT_LEVEL;
    2.68 +				levelParseError = true;
    2.69 +			}
    2.70 +		}
    2.71 +		handler.setLevel(level);
    2.72 +		logger.setLevel(level);
    2.73 +		if (levelParseError) {
    2.74 +			log.log(Level.WARNING, "Invalid logging level \u201e{0}\u201c specified in \u201e{1}\u201c \u2192 using default level \u201e{2}\u201c", new Object[]{cliLevel, LEVEL_PROPERTY, DEFAULT_LEVEL});
    2.75 +		}
    2.76 +		formatter.setPrintStacktrace(level.intValue() < Level.INFO.intValue());
    2.77 +	}
    2.78 +
    2.79 +}
     3.1 --- a/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/logging/ColorfulConsoleFormatter.java	Mon Nov 17 20:38:38 2014 +0100
     3.2 +++ b/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/logging/ColorfulConsoleFormatter.java	Mon Nov 17 21:58:52 2014 +0100
     3.3 @@ -20,7 +20,6 @@
     3.4  import cz.frantovo.copyImageResizer.logging.ColorfulPrintWriter.TerminalColor;
     3.5  import cz.frantovo.copyImageResizer.logging.ColorfulPrintWriter.TerminalStyle;
     3.6  import java.io.StringWriter;
     3.7 -import java.util.logging.Formatter;
     3.8  import java.util.logging.Level;
     3.9  import java.util.logging.LogRecord;
    3.10  
    3.11 @@ -29,9 +28,7 @@
    3.12   *
    3.13   * @author Ing. František Kučera (frantovo.cz)
    3.14   */
    3.15 -public class ColorfulConsoleFormatter extends Formatter {
    3.16 -
    3.17 -	private boolean printStacktrace = false;
    3.18 +public class ColorfulConsoleFormatter extends AbstractFormatter {
    3.19  
    3.20  	@Override
    3.21  	public String format(LogRecord r) {
    3.22 @@ -71,7 +68,7 @@
    3.23  				out.print(": ");
    3.24  				out.print(message);
    3.25  			}
    3.26 -			if (printStacktrace) {
    3.27 +			if (isPrintStacktrace()) {
    3.28  				out.println();
    3.29  				out.setForegroundColor(TerminalColor.Yellow);
    3.30  				out.setStyle(TerminalStyle.Dim);
    3.31 @@ -80,21 +77,4 @@
    3.32  			}
    3.33  		}
    3.34  	}
    3.35 -
    3.36 -	public boolean isPrintStacktrace() {
    3.37 -		return printStacktrace;
    3.38 -	}
    3.39 -
    3.40 -	public void setPrintStacktrace(boolean printStacktrace) {
    3.41 -		this.printStacktrace = printStacktrace;
    3.42 -	}
    3.43 -
    3.44 -	private static String rpad(String s, int n) {
    3.45 -		if (n > 0) {
    3.46 -			return String.format("%1$-" + n + "s", s);
    3.47 -		} else {
    3.48 -			return s;
    3.49 -		}
    3.50 -	}
    3.51 -
    3.52  }
     4.1 --- a/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/logging/ConsoleLoggerInitializer.java	Mon Nov 17 20:38:38 2014 +0100
     4.2 +++ b/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/logging/ConsoleLoggerInitializer.java	Mon Nov 17 21:58:52 2014 +0100
     4.3 @@ -17,62 +17,17 @@
     4.4   */
     4.5  package cz.frantovo.copyImageResizer.logging;
     4.6  
     4.7 -import cz.frantovo.copyImageResizer.Constants;
     4.8 -import java.util.logging.ConsoleHandler;
     4.9 -import java.util.logging.Handler;
    4.10 -import java.util.logging.Level;
    4.11 -import java.util.logging.Logger;
    4.12 -
    4.13  /**
    4.14   * Configures logging subsystem.
    4.15 - * Usage: java -Djava.util.logging.config.class=info.globalcode.sql.dk.logging.ConsoleLoggerInitializer …
    4.16 + * Usage: java
    4.17 + * -Djava.util.logging.config.class=cz.frantovo.copyImageResizer.logging.ConsoleLoggerInitializer …
    4.18   *
    4.19   * @author Ing. František Kučera (frantovo.cz)
    4.20   */
    4.21 -public class ConsoleLoggerInitializer {
    4.22 +public class ConsoleLoggerInitializer extends AbstractInitializer {
    4.23  
    4.24 -	private static final Logger log = Logger.getLogger(ConsoleLoggerInitializer.class.getName());
    4.25 -	public static final String LEVEL_PROPERTY = ConsoleLoggerInitializer.class.getName() + ".level";
    4.26 -	private static final Level DEFAULT_LEVEL = Level.INFO;
    4.27 -
    4.28 -	public ConsoleLoggerInitializer() {
    4.29 -		Logger logger = Logger.getLogger(Constants.JAVA_PACKAGE);
    4.30 -		ConsoleHandler handler = new ConsoleHandler();
    4.31 -		ColorfulConsoleFormatter formatter = new ColorfulConsoleFormatter();
    4.32 -
    4.33 -		logger.addHandler(handler);
    4.34 -		handler.setFormatter(formatter);
    4.35 -
    4.36 -		setLevel(logger, handler, formatter);
    4.37 -
    4.38 -
    4.39 -		/**
    4.40 -		 * TODO: optional FileHandler – detailed logs in file in ~/sql-dk/log/…
    4.41 -		 */
    4.42 -	}
    4.43 -
    4.44 -	private void setLevel(Logger logger, Handler handler, ColorfulConsoleFormatter formatter) {
    4.45 -		boolean levelParseError = false;
    4.46 -		Level level;
    4.47 -		String cliLevel = System.getProperty(LEVEL_PROPERTY);
    4.48 -		if (cliLevel == null) {
    4.49 -			level = DEFAULT_LEVEL;
    4.50 -		} else {
    4.51 -			try {
    4.52 -				level = Level.parse(cliLevel);
    4.53 -			} catch (IllegalArgumentException e) {
    4.54 -				level = DEFAULT_LEVEL;
    4.55 -				levelParseError = true;
    4.56 -			}
    4.57 -		}
    4.58 -
    4.59 -		handler.setLevel(level);
    4.60 -		logger.setLevel(level);
    4.61 -
    4.62 -		if (levelParseError) {
    4.63 -			log.log(Level.WARNING, "Invalid logging level „{0}“ specified in „{1}“ → using default level „{2}“", new Object[]{cliLevel, LEVEL_PROPERTY, DEFAULT_LEVEL});
    4.64 -		}
    4.65 -
    4.66 -		formatter.setPrintStacktrace(level.intValue() < Level.INFO.intValue());
    4.67 +	@Override
    4.68 +	protected AbstractFormatter createFormatter() {
    4.69 +		return new ColorfulConsoleFormatter();
    4.70  	}
    4.71  }
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/logging/SimpleFormatter.java	Mon Nov 17 21:58:52 2014 +0100
     5.3 @@ -0,0 +1,103 @@
     5.4 +/**
     5.5 + * copy-image-resizer
     5.6 + * Copyright © 2013 František Kučera (frantovo.cz)
     5.7 + *
     5.8 + * This program is free software: you can redistribute it and/or modify
     5.9 + * it under the terms of the GNU General Public License as published by
    5.10 + * the Free Software Foundation, either version 3 of the License, or
    5.11 + * (at your option) any later version.
    5.12 + *
    5.13 + * This program is distributed in the hope that it will be useful,
    5.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    5.16 + * GNU General Public License for more details.
    5.17 + *
    5.18 + * You should have received a copy of the GNU General Public License
    5.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
    5.20 + */
    5.21 +package cz.frantovo.copyImageResizer.logging;
    5.22 +
    5.23 +import java.io.PrintWriter;
    5.24 +import java.io.StringWriter;
    5.25 +import java.text.SimpleDateFormat;
    5.26 +import java.util.Date;
    5.27 +import java.util.logging.Level;
    5.28 +import java.util.logging.LogRecord;
    5.29 +
    5.30 +/**
    5.31 + * For console/terminal log output. Log messages are printed in brief and colorful form.
    5.32 + *
    5.33 + * @author Ing. František Kučera (frantovo.cz)
    5.34 + */
    5.35 +public class SimpleFormatter extends AbstractFormatter {
    5.36 +
    5.37 +	private static final ThreadLocal<SimpleDateFormat> dateFormatter = new ThreadLocal<SimpleDateFormat>() {
    5.38 +
    5.39 +		@Override
    5.40 +		protected SimpleDateFormat initialValue() {
    5.41 +			return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    5.42 +		}
    5.43 +
    5.44 +	};
    5.45 +
    5.46 +	@Override
    5.47 +	public String format(LogRecord r) {
    5.48 +		StringBuilder sb = new StringBuilder();
    5.49 +
    5.50 +		printTimestamp(sb, new Date(r.getMillis()));
    5.51 +		printSeparator(sb);
    5.52 +		printLevel(sb, r.getLevel());
    5.53 +		printSeparator(sb);
    5.54 +		printMessage(sb, r);
    5.55 +		printSeparator(sb);
    5.56 +		printThrowable(sb, r);
    5.57 +		sb.append("\n");
    5.58 +
    5.59 +		return sb.toString();
    5.60 +	}
    5.61 +
    5.62 +	private void printSeparator(StringBuilder out) {
    5.63 +		out.append(" | ");
    5.64 +	}
    5.65 +
    5.66 +	private void printTimestamp(StringBuilder out, Date date) {
    5.67 +		out.append(dateFormatter.get().format(date));
    5.68 +	}
    5.69 +
    5.70 +	private void printLevel(StringBuilder out, Level l) {
    5.71 +
    5.72 +		if (l == Level.SEVERE) {
    5.73 +			out.append(rpad("ERROR", 10));
    5.74 +		} else if (l == Level.INFO) {
    5.75 +			out.append(rpad("OK", 10));
    5.76 +		} else {
    5.77 +			out.append(rpad(l.getName(), 10));
    5.78 +		}
    5.79 +	}
    5.80 +
    5.81 +	private void printMessage(StringBuilder out, LogRecord r) {
    5.82 +		String message = formatMessage(r);
    5.83 +		// convert to single-line message
    5.84 +		message = message.replaceAll("\\\\", "\\\\"); // escape backslashes
    5.85 +		message = message.replaceAll("\\n", "\\n"); // escape line ends
    5.86 +		out.append(message);
    5.87 +	}
    5.88 +
    5.89 +	private void printThrowable(StringBuilder out, LogRecord r) {
    5.90 +		Throwable t = r.getThrown();
    5.91 +		if (t != null) {
    5.92 +			out.append(t.getClass().getSimpleName());
    5.93 +			String message = t.getLocalizedMessage();
    5.94 +			if (message != null) {
    5.95 +				out.append(": ");
    5.96 +				out.append(message);
    5.97 +			}
    5.98 +			if (isPrintStacktrace()) {
    5.99 +				out.append("\n");
   5.100 +				StringWriter sw = new StringWriter();
   5.101 +				t.printStackTrace(new PrintWriter(sw));
   5.102 +				out.append(sw.toString());
   5.103 +			}
   5.104 +		}
   5.105 +	}
   5.106 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/java/copy-image-resizer/src/cz/frantovo/copyImageResizer/logging/SimpleLoggerInitializer.java	Mon Nov 17 21:58:52 2014 +0100
     6.3 @@ -0,0 +1,36 @@
     6.4 +/**
     6.5 + * copy-image-resizer
     6.6 + * Copyright © 2013 František Kučera (frantovo.cz)
     6.7 + *
     6.8 + * This program is free software: you can redistribute it and/or modify
     6.9 + * it under the terms of the GNU General Public License as published by
    6.10 + * the Free Software Foundation, either version 3 of the License, or
    6.11 + * (at your option) any later version.
    6.12 + *
    6.13 + * This program is distributed in the hope that it will be useful,
    6.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    6.16 + * GNU General Public License for more details.
    6.17 + *
    6.18 + * You should have received a copy of the GNU General Public License
    6.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
    6.20 + */
    6.21 +package cz.frantovo.copyImageResizer.logging;
    6.22 +
    6.23 +/**
    6.24 + * Configures logging subsystem.
    6.25 + * Usage: java
    6.26 + * -Djava.util.logging.config.class=cz.frantovo.copyImageResizer.logging.SimpleLoggerInitializer …
    6.27 + *
    6.28 + * @author Ing. František Kučera (frantovo.cz)
    6.29 + */
    6.30 +public class SimpleLoggerInitializer extends AbstractInitializer {
    6.31 +
    6.32 +	public static final String LEVEL_PROPERTY = ConsoleLoggerInitializer.class.getName() + ".level";
    6.33 +
    6.34 +	@Override
    6.35 +	protected AbstractFormatter createFormatter() {
    6.36 +		return new SimpleFormatter();
    6.37 +	}
    6.38 +
    6.39 +}
     7.1 --- a/scripts/copy-image-resizer.sh	Mon Nov 17 20:38:38 2014 +0100
     7.2 +++ b/scripts/copy-image-resizer.sh	Mon Nov 17 21:58:52 2014 +0100
     7.3 @@ -19,6 +19,8 @@
     7.4  DIR="`dirname $0`";
     7.5  JAR="$DIR/../java/copy-image-resizer/dist/copy-image-resizer.jar";
     7.6  
     7.7 +# TODO: tune the path to the .jar file
     7.8 +
     7.9  LOGGER="-Djava.util.logging.config.class=info.globalcode.sql.dk.logging.LoggerInitializer";
    7.10  [ -n "$LOG_LEVEL" ] && LOGGER_LEVEL="-Dinfo.globalcode.sql.dk.logging.LoggerInitializer.level=$LOG_LEVEL";
    7.11  
    7.12 @@ -26,10 +28,14 @@
    7.13  
    7.14  MAIN_CLASS="cz.frantovo.copyImageResizer.cli.CLIStarter";
    7.15  
    7.16 -LOGGER_INITIALIZER_CLASS="cz.frantovo.copyImageResizer.logging.ConsoleLoggerInitializer";
    7.17 +# Customize logger output:
    7.18 +LOGGER_INITIALIZER_CLASS="cz.frantovo.copyImageResizer.logging.ConsoleLoggerInitializer"; # colorful log for interactive work (human readable)
    7.19 +LOGGER_INITIALIZER_CLASS="cz.frantovo.copyImageResizer.logging.SimpleLoggerInitializer";  # simple log for redirecting STDOUT to a file (machine readable)
    7.20 +
    7.21  LOGGER="-Djava.util.logging.config.class=$LOGGER_INITIALIZER_CLASS";
    7.22 -[ -n "$LOG_LEVEL" ] && LOGGER_LEVEL="-D$LOGGER_INITIALIZER_CLASS.level=$LOG_LEVEL";
    7.23 +
    7.24 +# by LOG_LEVEL variable you can set custom log level. Default is INFO. Possible values are: ALL, FINE, FINER, FINEST, CONFIG, INFO, OFF. SEVERE, WARNING (see java.util.logging.Level class)
    7.25 +[ -n "$LOG_LEVEL" ] && LOGGER_LEVEL="-Dcz.frantovo.copyImageResizer.logging.AbstractInitializer.level=$LOG_LEVEL";
    7.26  
    7.27  java $LOGGER $LOGGER_LEVEL -cp "$CLASS_PATH" $MAIN_CLASS "$@"
    7.28  
    7.29 -