001/*
002 * This is free and unencumbered software released into the public domain.
003 *
004 * Please see https://github.com/binkley/binkley/blob/master/LICENSE.md.
005 */
006
007package hm.binkley.util.logging;
008
009import ch.qos.logback.classic.Level;
010import org.slf4j.Logger;
011import org.slf4j.LoggerFactory;
012import org.slf4j.Marker;
013import org.slf4j.ext.LoggerWrapper;
014
015import javax.annotation.Nonnull;
016
017import static ch.qos.logback.classic.Level.DEBUG;
018import static ch.qos.logback.classic.Level.ERROR;
019import static ch.qos.logback.classic.Level.INFO;
020import static ch.qos.logback.classic.Level.TRACE;
021import static ch.qos.logback.classic.Level.WARN;
022import static java.lang.String.format;
023import static java.lang.System.out;
024
025/**
026 * {@code MinimalLogger} complains about trivial logging.  When a logger supports only a given level
027 * or greater, attempts to log at a lesser level throw {@code IllegalStateException}.
028 *
029 * @author <a href="mailto:binkley@alumni.rice.edu">B. K. Oxley (binkley)</a>
030 */
031public class MinimumLogger
032        extends LoggerWrapper {
033    private final Level minimum;
034
035    /**
036     * Gets the underlying wrapped logger for extensions.
037     *
038     * @return the underlying logger, never missing
039     */
040    @Nonnull
041    public final Logger getUnderlying() {
042        return logger;
043    }
044
045    /**
046     * Constructs a new {@code MinimalLogger} for the given parameters.
047     *
048     * @param logger the logger to delegate to, never missing
049     * @param minimum the minimum, non-trivial level of logging, never missing
050     */
051    public MinimumLogger(@Nonnull final Logger logger, @Nonnull final Level minimum) {
052        this(logger, MinimumLogger.class.getName(), minimum);
053    }
054
055    /**
056     * Constructs a new {@code MinimalLogger} for the given parameters suitable as a base class.
057     *
058     * @param logger the logger to delegate to, never missing
059     * @param fqcn the fully-qualified class name of the extending logger, never missing
060     * @param minimum the minimum, non-trivial level of logging, never missing
061     */
062    public MinimumLogger(@Nonnull final Logger logger, @Nonnull final String fqcn,
063            @Nonnull final Level minimum) {
064        super(logger, fqcn);
065        this.minimum = minimum;
066    }
067
068    @Override
069    public boolean isTraceEnabled() {
070        return TRACE.isGreaterOrEqual(minimum) && logger.isTraceEnabled();
071    }
072
073    @Override
074    public boolean isTraceEnabled(final Marker marker) {
075        return TRACE.isGreaterOrEqual(minimum) && logger.isTraceEnabled(marker);
076    }
077
078    @Override
079    public void trace(final String msg) {
080        require(TRACE);
081        super.trace(msg);
082    }
083
084    @Override
085    public void trace(final String format, final Object arg) {
086        require(TRACE);
087        super.trace(format, arg);
088    }
089
090    @Override
091    public void trace(final String format, final Object arg1, final Object arg2) {
092        require(TRACE);
093        super.trace(format, arg1, arg2);
094    }
095
096    @Override
097    public void trace(final String format, final Object... args) {
098        require(TRACE);
099        super.trace(format, args);
100    }
101
102    @Override
103    public void trace(final String msg, final Throwable t) {
104        require(TRACE);
105        super.trace(msg, t);
106    }
107
108    @Override
109    public void trace(final Marker marker, final String msg) {
110        require(TRACE);
111        super.trace(marker, msg);
112    }
113
114    @Override
115    public void trace(final Marker marker, final String format, final Object arg) {
116        require(TRACE);
117        super.trace(marker, format, arg);
118    }
119
120    @Override
121    public void trace(final Marker marker, final String format, final Object arg1,
122            final Object arg2) {
123        require(TRACE);
124        super.trace(marker, format, arg1, arg2);
125    }
126
127    @Override
128    public void trace(final Marker marker, final String format, final Object... args) {
129        require(TRACE);
130        super.trace(marker, format, args);
131    }
132
133    @Override
134    public void trace(final Marker marker, final String msg, final Throwable t) {
135        require(TRACE);
136        super.trace(marker, msg, t);
137    }
138
139    @Override
140    public boolean isDebugEnabled() {
141        return DEBUG.isGreaterOrEqual(minimum) && logger.isDebugEnabled();
142    }
143
144    @Override
145    public boolean isDebugEnabled(final Marker marker) {
146        return DEBUG.isGreaterOrEqual(minimum) && logger.isDebugEnabled(marker);
147    }
148
149    @Override
150    public void debug(final String msg) {
151        require(DEBUG);
152        super.debug(msg);
153    }
154
155    @Override
156    public void debug(final String format, final Object arg) {
157        require(DEBUG);
158        super.debug(format, arg);
159    }
160
161    @Override
162    public void debug(final String format, final Object arg1, final Object arg2) {
163        require(DEBUG);
164        super.debug(format, arg1, arg2);
165    }
166
167    @Override
168    public void debug(final String format, final Object... argArray) {
169        require(DEBUG);
170        super.debug(format, argArray);
171    }
172
173    @Override
174    public void debug(final String msg, final Throwable t) {
175        require(DEBUG);
176        super.debug(msg, t);
177    }
178
179    @Override
180    public void debug(final Marker marker, final String msg) {
181        require(DEBUG);
182        super.debug(marker, msg);
183    }
184
185    @Override
186    public void debug(final Marker marker, final String format, final Object arg) {
187        require(DEBUG);
188        super.debug(marker, format, arg);
189    }
190
191    @Override
192    public void debug(final Marker marker, final String format, final Object arg1,
193            final Object arg2) {
194        require(DEBUG);
195        super.debug(marker, format, arg1, arg2);
196    }
197
198    @Override
199    public void debug(final Marker marker, final String format, final Object... argArray) {
200        require(DEBUG);
201        super.debug(marker, format, argArray);
202    }
203
204    @Override
205    public void debug(final Marker marker, final String msg, final Throwable t) {
206        require(DEBUG);
207        super.debug(marker, msg, t);
208    }
209
210    @Override
211    public boolean isInfoEnabled() {
212        return INFO.isGreaterOrEqual(minimum) && logger.isInfoEnabled();
213    }
214
215    @Override
216    public boolean isInfoEnabled(final Marker marker) {
217        return INFO.isGreaterOrEqual(minimum) && logger.isInfoEnabled(marker);
218    }
219
220    @Override
221    public void info(final String msg) {
222        require(INFO);
223        super.info(msg);
224    }
225
226    @Override
227    public void info(final String format, final Object arg) {
228        require(INFO);
229        super.info(format, arg);
230    }
231
232    @Override
233    public void info(final String format, final Object arg1, final Object arg2) {
234        require(INFO);
235        super.info(format, arg1, arg2);
236    }
237
238    @Override
239    public void info(final String format, final Object... args) {
240        require(INFO);
241        super.info(format, args);
242    }
243
244    @Override
245    public void info(final String msg, final Throwable t) {
246        require(INFO);
247        super.info(msg, t);
248    }
249
250    @Override
251    public void info(final Marker marker, final String msg) {
252        require(INFO);
253        super.info(marker, msg);
254    }
255
256    @Override
257    public void info(final Marker marker, final String format, final Object arg) {
258        require(INFO);
259        super.info(marker, format, arg);
260    }
261
262    @Override
263    public void info(final Marker marker, final String format, final Object arg1,
264            final Object arg2) {
265        require(INFO);
266        super.info(marker, format, arg1, arg2);
267    }
268
269    @Override
270    public void info(final Marker marker, final String format, final Object... args) {
271        require(INFO);
272        super.info(marker, format, args);
273    }
274
275    @Override
276    public void info(final Marker marker, final String msg, final Throwable t) {
277        require(INFO);
278        super.info(marker, msg, t);
279    }
280
281    @Override
282    public boolean isWarnEnabled() {
283        return WARN.isGreaterOrEqual(minimum) && logger.isWarnEnabled();
284    }
285
286    @Override
287    public boolean isWarnEnabled(final Marker marker) {
288        return WARN.isGreaterOrEqual(minimum) && logger.isWarnEnabled(marker);
289    }
290
291    @Override
292    public void warn(final String msg) {
293        require(WARN);
294        super.warn(msg);
295    }
296
297    @Override
298    public void warn(final String format, final Object arg) {
299        require(WARN);
300        super.warn(format, arg);
301    }
302
303    @Override
304    public void warn(final String format, final Object arg1, final Object arg2) {
305        require(WARN);
306        super.warn(format, arg1, arg2);
307    }
308
309    @Override
310    public void warn(final String format, final Object... args) {
311        require(WARN);
312        super.warn(format, args);
313    }
314
315    @Override
316    public void warn(final String msg, final Throwable t) {
317        require(WARN);
318        super.warn(msg, t);
319    }
320
321    @Override
322    public void warn(final Marker marker, final String msg) {
323        require(WARN);
324        super.warn(marker, msg);
325    }
326
327    @Override
328    public void warn(final Marker marker, final String format, final Object arg) {
329        require(WARN);
330        super.warn(marker, format, arg);
331    }
332
333    @Override
334    public void warn(final Marker marker, final String format, final Object arg1,
335            final Object arg2) {
336        require(WARN);
337        super.warn(marker, format, arg1, arg2);
338    }
339
340    @Override
341    public void warn(final Marker marker, final String format, final Object... args) {
342        require(WARN);
343        super.warn(marker, format, args);
344    }
345
346    @Override
347    public void warn(final Marker marker, final String msg, final Throwable t) {
348        require(WARN);
349        super.warn(marker, msg, t);
350    }
351
352    @Override
353    public boolean isErrorEnabled() {
354        return WARN.isGreaterOrEqual(minimum) && logger.isWarnEnabled();
355    }
356
357    @Override
358    public boolean isErrorEnabled(final Marker marker) {
359        return WARN.isGreaterOrEqual(minimum) && logger.isWarnEnabled(marker);
360    }
361
362    @Override
363    public void error(final String msg) {
364        require(ERROR);
365        super.error(msg);
366    }
367
368    @Override
369    public void error(final String format, final Object arg) {
370        require(ERROR);
371        super.error(format, arg);
372    }
373
374    @Override
375    public void error(final String format, final Object arg1, final Object arg2) {
376        require(ERROR);
377        super.error(format, arg1, arg2);
378    }
379
380    @Override
381    public void error(final String format, final Object... args) {
382        require(ERROR);
383        super.error(format, args);
384    }
385
386    @Override
387    public void error(final String msg, final Throwable t) {
388        require(ERROR);
389        super.error(msg, t);
390    }
391
392    @Override
393    public void error(final Marker marker, final String msg) {
394        require(ERROR);
395        super.error(marker, msg);
396    }
397
398    @Override
399    public void error(final Marker marker, final String format, final Object arg) {
400        require(ERROR);
401        super.error(marker, format, arg);
402    }
403
404    @Override
405    public void error(final Marker marker, final String format, final Object arg1,
406            final Object arg2) {
407        require(ERROR);
408        super.error(marker, format, arg1, arg2);
409    }
410
411    @Override
412    public void error(final Marker marker, final String format, final Object... args) {
413        require(ERROR);
414        super.error(marker, format, args);
415    }
416
417    @Override
418    public void error(final Marker marker, final String msg, final Throwable t) {
419        require(ERROR);
420        super.error(marker, msg, t);
421    }
422
423    private void require(final Level current) {
424        if (!current.isGreaterOrEqual(minimum))
425            throw new IllegalStateException(
426                    format("%s logging disabled for logger \"%s\" [%s]", current, getName(),
427                            getClass().getName()));
428    }
429
430    public static void main(final String... args) {
431        try {
432            final MinimumLogger main = new MinimumLogger(LoggerFactory.getLogger("main"), INFO);
433            main.info("Just fine");
434            main.trace("Too trivial!");
435        } catch (final IllegalStateException e) {
436            e.printStackTrace(out);
437        }
438    }
439}