001/*
002 * Syncany, www.syncany.org
003 * Copyright (C) 2011-2016 Philipp C. Heckel <philipp.heckel@gmail.com>
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU General Public License as published by
007 * the Free Software Foundation, either version 3 of the License, or
008 * (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU General Public License for more details.
014 *
015 * You should have received a copy of the GNU General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018package org.syncany.config;
019
020import java.io.PrintWriter;
021import java.io.StringWriter;
022import java.io.Writer;
023import java.text.DateFormat;
024import java.text.SimpleDateFormat;
025import java.util.Date;
026import java.util.logging.Formatter;
027import java.util.logging.Level;
028import java.util.logging.LogRecord;
029
030/**
031 * The log formatter implements a {@link Formatter}. It is used by the application's
032 * logging functionality to pretty-print the log output.
033 *
034 * <p>Log format:
035 * <ul>
036 *   <li>Date/time</li>
037 *   <li>Logger name</li>
038 *   <li>Thread name</li>
039 *   <li>Log level</li>
040 *   <li>Log message</li>
041 * </ul>
042 *
043 * <p><b>Note</b>: This class might not be directly referenced through code
044 * Instead, it can be referenced (and instantiated) using a logging.properties
045 * file.
046 *
047 * @author Philipp C. Heckel (philipp.heckel@gmail.com)
048 */
049public class LogFormatter extends Formatter {
050        private DateFormat dateFormat;
051
052        public LogFormatter() {
053                this.dateFormat = new SimpleDateFormat("d-M-yy H:mm:ss.SSS");
054        }
055
056        @Override
057        public String format(LogRecord record) {
058                StringBuilder sb = new StringBuilder();
059
060                sb.append(dateFormat.format(new Date(record.getMillis())));
061                sb.append(" | ").append(formatLoggerName(record.getLoggerName()));
062                sb.append(" | ").append(formatThreadName(Thread.currentThread().getName()));
063                sb.append(" | ").append(formatShortLogLevel(record.getLevel()));
064                sb.append(" : ").append(formatMessage(record));
065                sb.append('\n');
066
067                if (record.getThrown() != null) {
068                        sb.append(formatStackTrace(record.getThrown()));
069                }
070
071                return sb.toString();
072        }
073
074        private String formatLoggerName(String loggerName) {
075                if (loggerName.length() > 15) {
076                        loggerName = loggerName.substring(0, 15);
077                }
078
079                return String.format("%-15s", loggerName);
080        }
081
082        private String formatThreadName(String threadName) {
083                if (threadName.length() > 14) {
084                        threadName = threadName.substring(0, 14);
085                }
086
087                return String.format("%-14s", threadName);
088        }
089
090        private String formatShortLogLevel(Level level) {
091                if (level.getName().length() <= 4) {
092                        return level.getName();
093                }
094                else {
095                        return level.getName().substring(0, 4);
096                }
097        }
098
099        private String formatStackTrace(Throwable aThrowable) {
100                Writer result = new StringWriter();
101                PrintWriter printWriter = new PrintWriter(result);
102                aThrowable.printStackTrace(printWriter);
103
104                return result.toString();
105        }
106}