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 */ 017package org.apache.logging.log4j.simple; 018 019import java.io.ByteArrayOutputStream; 020import java.io.PrintStream; 021import java.text.DateFormat; 022import java.text.SimpleDateFormat; 023import java.util.Date; 024import java.util.Map; 025 026import org.apache.logging.log4j.Level; 027import org.apache.logging.log4j.Marker; 028import org.apache.logging.log4j.ThreadContext; 029import org.apache.logging.log4j.message.Message; 030import org.apache.logging.log4j.message.MessageFactory; 031import org.apache.logging.log4j.spi.AbstractLogger; 032import 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 */ 037public 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}