001/* 002 * Copyright 2010-2019 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2010-2019 Ping Identity Corporation 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<>(); 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 = new ThreadLocal<>(); 065 066 067 068 /** 069 * The serial version UID for this serializable class. 070 */ 071 private static final long serialVersionUID = -2884878613513769233L; 072 073 074 075 // Indicates whether to include the log level in the message header. 076 private final boolean includeLevel; 077 078 // Indicates whether to include a line break after the header. 079 private final boolean lineBreakAfterHeader; 080 081 // Indicates whether to include a line break after the message. 082 private final boolean lineBreakAfterMessage; 083 084 // The format string that will be used to generate timestamps, if appropriate. 085 private final String timestampFormat; 086 087 088 089 /** 090 * Creates a new instance of this log formatter with the default settings. 091 * Generated messages will include a timestamp generated using the format 092 * string "{@code '['dd/MMM/yyyy:HH:mm:ss Z']'}", will not include the log 093 * level, and will not include a line break after the timestamp or the 094 * message. 095 */ 096 public MinimalLogFormatter() 097 { 098 this(DEFAULT_TIMESTAMP_FORMAT, false, false, false); 099 } 100 101 102 103 /** 104 * Creates a new instance of this log formatter with the provided 105 * configuration. 106 * 107 * @param timestampFormat The format string used to generate 108 * timestamps. If this is {@code null}, then 109 * timestamps will not be included in log 110 * messages. 111 * @param includeLevel Indicates whether to include the log level 112 * in the generated messages. 113 * @param lineBreakAfterHeader Indicates whether to insert a line break 114 * after the timestamp and/or log level. 115 * @param lineBreakAfterMessage Indicates whether to insert aline break 116 * after the generated message. 117 */ 118 public MinimalLogFormatter(final String timestampFormat, 119 final boolean includeLevel, 120 final boolean lineBreakAfterHeader, 121 final boolean lineBreakAfterMessage) 122 { 123 this.timestampFormat = timestampFormat; 124 this.includeLevel = includeLevel; 125 this.lineBreakAfterHeader = lineBreakAfterHeader; 126 this.lineBreakAfterMessage = lineBreakAfterMessage; 127 } 128 129 130 131 /** 132 * Formats the provided log record. 133 * 134 * @param record The log record to be formatted. 135 * 136 * @return A string containing the formatted log record. 137 */ 138 @Override() 139 public String format(final LogRecord record) 140 { 141 StringBuilder b = BUFFERS.get(); 142 if (b == null) 143 { 144 b = new StringBuilder(); 145 BUFFERS.set(b); 146 } 147 else 148 { 149 b.setLength(0); 150 } 151 152 if (timestampFormat != null) 153 { 154 SimpleDateFormat f = DATE_FORMATTERS.get(); 155 if (f == null) 156 { 157 f = new SimpleDateFormat(timestampFormat); 158 DATE_FORMATTERS.set(f); 159 } 160 161 b.append(f.format(new Date())); 162 } 163 164 if (includeLevel) 165 { 166 if (b.length() > 0) 167 { 168 b.append(' '); 169 } 170 171 b.append(record.getLevel().toString()); 172 } 173 174 if (lineBreakAfterHeader) 175 { 176 b.append(StaticUtils.EOL); 177 } 178 else if (b.length() > 0) 179 { 180 b.append(' '); 181 } 182 183 b.append(formatMessage(record)); 184 185 if (lineBreakAfterMessage) 186 { 187 b.append(StaticUtils.EOL); 188 } 189 190 return b.toString(); 191 } 192}