View Javadoc
1   /*
2    * This file is a part of the SchemaSpy project (http://schemaspy.sourceforge.net).
3    * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 John Currier
4    *
5    * SchemaSpy is free software; you can redistribute it and/or
6    * modify it under the terms of the GNU Lesser General Public
7    * License as published by the Free Software Foundation; either
8    * version 2.1 of the License, or (at your option) any later version.
9    *
10   * SchemaSpy is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   * Lesser General Public License for more details.
14   *
15   * You should have received a copy of the GNU Lesser General Public
16   * License along with this library; if not, write to the Free Software
17   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18   */
19  package net.sourceforge.schemaspy.util;
20  
21  import java.io.PrintWriter;
22  import java.io.StringWriter;
23  import java.text.DateFormat;
24  import java.text.SimpleDateFormat;
25  import java.util.Date;
26  import java.util.logging.Formatter;
27  import java.util.logging.LogRecord;
28  
29  /**
30   * Format a LogRecord into a single concise line.
31   *
32   * @author John Currier
33   */
34  public class LogFormatter extends Formatter {
35      private final String lineSeparator = System.getProperty("line.separator");
36      private final int MAX_LEVEL_LEN = 7;
37      private static final String formatSpec = "HH:mm:ss.";
38  
39      /**
40       * Date formatter for time-to-text translation.
41       * These are very expensive to create and not thread-safe, so do it once per thread.
42       */
43      private static final ThreadLocal<DateFormat> dateFormatter = ThreadLocal.withInitial(() -> new SimpleDateFormat(formatSpec));
44  
45      /**
46       * Optimization to keep from creating a new {@link java.util.Date} for every call to
47       * {@link #toString()}.
48       */
49      private static final ThreadLocal<Date> date = ThreadLocal.withInitial(Date::new);
50  
51      /**
52       * Format the given LogRecord.
53       *
54       * @param logRecord
55       *            the log record to be formatted.
56       * @return a formatted log record
57       */
58      @Override
59      public String format(LogRecord logRecord) {
60          StringBuilder buf = new StringBuilder(128);
61  
62          // format the date portion:
63  
64          // thread-safe pseudo-singletons:
65          date.get().setTime(logRecord.getMillis());
66          buf.append(dateFormatter.get().format(date.get()));
67  
68          // compute frac as the number of milliseconds off of a whole second
69          long frac = logRecord.getMillis() % 1000;
70  
71          // force longFrac to overflow 1000 to give 1 followed by
72          // 'leading' zeros
73          frac += 1000;
74  
75          // append the fraction of a second at the end (w/o leading overflowed 1)
76          buf.append(Long.toString(frac).substring(1));
77  
78          buf.append(" ");
79          StringBuilder level = new StringBuilder(logRecord.getLevel().getLocalizedName());
80          if (level.length() > MAX_LEVEL_LEN)
81              level.setLength(MAX_LEVEL_LEN);
82          level.append(":");
83          while (level.length() < MAX_LEVEL_LEN + 1)
84              level.append(' ');
85          buf.append(level);
86          buf.append(" ");
87  
88          String name;
89          if (logRecord.getSourceClassName() != null) {
90              name = logRecord.getSourceClassName();
91          } else {
92              name = logRecord.getLoggerName();
93          }
94  
95          int lastDot = name.lastIndexOf('.');
96          if (lastDot >= 0 && lastDot < name.length() - 1)
97              name = name.substring(lastDot + 1);
98          buf.append(name);
99  
100         if (logRecord.getSourceMethodName() != null) {
101             buf.append('.');
102             buf.append(logRecord.getSourceMethodName());
103         }
104 
105         buf.append(" - ");
106         buf.append(formatMessage(logRecord));
107         buf.append(lineSeparator);
108 
109         if (logRecord.getThrown() != null) {
110             try {
111                 StringWriter stacktrace = new StringWriter();
112                 logRecord.getThrown().printStackTrace(new PrintWriter(stacktrace, true));
113                 buf.append(stacktrace);
114                 // stack trace already has a line separator
115             } catch (Exception ignore) {
116             }
117         }
118 
119         return buf.toString();
120     }
121 }