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