    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    public 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    }