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 public void setStream(final PrintStream stream) { 096 this.stream = stream; 097 } 098 099 public Level getLevel() { 100 return level; 101 } 102 103 public void setLevel(final Level level) { 104 if (level != null) { 105 this.level = level; 106 } 107 } 108 109 @Override 110 public void log(final Marker marker, final String fqcn, final Level level, final Message msg, 111 final Throwable throwable) { 112 final StringBuilder sb = new StringBuilder(); 113 // Append date-time if so configured 114 if (showDateTime) { 115 final Date now = new Date(); 116 String dateText; 117 synchronized (dateFormatter) { 118 dateText = dateFormatter.format(now); 119 } 120 sb.append(dateText); 121 sb.append(SPACE); 122 } 123 124 sb.append(level.toString()); 125 sb.append(SPACE); 126 if (logName != null && logName.length() > 0) { 127 sb.append(logName); 128 sb.append(SPACE); 129 } 130 sb.append(msg.getFormattedMessage()); 131 if (showContextMap) { 132 final Map<String, String> mdc = ThreadContext.getContext(); 133 if (mdc.size() > 0) { 134 sb.append(SPACE); 135 sb.append(mdc.toString()); 136 sb.append(SPACE); 137 } 138 } 139 final Object[] params = msg.getParameters(); 140 Throwable t; 141 if (throwable == null && params != null && params[params.length - 1] instanceof Throwable) { 142 t = (Throwable) params[params.length - 1]; 143 } else { 144 t = throwable; 145 } 146 if (t != null) { 147 sb.append(SPACE); 148 final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 149 t.printStackTrace(new PrintStream(baos)); 150 sb.append(baos.toString()); 151 } 152 stream.println(sb.toString()); 153 } 154 155 @Override 156 protected boolean isEnabled(final Level level, final Marker marker, final String msg) { 157 return this.level.intLevel() >= level.intLevel(); 158 } 159 160 161 @Override 162 protected boolean isEnabled(final Level level, final Marker marker, final String msg, final Throwable t) { 163 return this.level.intLevel() >= level.intLevel(); 164 } 165 166 @Override 167 protected boolean isEnabled(final Level level, final Marker marker, final String msg, final Object... p1) { 168 return this.level.intLevel() >= level.intLevel(); 169 } 170 171 @Override 172 protected boolean isEnabled(final Level level, final Marker marker, final Object msg, final Throwable t) { 173 return this.level.intLevel() >= level.intLevel(); 174 } 175 176 @Override 177 protected boolean isEnabled(final Level level, final Marker marker, final Message msg, final Throwable t) { 178 return this.level.intLevel() >= level.intLevel(); 179 } 180 181}