001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017 package org.apache.logging.log4j.simple;
018
019 import java.io.ByteArrayOutputStream;
020 import java.io.PrintStream;
021 import java.text.DateFormat;
022 import java.text.SimpleDateFormat;
023 import java.util.Date;
024 import java.util.Map;
025
026 import org.apache.logging.log4j.Level;
027 import org.apache.logging.log4j.Marker;
028 import org.apache.logging.log4j.ThreadContext;
029 import org.apache.logging.log4j.message.Message;
030 import org.apache.logging.log4j.message.MessageFactory;
031 import org.apache.logging.log4j.spi.AbstractLogger;
032 import org.apache.logging.log4j.util.PropertiesUtil;
033
034 /**
035 * This is the default logger that is used when no suitable logging implementation is available.
036 */
037 public class SimpleLogger extends AbstractLogger {
038
039 private static final long serialVersionUID = 1L;
040
041 private static final char SPACE = ' ';
042
043 /**
044 * Used to format times.
045 * <p>
046 * Note that DateFormat is not Thread-safe.
047 * </p>
048 */
049 private DateFormat dateFormatter;
050
051 private Level level;
052
053 private final boolean showDateTime;
054
055 private final boolean showContextMap;
056
057 private PrintStream stream;
058
059 private final String logName;
060
061
062 public SimpleLogger(final String name, final Level defaultLevel, final boolean showLogName,
063 final boolean showShortLogName, final boolean showDateTime, final boolean showContextMap,
064 final String dateTimeFormat, final MessageFactory messageFactory, final PropertiesUtil props,
065 final PrintStream stream) {
066 super(name, messageFactory);
067 final String lvl = props.getStringProperty(SimpleLoggerContext.SYSTEM_PREFIX + name + ".level");
068 this.level = Level.toLevel(lvl, defaultLevel);
069 if (showShortLogName) {
070 final int index = name.lastIndexOf(".");
071 if (index > 0 && index < name.length()) {
072 this.logName = name.substring(index + 1);
073 } else {
074 this.logName = name;
075 }
076 } else if (showLogName) {
077 this.logName = name;
078 } else {
079 this.logName = null;
080 }
081 this.showDateTime = showDateTime;
082 this.showContextMap = showContextMap;
083 this.stream = stream;
084
085 if (showDateTime) {
086 try {
087 this.dateFormatter = new SimpleDateFormat(dateTimeFormat);
088 } catch (final IllegalArgumentException e) {
089 // If the format pattern is invalid - use the default format
090 this.dateFormatter = new SimpleDateFormat(SimpleLoggerContext.DEFAULT_DATE_TIME_FORMAT);
091 }
092 }
093 }
094
095 @Override
096 public Level getLevel() {
097 return level;
098 }
099
100 @Override
101 public boolean isEnabled(final Level level, final Marker marker, final Message msg, final Throwable t) {
102 return this.level.intLevel() >= level.intLevel();
103 }
104
105 @Override
106 public boolean isEnabled(final Level level, final Marker marker, final Object msg, final Throwable t) {
107 return this.level.intLevel() >= level.intLevel();
108 }
109
110 @Override
111 public boolean isEnabled(final Level level, final Marker marker, final String msg) {
112 return this.level.intLevel() >= level.intLevel();
113 }
114
115 @Override
116 public boolean isEnabled(final Level level, final Marker marker, final String msg, final Object... p1) {
117 return this.level.intLevel() >= level.intLevel();
118 }
119
120 @Override
121 public boolean isEnabled(final Level level, final Marker marker, final String msg, final Throwable t) {
122 return this.level.intLevel() >= level.intLevel();
123 }
124
125 @Override
126 public void logMessage(final String fqcn, final Level level, final Marker marker, final Message msg,
127 final Throwable throwable) {
128 final StringBuilder sb = new StringBuilder();
129 // Append date-time if so configured
130 if (showDateTime) {
131 final Date now = new Date();
132 String dateText;
133 synchronized (dateFormatter) {
134 dateText = dateFormatter.format(now);
135 }
136 sb.append(dateText);
137 sb.append(SPACE);
138 }
139
140 sb.append(level.toString());
141 sb.append(SPACE);
142 if (logName != null && logName.length() > 0) {
143 sb.append(logName);
144 sb.append(SPACE);
145 }
146 sb.append(msg.getFormattedMessage());
147 if (showContextMap) {
148 final Map<String, String> mdc = ThreadContext.getContext();
149 if (mdc.size() > 0) {
150 sb.append(SPACE);
151 sb.append(mdc.toString());
152 sb.append(SPACE);
153 }
154 }
155 final Object[] params = msg.getParameters();
156 Throwable t;
157 if (throwable == null && params != null && params.length > 0 && params[params.length - 1] instanceof Throwable) {
158 t = (Throwable) params[params.length - 1];
159 } else {
160 t = throwable;
161 }
162 if (t != null) {
163 sb.append(SPACE);
164 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
165 t.printStackTrace(new PrintStream(baos));
166 sb.append(baos.toString());
167 }
168 stream.println(sb.toString());
169 }
170
171 public void setLevel(final Level level) {
172 if (level != null) {
173 this.level = level;
174 }
175 }
176
177 public void setStream(final PrintStream stream) {
178 this.stream = stream;
179 }
180
181 }