001package org.slf4j.helpers;
002
003import java.io.PrintStream;
004
005/**
006 * An internally used class for reporting internal messages generated by SLF4J itself, typically
007 * during initialization.
008 *
009 * <p>
010 * Internal reporting is performed by calling the {@link #debug(String)}, {@link #info(String)},
011 * {@link #warn(String)} (String)} {@link #error(String)} (String)}  and
012 * {@link  #error(String, Throwable)} methods.
013 * </p>
014 * <p>See {@link #SLF4J_INTERNAL_VERBOSITY_KEY} and {@link #SLF4J_INTERNAL_REPORT_STREAM_KEY} for
015 * configuration options.</p>
016 * <p>
017 * <p>
018 * Note that this system is independent of the logging back-end in use.
019 *
020 * @since 2.0.10
021 */
022public class Reporter {
023
024    /**
025     * this class is used internally by Reporter
026     */
027    private enum Level {
028        DEBUG(0), INFO(1), WARN(2), ERROR(3);
029
030        int levelInt;
031
032        private Level(int levelInt) {
033            this.levelInt = levelInt;
034        }
035
036        private int getLevelInt() {
037            return levelInt;
038        }
039    }
040
041    private enum TargetChoice {
042        Stderr, Stdout;
043    }
044
045    static final String SLF4J_DEBUG_PREFIX = "SLF4J(D): ";
046    static final String SLF4J_INFO_PREFIX = "SLF4J(I): ";
047    static final String SLF4J_WARN_PREFIX = "SLF4J(W): ";
048    static final String SLF4J_ERROR_PREFIX = "SLF4J(E): ";
049
050
051    /**
052     * This system property controls the target for internal reports output by SLF4J.
053     * Recognized values for this key are "System.out", "stdout", "sysout", "System.err",
054     * "stderr" and "syserr".
055     *
056     * <p>By default, output is directed to "stderr".</p>
057     */
058    public static final String SLF4J_INTERNAL_REPORT_STREAM_KEY = "slf4j.internal.report.stream";
059    static private final String[] SYSOUT_KEYS = {"System.out", "stdout", "sysout"};
060
061    /**
062     * This system property controls the internal level of chattiness
063     * of SLF4J. Recognized settings are "INFO", "WARN" and "ERROR". The default value is "INFO".
064     */
065    public static final String SLF4J_INTERNAL_VERBOSITY_KEY = "slf4j.internal.verbosity";
066
067
068    static private final TargetChoice TARGET_CHOICE = getTargetChoice();
069
070    static private final Level INTERNAL_VERBOSITY = initVerbosity();
071
072    static private TargetChoice getTargetChoice() {
073        String reportStreamStr = System.getProperty(SLF4J_INTERNAL_REPORT_STREAM_KEY);
074
075        if(reportStreamStr == null || reportStreamStr.isEmpty()) {
076            return TargetChoice.Stderr;
077        }
078
079        for(String s : SYSOUT_KEYS) {
080            if(s.equalsIgnoreCase(reportStreamStr))
081                return TargetChoice.Stdout;
082        }
083        return TargetChoice.Stderr;
084    }
085
086
087    static private Level initVerbosity() {
088        String verbosityStr = System.getProperty(SLF4J_INTERNAL_VERBOSITY_KEY);
089
090        if(verbosityStr == null || verbosityStr.isEmpty()) {
091            return Level.INFO;
092        }
093
094        if(verbosityStr.equalsIgnoreCase("DEBUG")) {
095            return Level.DEBUG;
096        }
097
098        if(verbosityStr.equalsIgnoreCase("ERROR")) {
099            return Level.ERROR;
100        }
101
102
103        if(verbosityStr.equalsIgnoreCase("WARN")) {
104            return Level.WARN;
105        }
106
107        // anything else including verbosityStr.equalsIgnoreCase("INFO")
108        return Level.INFO;
109    }
110
111    static boolean isEnabledFor(Level level) {
112        return (level.levelInt >= INTERNAL_VERBOSITY.levelInt);
113    }
114
115    static private PrintStream getTarget() {
116        switch(TARGET_CHOICE) {
117            case Stdout:
118                return System.out;
119            case Stderr:
120            default:
121                return System.err;
122        }
123    }
124
125    /**
126     * Report an internal message of level DEBUG. Message text is prefixed with the string "SLF4J(D)",
127     * with (D) standing as a shorthand for DEBUG.
128     *
129     * <p>Messages of level DEBUG are be enabled when the {@link #SLF4J_INTERNAL_VERBOSITY_KEY}
130     * system property is set to "DEBUG" and disabled when set to "INFO", "WARN" or "ERROR". By default,
131     * {@link #SLF4J_INTERNAL_VERBOSITY_KEY} is set to "INFO".</p>
132     *
133     * @param msg the message text
134     * @since 2.0.16
135     */
136    public static void debug(String msg) {
137        if(isEnabledFor(Level.DEBUG)) {
138            getTarget().println(SLF4J_DEBUG_PREFIX + msg);
139        }
140    }
141
142    /**
143     * Report an internal message of level INFO. Message text is prefixed with the string "SLF4J(I)", with
144     * (I) standing as a shorthand for INFO.
145     *
146     * <p>Messages of level INFO are be enabled when the {@link #SLF4J_INTERNAL_VERBOSITY_KEY} system property is
147     * set to "DEBUG" or "INFO" and disabled when set to "WARN" or "ERROR". By default,
148     * {@link #SLF4J_INTERNAL_VERBOSITY_KEY} is set to "INFO".</p>
149     *
150     * @param msg the message text
151     */
152    public static void info(String msg) {
153        if(isEnabledFor(Level.INFO)) {
154            getTarget().println(SLF4J_INFO_PREFIX + msg);
155        }
156    }
157
158
159    /**
160     * Report an internal message of level "WARN". Message text is prefixed with the string "SLF4J(W)", with
161     * (W) standing as a shorthand for  WARN.
162     *
163     * <p>Messages of level WARN are be enabled when the {@link #SLF4J_INTERNAL_VERBOSITY_KEY} system property is
164     * set to "DEBUG", "INFO" or "WARN" and disabled when set to "ERROR". By default,
165     * {@link #SLF4J_INTERNAL_VERBOSITY_KEY} is set to "INFO".</p>
166     *
167     * @param msg the message text
168     */
169    static final public void warn(String msg) {
170        if(isEnabledFor(Level.WARN)) {
171            getTarget().println(SLF4J_WARN_PREFIX + msg);
172        }
173    }
174
175    /**
176     * Report an internal message of level "ERROR  accompanied by a {@link Throwable}.
177     * Message text is prefixed with the string "SLF4J(E)", with (E) standing as a shorthand for ERROR.
178     *
179     * <p>Messages of level ERROR are always enabled.
180     *
181     * @param msg the message text
182     * @param t a Throwable
183     */
184    static final public void error(String msg, Throwable t) {
185        // error cannot be disabled
186        getTarget().println(SLF4J_ERROR_PREFIX + msg);
187        getTarget().println(SLF4J_ERROR_PREFIX + "Reported exception:");
188        t.printStackTrace(getTarget());
189    }
190
191    /**
192     * Report an internal message of level "ERROR". Message text is prefixed with the string "SLF4J(E)",
193     * with (E)  standing as a shorthand for ERROR.
194     *
195     * <p>Messages of level ERROR are always enabled.
196     *
197     * @param msg the message text
198     */
199
200    static final public void error(String msg) {
201        // error cannot be disabled
202        getTarget().println(SLF4J_ERROR_PREFIX + msg);
203    }
204}