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 */ 038 public class SimpleLogger extends AbstractLogger { 039 040 /** 041 * Used to format times. 042 * <p> 043 * Note that DateFormat is not Thread-safe. 044 */ 045 private DateFormat dateFormatter = null; 046 047 private Level level; 048 049 private final boolean showDateTime; 050 051 private final boolean showContextMap; 052 053 private PrintStream stream; 054 055 private String logName; 056 057 058 public SimpleLogger(final String name, final Level defaultLevel, final boolean showLogName, 059 final boolean showShortLogName, final boolean showDateTime, final boolean showContextMap, 060 final String dateTimeFormat, final MessageFactory messageFactory, final PropertiesUtil props, 061 final PrintStream stream) { 062 super(name, messageFactory); 063 final String lvl = props.getStringProperty(SimpleLoggerContext.SYSTEM_PREFIX + name + ".level"); 064 this.level = Level.toLevel(lvl, defaultLevel); 065 if (showShortLogName) { 066 final int index = name.lastIndexOf("."); 067 if (index > 0 && index < name.length()) { 068 this.logName = name.substring(index + 1); 069 } else { 070 this.logName = name; 071 } 072 } else if (showLogName) { 073 this.logName = name; 074 } 075 this.showDateTime = showDateTime; 076 this.showContextMap = showContextMap; 077 this.stream = stream; 078 079 if (showDateTime) { 080 try { 081 this.dateFormatter = new SimpleDateFormat(dateTimeFormat); 082 } catch (final IllegalArgumentException e) { 083 // If the format pattern is invalid - use the default format 084 this.dateFormatter = new SimpleDateFormat(SimpleLoggerContext.DEFAULT_DATE_TIME_FORMAT); 085 } 086 } 087 } 088 089 public void setStream(final PrintStream stream) { 090 this.stream = stream; 091 } 092 093 public Level getLevel() { 094 return level; 095 } 096 097 public void setLevel(final Level level) { 098 if (level != null) { 099 this.level = level; 100 } 101 } 102 103 @Override 104 public void log(final Marker marker, final String fqcn, final Level level, final Message msg, 105 final Throwable throwable) { 106 final StringBuilder sb = new StringBuilder(); 107 // Append date-time if so configured 108 if (showDateTime) { 109 final Date now = new Date(); 110 String dateText; 111 synchronized (dateFormatter) { 112 dateText = dateFormatter.format(now); 113 } 114 sb.append(dateText); 115 sb.append(" "); 116 } 117 118 sb.append(level.toString()); 119 sb.append(" "); 120 if (logName != null && logName.length() > 0) { 121 sb.append(logName); 122 sb.append(" "); 123 } 124 sb.append(msg.getFormattedMessage()); 125 if (showContextMap) { 126 final Map<String, String> mdc = ThreadContext.getContext(); 127 if (mdc.size() > 0) { 128 sb.append(" "); 129 sb.append(mdc.toString()); 130 sb.append(" "); 131 } 132 } 133 final Object[] params = msg.getParameters(); 134 Throwable t; 135 if (throwable == null && params != null && params[params.length - 1] instanceof Throwable) { 136 t = (Throwable) params[params.length - 1]; 137 } else { 138 t = throwable; 139 } 140 if (t != null) { 141 sb.append(" "); 142 final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 143 t.printStackTrace(new PrintStream(baos)); 144 sb.append(baos.toString()); 145 } 146 stream.println(sb.toString()); 147 } 148 149 @Override 150 protected boolean isEnabled(final Level level, final Marker marker, final String msg) { 151 return this.level.intLevel() >= level.intLevel(); 152 } 153 154 155 @Override 156 protected boolean isEnabled(final Level level, final Marker marker, final String msg, final Throwable t) { 157 return this.level.intLevel() >= level.intLevel(); 158 } 159 160 @Override 161 protected boolean isEnabled(final Level level, final Marker marker, final String msg, final Object... p1) { 162 return this.level.intLevel() >= level.intLevel(); 163 } 164 165 @Override 166 protected boolean isEnabled(final Level level, final Marker marker, final Object msg, final Throwable t) { 167 return this.level.intLevel() >= level.intLevel(); 168 } 169 170 @Override 171 protected boolean isEnabled(final Level level, final Marker marker, final Message msg, final Throwable t) { 172 return this.level.intLevel() >= level.intLevel(); 173 } 174 175 }