001/*
002 * Copyright 2010-2017 UnboundID Corp.
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2010-2017 UnboundID Corp.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021package com.unboundid.util;
022
023
024
025import java.io.Serializable;
026import java.text.SimpleDateFormat;
027import java.util.Date;
028import java.util.logging.Formatter;
029import java.util.logging.LogRecord;
030
031
032
033/**
034 * This class provides a log formatter for use in the Java logging framework
035 * that may be used to minimize the formatting applied to log messages.
036 */
037@NotMutable()
038@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
039public final class MinimalLogFormatter
040       extends Formatter
041       implements Serializable
042{
043  /**
044   * The default format string that will be used for generating timestamps.
045   */
046  public static final String DEFAULT_TIMESTAMP_FORMAT =
047       "'['dd/MMM/yyyy:HH:mm:ss Z']'";
048
049
050
051  /**
052   * The set of thread-local date formatters that will be used for generating
053   * message timestamps.
054   */
055  private static final ThreadLocal<SimpleDateFormat> DATE_FORMATTERS =
056       new ThreadLocal<SimpleDateFormat>();
057
058
059
060  /**
061   * The set of thread-local buffers that will be used for generating the
062   * message.
063   */
064  private static final ThreadLocal<StringBuilder> BUFFERS =
065       new ThreadLocal<StringBuilder>();
066
067
068
069  /**
070   * The serial version UID for this serializable class.
071   */
072  private static final long serialVersionUID = -2884878613513769233L;
073
074
075
076  // Indicates whether to include the log level in the message header.
077  private final boolean includeLevel;
078
079  // Indicates whether to include a line break after the header.
080  private final boolean lineBreakAfterHeader;
081
082  // Indicates whether to include a line break after the message.
083  private final boolean lineBreakAfterMessage;
084
085  // The format string that will be used to generate timestamps, if appropriate.
086  private final String timestampFormat;
087
088
089
090  /**
091   * Creates a new instance of this log formatter with the default settings.
092   * Generated messages will include a timestamp generated using the format
093   * string "{@code '['dd/MMM/yyyy:HH:mm:ss Z']'}", will not include the log
094   * level, and will not include a line break after the timestamp or the
095   * message.
096   */
097  public MinimalLogFormatter()
098  {
099    this(DEFAULT_TIMESTAMP_FORMAT, false, false, false);
100  }
101
102
103
104  /**
105   * Creates a new instance of this log formatter with the provided
106   * configuration.
107   *
108   * @param  timestampFormat        The format string used to generate
109   *                                timestamps.  If this is {@code null}, then
110   *                                timestamps will not be included in log
111   *                                messages.
112   * @param  includeLevel           Indicates whether to include the log level
113   *                                in the generated messages.
114   * @param  lineBreakAfterHeader   Indicates whether to insert a line break
115   *                                after the timestamp and/or log level.
116   * @param  lineBreakAfterMessage  Indicates whether to insert aline break
117   *                                after the generated message.
118   */
119  public MinimalLogFormatter(final String timestampFormat,
120                             final boolean includeLevel,
121                             final boolean lineBreakAfterHeader,
122                             final boolean lineBreakAfterMessage)
123  {
124    this.timestampFormat       = timestampFormat;
125    this.includeLevel          = includeLevel;
126    this.lineBreakAfterHeader  = lineBreakAfterHeader;
127    this.lineBreakAfterMessage = lineBreakAfterMessage;
128  }
129
130
131
132  /**
133   * Formats the provided log record.
134   *
135   * @param  record  The log record to be formatted.
136   *
137   * @return  A string containing the formatted log record.
138   */
139  @Override()
140  public String format(final LogRecord record)
141  {
142    StringBuilder b = BUFFERS.get();
143    if (b == null)
144    {
145      b = new StringBuilder();
146      BUFFERS.set(b);
147    }
148    else
149    {
150      b.setLength(0);
151    }
152
153    if (timestampFormat != null)
154    {
155      SimpleDateFormat f = DATE_FORMATTERS.get();
156      if (f == null)
157      {
158        f = new SimpleDateFormat(timestampFormat);
159        DATE_FORMATTERS.set(f);
160      }
161
162      b.append(f.format(new Date()));
163    }
164
165    if (includeLevel)
166    {
167      if (b.length() > 0)
168      {
169        b.append(' ');
170      }
171
172      b.append(record.getLevel().toString());
173    }
174
175    if (lineBreakAfterHeader)
176    {
177      b.append(StaticUtils.EOL);
178    }
179    else if (b.length() > 0)
180    {
181      b.append(' ');
182    }
183
184    b.append(formatMessage(record));
185
186    if (lineBreakAfterMessage)
187    {
188      b.append(StaticUtils.EOL);
189    }
190
191    return b.toString();
192  }
193}