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.PrintStream; 020import java.text.DateFormat; 021import java.text.SimpleDateFormat; 022import java.util.Date; 023import java.util.Map; 024 025import org.apache.logging.log4j.Level; 026import org.apache.logging.log4j.Marker; 027import org.apache.logging.log4j.ThreadContext; 028import org.apache.logging.log4j.message.Message; 029import org.apache.logging.log4j.message.MessageFactory; 030import org.apache.logging.log4j.spi.AbstractLogger; 031import org.apache.logging.log4j.util.PropertiesUtil; 032import org.apache.logging.log4j.util.Strings; 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 public SimpleLogger(final String name, final Level defaultLevel, final boolean showLogName, 062 final boolean showShortLogName, final boolean showDateTime, final boolean showContextMap, 063 final String dateTimeFormat, final MessageFactory messageFactory, final PropertiesUtil props, 064 final PrintStream stream) { 065 super(name, messageFactory); 066 final String lvl = props.getStringProperty(SimpleLoggerContext.SYSTEM_PREFIX + name + ".level"); 067 this.level = Level.toLevel(lvl, defaultLevel); 068 if (showShortLogName) { 069 final int index = name.lastIndexOf("."); 070 if (index > 0 && index < name.length()) { 071 this.logName = name.substring(index + 1); 072 } else { 073 this.logName = name; 074 } 075 } else if (showLogName) { 076 this.logName = name; 077 } else { 078 this.logName = null; 079 } 080 this.showDateTime = showDateTime; 081 this.showContextMap = showContextMap; 082 this.stream = stream; 083 084 if (showDateTime) { 085 try { 086 this.dateFormatter = new SimpleDateFormat(dateTimeFormat); 087 } catch (final IllegalArgumentException e) { 088 // If the format pattern is invalid - use the default format 089 this.dateFormatter = new SimpleDateFormat(SimpleLoggerContext.DEFAULT_DATE_TIME_FORMAT); 090 } 091 } 092 } 093 094 @Override 095 public Level getLevel() { 096 return level; 097 } 098 099 @Override 100 public boolean isEnabled(final Level testLevel, final Marker marker, final Message msg, final Throwable t) { 101 return this.level.intLevel() >= testLevel.intLevel(); 102 } 103 104 @Override 105 public boolean isEnabled(final Level testLevel, final Marker marker, final Object msg, final Throwable t) { 106 return this.level.intLevel() >= testLevel.intLevel(); 107 } 108 109 @Override 110 public boolean isEnabled(final Level testLevel, final Marker marker, final String msg) { 111 return this.level.intLevel() >= testLevel.intLevel(); 112 } 113 114 @Override 115 public boolean isEnabled(final Level testLevel, final Marker marker, final String msg, final Object... p1) { 116 return this.level.intLevel() >= testLevel.intLevel(); 117 } 118 119 @Override 120 public boolean isEnabled(final Level testLevel, final Marker marker, final String msg, final Throwable t) { 121 return this.level.intLevel() >= testLevel.intLevel(); 122 } 123 124 @Override 125 public void logMessage(final String fqcn, final Level mgsLevel, final Marker marker, final Message msg, 126 final Throwable throwable) { 127 final StringBuilder sb = new StringBuilder(); 128 // Append date-time if so configured 129 if (showDateTime) { 130 final Date now = new Date(); 131 String dateText; 132 synchronized (dateFormatter) { 133 dateText = dateFormatter.format(now); 134 } 135 sb.append(dateText); 136 sb.append(SPACE); 137 } 138 139 sb.append(mgsLevel.toString()); 140 sb.append(SPACE); 141 if (Strings.isNotEmpty(logName)) { 142 sb.append(logName); 143 sb.append(SPACE); 144 } 145 sb.append(msg.getFormattedMessage()); 146 if (showContextMap) { 147 final Map<String, String> mdc = ThreadContext.getImmutableContext(); 148 if (mdc.size() > 0) { 149 sb.append(SPACE); 150 sb.append(mdc.toString()); 151 sb.append(SPACE); 152 } 153 } 154 final Object[] params = msg.getParameters(); 155 Throwable t; 156 if (throwable == null && params != null && params.length > 0 157 && params[params.length - 1] instanceof Throwable) { 158 t = (Throwable) params[params.length - 1]; 159 } else { 160 t = throwable; 161 } 162 stream.println(sb.toString()); 163 if (t != null) { 164 stream.print(SPACE); 165 t.printStackTrace(stream); 166 } 167 } 168 169 public void setLevel(final Level level) { 170 if (level != null) { 171 this.level = level; 172 } 173 } 174 175 public void setStream(final PrintStream stream) { 176 this.stream = stream; 177 } 178 179}